Skip to content

Commit

Permalink
Simplify Zest tests by using the SWTBot
Browse files Browse the repository at this point in the history
This removes classes such as the WidgetVisitor in favor of using the
methods provided by the SWTBot. Note that because the SWTBot doesn't
understand the Zest model, the tests still have to be executed in the UI
thread.
  • Loading branch information
ptziegler authored and azoitl committed Aug 19, 2024
1 parent 300334c commit b1f6f28
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 173 deletions.
4 changes: 3 additions & 1 deletion org.eclipse.zest.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: Graphical Editing Framework Zest Tests
Bundle-SymbolicName: org.eclipse.zest.tests;singleton:=true
Bundle-Version: 1.8.600.qualifier
Import-Package: org.slf4j;version="1.7.30"
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.pde,
Expand All @@ -14,7 +15,8 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.zest.core,
org.eclipse.zest.examples,
org.eclipse.zest.layouts,
org.junit
org.junit,
org.eclipse.swtbot.swt.finder;bundle-version="4.2.1"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
Automatic-Module-Name: org.eclipse.zest.tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,9 @@
import java.util.Objects;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.core.runtime.Assert;
import org.eclipse.zest.core.widgets.Graph;
Expand All @@ -51,7 +46,6 @@
import org.eclipse.zest.layouts.dataStructures.InternalRelationship;
import org.eclipse.zest.tests.utils.GraphicalRobot;
import org.eclipse.zest.tests.utils.Snippet;
import org.eclipse.zest.tests.utils.WidgetVisitor;

import org.eclipse.draw2d.EventDispatcher;
import org.eclipse.draw2d.IFigure;
Expand Down Expand Up @@ -381,52 +375,6 @@ protected static void assertInstanceOf(Object object, Class<?> clazz) {
assertTrue(clazz.isAssignableFrom(object.getClass()));
}

/**
* @return the {@link Button} with given text.
*/
protected static Button findButtonByName(Shell shell, String text) {
return findWidget(shell, Button.class, b -> text.equals(b.getText()));
}

/**
* @return the first {@link Text} in the given {@link Shell}.
*/
protected static Text findText(Shell shell) {
return findWidget(shell, Text.class, t -> true);
}

/**
* @return the first {@link Canvas} in the given {@link Shell}.
*/
protected static Canvas findCanvas(Shell shell) {
return findWidget(shell, Canvas.class, t -> true);
}

/**
* Convenience method for finding a given {@link Widget} in a {@link Shell}.
* type.
*
* @return The first widget of type {@code T}, matching the predicate. Returns
* {@code null} if no such widget is found.
*/
private static <T extends Widget> T findWidget(Shell shell, Class<T> clazz, Predicate<T> predicate) {
AtomicReference<T> ref = new AtomicReference<>();
new WidgetVisitor() {
@Override
public boolean visit(Widget w) {
if (clazz.isAssignableFrom(w.getClass())) {
T widget = clazz.cast(w);
if (predicate.test(widget)) {
ref.set(widget);
return false;
}
}
return true;
}
}.traverse(shell);
return ref.get();
}

