/*******************************************************************************
* Copyright (c) 2012 Pivotal Software, Inc.
* 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:
* Pivotal Software, Inc. - initial API and implementation
*******************************************************************************/
package org.springsource.ide.eclipse.commons.frameworks.test.util;
import java.io.File;
import java.util.List;
import junit.framework.TestSuite;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.SWTBotTestCase;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotList;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.springsource.ide.eclipse.commons.tests.util.StsTestUtil;
/**
* @author Kris De Volder
* @author Nieraj Singh
*/
public class UITestCase extends SWTBotTestCase {
private static Class<? extends UITestCase> isClassSetup = null;
private static Class<? extends UITestCase> setupClassTried = null;
protected static TestKeyboard keyboard;
protected static SWTWorkbenchBot bot;
protected static SWTBotShell mainShell;
private static long defaultTimeOut;
private static String defaultKeyboard;
public static TestSuite createSuite(Class<? extends UITestCase> klass) {
TestSuite suite = new TestSuite(klass);
suite.addTest(TestSuite.createTest(klass, "tearDownClass"));
return suite;
}
/**
* This method is made final, override setUpInstance and/or setupClass
* instead.
*/
@Override
public final void setUp() {
try {
if (enablePrinting()) {
SWTBotUtils.enablePrinting();;
}
if (!isClassSetup()) {
try {
setupClass();
} finally {
setupClassTried = this.getClass();
}
isClassSetup = this.getClass();
}
setupInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected boolean enablePrinting() {
return true;
}
protected void print(String message) {
SWTBotUtils.print(message);
}
/**
* @return
*/
private boolean isClassSetup() {
return this.getClass() == isClassSetup;
}
private boolean setupClassTried() {
return this.getClass() == setupClassTried;
}
public void setupClass() throws Exception {
bot = new SWTWorkbenchBot();
mainShell = new SWTBotShell(SWTBotUtils.getMainShell());
System.out.println("mainShell = " + mainShell);
System.out.println(" with text= " + mainShell.getText());
defaultTimeOut = SWTBotPreferences.TIMEOUT;
// SWTBotPreferences.TIMEOUT = 30000; // a bit excessive? But some
// grails commands take long time.
SWTBotPreferences.KEYBOARD_LAYOUT = "EN_US"; // In superclass
keyboard = new TestKeyboard(bot);
workspaceCleanUp(); // Get rid of artefacts left behind by other badly
// behaved suites.
workspaceFileSystemCleanup(); // Cleanup artefacts left behind
// in the file system (out of synhc with Eclipse IResources)
try {
bot.viewByTitle("Welcome").close();
} catch (WidgetNotFoundException e) {
}
if (!setupClassTried() && !StsTestUtil.isOnBuildSite()) {
System.out.println("Deleting old screenshots...");
File screenshotDir = new File("screenshots");
File[] screenshots = screenshotDir.listFiles();
if (screenshots != null) {
for (int i = 0; i < screenshots.length; i++) {
if (screenshots[i].toString().endsWith(".jpeg")) {
screenshots[i].delete();
}
}
}
}
}
/**
* Create a general project in the workspace. To be used as test fixture.
*
* @return an IProject referring to the create project.
* @throws CoreException
*/
protected IProject createGeneralProject(String name) throws CoreException {
IProject project = ResourcesPlugin.getWorkspace().getRoot()
.getProject(name);
if (!project.exists())
project.create(null);
if (!project.isOpen())
project.open(null);
return project;
}
/**
* General cleanup: close all editors. Delete all projects. Copied from:
* StsUiTestCase
*
* @author Steffen Pingel
*/
public static void workspaceCleanUp() throws CoreException {
List<? extends SWTBotEditor> editors = bot.editors();
for (SWTBotEditor editor : editors) {
editor.close();
}
deleteAllProjects();
}
public static void deleteAllProjects() throws CoreException {
IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (IProject project : allProjects) {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
project.delete(true, true, null);
}
}
private void workspaceFileSystemCleanup() {
File workspace = StsTestUtil.getWorkspaceRoot().getLocation().toFile();
File[] wsFiles = workspace.listFiles();
System.out.println(">>>> wsFiles");
for (File file : wsFiles) {
System.out.println(file);
if (file.toString().endsWith(".metadata")) {
//Skip
}
else {
deleteFiles(file);
}
}
System.out.println("<<<< wsFiles");
}
private void deleteFiles(File file) {
System.out.println("Deleting file: "+file);
if (file.isDirectory()) {
File[] subfiles = file.listFiles();
for (File subfile : subfiles) {
deleteFiles(subfile);
}
}
file.delete();
}
private static void closeAllShells() {
Shell mainWidget = SWTBotUtils.getMainShell();
SWTBotShell[] shells = bot.shells();
SWTBotShell mainShell = null;
for (SWTBotShell shell : shells) {
if (shell.widget != mainWidget) {
shell.close();
} else {
mainShell = shell;
}
}
if (mainShell != null) {
mainShell.activate();
}
}
public void setupInstance() throws Exception {
}
@Override
protected void tearDown() throws Exception {
closeAllShells(); // crashed tests may leave open some windows / dialogs
// interfering with the
// other tests and causing cascading failures.
super.tearDown();
}
/**
* Warning!!! Junit3 has no mechanism to ensure that this method is called.
* You can use the createSuite method provided in this class to make a suite
* that calls this method at the end of the suite.
* <p>
* For example, add the following code to your test Suite
*
* <code>
* class MySuite {
* public static TestSuite suite() {
* TestSuite suite = ...
* ...
* suiteAddTest(GrailsUITests.createSuite(MyTests.class));
* ...
* }
* }
* </code>
*
* @throws Exception
*/
public void tearDownClass() throws Exception {
workspaceCleanUp();
SWTBotPreferences.KEYBOARD_LAYOUT = defaultKeyboard;
SWTBotPreferences.TIMEOUT = defaultTimeOut;
}
protected String getProjectViewCategory() {
return "General";
}
protected String getProjectViewName() {
return "Project Explorer";
}
/**
* Opens a particular view, from the Eclipse Window >> Show View menu.
*/
protected SWTBotView openView() {
String category = getProjectViewCategory();
String viewName = getProjectViewName();
SWTBotView explorer = null;
try {
explorer = bot.viewByTitle(viewName);
explorer.setFocus();
}
catch (Exception e) {
e.printStackTrace();
SWTBotUtils.menu(bot, "Window").menu("Show View").menu("Other...")
.click();
SWTBotUtils
.selectChildTreeElement(bot, "Show View", category, viewName);
bot.button("OK").click();
explorer = getView();
}
assertTrue(explorer.isActive());
return explorer;
}
/**
* Gets a view by name. It assumes the view MUST be opened, although not
* necessarily active. Open the view first if necessary.
*
* @return Active, focused explorer view
*/
protected SWTBotView getView() {
return SWTBotUtils.getView(bot, getProjectViewName());
}
/**
* Gets a view by name. It assumes the view MUST be opened, although not necessarily active.
* Open the view first if necessary.
* @return Active, focused explorer view
*/
protected SWTBotView getView(String name) {
return SWTBotUtils.getView(bot, name);
}
/**
* Sometimes widgets respond slowly to selection and key presses. Use this
* method to wait for a selection to become what you expect it to be.
* Otherwise, trying to proceed will probably fail the test.
*/
protected void waitForSelection(final String expected, final SWTBotList list) {
SWTBotUtils.waitForSelection(bot, expected, list);
}
/**
* Wait for a selection to become what you expect it to be. This method
* assumes a SWTBotTree that only has a single column selection.
*/
protected void waitForSelection(final String expected, final SWTBotTree tree) {
SWTBotUtils.waitForSelection(bot, expected, tree);
}
protected String getSelection(SWTBotTree tree) {
return SWTBotUtils.getSelection(tree);
}
/**
* Activate a wizard from the "File >> New" menu.
*
* @param projectWizardName
* @param wizardShellName
* @return A reference to the Wizard's shell.
*/
protected SWTBotShell activateFileNewWizardShell(String projectWizardName,
String wizardShellName) {
SWTBotUtils.menu(bot, "File").menu("New").menu(projectWizardName)
.click();
SWTBotShell shell = bot.shell(wizardShellName);
shell.activate();
return shell;
}
/**
* Selects a project in the currently opened view. A view must be opened
* prior to using this method.
*
* @param projectName
* @return
*/
protected SWTBotTree selectProject(String projectName) {
return SWTBotUtils.selectProject(bot, projectName, getProjectViewName());
}
protected Object getTreeItemObject(final SWTBotTreeItem item) {
final Object[] result = new Object[1];
UIThreadRunnable.syncExec(bot.getDisplay(), new VoidResult() {
public void run() {
result[0] = item.widget.getData();
}
});
return result[0];
}
/**
* Gets the explorer tree in a currently OPENED explorer view. The explorer
* view MUST be opened before invoking this method
*
* @return explorer view tree
*/
protected SWTBotTree getExplorerViewTree() {
SWTBotView explorer = getView();
return explorer.bot().tree();
}
}