diff --git a/.gitignore b/.gitignore index 4c565fe6..2ed7345d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ target/ *.iml saucelabs.properties atlassian-ide-plugin.xml +/bin diff --git a/src/main/java/com/xebia/incubator/xebium/SeleniumDriverFixture.java b/src/main/java/com/xebia/incubator/xebium/SeleniumDriverFixture.java index c221e899..003c80ec 100644 --- a/src/main/java/com/xebia/incubator/xebium/SeleniumDriverFixture.java +++ b/src/main/java/com/xebia/incubator/xebium/SeleniumDriverFixture.java @@ -23,17 +23,29 @@ import com.thoughtworks.selenium.HttpCommandProcessor; import com.thoughtworks.selenium.SeleniumException; import com.thoughtworks.selenium.webdriven.WebDriverCommandProcessor; + +import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + import static com.xebia.incubator.xebium.FitNesseUtil.*; import static org.apache.commons.lang.StringUtils.join; @@ -44,7 +56,7 @@ public class SeleniumDriverFixture { private static final Logger LOG = LoggerFactory.getLogger(SeleniumDriverFixture.class); - private DefaultWebDriverSupplier defaultWebDriverSupplier = new DefaultWebDriverSupplier(); + private DefaultWebDriverSupplier defaultWebDriverSupplier = new DefaultWebDriverSupplier(); private static final String ALIAS_PREFIX = "%"; @@ -69,59 +81,59 @@ public SeleniumDriverFixture() { super(); } - private WebDriver defaultWebDriverInstance() { - return defaultWebDriverSupplier.newWebDriver(); - } + private WebDriver defaultWebDriverInstance() { + return defaultWebDriverSupplier.newWebDriver(); + } - private CommandProcessor startWebDriverCommandProcessor(String browserUrl, WebDriver webDriver) { + private CommandProcessor startWebDriverCommandProcessor(String browserUrl, WebDriver webDriver) { browserUrl = removeAnchorTag(browserUrl); - WebDriverCommandProcessor driver = new WebDriverCommandProcessor(browserUrl, webDriver); - addMissingSeleneseCommands(driver); - return driver; + WebDriverCommandProcessor driver = new WebDriverCommandProcessor(browserUrl, webDriver); + addMissingSeleneseCommands(driver); + return driver; } - private void addMissingSeleneseCommands(WebDriverCommandProcessor driver) { - driver.addMethod("sendKeys", driver.getMethod("typeKeys")); - } + private void addMissingSeleneseCommands(WebDriverCommandProcessor driver) { + driver.addMethod("sendKeys", driver.getMethod("typeKeys")); + } - /** - * Configure the custom Firefox preferences (javascript) file on the webdriver factory. - * - * @param filename - */ - public void loadCustomBrowserPreferencesFromFile(String filename) { - defaultWebDriverSupplier.setCustomProfilePreferencesFile(new File(filename)); - } + /** + * Configure the custom Firefox preferences (javascript) file on the webdriver factory. + * + * @param filename + */ + public void loadCustomBrowserPreferencesFromFile(String filename) { + defaultWebDriverSupplier.setCustomProfilePreferencesFile(new File(filename)); + } /** - * Configure the custom Firefox profiledirectory on the webdriver factory. - * + * Configure the custom Firefox profiledirectory on the webdriver factory. + * * @param directory */ public void loadFirefoxProfileFromDirectory(String directory) { - defaultWebDriverSupplier.setCustomProfilePreferencesFile(new File(directory)); + defaultWebDriverSupplier.setCustomProfilePreferencesFile(new File(directory)); } /** * @param browser Name of the browser, as accepted by the DefaultWebDriverSupplier. */ private void setBrowser(String browser) { - defaultWebDriverSupplier.setBrowser(browser); - } - - /** - *

- * | start driver | $Driver | on url | http://localhost | - *

- * - * @param webDriver a WebDriver instance - * @param browserUrl - */ - public void startDriverOnUrl(final WebDriver webDriver, final String browserUrl) { - setCommandProcessor(startWebDriverCommandProcessor(browserUrl, webDriver)); - setTimeoutOnSelenium(); - LOG.debug("Started command processor"); - } + defaultWebDriverSupplier.setBrowser(browser); + } + + /** + *

+ * | start driver | $Driver | on url | http://localhost | + *

+ * + * @param webDriver a WebDriver instance + * @param browserUrl + */ + public void startDriverOnUrl(final WebDriver webDriver, final String browserUrl) { + setCommandProcessor(startWebDriverCommandProcessor(browserUrl, webDriver)); + setTimeoutOnSelenium(); + LOG.debug("Started command processor"); + } /** *

@@ -133,7 +145,7 @@ public void startDriverOnUrl(final WebDriver webDriver, final String browserUrl) */ public void startBrowserOnUrl(final String browser, final String browserUrl) { setBrowser(browser); - startDriverOnUrl(defaultWebDriverInstance(), browserUrl); + startDriverOnUrl(defaultWebDriverInstance(), browserUrl); } /** @@ -226,9 +238,9 @@ public void setTimeoutToSeconds(long timeout) { */ private void setTimeoutOnSelenium() { executeCommand("setTimeout", new String[] { "" + this.timeout }); - WebDriver.Timeouts timeouts = getWebDriver().manage().timeouts(); - timeouts.setScriptTimeout(this.timeout, TimeUnit.MILLISECONDS); - timeouts.pageLoadTimeout(this.timeout, TimeUnit.MILLISECONDS); + WebDriver.Timeouts timeouts = getWebDriver().manage().timeouts(); + timeouts.setScriptTimeout(this.timeout, TimeUnit.MILLISECONDS); + timeouts.pageLoadTimeout(this.timeout, TimeUnit.MILLISECONDS); } /** @@ -361,22 +373,22 @@ public String isOn(final String command, final String target) { return is(command, new String[] { unalias(target) }); } - public String is(final String command, final String[] parameters) { - ExtendedSeleniumCommand seleniumCommand = new ExtendedSeleniumCommand(command); - String output = executeCommand(seleniumCommand, parameters, stepDelay); + public String is(final String command, final String[] parameters) { + ExtendedSeleniumCommand seleniumCommand = new ExtendedSeleniumCommand(command); + String output = executeCommand(seleniumCommand, parameters, stepDelay); - if (seleniumCommand.isBooleanCommand() && seleniumCommand.isNegateCommand()) { - if ("true".equals(output)) { - output = "false"; - } else if ("false".equals(output)) { - output = "true"; - } else { - throw new IllegalStateException("Illegal boolean value: '" + output + "'"); - } - } + if (seleniumCommand.isBooleanCommand() && seleniumCommand.isNegateCommand()) { + if ("true".equals(output)) { + output = "false"; + } else if ("false".equals(output)) { + output = "true"; + } else { + throw new IllegalStateException("Illegal boolean value: '" + output + "'"); + } + } - return output; - } + return output; + } /** * Same as {@link #isOn(String, String)}, only with "with" statement, analog to "do-on-with" command. @@ -413,19 +425,75 @@ private String unalias(String value) { String alias = value.substring(ALIAS_PREFIX.length()); String subst = aliases.get(alias); if (subst != null) { - LOG.info("Expanded alias '" + alias + "' to '" + result + "'"); - result = subst; + LOG.info("Expanded alias '" + alias + "' to '" + result + "'"); + result = subst; } } return result; } + // The Below 2 functions (searchAllFrames) are used to search all frames for a specific xpath search, and also switchTo the frame that has the found web element + + public WebElement searchAllFrames(String elementXpath) { + return searchAllFrames(getWebDriver(), elementXpath, new ArrayList()); + } + + public WebElement searchAllFrames(WebDriver driver, String elementXpath, List frameSwitches) { + if (frameSwitches.size() == 0) //if starting then make sure to search from top + driver.switchTo().defaultContent(); + WebElement element = null; //return null if not found or error during search. + try { + element = driver.findElement(By.xpath(elementXpath));// need to catch in case not found + }catch(Exception e) {} + if (element == null) + { + List framesList = null; + try { + framesList = driver.findElements(By.xpath("//iframe|//frame")); + framesList = driver.findElements(By.cssSelector("iframe|frame")); + }catch(Exception e) {} + if (framesList == null) + return null; + for(WebElement frame:framesList){ + // need to start from the top and switch back to next frame + driver.switchTo().defaultContent(); + for(WebElement nestedFrame:frameSwitches){//nested frames list + driver.switchTo().frame(nestedFrame); + } + driver.switchTo().frame(frame); + + frameSwitches.add(frame); + element = searchAllFrames(driver, elementXpath, frameSwitches); + if (element != null) + return element; // element found + else + frameSwitches.remove(frame); //this frame had nothing so remove it from the list + } + return null; //element not found + } + else + return element; //element found + } + private boolean executeDoCommand(final String methodName, final String[] values) { + String output = null; + boolean result = true; + ExtendedSeleniumCommand command = new ExtendedSeleniumCommand(methodName); + boolean locatorFlag = locatorCheck.verifyElementPresent(command, values); + SeleniumCommandResult commandResult; + if (!locatorFlag) { // if it is a locator command and verifyElementPresent fails + String xpathStr = ""; + if (values.length > 0) + xpathStr = values[0]; + if (searchAllFrames(xpathStr) != null) + locatorFlag = true; //searchAllFrames found a matched and switchTo the correct frame + } + if (!locatorCheck.verifyElementPresent(command, values)) { commandResult = failure(); } else if (command.requiresPolling()) { @@ -456,6 +524,81 @@ private boolean executeDoCommand(final String methodName, final String[] values) } } + private String encryptString(String password) { //encrypt exposed passwords or information stub + + if (password != null) { + Cipher aes = null; + try { + aes = Cipher.getInstance("AES/ECB/PKCS5Padding"); + aes.init(Cipher.ENCRYPT_MODE, generateKey()); + byte[] ciphertext = aes.doFinal(password.getBytes()); + password = "decrypt:" + bytesToHex(ciphertext); //prefix with "decrypt:" + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return password; + } + + public String bytesToHex(byte[] bytes) { //generate hex values for data encryption + final char[] hexArray = "0123456789ABCDEF".toCharArray(); + char[] hexChars = new char[bytes.length * 2]; + int v; + for ( int j = 0; j < bytes.length; j++ ) { + v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + public static SecretKeySpec generateKey() { //salting of the data stub + String passStr="XebiumIsConnectedToTheSikuliBone"; + SecretKey tmp = null; + try{ + String saltStr = "fijsd@#saltr9jsfizxnv"; + byte[] salt = saltStr.getBytes(); + int iterations = 43210; + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); + tmp = factory.generateSecret(new PBEKeySpec(passStr.toCharArray(), salt, iterations, 128)); + } + catch(Exception e){ + e.printStackTrace(); + } + return new SecretKeySpec(tmp.getEncoded(), "AES"); + } + + public static byte[] hexToBytes(String hex) {//generate bytes value for use internal to fixture + int len = hex.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i+1), 16)); + } + return data; + } + + public static String processDecryptionString(DefaultWebDriverSupplier driver, String val) { //decrypt the value + + if (val.startsWith("decrypt:") ) { + try { + val = val.substring(val.indexOf(":") + 1); + SecretKeySpec key = generateKey(); + Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding"); + aes.init(Cipher.DECRYPT_MODE, key); + String cleartext = new String(aes.doFinal(hexToBytes(val))); + return cleartext; + } + catch (Exception e) { + //LOG.info("Exception processDecryptionString:" + e.getMessage()); + e.printStackTrace(); + return val; + } + } + else + return val; + } + private SeleniumCommandResult executeDoCommandPolling(String[] values, ExtendedSeleniumCommand command) { SeleniumCommandResult commandResult; long timeoutTime = System.currentTimeMillis() + timeout; @@ -497,7 +640,7 @@ private String executeCommand(final ExtendedSeleniumCommand command, final Strin if (commandProcessor == null) { throw new IllegalStateException("Command processor not running. " + - "First start it by invoking startBrowserOnUrl."); + "First start it by invoking startBrowserOnUrl."); } if ("pause".equals(command.getSeleniumCommand())) { @@ -505,6 +648,17 @@ private String executeCommand(final ExtendedSeleniumCommand command, final Strin return null; } + if ("contextMenu".equals(command.getSeleniumCommand())) { + try { + WebElement webElement = getWebDriver().findElement(By.xpath(values[0])); + new Actions(getWebDriver()).contextClick(webElement).perform(); + LOG.info("Performing | contextMenu | " + values[0] + " | " ); + } catch (Exception e) { + LOG.warn("contextMenu command interrupted", e); + } + return null; + } + String output = getCommandOutput(command, values); waitForPageLoadIfNeeded(command); @@ -583,7 +737,7 @@ private boolean checkResult(ExtendedSeleniumCommand command, String expected, St private void writeToFile(final String filename, final String output) { File file = asFile(filename); try { - createParentDirectoryIfNeeded(file); + createParentDirectoryIfNeeded(file); ScreenCapture.writeToFile(file, output); } catch (IOException e) { @@ -591,15 +745,15 @@ private void writeToFile(final String filename, final String output) { } } - private void createParentDirectoryIfNeeded(File file) throws IOException { - if (file.getParentFile() != null && !file.getParentFile().exists()) { - if (!file.getParentFile().mkdirs()) { - throw new IOException("Could not create parent directory " + file.getParent()); - } - } - } + private void createParentDirectoryIfNeeded(File file) throws IOException { + if (file.getParentFile() != null && !file.getParentFile().exists()) { + if (!file.getParentFile().mkdirs()) { + throw new IOException("Could not create parent directory " + file.getParent()); + } + } + } - public void stopBrowser() { + public void stopBrowser() { commandProcessor.stop(); commandProcessor = null; @@ -613,7 +767,7 @@ public CommandProcessor getCommandProcessor() { public WebDriver getWebDriver() { return commandProcessor instanceof WebDriverCommandProcessor ? ((WebDriverCommandProcessor) commandProcessor).getWrappedDriver() - : null; + : null; } private static class SeleniumCommandResult {