diff options
Diffstat (limited to 'tests/junit/plugins/uml/profile/org.eclipse.papyrus.uml.profile.tests/src/org/eclipse/papyrus/uml/profile/tests/DialogInteractionRule.java')
-rw-r--r-- | tests/junit/plugins/uml/profile/org.eclipse.papyrus.uml.profile.tests/src/org/eclipse/papyrus/uml/profile/tests/DialogInteractionRule.java | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/tests/junit/plugins/uml/profile/org.eclipse.papyrus.uml.profile.tests/src/org/eclipse/papyrus/uml/profile/tests/DialogInteractionRule.java b/tests/junit/plugins/uml/profile/org.eclipse.papyrus.uml.profile.tests/src/org/eclipse/papyrus/uml/profile/tests/DialogInteractionRule.java new file mode 100644 index 00000000000..e2b42f79984 --- /dev/null +++ b/tests/junit/plugins/uml/profile/org.eclipse.papyrus.uml.profile.tests/src/org/eclipse/papyrus/uml/profile/tests/DialogInteractionRule.java @@ -0,0 +1,178 @@ +/***************************************************************************** + * Copyright (c) 2015 Christian W. Damus and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.profile.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.junit.utils.JUnitUtils; +import org.eclipse.papyrus.uml.profile.service.ui.RefreshProfileDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; + +/** + * A JUnit rule that interacts (or not) with the editor's Profile Migration Dialog. + */ +public class DialogInteractionRule extends TestWatcher { + private DialogInteractionKind interactionMode; + private volatile boolean active; + + private final Lock lock = new ReentrantLock(); + private final Condition dialogInteractionDone = lock.newCondition(); + private final AtomicReference<Boolean> interactionResult = new AtomicReference<>(); + + public void assertInteraction() { + waitForInteraction(); + + Boolean result = interactionResult.get(); + assertThat("No dialog interaction occurred", result, notNullValue()); + assertThat("Expected dialog interaction did not occur: " + interactionMode, result, is(true)); + } + + @Override + protected void starting(Description description) { + interactionMode = JUnitUtils.getAnnotation(description, DialogInteractionMode.class).value(); + active = true; + + Display.getDefault().asyncExec(new InteractionRunnable()); + } + + @Override + protected void finished(Description description) { + active = false; + } + + protected void waitForInteraction() { + Display current = Display.getCurrent(); + + if (current != null) { + // This is the UI thread. Flush it + for (;;) { + try { + if (!current.readAndDispatch()) { + break; + } + } catch (Exception e) { + // It may provide diagnostic information for the test + e.printStackTrace(); + } + } + } else { + // Synchronize with the UI thread + Display.getDefault().syncExec(new Runnable() { + + @Override + public void run() { + // Pass + } + }); + } + } + + static <W extends Window> W findWindow(Class<W> windowType) { + W result = null; + + for (Shell next : Display.getDefault().getShells()) { + if (windowType.isInstance(next.getData())) { + result = windowType.cast(next.getData()); + break; + } + } + + return result; + } + + static Button findButton(Composite composite, int code) { + Button result = null; + + Integer id = code; + Control[] controls = composite.getChildren(); + for (int i = 0; (i < controls.length) && (result == null); i++) { + final Control next = controls[i]; + + if (next instanceof Button) { + Button button = (Button) next; + if (id.equals(button.getData())) { + result = button; + } + } else if (next instanceof Composite) { + result = findButton((Composite) next, code); + } + } + + return result; + } + + // + // Nested types + // + + /** + * An asynchronous UI runnable that is schedule to run after the editor has opened, + * and so after it has shown the profile migration dialog (if any), to interact with + * it if it is open. + */ + private class InteractionRunnable implements Runnable { + @Override + public void run() { + Boolean result = false; + + if (active) { + RefreshProfileDialog dialog = findWindow(RefreshProfileDialog.class); + + switch (interactionMode) { + case CANCEL: + if (dialog != null) { + result = true; + findButton(dialog.getShell(), IDialogConstants.CANCEL_ID).notifyListeners(SWT.Selection, new Event()); + } + break; + case OK: + if (dialog != null) { + result = true; + findButton(dialog.getShell(), IDialogConstants.OK_ID).notifyListeners(SWT.Selection, new Event()); + } + break; + default: // NONE + result = dialog == null; + break; + } + } + + lock.lock(); + + try { + interactionResult.set(result); + dialogInteractionDone.signalAll(); + } finally { + lock.unlock(); + } + } + } +} |