/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.codingspectator.ui.tests;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.allOf;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withMnemonic;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withStyle;
import static org.junit.Assert.assertTrue;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.ltk.internal.core.refactoring.RefactoringCorePlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.eclipse.finder.waits.Conditions;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEclipseEditor;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
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.FileUtils;
import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.eclipse.swtbot.swt.finder.waits.ICondition;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
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.hamcrest.Matcher;
import org.osgi.framework.Bundle;
import edu.illinois.codingspectator.efs.EFSFile;
/**
*
* @author Mohsen Vakilian
* @author nchen
* @author Balaji Ambresh Rajkumar
*
*/
@SuppressWarnings("restriction")
public class CodingSpectatorBot {
public static final String CONTINUE_LABEL= "Continue";
public static final String PREVIEW_LABEL= "Preview >";
static final String PLUGIN_NAME= "edu.illinois.codingspectator.ui.tests";
public static final String PACKAGE_NAME= "edu.illinois.codingspectator";
protected static final String REFACTOR_MENU_NAME= "Refactor";
protected static final int SLEEPTIME= 500;
SWTWorkbenchBot bot= new SWTWorkbenchBot();
public void dismissWelcomeScreenIfPresent() {
try {
bot.viewByTitle("Welcome").close();
} catch (WidgetNotFoundException exception) {
// The welcome screen might not be shown so just ignore
}
}
public SWTWorkbenchBot getBot() {
return bot;
}
public void waitUntil(ICondition condition) {
bot.waitUntil(condition);
}
public void createANewJavaProject(String projectName) {
bot.menu("File").menu("New").menu("Project...").click();
final SWTBotShell shell= activateShellWithName("New Project");
getCurrentTree().expandNode("Java").select("Java Project");
bot.button(IDialogConstants.NEXT_LABEL).click();
bot.textWithLabel("Project name:").setText(projectName);
bot.button(IDialogConstants.FINISH_LABEL).click();
waitUntil(new DefaultCondition() {
@Override
public boolean test() throws Exception {
return !shell.isOpen() || bot.shell("Open Associated Perspective?").isOpen();
}
@Override
public String getFailureMessage() {
return "Failed to close the new project wizard.";
}
});
dismissJavaPerspectiveIfPresent();
waitUntil(Conditions.shellCloses(shell));
}
private EFSFile getEclipseRefactoringsEFSFile() {
return new EFSFile(RefactoringCorePlugin.getDefault().getStateLocation().append(".refactorings"));
}
private void deleteProjectSpecificEclipseRefactoringLog(String projectName) throws CoreException {
getEclipseRefactoringsEFSFile().append(projectName).delete();
}
public void deleteEclipseRefactoringLog() throws CoreException {
getEclipseRefactoringsEFSFile().delete();
}
public void deleteProject(String projectName) throws CoreException {
selectJavaProject(projectName).contextMenu("Delete").click();
SWTBotShell shell= activateShellWithName("Delete Resources");
if (!bot.checkBox().isChecked()) {
bot.checkBox().click();
}
bot.button(IDialogConstants.OK_LABEL).click();
deleteProjectSpecificEclipseRefactoringLog(projectName);
waitUntil(Conditions.shellCloses(shell));
}
public SWTBotTree getCurrentTree() {
return bot.tree();
}
public SWTBotShell activateShellWithName(String text) {
SWTBotShell shell= bot.shell(text);
shell.activate();
return shell;
}
private void dismissJavaPerspectiveIfPresent() {
try {
bot.checkBox("Remember my decision").click();
bot.button(IDialogConstants.YES_LABEL).click();
} catch (WidgetNotFoundException exception) {
// The second and subsequent time this is invoked the Java perspective change dialog will not be shown.
}
}
public void createANewJavaClass(String projectName, final String className) {
selectJavaProject(projectName);
bot.menu("File").menu("New").menu("Class").click();
activateShellWithName("New Java Class");
bot.textWithLabel("Package:").setText(PACKAGE_NAME);
bot.textWithLabel("Name:").setText(className);
bot.button(IDialogConstants.FINISH_LABEL).click();
waitUntil(new DefaultCondition() {
@Override
public boolean test() throws Exception {
return getTextEditor(className + ".java") != null;
}
@Override
public String getFailureMessage() {
return "Failed to find the open editor of class " + className;
}
});
}
public SWTBotTree selectJavaProject(String projectName) {
SWTBotView packageExplorerView= bot.viewByTitle("Package Explorer");
packageExplorerView.show();
Composite packageExplorerComposite= (Composite)packageExplorerView.getWidget();
Tree swtTree= (Tree)bot.widget(widgetOfType(Tree.class), packageExplorerComposite);
SWTBotTree tree= new SWTBotTree(swtTree);
return tree.select(projectName);
}
public SWTBotEclipseEditor getTextEditor(String editorTitle) {
return bot.editorByTitle(editorTitle).toTextEditor();
}
public void prepareJavaTextInEditor(String testInputLocation, String testFileFullName) throws Exception {
Bundle bundle= Platform.getBundle(PLUGIN_NAME);
String contents= FileUtils.read(bundle.getEntry("test-files/" + testInputLocation + "/" + testFileFullName));
SWTBotEclipseEditor editor= getTextEditor(testFileFullName);
editor.setText(contents);
editor.save();
}
/**
* Prefer {@link #waitUntil(ICondition)} over {@link #sleep()} in your tests because it's faster
* and makes the tests more reliable.
*/
public void sleep() {
bot.sleep(SLEEPTIME);
}
public void invokeRefactoringFromMenu(String refactoringMenuItemName) {
SWTBotMenu refactorMenu= bot.menu(REFACTOR_MENU_NAME);
assertTrue(refactorMenu.isEnabled());
SWTBotMenu refactoringMenuItem= refactorMenu.menu(refactoringMenuItemName);
assertTrue(refactoringMenuItem.isEnabled());
refactoringMenuItem.click();
}
public void clickButtons(String... buttonNames) {
for (String buttonName : buttonNames) {
bot.button(buttonName).click();
}
}
/**
* Selects part of the given line from the given column number for the specified length.
*
* @param line The line number to be selected. This number is zero-based.
* @param column The column number of the beginning of the selection. This number is zero-based.
* If you use Eclipse editor to find the column number, you should be aware that the
* Eclipse editor displays offsets of the caret by expanding tabs into spaces. So, to
* get the column number from Eclipse editor safely, convert the tabs to spaces
* first.
* @param length The length of the selection.
*/
public void selectElementToRefactor(String testFileFullName, int line, int column, int length) {
SWTBotEclipseEditor editor= bot.editorByTitle(testFileFullName).toTextEditor();
editor.setFocus();
editor.selectRange(line, column, length);
}
public void fillTextField(String textFieldLabel, String textFieldValue) {
bot.textWithLabel(textFieldLabel).setText(textFieldValue);
}
public void setComboBox(String label, String value) {
bot.comboBoxWithLabel(label).setText(value);
}
/**
* Selects the element at the given path from the package explorer view.
*/
public void selectFromPackageExplorer(String projectName, String... pathElements) {
SWTBotTree tree= selectJavaProject(projectName);
SWTBotTreeItem treeItem= tree.getTreeItem(projectName).expand();
for (int i= 0; i < pathElements.length - 1; i++) {
treeItem= treeItem.expandNode(pathElements[i]);
}
if (pathElements.length > 0) {
treeItem.select(pathElements[pathElements.length - 1]);
}
}
/**
*
* This method provides a workaround for Eclipse bug 344484.
*
* @param radioText
*/
public void deselectRadio(final String radioText) {
UIThreadRunnable.syncExec(new VoidResult() {
public void run() {
@SuppressWarnings("unchecked")
Matcher<Widget> matcher= allOf(widgetOfType(Button.class), withStyle(SWT.RADIO, "SWT.RADIO"), withMnemonic(radioText));
Button b= (Button)bot.widget(matcher);
b.setSelection(false);
}
});
}
}