/*******************************************************************************
* Copyright (c) 2012 VMWare, 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:
* VMWare, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.ui.test;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.springsource.ide.eclipse.commons.frameworks.core.internal.plugins.PluginVersion;
import org.springsource.ide.eclipse.commons.frameworks.test.util.SWTBotUtils;
import org.springsource.ide.eclipse.commons.frameworks.ui.internal.plugins.PluginState;
import org.grails.ide.eclipse.ui.test.util.SWTBotPluginManagerUtil;
/**
* @author Nieraj Singh
* @author Kris De Volder
* @created Jul 22, 2010
*/
public class GrailsPluginManagerHarness extends GrailsProjectHarness {
protected SWTBotShell getPopulatedPluginManagerDialogue() throws Exception {
SWTBotShell manager = SWTBotPluginManagerUtil
.getGrailsManagerDialogueViaShortcutKey(bot,
getProjectViewName(), getTestProject().getName())
.getOpenedGrailsManager();
assertNotNull(manager);
assertTrue(manager.isActive());
assertTrue(isManagerOpen());
return manager;
}
protected boolean isManagerOpen() throws Exception {
return SWTBotPluginManagerUtil.getGrailsManagerDialogueViaShortcutKey(
bot, getProjectViewName(), getTestProject().getName()).isOpen();
}
protected PluginVersion getPublishedVersion(SWTBotTreeItem item) {
PluginVersion version = SWTBotPluginManagerUtil.getPublishedVersion(
bot, item);
assertNotNull(version);
return version;
}
public void setupInstance() throws Exception {
super.setupInstance();
assertTrue(getTestProject().exists());
getPopulatedPluginManagerDialogue();
}
public void tearDownClass() throws Exception {
if(isManagerOpen()) {
getPopulatedPluginManagerDialogue().close();
}
super.tearDownClass();
}
/**
* <p>
* Press the "Install" button on the given root plugin, and performs the
* following verifications:
* </p>
* <p>
* Verifies that the corresponding child version is also marked, and that
* the root version and plugins state matches the marked child version, and
* that the root element state matches the expected state.
* </p>
* <p>
* Verifies that no other child versions are marked. NOTE: This means that
* this method WILL FAIL if other child versions are expected to be marked.
* Therefore use this method only to press install when the outcome is to
* have exactly ONE child version marked.
* </p>
* <p>
* If all verification passes, returns the selected root Item.
* </p>
* <p>
* Install operation can be used to UNDO an Uninstall selection, therefore
* the expected plugin state is the state expected when the install
* operation is performed. It will vary depending on whether install is used
* to select a plugin for install or used to undo an uninstall.
* </p>
*
* @param pluginName
* to install or undo
* @param expectedPluginState
* state after install performed
* @return
*/
protected SWTBotTreeItem pressInstallOnRoot(String pluginName,
PluginState expectedPluginState) {
SWTBotTreeItem rootItem = selectRootTreeItem(pluginName);
// Get the corresponding child version, and verify
// it is the actual corresponding child
String rootID = getVersionID(rootItem);
SWTBotTreeItem expectedVersion = getTreeItem(pluginName, rootID);
assertTrue(isInstallButtonEnabled());
pressInstallButton();
assertCorrectnessInstalledOrUninstallPlugin(rootItem, expectedVersion,
expectedPluginState);
return rootItem;
}
/**
* Press install on the specified plugin version and checks the state
* against the expected state. In addition performs the following
* validations:
* <p>
* Verifies that the root reflects the version that is marked for install,
* meaning that the root pluginstate and version ID should match the version
* that was selected
* </p>
* <p>
* Verifies that no other child version for that plugin is marked. NOTE:
* This means that this method WILL FAIL if other child versions are
* expected to be marked. Therefore use this method only to press install
* when the outcome is to have exactly ONE child version marked.
* </p>
* <p>
* If all verification passes, returns the selected child version
* </p>
* <p>
* Install operation can be used to UNDO an Uninstall selection, therefore
* the expected plugin state is the state expected when the install
* operation is performed. It will vary depending on whether install is used
* to select a plugin for install or used to undo an uninstall.
* </p>
*
* @param pluginName
* to install or to undo
* @param versionIDToSelect
* version ID to select for install
* @param expectedPluginState
* state after install performed
* @return
*/
protected SWTBotTreeItem pressInstallOnSelectedChildVersion(
String pluginName, PluginState expectedPluginState,
String versionIDToSelect) {
SWTBotTreeItem childVersion = selectChildVersionElement(pluginName,
versionIDToSelect);
SWTBotTreeItem root = getTreeItem(pluginName, null);
assertTrue(isInstallButtonEnabled());
pressInstallButton();
assertCorrectnessInstalledOrUninstallPlugin(root, childVersion,
expectedPluginState);
return childVersion;
}
protected void installPlugins(String[][] plugins) throws Exception {
getPopulatedPluginManagerDialogue(); //Code below relies on Plug. Man to be there! Ensure it is open!
for (String[] plugin : plugins) {
String pluginName = plugin[0];
String version = plugin.length > 1 ? plugin[1] : null;
SWTBotTreeItem item = selectChildVersionElement(pluginName, version);
assertNotNull(item);
pressInstallButton();
}
pressOKButton();
bot.sleep(30000);
SWTBotUtils.waitForAllBuildJobs(bot);
}
/**
* Press Uninstall on the specified root element. Validates against the
* expected state after the uninstall is pressed. NOTE: this Only works when
* expecting one Child version to be marked after the operation completes.
* It will detect and fail if any other child versions are marked after an
* uninstall operation is performed.
* <p>
* Verifies that the root and corresponding child versions are both marked
* correctly, and that the root version ID matches the corresponding child
* version ID
* </p>
* <p>
* If Verification passes, returns the selected root plugin element
* </p>
* <p>
* Note that the uninstall operation can also be used to UNDO a selection
* marked for install. Therefore the expected plugin state is the state
* expected once an undo operation is performed, and it may vary based on
* whether uninstall is performed to uninstall an installed plugin, or to
* undo a selection marked for install.
* </p>
*
* @param pluginName
* to uninstall or undo
* @param expectedState
* state after the uninstall is performed
* @return
*/
protected SWTBotTreeItem pressUninstallOnRoot(String pluginName,
PluginState expectedState) {
SWTBotTreeItem rootItem = selectRootTreeItem(pluginName);
assertTrue(isUninstallButtonEnabled());
pressUninstallButton();
// Verify that the version of the root has not changed and that it has
// no plugin state
assertCorrectnessInstalledOrUninstallPlugin(rootItem, null,
expectedState);
return rootItem;
}
/**
* Get the corresponding child version that matches the version of the root
* element
*
* @param rootItem
* @return
*/
protected SWTBotTreeItem getCorrespondingChildVersion(
SWTBotTreeItem rootItem) {
return SWTBotPluginManagerUtil.getCorrespondingChildVersion(bot,
rootItem);
}
protected void pressInstallButton() {
SWTBotPluginManagerUtil.pressInstallButton(bot);
}
protected void pressUninstallButton() {
SWTBotPluginManagerUtil.pressUninstallButton(bot);
}
protected void pressUpdateButton() {
SWTBotPluginManagerUtil.pressUpdateButton(bot);
}
protected void pressOKButton() {
SWTBotPluginManagerUtil.pressOKButton(bot);
}
protected boolean isInstallButtonEnabled() {
return SWTBotPluginManagerUtil.getInstallButton(bot).isEnabled();
}
protected boolean isUninstallButtonEnabled() {
return SWTBotPluginManagerUtil.getUninstallButton(bot).isEnabled();
}
protected boolean isUpdateButtonEnabled() {
return SWTBotPluginManagerUtil.getUpdateButton(bot).isEnabled();
}
/**
* Gets a tree item WITHOUT selecting it. If a version ID is specified, it
* will get the child version element. If no version ID is specified, it
* will get the root element matching the plugin name.
*
* @param pluginName
* @param versionID
* @return
*/
protected SWTBotTreeItem getTreeItem(String pluginName, String versionID) {
return SWTBotPluginManagerUtil.getPluginTreeItem(bot, pluginName,
versionID);
}
/**
* Select a particular child version for the given plugin. Asserts that the
* selection has been made before returning the selection.
*
* @param pluginName
* @param versionID
* if null, it will only select the root element matching the
* plugin name
* @return
*/
protected SWTBotTreeItem selectChildVersionElement(String pluginName,
String versionID) {
SWTBotTreeItem foundItem = SWTBotPluginManagerUtil.getPluginTreeItem(
bot, pluginName, versionID);
foundItem.select();
assertNotNull(foundItem);
assertTrue(foundItem.isSelected());
return foundItem;
}
/**
* Selects the root tree element matching the given pluginName. Asserts that
* the selection has been made before returning the selection.
*
* @param pluginName
* @return
*/
protected SWTBotTreeItem selectRootTreeItem(String pluginName) {
return selectChildVersionElement(pluginName, null);
}
/**
* Verifies that none of the other child versions of a given plugin are
* marked, except those that are listed as exempt.
*
* @param rootItem
* @param exempt
* @return
*/
protected boolean verifyRemainingChildVersionUnmarked(
SWTBotTreeItem rootItem, Set<PluginVersion> exempt) {
SWTBotTreeItem[] children = rootItem.getItems();
for (SWTBotTreeItem child : children) {
PluginState childState = getPluginState(child);
PluginVersion version = SWTBotPluginManagerUtil
.getPublishedVersion(bot, child);
if ((exempt == null || !exempt.contains(version))
&& childState != null) {
print("Verifying child version states. Expected null, but actual: "
+ childState);
return false;
}
}
return true;
}
/**
* <p>
* Asserts whether the root plugin state and version ID match the expected
* child version Note that this ONLY works for installing NEW plugins and
* uninstalling existing plugins. It does NOT work for plugins that are
* installed but have another version marked for update, as the latter will
* have two child versions that are marked, the version that is installed
* and the version that the user wants to upgrade/downgrade to.
* </p>
* if no expected corresponding version is specified, it will check the root
* selection state against the corresponding child version it actually
* finds, but it will not check it against an expected child version.
* <p>
* if no expected Version ID is specified, it will verify that the root
* version and the corresponding version it finds have the same ID, but does
* not check it against an expected version ID.
* </p>
*
* @param root
* @param expectedCorrespondingVersion
* @param expectedRootChildState
* @param expectedVersionID
*/
protected void assertCorrectnessInstalledOrUninstallPlugin(
SWTBotTreeItem root, SWTBotTreeItem expectedCorrespondingVersion,
PluginState expectedRootChildState) {
// Verify there is a corresponding version child for the root
// and it matches the expected corresponding version
SWTBotTreeItem childTreeItem = getCorrespondingChildVersion(root);
assertNotNull(childTreeItem);
if (expectedCorrespondingVersion != null) {
assertEquals(getPublishedVersion(childTreeItem),
getPublishedVersion(expectedCorrespondingVersion));
childTreeItem = expectedCorrespondingVersion;
}
// Verify that the expected version number of the root matches the
// actual root version
String actualRootVersion = getVersionID(root);
String correspondingChildVersion = getVersionID(childTreeItem);
assertTrue(actualRootVersion.equals(correspondingChildVersion));
// Verify that the root and corresponding child both have the same
// expected state
assertTrue(validateRootAndChildVersionState(expectedRootChildState,
root));
// Verify that none of the other child versions are marked.
assertTrue(verifyRemainingChildVersionUnmarked(root, childTreeItem));
}
/**
* Verifies that the root is marked with a "Update Available" state, that
* it's version id matches a child version element marked with "installed"
* and that no other child versions are marked.
*
* @param pluginName
* @param expectedInstalledVersionID
*/
protected void assertCorrectnessOfInstalledPluginWithUpdate(
String pluginName, String expectedInstalledVersionID) {
// Verify that both the root and corresponding child version
// match the expected version ID
SWTBotTreeItem root = getTreeItem(pluginName, null);
String versionID = getVersionID(root);
assertTrue(versionID.equals(expectedInstalledVersionID));
SWTBotTreeItem correspondingChild = getCorrespondingChildVersion(root);
versionID = getVersionID(correspondingChild);
assertTrue(versionID.equals(expectedInstalledVersionID));
// Validate that the root and corresponding child have the correct state
assertTrue(validateRootAndChildVersionState(
PluginState.UPDATE_AVAILABLE, root));
Set<PluginVersion> markedVersions = new HashSet<PluginVersion>();
markedVersions.add(getPublishedVersion(correspondingChild));
// Verify that none of the other child versions are marked.
assertTrue(verifyRemainingChildVersionUnmarked(root, markedVersions));
}
/**
* Verify that when a newer/older version of a currently installed plugin is
* selected for install, and that the root of the plugin reflects the
* selected version marked for update. It also verifies that the installed
* version is still marked as installed.
* <p>
* This method checks that there are TWO marked versions, the version
* currently installed and the version that has been marked for
* updating/downgrading, and verifies that both are different.
* </p>
*
* @param pluginName
* @param installedVersionID
* @param expectedUpdatedVersionID
*/
protected void assertPluginHasBeenUpdated(String pluginName,
String installedVersionID, String expectedUpdatedVersionID) {
// The root should be marked with the updated version ID
SWTBotTreeItem root = getTreeItem(pluginName, null);
String versionID = getVersionID(root);
assertTrue(versionID.equals(expectedUpdatedVersionID));
SWTBotTreeItem updatedChild = getCorrespondingChildVersion(root);
versionID = getVersionID(updatedChild);
assertTrue(versionID.equals(expectedUpdatedVersionID));
SWTBotTreeItem installedChild = getTreeItem(pluginName,
installedVersionID);
// Verify the expected version is not the same as the installed version
assertTrue(!installedVersionID.equals(expectedUpdatedVersionID));
assertNotSame(installedChild, updatedChild);
// Verify that the root and its corresponding updated child are marked
// as select install
// (i.e. meaning they are marked to be updated)
assertTrue(validateRootAndChildVersionState(PluginState.SELECT_INSTALL,
root));
// Verify that the installed version is marked as installed. THis should
// not change even when selecting another version to upgrade to.
assertTrue(getPluginState(installedChild) == PluginState.INSTALLED);
// Verify that no other children except the two mentioned above (the
// installed version
// and the updated version) are marked
Set<PluginVersion> markedVersions = new HashSet<PluginVersion>();
markedVersions.add(getPublishedVersion(updatedChild));
markedVersions.add(getPublishedVersion(installedChild));
// Verify that none of the other child versions are marked.
assertTrue(verifyRemainingChildVersionUnmarked(root, markedVersions));
}
/**
* This verifies that no other child versions are marked except for those
* listed as exempt.
*
* @param rootItem
* @param exemptVersionItem
* @return
*/
protected boolean verifyRemainingChildVersionUnmarked(
SWTBotTreeItem rootItem, SWTBotTreeItem exemptVersionItem) {
Set<PluginVersion> set = new HashSet<PluginVersion>();
if (exemptVersionItem != null) {
set.add(getPublishedVersion(exemptVersionItem));
}
return verifyRemainingChildVersionUnmarked(rootItem, set);
}
/**
* Returns the version ID for any given tree item, whether root or child.
*
* @param treeItem
* @return
*/
protected String getVersionID(SWTBotTreeItem treeItem) {
return SWTBotPluginManagerUtil.getPublishedVersion(bot, treeItem)
.getVersion();
}
/**
* The root element always reflects the current version selection, therefore
* the root element state must match the child version state, EXCEPT for
* root elements marked as update available. The latter case is also handled
* by this method, where the root version is checked to be in
* "update available" state and the corresponding child in "installed"
* state.
*
* @param expectedState
* @param rootItem
* @return true if the match, false otherwise
*/
protected boolean validateRootAndChildVersionState(
PluginState expectedState, SWTBotTreeItem rootItem) {
SWTBotTreeItem childItem = SWTBotPluginManagerUtil
.getCorrespondingChildVersion(bot, rootItem);
PluginState rootState = getPluginState(rootItem);
PluginState childState = getPluginState(childItem);
boolean isValid = (rootState == expectedState);
print("Validating root state. Expected state: " + expectedState
+ " Actual State: " + rootState);
if (expectedState == null) {
isValid &= childState == null;
} else {
switch (expectedState) {
case SELECT_INSTALL:
case SELECT_UNINSTALL:
case INSTALLED:
isValid &= (childState == expectedState);
print("Validating child state. Expected state: "
+ expectedState + " Actual State: " + childState);
break;
case UPDATE_AVAILABLE:
isValid &= (childState == PluginState.INSTALLED);
print("Validating child state. Expected state: "
+ expectedState + " Actual State: " + childState);
break;
}
}
return isValid;
}
protected PluginState getPluginState(SWTBotTreeItem item) {
return SWTBotPluginManagerUtil.getStateOfPlugin(bot, item);
}
protected void assertSelectionButtonEnablement(boolean installEnablement,
boolean uninstallEnablement, boolean updateEnablement) {
assertEquals(installEnablement, isInstallButtonEnabled());
assertEquals(uninstallEnablement, isUninstallButtonEnabled());
assertEquals(updateEnablement, isUpdateButtonEnabled());
}
}