/**
* Pumps the event loop for the given number of milliseconds. At least one
* events loop will be executed.
Expand All @@ -435,7 +383,7 @@ protected static void waitEventLoop(int time) {
long start = System.currentTimeMillis();
do {
while (Display.getCurrent().readAndDispatch()) {
// do nothing
Thread.yield();
}
} while (System.currentTimeMillis() - start < time);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import java.lang.invoke.VarHandle;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.swt.widgets.Button;

import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.zest.core.viewers.GraphViewer;
Expand Down Expand Up @@ -175,8 +173,7 @@ public void testGraphJFaceSnippet5() {
assertEquals(graph.getConnections().size(), 3);
assertEquals(graph.getNodes().size(), 3);

Button refresh = findButtonByName(graph.getShell(), "Refresh");
robot.select(refresh);
robot.button("Refresh").click();

assertConnection(graph.getConnections().get(0), "Paper", "Rock");
assertConnection(graph.getConnections().get(1), "Scissors", "Paper");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphConnection;
import org.eclipse.zest.core.widgets.GraphContainer;
Expand Down Expand Up @@ -116,8 +118,7 @@ public void testAnimationSnippet() {
AtomicInteger repaintCount = new AtomicInteger();
graph.addPaintListener(event -> repaintCount.incrementAndGet());

Button button = findButtonByName(graph.getShell(), "Animate");
robot.select(button);
robot.button("Animate").click();

assertTrue("Animation was likely not drawn!", repaintCount.get() > 0);
assertNoOverlap(graph);
Expand Down Expand Up @@ -172,22 +173,23 @@ public void testGraphSnippet1() {

// The NodeSearchDialog should now be active
dialogShell = graph.getDisplay().getActiveShell();
Text text = findText(dialogShell);
Button next = findButtonByName(dialogShell, "Next");
SWTBot dialogRobot = new SWTBot(dialogShell);
SWTBotText textRobot = dialogRobot.text();
SWTBotButton buttonRobot = dialogRobot.button("Next");

text.setText("Paper");
robot.focusOut(text);
robot.select(next);
textRobot.setText("Paper");
focusOut(textRobot);
buttonRobot.click();
assertEquals(graph.getSelection(), List.of(node1));

text.setText("Rock");
robot.focusOut(text);
robot.select(next);
textRobot.setText("Rock");
focusOut(textRobot);
buttonRobot.click();
assertEquals(graph.getSelection(), List.of(node2));

text.setText("Scissor");
robot.focusOut(text);
robot.select(next);
textRobot.setText("Scissors");
focusOut(textRobot);
buttonRobot.click();
assertEquals(graph.getSelection(), List.of(node3));
} finally {
if (dialogShell != null) {
Expand All @@ -196,6 +198,16 @@ public void testGraphSnippet1() {
}
}

/**
* This method simulates a {@link SWT#FocusOut} event using the given
* {@code widget}. Events are sent to the argument.
*
* @param widget The widget whose focus has been lost.
*/
private static void focusOut(SWTBotText robot) {
robot.widget.notifyListeners(SWT.FocusOut, new Event());
}

/**
* Tests whether images are properly handled.
*/
Expand Down Expand Up @@ -418,10 +430,9 @@ public void testGraphSnippet10() {
assertConnection(connection2, "Rock", "Scissors");
assertConnection(connection3, "Scissors", "Paper");

Button button = findButtonByName(graph.getShell(), "Change Curve");
for (int i = 0; i < 4; ++i) {
if (i > 0) {
robot.select(button);
robot.button("Change Curve").click();
}
// Old connection is removed and a new one is added
assertArc(graph.getConnections().get(2), i * 10 /* ° */);
Expand Down Expand Up @@ -692,12 +703,12 @@ public void testPaintSnippet() {
graph.selectAll();
waitEventLoop(0);

Button button = findButtonByName(graph.getShell(), "Take Screenshot");
robot.select(button);
robot.button("Take Screenshot").click();
waitEventLoop(0);

Shell popupShell = graph.getDisplay().getActiveShell();
Canvas popupCanvas = findCanvas(popupShell);
SWTBot popupRobot = new SWTBot(popupShell);
Canvas popupCanvas = popupRobot.canvas().widget;
Rectangle bounds = popupCanvas.getBounds();

GC gc = new GC(popupCanvas);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.core.runtime.Assert;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphItem;
import org.eclipse.zest.core.widgets.GraphNode;
Expand All @@ -28,10 +28,11 @@
/**
* Utility class to simulate user events (clicks, etc.) on a {@link Graph}.
*/
public class GraphicalRobot {
public class GraphicalRobot extends SWTBot {
private final Graph graph;

public GraphicalRobot(Graph graph) {
super(graph.getShell());
this.graph = graph;
}

Expand Down Expand Up @@ -108,31 +109,9 @@ public void mouseDown(int x, int y) {
* @param node The graph node to select.
*/
public void select(GraphNode node) {
graph.setSelection(new GraphItem[] { node });
select(graph);
}

/**
* This method simulates a {@link SWT#Selection} event using the given
* {@code widget}. Events are sent to the argument.
*
* @param widget The widget to select.
*/
@SuppressWarnings("static-method")
public void select(Widget widget) {
Event event = createMouseEvent(SWT.Selection, 1, 1);
widget.notifyListeners(event.type, event);
}

/**
* This method simulates a {@link SWT#FocusOut} event using the given
* {@code widget}. Events are sent to the argument.
*
* @param widget The widget whose focus has been lost.
*/
@SuppressWarnings("static-method")
public void focusOut(Widget widget) {
widget.notifyListeners(SWT.FocusOut, new Event());
graph.setSelection(new GraphItem[] { node });
graph.notifyListeners(event.type, event);
}

/**
Expand Down

This file was deleted.

0 comments on commit b1f6f28

Please sign in to comment.