| /******************************************************************************* |
| * Copyright (c) 2010 SAP AG, Walldorf. |
| * 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: |
| * SAP AG - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.platform.discovery.testutils.utils.abbot.util.internal;
|
|
|
| import java.util.Arrays;
|
| import java.util.HashSet;
|
| import java.util.Set;
|
|
|
| import org.eclipse.platform.discovery.testutils.internal.plugin.TestPlugin;
|
| import org.eclipse.platform.discovery.testutils.utils.abbot.ActiveSWTTestSuite;
|
| import org.eclipse.swt.SWT;
|
| import org.eclipse.swt.widgets.Display;
|
| import org.eclipse.swt.widgets.Shell;
|
| import org.eclipse.ui.PlatformUI;
|
|
|
| import abbot.swt.Robot;
|
|
|
| /**
|
| * Tool class providing the functionality to clean up the UI after a test has
|
| * been called. A typical scenario is to close all modal dialogs (which may have
|
| * not been expected by the test and hence have made it fail) to ensure that the
|
| * UI thread is not blocked and that following UI tests can start in a defined
|
| * state. Note that however there is no mean to avoid all interference between
|
| * UI test, just for the sheer complexity of the UI.
|
| * <p>
|
| * For the possible cleanup actions, see the
|
| * {@link UICleanupManager.CleanupMethod} constants.
|
| * </p>
|
| * <p>
|
| * This class is not public since it has inherited design flaws from legacy
|
| * classes using this class. Specifically, the fact that calls to
|
| * <code>setCleanupMethod</code> must be permitted after
|
| * <code>registerUIState</code> entails a potentially inefficient
|
| * implementation. However, not being public it can be easily refactored if
|
| * functionality of this class shall be made available in other projects.
|
| * </p>
|
| *
|
| * @see ActiveSWTTestSuite
|
| */
|
| public class UICleanupManager /* implements ISideEffectCleanupManager */{
|
| /** Selected cleanup method. */
|
| private CleanupMethod cleanupMethod;
|
| /** List of shells that were open before the test. */
|
| private Set<Shell> shellsBeforeExecution = null;
|
| /** Name of test using this manager (for debug output). */
|
| private String testDebugName;
|
|
|
| /**
|
| * Approaches for cleaning up spurious UI elements (modal dialogs, context
|
| * menus, etc.) after the test execution.
|
| */
|
| public static enum CleanupMethod {
|
| /**
|
| * Register open shells before the test is executed and call
|
| * <code>close()</code> on every shell that has been left open by the
|
| * test, in addition to sending escapes.
|
| * <p>
|
| * Warning: This method is known to cause problems with the Graphical
|
| * Editing Framework (GEF) as of Eclipse version 3.3, since GEF stores a
|
| * shell in a static member.
|
| * </p>
|
| */
|
| SHELL_CLOSE_AND_ESCAPES,
|
| /**
|
| * Send escape keys as a heuristic to close dialogs and context menus
|
| * after the test execution.
|
| */
|
| ESCAPES
|
| }
|
|
|
| /**
|
| * Constructs a manager instance using the most widely applicable cleanup
|
| * method.
|
| */
|
| public UICleanupManager() {
|
| this(CleanupMethod.ESCAPES);
|
| }
|
|
|
| /**
|
| * Constructs a manager instance with the specified cleanup method.
|
| *
|
| * @param the
|
| * cleanup method to use. Must not be <code>null</code>.
|
| */
|
| public UICleanupManager(final CleanupMethod method) {
|
| if (method == null) {
|
| throw new NullPointerException("The method parameter must not be null.");
|
| }
|
| this.cleanupMethod = method;
|
| }
|
|
|
| /**
|
| * Call this method before executing a test.
|
| */
|
| public void registerUIState() {
|
| // register currently open shells; NB: this step must be done
|
| // irrespective of the active cleanup method because users of this
|
| // class require that setCleanupMethod may still be called after
|
| // calling this method
|
| final Display display = Display.getDefault();
|
| display.syncExec(new Runnable() {
|
| public void run() {
|
| UICleanupManager.this.registerOpenShells(display);
|
| }
|
| });
|
| }
|
|
|
| /**
|
| * Call this method after executing a test in order to provide a "clean" UI
|
| * before the next test is started.
|
| *
|
| * @throws IllegalStateException
|
| * if {@link #registerUIState()} has not yet been called.
|
| */
|
| public void cleanUp() throws IllegalStateException {
|
| if (shellsBeforeExecution == null)
|
| throw new IllegalStateException("registerUIState() must be called before cleanUp().");
|
|
|
| if (cleanupMethod == CleanupMethod.SHELL_CLOSE_AND_ESCAPES) {
|
| // explicitly close those shells that were not open before the test method was run
|
| final Display display = Display.getDefault();
|
| display.syncExec(new Runnable() {
|
| public void run() {
|
| UICleanupManager.this.closeLeftOverShells(display);
|
| }
|
| });
|
| }
|
|
|
| switch (cleanupMethod) {
|
| case SHELL_CLOSE_AND_ESCAPES:
|
| case ESCAPES:
|
| // attempt to close dialogs and context menus
|
| final Robot robot = new Robot(PlatformUI.getWorkbench().getDisplay());
|
| for (int i = 0; i < 25; i++) {
|
| robot.key(SWT.ESC);
|
| }
|
| }
|
| }
|
|
|
| /**
|
| * Stores the currently open shells. Must be called within the UI thread.
|
| *
|
| * @param display
|
| * the default display.
|
| */
|
| private void registerOpenShells(final Display display) {
|
| final Shell[] currentShells = display.getShells();
|
| shellsBeforeExecution = new HashSet<Shell>(Arrays.asList(currentShells));
|
| }
|
|
|
| /**
|
| * Closes shells that were not open when {@link #registerUIState()} was
|
| * called. Must be called within the UI thread.
|
| *
|
| * @param display
|
| * the default display.
|
| */
|
| private void closeLeftOverShells(final Display display) {
|
| final Shell[] openShells = display.getShells();
|
| for (final Shell s : openShells) {
|
| if (!shellsBeforeExecution.contains(s)) {
|
| TestPlugin.logWarning("WARNING: " + testDebugName
|
| + ": There is a shell open which has not been open when the test was started: " + s);
|
| ActiveSWTTestSuite.closeShells(new Shell[] { s });
|
| }
|
| }
|
| }
|
|
|
| public CleanupMethod getCleanupMethod() {
|
| return cleanupMethod;
|
| }
|
|
|
| public void setCleanupMethod(final CleanupMethod method) throws IllegalStateException {
|
| this.cleanupMethod = method;
|
| }
|
| }
|