package pipe.controllers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import pipe.gui.*;
import pipe.historyActions.component.DeletePetriNetObject;
import uk.ac.imperial.pipe.exceptions.PetriNetComponentException;
import uk.ac.imperial.pipe.exceptions.PetriNetComponentNotFoundException;
import uk.ac.imperial.pipe.models.petrinet.*;
import uk.ac.imperial.pipe.visitor.TranslationVisitor;
import uk.ac.imperial.pipe.visitor.component.PetriNetComponentVisitor;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.UndoableEdit;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class PetriNetControllerTest {
@Rule
public ExpectedException expectedEx = ExpectedException.none();
private PetriNetController controller;
private PetriNet net;
@Mock
private GUIAnimator mockAnimator;
@Mock
private PetriNetTab mocKTab;
@Mock
UndoableEditListener undoListener;
@Before
public void setUp() {
net = new PetriNet();
CopyPasteManager copyPasteManager = mock(CopyPasteManager.class);
ZoomController zoomController = mock(ZoomController.class);
controller = new PetriNetController(net, undoListener, mockAnimator, copyPasteManager, zoomController, mocKTab);
}
@Test
public void containsSelected() {
PetriNetComponent dummyComponent = new DummyPetriNetComponent();
controller.select(dummyComponent);
assertTrue(controller.isSelected(dummyComponent));
}
@Test
public void doesNotContainDeselected() {
PetriNetComponent dummyComponent = new DummyPetriNetComponent();
controller.select(dummyComponent);
controller.deselect(dummyComponent);
assertFalse(controller.isSelected(dummyComponent));
}
@Test
public void deselectAllEmptiesSelected() {
PetriNetComponent dummyComponent = new DummyPetriNetComponent();
controller.select(dummyComponent);
controller.deselectAll();
assertFalse(controller.isSelected(dummyComponent));
}
@Test
public void deletesSelectedRemovesFromNet() throws PetriNetComponentException {
Place place = new DiscretePlace("", "");
net.addPlace(place);
controller.select(place);
controller.deleteSelection();
assertFalse(net.getPlaces().contains(place));
}
@Test
public void deletingSelectionReturnsListOfAbstractUndoEdits() throws PetriNetComponentException {
Place place = new DiscretePlace("", "");
net.addPlace(place);
controller.select(place);
List<UndoableEdit> edits = controller.deleteSelection();
DeletePetriNetObject deleteAction = new DeletePetriNetObject(place, net);
assertEquals(1, edits.size());
assertTrue(edits.contains(deleteAction));
}
@Test
public void deleteComponentRemovesFromPetriNet() throws PetriNetComponentException {
Place place = new DiscretePlace("", "");
net.addPlace(place);
controller.delete(place);
assertFalse("Petrinet contains place after deletion", net.getPlaces().contains(place));
}
@Test
public void deletingComponentAddsToHistoryManager() throws PetriNetComponentException {
Place place = new DiscretePlace("", "");
net.addPlace(place);
UndoableEdit edit = controller.delete(place);
DeletePetriNetObject deleteAction = new DeletePetriNetObject(place, net);
assertEquals(edit, deleteAction);
}
@Test
public void deletesSelectedNotifiesObserver() throws PetriNetComponentException {
Place place = new DiscretePlace("", "");
net.addPlace(place);
PropertyChangeListener mockListener = mock(PropertyChangeListener.class);
net.addPropertyChangeListener(mockListener);
controller.select(place);
controller.deleteSelection();
verify(mockListener, atLeastOnce()).propertyChange(any(PropertyChangeEvent.class));
}
@Test
public void selectsItemLocatedWithinSelectionArea() {
Place place = mock(Place.class);
when(place.getX()).thenReturn(5);
when(place.getY()).thenReturn(10);
when(place.getWidth()).thenReturn(5);
when(place.getHeight()).thenReturn(20);
net.addPlace(place);
Rectangle selectionRectangle = new Rectangle(5, 10, 40, 40);
controller.select(selectionRectangle);
assertTrue(controller.isSelected(place));
}
/**
* Even if top left x, y is out of the selection area if the height and width are in then select item
*/
@Test
public void selectsItemWithWidthAndHeightWithinSelectionArea() {
Place place = mock(Place.class);
when(place.getX()).thenReturn(0);
when(place.getY()).thenReturn(0);
when(place.getWidth()).thenReturn(10);
when(place.getHeight()).thenReturn(10);
net.addPlace(place);
Rectangle selectionRectangle = new Rectangle(5, 5, 40, 40);
controller.select(selectionRectangle);
assertTrue(controller.isSelected(place));
}
@Test
public void selectsArcIfIntersects() {
Transition t = new DiscreteTransition("T1", "T1");
InboundArc arc = mock(InboundArc.class);
when(arc.getTarget()).thenReturn(t);
Point2D.Double start = new Point2D.Double(0, 0);
Point2D.Double end = new Point2D.Double(10, 10);
when(arc.getArcPoints()).thenReturn(Arrays.asList(new ArcPoint(start, false), new ArcPoint(end, false)));
net.addArc(arc);
Rectangle selectionRectangle = new Rectangle(0, 0, 2, 2);
controller.select(selectionRectangle);
assertTrue(controller.isSelected(arc));
}
@Test
public void doesNotSelectArcIfDoesntIntersect() {
Transition t = new DiscreteTransition("T1", "T1");
InboundArc arc = mock(InboundArc.class);
when(arc.getTarget()).thenReturn(t);
Point2D.Double start = new Point2D.Double(0, 0);
Point2D.Double end = new Point2D.Double(10, 10);
when(arc.getArcPoints()).thenReturn(Arrays.asList(new ArcPoint(start, false), new ArcPoint(end, false)));
net.addArc(arc);
Rectangle selectionRectangle = new Rectangle(30, 30, 40, 40);
controller.select(selectionRectangle);
assertFalse(controller.isSelected(arc));
}
@Test
public void translatesSelectedItemsCorrectly() throws PetriNetComponentException {
Transition transition = mock(Transition.class);
when(transition.isDraggable()).thenReturn(true);
Place place = mock(Place.class);
when(place.isDraggable()).thenReturn(true);
net.addPlace(place);
net.addTransition(transition);
controller.select(place);
controller.select(transition);
int x_y_value = 40;
when(place.getX()).thenReturn(x_y_value);
when(place.getY()).thenReturn(x_y_value);
when(transition.getX()).thenReturn(x_y_value);
when(transition.getY()).thenReturn(x_y_value);
int translate_value = 50;
controller.translateSelected(new Point(translate_value, translate_value));
double expected_value = x_y_value + translate_value;
verify(place).accept(any(TranslationVisitor.class));
verify(transition).accept(any(TranslationVisitor.class));
}
@Test
public void doesNotTranslateNonDraggableItems() throws PetriNetComponentException {
PetriNetComponent petriNetComponent = mock(PetriNetComponent.class);
when(petriNetComponent.isDraggable()).thenReturn(false);
controller.select(petriNetComponent);
controller.translateSelected(new Point(23, 58));
verify(petriNetComponent, never()).accept(any(TranslationVisitor.class));
}
@Test
public void updateNameIfChanged() throws PetriNetComponentNotFoundException {
Token token = mock(Token.class);
String id = "id";
when(token.getId()).thenReturn(id);
boolean enabled = true;
Color color = Color.RED;
when(token.getColor()).thenReturn(color);
net.addToken(token);
controller.updateToken(id, "new", color);
verify(token).setId("new");
}
@Test
public void doesNotUpdateNameIfNotChanged() throws PetriNetComponentNotFoundException {
Token token = mock(Token.class);
String id = "id";
when(token.getId()).thenReturn(id);
boolean enabled = true;
Color color = new Color(255, 0, 0);
when(token.getColor()).thenReturn(color);
net.addToken(token);
controller.updateToken(id, id, color);
verify(token, never()).setId(anyString());
}
@Test
public void updateTokenColorIfChanged() throws PetriNetComponentNotFoundException {
Token token = mock(Token.class);
String id = "id";
when(token.getId()).thenReturn(id);
boolean enabled = true;
Color color = new Color(255, 0, 0);
when(token.getColor()).thenReturn(color);
net.addToken(token);
Color newColor = new Color(0, 0, 0);
controller.updateToken(id, id, newColor);
verify(token).setColor(newColor);
}
@Test
public void doesNotUpdateTokenColorIfNotChanged() throws PetriNetComponentNotFoundException {
Token token = mock(Token.class);
String id = "id";
when(token.getId()).thenReturn(id);
boolean enabled = true;
Color color = new Color(255, 0, 0);
when(token.getColor()).thenReturn(color);
net.addToken(token);
controller.updateToken(id, id, color);
verify(token, never()).setColor(any(Color.class));
}
@Test
public void createNewToken() {
String name = "testToken";
boolean enabled = true;
Color color = new Color(160, 92, 240);
controller.createNewToken(name, color);
Collection<Token> tokens = net.getTokens();
assertEquals(1, tokens.size());
Token token = tokens.iterator().next();
assertEquals(name, token.getId());
assertEquals(color, token.getColor());
}
private class DummyPetriNetComponent implements PetriNetComponent {
@Override
public boolean isSelectable() {
return false;
}
@Override
public boolean isDraggable() {
return false;
}
@Override
public void accept(PetriNetComponentVisitor visitor) {
}
@Override
public String getId() {
return "";
}
@Override
public void setId(String id) {
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
}
}