Java tutorial
/** ** Copyright (C) SAS Institute, All rights reserved. ** General Public License: http://www.opensource.org/licenses/gpl-license.php **/ package org.safs.selenium.webdriver; /** * Logs for developers, not published to API DOC. * History:<br> * <br> JUL 05, 2011 (LeiWang) Update method setFocus(). * <br> JAN 16, 2014 (DHARMESH) Update Start/Stop Browser call. * <br> FEB 02, 2014 (DHARMESH) Add Resize and Maximize WebBrowser window KW. * <br> APR 15, 2014 (DHARMESH) Added HighLight keyword * <br> MAY 21, 2014 (CANAGL) Refactored for better (custom) subclassing. * <br> AUG 29, 2014 (DHARMESH) Add selenium grid host and port support. * <br> SEP 10, 2014 (CANAGL) Fixed StartWebBrowser documentation and config() and System Properties support.. * <br> NOV 26, 2014 (SBJLWA) Support setFocus(), waitForGuiGone(). * <br> APR 08, 2015 (SBJLWA) Modify method startWebBrowser(): get property value of JVM Options for Remote Selenium Server. * <br> APR 16, 2015 (CANAGL) Modify method startWebBrowser to ignore the isRemote parameter, if provided. * <br> JUN 23, 2015 (SCNTAX) Add waitForPropertyValueStatus(): wait for property value match or gone with expected value. * <br> JUN 29, 2015 (LeiWang) Modify startWebBrowser(): launch selenium server remotely. * Add launchSeleniumServers(): start selenium standalone or grid automatically. * <br> JUL 24, 2015 (LeiWang) Add sendHttpGetRequest(): handle keyword like GetURL, SaveURLToFile, VerifyURLContent, VerifyURLToFile. * <br> NOV 20, 2015 (LeiWang) Use java AtomicBoolean to replace my AtomicReady class. * Modify method sendHttpGetRequest(): set the thread (executing AJAX request) as daemon. * <br> DEC 24, 2015 (LeiWang) Modify method sendHttpGetRequest(): check known issue 'ajax execution stuck with firefox'. * <br> MAR 31, 2016 (LeiWang) Add onGUIGotoCommands(): implement OnGUIExistsGotoBlockID/OnGUINotExistGotoBlockID, * I did nothing but set the BLOCKID to test-record's status-info. * <br> APR 07, 2016 (SBJLWA) Refactor to handle OnGUIExistsGotoBlockID/OnGUINotExistGotoBlockID in super class DriverCommand * <br> AUT 05, 2016 (SBJLWA) Modified waitForGui/waitForGuiGone: if the RC is SCRIPT_NOT_EXECUTED (4) then stop handling here. */ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.concurrent.atomic.AtomicBoolean; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.safs.DriverCommand; import org.safs.GuiObjectRecognition; import org.safs.IndependantLog; import org.safs.JavaHook; import org.safs.Log; import org.safs.Processor; import org.safs.SAFSException; import org.safs.SAFSObjectNotFoundException; import org.safs.STAFHelper; import org.safs.StatusCodes; import org.safs.StringUtils; import org.safs.model.commands.DDDriverCommands; import org.safs.model.commands.DDDriverFlowCommands; import org.safs.net.IHttpRequest.Key; import org.safs.net.NetUtilities; import org.safs.selenium.util.SeleniumServerRunner; import org.safs.selenium.webdriver.WebDriverGUIUtilities.GridNode; import org.safs.selenium.webdriver.lib.RemoteDriver; import org.safs.selenium.webdriver.lib.SelectBrowser; import org.safs.selenium.webdriver.lib.SeleniumPlusException; import org.safs.selenium.webdriver.lib.WDLibrary; import org.safs.selenium.webdriver.lib.interpreter.WDTestRun; import org.safs.selenium.webdriver.lib.interpreter.WDTestRunFactory; import org.safs.text.FAILKEYS; import org.safs.text.FAILStrings; import org.safs.text.FileUtilities; import org.safs.text.GENKEYS; import org.safs.text.GENStrings; import org.safs.tools.CaseInsensitiveFile; import org.safs.tools.consoles.ProcessCapture; import org.safs.tools.drivers.DriverConstant.SeleniumConfigConstant; import org.safs.tools.drivers.DriverInterface; import org.safs.tools.stringutils.StringUtilities; import com.ibm.staf.STAFResult; import com.sebuilder.interpreter.Script; import com.sebuilder.interpreter.Step; import com.sebuilder.interpreter.webdriverfactory.WebDriverFactory; public class DCDriverCommand extends DriverCommand { public static final String DEFAULT_BROWSER = SelectBrowser.BROWSER_NAME_FIREFOX; public static final int DEFAULT_BROWSER_TIMEOUT = 15;//in seconds public static final int DEFAULT_GET_URL_TIMEOUT = 120;//in seconds /**A convenient GUIUtilities*/ protected WebDriverGUIUtilities wdgu = null; //STestRecordHelper testRecordData; public DCDriverCommand() { super(); } /** * Convert the general GUIUtilities to a specific one. **/ protected void init() throws SAFSException { super.init(); try { wdgu = (WebDriverGUIUtilities) utils; } catch (Exception e) { String msg = " Met Exception " + StringUtils.debugmsg(e); IndependantLog.error(StringUtils.debugmsg(false) + msg); throw new SAFSException("Failed to convert GUIUtilities, " + msg); } } protected void commandProcess() { String dbg = getClass().getName() + ".commandProcess "; Log.info(dbg + "processing: " + command); if (command.equalsIgnoreCase(DDDriverCommands.STARTWEBBROWSER_KEYWORD)) { startWebBrowser(); } else if (command.equalsIgnoreCase(DDDriverCommands.STOPWEBBROWSER_KEYWORD)) { stopWebBrowser(); } else if (command.equalsIgnoreCase(DDDriverCommands.USEWEBBROWSER_KEYWORD)) { useWebBrowser(); } else if (command.equalsIgnoreCase(DDDriverCommands.WAITFORGUI_KEYWORD) || command.equalsIgnoreCase(DDDriverCommands.WAITFORWEBPAGE_KEYWORD)) { waitForGui(); } else if (command.equalsIgnoreCase(DDDriverCommands.WAITFORGUIGONE_KEYWORD)) { waitForGuiGone(); } else if (command.equalsIgnoreCase(DDDriverCommands.SETCONTEXT_KEYWORD) || command.equalsIgnoreCase(DDDriverCommands.SETFOCUS_KEYWORD)) { setFocus(); } else if (command.equalsIgnoreCase(DDDriverCommands.CLEARAPPMAPCACHE_KEYWORD)) { clearAppMapCache(); } else if (command.equalsIgnoreCase(DDDriverCommands.HIGHLIGHT_KEYWORD)) { highlight(); } else if (command.equalsIgnoreCase(DDDriverFlowCommands.CALLSCRIPT_KEYWORD)) { callScript(); } else if (command.equalsIgnoreCase(DDDriverCommands.WAITFORPROPERTYVALUE_KEYWORD)) { waitForPropertyValueStatus(true); } else if (command.equalsIgnoreCase(DDDriverCommands.WAITFORPROPERTYVALUEGONE_KEYWORD)) { waitForPropertyValueStatus(false); } else if (command.equalsIgnoreCase(DDDriverCommands.GETURL_KEYWORD) || command.equalsIgnoreCase(DDDriverCommands.SAVEURLTOFILE_KEYWORD) || command.equalsIgnoreCase(DDDriverCommands.VERIFYURLCONTENT_KEYWORD) || command.equalsIgnoreCase(DDDriverCommands.VERIFYURLTOFILE_KEYWORD)) { sendHttpGetRequest(); } } public static final String SUFFIX_VARIABLE_READY_STATE = ".readyState"; public static final String SUFFIX_VARIABLE_HEADERS = ".headers"; public static final String SUFFIX_VARIABLE_STATUS = ".status"; public static final String SUFFIX_VARIABLE_STATUS_TEXT = ".statusText"; public static final String SUFFIX_VARIABLE_XML = ".xml"; protected void sendHttpGetRequest() { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); if (params.size() < 2) { this.issueParameterCountFailure(); return; } final String debugmsg = StringUtils.debugmsg(false); //Check the known issue with selenium-standalone2.47.1 and Firefox 42.0 //It seems that stuck happen with previous firefox too :-( try { WDLibrary.checkKnownIssue(command); } catch (SeleniumPlusException e) { testRecordData.setStatusCode(StatusCodes.SCRIPT_NOT_EXECUTED); log.logMessage(testRecordData.getFac(), command + " NOT executed.", e.getMessage(), WARNING_MESSAGE); return; } final String url = iterator.next();//The first is URL IndependantLog.debug(debugmsg + " parameters: url=" + url); //Second parameter: //'variable name' for GetURL, 'string content' for VerifyURLContent, 'test file' for SaveURLToFile, and 'bench file' for VerifyURLToFile String secondParam = iterator.next(); IndependantLog.debug(debugmsg + " parameters: variable/content/test file/bench file=" + secondParam); File fn = null;//for SavaURLToFile and VerifyURLToFile try { if (DDDriverCommands.SAVEURLTOFILE_KEYWORD.equalsIgnoreCase(command)) fn = deduceTestFile(secondParam); else if (DDDriverCommands.VERIFYURLTOFILE_KEYWORD.equalsIgnoreCase(command)) fn = deduceBenchFile(secondParam); if (fn != null) IndependantLog.debug(debugmsg + " deduced file=" + fn.getAbsolutePath()); } catch (SAFSException e) { issueParameterValueFailure("Test File or Bench File " + e.getMessage()); return; } //get optional parameters, first is timeout int timeout = DEFAULT_GET_URL_TIMEOUT; try { if (iterator.hasNext()) { timeout = Integer.parseInt(iterator.next()); } } catch (NumberFormatException e) { IndependantLog.warn(debugmsg + "Parameter timeout is not valid. " + e.getMessage()); timeout = DEFAULT_GET_URL_TIMEOUT; } //get other optional parameters, pairs of (headerName, headerValue) final Map<String, String> headers = new HashMap<String, String>(); String headerName = null; String headerValue = null; while (iterator.hasNext()) { headerName = iterator.next(); if (iterator.hasNext()) { headerValue = iterator.next(); headers.put(headerName, headerValue); } else { IndependantLog .warn(debugmsg + " parameter pairs (headerName, headerValue) are not pair for header '" + headerName + "'!"); } } final Map<String, Object> resultMap = new HashMap<String, Object>(); final AtomicBoolean resultReady = new AtomicBoolean(false); try { Thread threadGetUrl = new Thread(new Runnable() { public void run() { try { Map<String, Object> results = WDLibrary.AJAX.getURL(url, headers); for (String key : results.keySet()) { resultMap.put(key, results.get(key)); } resultReady.set(true); } catch (Throwable e) { IndependantLog.error(debugmsg + " AJAX.getURL Thread: Met " + StringUtils.debugmsg(e)); } } }); //Set as daemon, we don't want this thread to block the termination of the main thread. threadGetUrl.setDaemon(true); threadGetUrl.start(); //Wait for the sub thread to terminate threadGetUrl.join(timeout * 1000); if (!resultReady.get()) { throw new SeleniumPlusException("Cannot get result ready from url '" + url + "'"); } String content = String.valueOf(resultMap.get(Key.RESPONSE_TEXT.value())); IndependantLog.debug(debugmsg + " http response\n" + content); if (DDDriverCommands.GETURL_KEYWORD.equalsIgnoreCase(command)) { //second parameter is the variable to store the url's content String var = secondParam; String varState = secondParam + SUFFIX_VARIABLE_READY_STATE; String varStatus = secondParam + SUFFIX_VARIABLE_STATUS; String varStatusTxt = secondParam + SUFFIX_VARIABLE_STATUS_TEXT; String varHeaders = secondParam + SUFFIX_VARIABLE_HEADERS; String varXml = secondParam + SUFFIX_VARIABLE_XML; setVariable(var, content); setVariable(varState, String.valueOf(resultMap.get(Key.READY_STATE.value()))); setVariable(varStatus, String.valueOf(resultMap.get(Key.RESPONSE_STATUS.value()))); setVariable(varStatusTxt, String.valueOf(resultMap.get(Key.RESPONSE_STATUS_TEXT.value()))); setVariable(varHeaders, String.valueOf(resultMap.get(Key.RESPONSE_HEADERS.value()))); setVariable(varXml, String.valueOf(resultMap.get(Key.RESPONSE_XML.value()))); String temp = "Requesting URL '" + url + "', content/readyState/Status/StatusText/ResponseHeaders/contentXML"; String value = " variable '" + var + "'/'" + varState + "'/'" + varStatus + "'/'" + varStatusTxt + "'/'" + varHeaders + "'/'" + varXml + "'"; issuePassedSuccess(GENStrings.convert(GENStrings.BE_SAVED_TO, temp + " has been saved to " + value + "", temp, value)); } else if (DDDriverCommands.SAVEURLTOFILE_KEYWORD.equalsIgnoreCase(command)) { FileUtilities.writeStringToUTF8File(fn.getAbsolutePath(), content); issuePassedSuccess(GENStrings.convert(GENStrings.BE_SAVED_TO, "The contet of URL '" + url + "' has been saved to '" + fn.getAbsolutePath() + "'", "The contet of URL '" + url + "'", fn.getAbsolutePath())); } else if (DDDriverCommands.VERIFYURLCONTENT_KEYWORD.equalsIgnoreCase(command)) { //second parameter is the url's content to compare with for verification. if (content.equals(secondParam)) { issuePassedSuccess(GENStrings.convert(GENStrings.CONTENT_MATCHES_KEY, "the content of '" + url + "' matches the content of '" + secondParam + "'", url, secondParam)); } else { String detail = GENStrings.convert(GENStrings.CONTENT_NOT_MATCHES_KEY, "the content of '" + url + "' does not match the content of '" + secondParam + "'", url, "'" + secondParam + "'"); issueActionUsingNegativeMessage(command, detail); } } else if (DDDriverCommands.VERIFYURLTOFILE_KEYWORD.equalsIgnoreCase(command)) { //verify with bench file String benchContent = FileUtilities.readStringFromUTF8File(fn.getAbsolutePath()); if (content.equals(benchContent)) { issuePassedSuccess(GENStrings.convert(GENStrings.CONTENT_MATCHES_KEY, "the content of '" + url + "' matches the content of '" + fn.getCanonicalPath() + "'", url, fn.getCanonicalPath())); } else { String detail = GENStrings.convert( GENStrings.CONTENT_NOT_MATCHES_KEY, "the content of '" + url + "' does not match the content of '" + fn.getCanonicalPath() + "'", url, fn.getCanonicalPath()); issueActionUsingNegativeMessage(command, detail); } } else { IndependantLog.warn(debugmsg + "action '" + command + "' should not be executed here."); testRecordData.setStatusCode(StatusCodes.SCRIPT_NOT_EXECUTED); return; } //success! set status to ok testRecordData.setStatusCode(StatusCodes.OK); } catch (Exception e) { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); this.issueErrorPerformingAction(StringUtils.debugmsg(e)); } } private void callScript() { String debugmsg = "DCDriverCommand.callScript "; if (params.size() < 1) { issueParameterCountFailure(); return; } Iterator iterator = params.iterator(); String path = (String) iterator.next(); CaseInsensitiveFile file = new CaseInsensitiveFile(path); if (file.isAbsolute() && (!file.exists() || !file.canRead())) { issueFileErrorFailure(path); return; } File actual = file.toFile(); if (!file.isAbsolute()) { try { actual = deduceProjectFile(path); if (!actual.isAbsolute() || !actual.exists() || !actual.canRead()) { issueFileErrorFailure(path); return; } } catch (Exception x) { issueFileErrorFailure(path); return; } } // actual should now be an absolute file path String p1 = actual.getName(); try { //Push the test-record-data into a stack, before executing the scripts pushTestRecord(testRecordData); // load the Script and prepare to run it Step by Step Script script = WDLibrary.getSeleniumBuilderScript(actual.getAbsolutePath()); // How does a script explicitly say it does or does NOT want to close the driver? // Scripts seem to be set to closeDriver=true by default. script.closeDriver = false; script.testRunFactory = new WDTestRunFactory(); WebDriverFactory factory = WDLibrary.getWebDriverAsWebDriverFactory(); WDTestRun test = (WDTestRun) script.start((org.apache.commons.logging.Log) log, factory, null, new HashMap<String, String>()); boolean finished = false; boolean success = true; //boolean shutdownHook = false; boolean retryStep = false; Step step = null; String driverStatus = null; boolean stepping = false; boolean stepSuccess = false; ArrayList<String> errorlist = new ArrayList<String>(); int stepnumber = 0; mainloop: while (!finished) { Log.suspend(); try { driverStatus = getVariable(DriverInterface.DRIVER_CONTROL_VAR); } catch (Exception any) { driverStatus = JavaHook.RUNNING_EXECUTION; } stepping = driverStatus.equalsIgnoreCase(JavaHook.RUNNING_EXECUTION); holdloop: while (!driverStatus.equalsIgnoreCase(JavaHook.RUNNING_EXECUTION)) { // PAUSE if (driverStatus.equalsIgnoreCase(JavaHook.PAUSE_EXECUTION)) { //check every 100 millis try { Thread.sleep(100); } catch (Exception x) { ; } // STEPPING } else if (driverStatus.equalsIgnoreCase(JavaHook.STEPPING_EXECUTION)) { setVariable(DriverInterface.DRIVER_CONTROL_VAR, JavaHook.PAUSE_EXECUTION); // STEP } else if (driverStatus.equalsIgnoreCase(JavaHook.STEP_EXECUTION)) { setVariable(DriverInterface.DRIVER_CONTROL_VAR, JavaHook.STEPPING_EXECUTION); break holdloop; // SHUTDOWN } else if (driverStatus.equalsIgnoreCase(JavaHook.SHUTDOWN_RECORD)) { Log.resume(); Log.info(debugmsg + " processing USER SHUTDOWN REQUEST..."); success = false; stepping = false; break mainloop; // STEP_RETRY_EXECUTION } else if (driverStatus.equalsIgnoreCase(JavaHook.STEP_RETRY_EXECUTION)) { setVariable(DriverInterface.DRIVER_CONTROL_VAR, JavaHook.STEPPING_RETRY_EXECUTION); retryStep = true; break holdloop; // STEPPING_RETRY_EXECUTION } else if (driverStatus.equalsIgnoreCase(JavaHook.STEPPING_RETRY_EXECUTION)) { retryStep = false; setVariable(DriverInterface.DRIVER_CONTROL_VAR, JavaHook.PAUSE_EXECUTION); } else { Log.resume(); Log.info(debugmsg + " unknown or invalid SAFS_DRIVER_CONTROL status. ReSet to RUNNING!"); Log.suspend(); setVariable(DriverInterface.DRIVER_CONTROL_VAR, JavaHook.RUNNING_EXECUTION); stepping = false; break holdloop; } try { driverStatus = getVariable(DriverInterface.DRIVER_CONTROL_VAR); } catch (Exception any) { driverStatus = JavaHook.RUNNING_EXECUTION; } stepping = driverStatus.equalsIgnoreCase(JavaHook.RUNNING_EXECUTION); } // end of holdloop: Log.resume(); // continue in mainloop: stepSuccess = true; if (!retryStep || step == null) { step = test.popNext(); if (step == null) { finished = true; test.cleanup(); } else { stepnumber++; stepSuccess = test.runStep(step); if (!stepSuccess) success = false;// set and keep the false setting } } else { // EXPERIMENTAL: retry last Step try { stepSuccess = test.runStep(step); if (!stepSuccess) success = false; } catch (Exception x) { // what do we want to do when a retry blows up? // currently, we are going to DebugLog it and let the execution/stepping continue. Log.debug(debugmsg + " ignoring Step retry " + x.getClass().getSimpleName() + ", " + x.getMessage(), x); } } retryStep = false; // insure reset if (!stepSuccess) { // do we want to set finished = true? // or does the Script/TestRun automatically do that for us? errorlist.add(p1 + ": Step #" + stepnumber + ": " + step.type.getClass().getSimpleName() + " " + step.toString() + " was not successful.\n"); } } // end of mainloop: Log.resume(); //Pop the 'test-record-data' from the stack after 'scripts execution', and restore the 'test-record-data' if the //'script execution' changed the shared class field 'test-record-data'. popTestRecord(); if (success) { issueGenericSuccessUsing(actual.getAbsolutePath(), null); return; } else { String detail = "\n"; for (String line : errorlist.toArray(new String[] {})) detail += line; issueActionUsingNegativeMessage(actual.getAbsolutePath(), detail); return; } } catch (Throwable t) { Log.resume(); String p2 = t.getClass().getSimpleName() + ": " + t.getMessage(); Log.debug(p2, t); issueErrorPerformingAction(FAILStrings.convert(FAILStrings.SCRIPT_ERROR, "Script '" + actual.getAbsolutePath() + "' error: " + p2, actual.getAbsolutePath(), p2)); } } private void clearAppMapCache() { //localClearAppMapCache(null, null); String msg = ""; try { testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); wdgu.clearAllAppMapCaches(); msg = genericText.convert("success2", "Selenium " + testRecordData.getCommand() + " successful.", "Selenium", testRecordData.getCommand()); } catch (Exception x) { ; } log.logMessage(testRecordData.getFac(), msg, GENERIC_MESSAGE); } /** * params[0] url<br> * params[1] browser id (default {@link #DEFAULT_BROWSER})<br> * params[2] browser name (default {@link #DEFAULT_BROWSER})<br> * params[3] timeout (default 30) in seconds.<br> * params[4] true/false isRemoteBrowser (ignored -- treated as always true)<br> * <br> * Following parameters indicate the extra parameters, they should be given by pair(key, value)<br> * The key can be one of:<br> * {@link SelectBrowser#getExtraParameterKeys()}<br> * <br> * params[5] extra parameter key1<br> * params[6] extra parameter value for key1<br> * <br> * params[7] extra parameter key2<br> * params[8] extra parameter value for key2<br> * <br> * params[9] extra parameter key3<br> * params[10] extra parameter value for key3<br> * ... */ private void startWebBrowser() { if (params.size() < 1) { issueParameterCountFailure(); return; } Iterator iterator = params.iterator(); String url = (String) iterator.next(); // params[0] String debugmsg = StringUtils.debugmsg(false); Log.info(debugmsg + " received URL: " + url); String id = DEFAULT_BROWSER; try { id = (String) iterator.next(); // params[1] } catch (Exception badvalue) { Log.info(debugmsg + " browser id may not be passed via parameters. Using Default."); } Log.info(debugmsg + " using browser id: " + id); String browser = DEFAULT_BROWSER; try { //First, try to get the browser name from the system properties String temp = System.getProperty(SelectBrowser.SYSTEM_PROPERTY_BROWSER_NAME); if (temp != null && !temp.isEmpty()) browser = temp; //Second, try to get the browser name from the parameter temp = (String) iterator.next(); // params[2] if (temp != null && !temp.trim().isEmpty()) browser = temp; } catch (Exception badvalue) { } Log.info(debugmsg + " using browser name: " + browser); int timeout = Processor.getSecsWaitForComponent(); //default timeout in seconds try { timeout = Integer.parseInt((String) iterator.next()); // params[3] } catch (Exception badvalue) { } Log.info(debugmsg + " using timeout: " + String.valueOf(timeout)); boolean isRemoteBrowser = true; // we will support a SYSTEM property that overrides the ALWAYS true concept (just in case) try { //First, try to get the browser-remote from the system properties. //This can be set on the command-line or in the [SAFS_SELENIUM] INI config file. String temp = System.getProperty(SelectBrowser.SYSTEM_PROPERTY_BROWSER_REMOTE); if (temp != null && !temp.isEmpty()) { Log.info(debugmsg + " SYSTEM PROPERTY for isRemoteBrowser: " + isRemoteBrowser); isRemoteBrowser = StringUtilities.convertBool(temp); } // Get the ignored browser-remote from the parameter, if present. // must READ the value to get it out of the iterator, but 'false' will be ignored temp = (String) iterator.next(); if (temp != null && !temp.isEmpty() && StringUtilities.convertBool(temp)) { Log.info(debugmsg + " parameter for isRemoteBrowser set 'true'."); isRemoteBrowser = true; } else { Log.info(debugmsg + " parameter for isRemoteBrowser missing or 'false' and will be ignored."); } } catch (Exception badvalue) { } Log.info(debugmsg + " using browser isRemoteBrowser: " + isRemoteBrowser); //Handle the extra parameters, appear as pair(key, value) String key = null; Object value = null; HashMap<String, Object> extraParameters = new HashMap<String, Object>(); while (iterator.hasNext()) { // params[5] + try { key = (String) iterator.next(); Log.info(debugmsg + " received extra parameter's key: " + key); value = iterator.next(); Log.info(debugmsg + " received extra parameter's value: " + value); extraParameters.put(key, value); } catch (Exception badvalue) { Log.info(debugmsg + " received extra parameter: ", badvalue); } } //if seleniumnode has been provided, we are going to launch grid-hub and grid-node, not standalone server. String nodesInfo = System.getProperty(SelectBrowser.SYSTEM_PROPERTY_SELENIUM_NODE); Log.info(debugmsg + " using selenium nodes: " + nodesInfo); boolean isGrid = StringUtils.isValid(nodesInfo); if (isGrid) extraParameters.put(SelectBrowser.KEY_GRID_NODES_SETTING, nodesInfo); try { WDLibrary.startBrowser(browser, url, id, timeout, isRemoteBrowser, extraParameters); testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.SUCCESS_3A, testRecordData.getCommand() + ":" + id + " " + url + " successful using " + browser, testRecordData.getCommand(), id, url, browser), GENERIC_MESSAGE); return; } catch (Throwable th) { String errorMsg = th.getMessage(); IndependantLog.warn(debugmsg + " Fail due to: " + errorMsg); try { if (isRemoteBrowser) { launchSeleniumServers(); WDLibrary.startBrowser(browser, url, id, timeout, isRemoteBrowser, extraParameters); testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.SUCCESS_3A, testRecordData.getCommand() + ":" + id + " " + url + " successful using " + browser, testRecordData.getCommand(), id, url, browser), GENERIC_MESSAGE); return; } } catch (SeleniumPlusException se) { errorMsg = StringUtils.debugmsg(se); } Log.error(debugmsg + " Fail due to " + errorMsg); testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); issueUnknownErrorFailure(errorMsg); } } /**'-port' followed by the port number of the Selenium Server is going to use*/ public static final String OPTION_PORT = "-port"; /**'-role' followed by the role name of the server, it can be hub or node*/ public static final String OPTION_ROLE = "-role"; /**'-hub' followed by the hubRegisterUrl, something like http://hubhost:hubport/grid/register */ public static final String OPTION_HUB = "-hub"; /**'hub' role name for the "grid hub"*/ public static final String ROLE_HUB = "hub"; /**'node' role name for the "grid node"*/ public static final String ROLE_NODE = "node"; /** * Launch Selenium-Standalone-Sever or Selenium-Grid-Hub + Selenium-Grid-Nodes according to the configuration information.<br> * If the grid-node information is provided, then the Grid-Hub + Node will be launched; otherwise, standalone server will be launched.<br> * <b>Note:</b> Before calling this method:<br> * We should set the JVM property {@link SelectBrowser#SYSTEM_PROPERTY_SELENIUM_HOST} and {@link SelectBrowser#SYSTEM_PROPERTY_PROXY_PORT}.<br> * If we want to launch "grid", we should also set the JVM property {@link SelectBrowser#SYSTEM_PROPERTY_SELENIUM_NODE}.<br> * @throws SeleniumPlusException, if the server has not been started successfully. */ private void launchSeleniumServers() throws SeleniumPlusException { String debugmsg = StringUtils.debugmsg(false); //Retrieve seleniumhost, seleniumport, seleniumnode //We have set them to system properties in EmbeddedSeleniumHookDriver#start(), We just need to get them from system properties. String host = System.getProperty(SelectBrowser.SYSTEM_PROPERTY_SELENIUM_HOST, SeleniumConfigConstant.DEFAULT_SELENIUM_HOST); String port = System.getProperty(SelectBrowser.SYSTEM_PROPERTY_SELENIUM_PORT, SeleniumConfigConstant.DEFAULT_SELENIUM_PORT); String nodesInfo = System.getProperty(SelectBrowser.SYSTEM_PROPERTY_SELENIUM_NODE);//There is no default value for seleniumnode Log.info(debugmsg + " using selenium host name: " + host); Log.info(debugmsg + " using selenium port: " + port); Log.info(debugmsg + " using selenium nodes: " + nodesInfo); //if seleniumnode has been provided, we are going to launch grid-hub and grid-node, not standalone server. boolean isGrid = StringUtils.isValid(nodesInfo); //serverRunning can tell if the server (standalone or grid-hub) is running or not. boolean serverRunning = false; //we are going to launch nodes, they have to know where to register them (by hubRegisterUrl) //but if the hub is stared with hostname as "localhost" or "127.0.0.1", the nodes (remote machines) will not able to register them on http://localhost or http://127.0.0.1 //we need to find the real IP address for localhost and use it to build the hubRegisterUrl String hubRegisterUrl = "http://" + host + ":" + port + WebDriverGUIUtilities.URL_PATH_GRID_REGISTER; if (isGrid && NetUtilities.isLocalHost(host)) { hubRegisterUrl = "http://" + NetUtilities.getLocalHostIP() + ":" + port + WebDriverGUIUtilities.URL_PATH_GRID_REGISTER; } //TODO We could simply use the IP address to build the hubRegisterUrl, it is easier. // hubRegisterUrl = "http://"+StringUtils.getHostIP(host)+":"+port+WebDriverGUIUtilities.URL_PATH_GRID_REGISTER; //Before start server, we need to verify that the server/node is NOT running. Otherwise, we just return. if (isGrid) { if (WebDriverGUIUtilities.isGridRunning(host, port)) { IndependantLog.debug(debugmsg + " the selenium grid-hub server is already running on port '" + port + "' at '" + host + "'"); serverRunning = true; if (WebDriverGUIUtilities.isNodesRunning(nodesInfo, true, host, port)) { IndependantLog.debug(debugmsg + " the selenium grid-hub nodes are already running."); return; } else { IndependantLog.warn(debugmsg + " some selenium grid-hub nodes may not run at this moment, we need to restart them."); } } } else { if (WebDriverGUIUtilities.isStandalongServerRunning(host, port)) { IndependantLog.debug(debugmsg + " the selenium standalone server is already running on port '" + port + "' at '" + host + "'"); serverRunning = true; return; } } //if it is Grid, the server is a grid-hub. Otherwise the server is standalone. String serverName = "Selenium " + (isGrid ? "Grid Hub" : "Standalone server"); //role contains parameter to determinate what server to start, "standalone", "hub" String role = isGrid ? " " + OPTION_ROLE + " " + ROLE_HUB + " " : " ";//"" for standalone, "-role hub" for grid-hub if (!serverRunning) { //Start Server: standalone or grid-hub IndependantLog .debug(debugmsg + " try to start the " + serverName + " at " + host + ":" + port + " ... "); if (!launchSeleniumServers(host, port, role)) { //If server cannot be launched, throw exception. throw new SeleniumPlusException(" Fail to start '" + serverName + "' at " + host + ":" + port); } IndependantLog.debug(debugmsg + " " + serverName + " seems started, try to connect it."); //Wait for "standalone server" or "grid hub server" to be ready if (!WebDriverGUIUtilities.waitSeleniumServerRunning(isGrid, false, false)) { IndependantLog.warn(debugmsg + serverName + " can not be connected! If it is caused by SocketTimeoutException, you can enlarge timeout by WebDriverGUIUtilities.setTimeoutForHttpConnection(int/*default is 1000*/)."); } } if (isGrid) {//Grid: hub + nodes //Need also to start the nodes, if some nodes fail to launch we just log a warning instead of throwing exception. //prepare parameter to register node, something like "-role node -hub http://hubhost:hubport/grid/register" role = " " + OPTION_ROLE + " " + ROLE_NODE + " " + OPTION_HUB + " " + hubRegisterUrl; List<GridNode> nodes = WebDriverGUIUtilities.getGridNodes(nodesInfo); String nodehost = null; String nodeport = null; for (GridNode node : nodes) { nodehost = node.getHostname(); nodeport = node.getPort(); if (!WebDriverGUIUtilities.canConnectHubURL(nodehost, nodeport)) { IndependantLog.debug(debugmsg + " try to register the selenium node '" + node + "' to hub " + hubRegisterUrl); if (launchSeleniumServers(nodehost, nodeport, role)) { IndependantLog .debug(debugmsg + " '" + node + "' has been launched, waiting for its ready... "); WebDriverGUIUtilities.waitSeleniumNodeRunning(nodehost, nodeport); } else { IndependantLog.warn(debugmsg + " Fail to register node '" + node + "'"); } } else { //"connect to hub" is not enough to tell that this node has registered to hub //We need to get the grid/console information to analyze the registered nodes IndependantLog.debug(debugmsg + " selenium node '" + node + "' seems running."); if (!WebDriverGUIUtilities.verifyNodesRegistered(host, port, node)) { IndependantLog.error(debugmsg + " selenium node '" + node + "' has not registered to hub " + hubRegisterUrl); } } } } //We only check if the server (standalone or grid-hub) is running //if some nodes are not running, we will not throw exception; test may run on other running nodes. if (!WebDriverGUIUtilities.isSeleniumServerRunning(host, port, isGrid, false, nodesInfo, false)) { throw new SeleniumPlusException(" unable to connect to '" + serverName + "' at " + host + ":" + port + (isGrid ? ", Grid Nodes are '" + nodesInfo + "'" : "")); } } /** * Used to launch standalone-server, grid-hub or grid-node.<br> * @param host String, the host name of the selenium server/node * @param port String, the port number of the selenium server/node * @param params String[], the extra parameters for starting server/node * <ul> * <li>params[0] role String, the role option, it can be<br> * "" for standalone server<br> * "-role hub" for grid hub server<br> * "-role node -hub HubRegisterUrl" for grid node<br> * </ul> * @throws SeleniumPlusException */ private boolean launchSeleniumServers(String host, String port, String... params) throws SeleniumPlusException { String debugmsg = StringUtils.debugmsg(false); boolean serverStarted = false; Log.info(debugmsg + " starting server with Options: host=" + host + " port=" + port + ", params=" + Arrays.toString(params)); //Prepare the optional parameters for starting Selenium Server. //1. selenium server port String serverPort = ""; if (!SeleniumConfigConstant.DEFAULT_SELENIUM_PORT.equals(port)) { serverPort = " " + OPTION_PORT + " " + port; } Log.info(debugmsg + " port Option: " + serverPort); //2. JVM options for starting selenium server String serverJVMOptions = WebDriverGUIUtilities.getRemoteServerJVMOptions(); if (serverJVMOptions != null && !serverJVMOptions.trim().isEmpty()) { //SELENIUMSERVER_JVM_OPTIONS=remoteServerJVMOptions serverJVMOptions = SeleniumConfigConstant.SELENIUMSERVER_JVM_OPTIONS + GuiObjectRecognition.DEFAULT_ASSIGN_SEPARATOR + serverJVMOptions; } else { serverJVMOptions = ""; } Log.info(debugmsg + " JVM Option: " + serverJVMOptions); //3. start the RMI server. // We need RMI server for the 2 situations: // a. "standalone server" on remote machine // b. "grid node" on remote machine with "grid hub" on local/remote machine String rmiServer = "-" + SeleniumServerRunner.PROPERTY_RMISERVER; List<String> paramsList = new ArrayList<String>(); for (String param : params) paramsList.add(param); paramsList.add(serverPort); paramsList.add(serverJVMOptions); if (NetUtilities.isLocalHost(host)) { //Start the selenium server on the local machine Log.info(debugmsg + " attempting to (re)start Server locally."); String projectdir = null; try { projectdir = getVariable(STAFHelper.SAFS_VAR_PROJECTDIRECTORY); } catch (SAFSException x) { Log.info(debugmsg + " getProjectDir ignoring " + x.getClass().getName() + ", " + x.getMessage()); } Log.debug(debugmsg + " getProjectDir '" + projectdir + "'."); //locally testing, we don't need RMI server. serverStarted = WebDriverGUIUtilities.startRemoteServer(projectdir, paramsList.toArray(new String[0])); //TODO we need to modify the batch script for starting a selenium server (standalone, grid-hub, grid-node) if (!serverStarted) serverStarted = WebDriverGUIUtilities.startRemoteServer(); } else { //Start the selenium server on the remote machine String launchServerCommand = " java " + RemoteDriver.class.getName(); //pass parameters such as "port number", "JVM options", "rmiServer option", "server role" to start server on remote machine //remotely testing, we need RMI server. paramsList.add(rmiServer); for (String param : paramsList.toArray(new String[0])) { if (!StringUtils.isQuoted(param)) param = StringUtils.quote(param); launchServerCommand += " " + param; } Log.info(debugmsg + " attempting to (re)start Server remotely at " + host + ":" + port + ", with command \n" + launchServerCommand); String outputFile = "c:" + File.separator + "stafhandle_launch_RemoteDriver_standardoutput.txt"; String commandWithOutput = launchServerCommand + " STDOUT " + outputFile + " STDERRTOSTDOUT ";//Append STAF parameter 'STDOUT' and 'STDERRTOSTDOUT' IndependantLog.debug(debugmsg + " RemoteServer launching, the console message will be in file '" + outputFile + "' on machine '" + host + "'"); try { //Try to start by STAFHandle, which requires STAF enabled in configuration file //[STAF] //NOSTAF=False IndependantLog.debug(debugmsg + " Try to launch RemoteServer remotely by STAFHandle."); STAFResult rc = testRecordData.getSTAFHelper().startProcess(host, commandWithOutput, null); IndependantLog.debug(debugmsg + " STAFHandle launch RemoteServer, returned RC: " + rc.rc + " and result: " + rc.result); serverStarted = (rc.rc == STAFResult.Ok); if (!serverStarted) IndependantLog.warn(debugmsg + " STAFHandle launch RemoteServer Failed!"); } catch (Exception e) { IndependantLog .warn(debugmsg + " STAFHandle launch RemoteServer Failed. " + StringUtils.debugmsg(e)); } if (!serverStarted) { Process process = null; ProcessCapture console = null; try { //try to launch the server on remote machine by launching directly a "staf machine process start command ..." command IndependantLog .debug(debugmsg + " Try to launch RemoteServer remotely by STAF process service."); String stafCommand = "staf " + host + " process start command " + commandWithOutput; IndependantLog.debug(debugmsg + " Runtime exec STAF command: " + stafCommand); process = Runtime.getRuntime().exec(stafCommand); console = new ProcessCapture(process, null, true, false); try { console.thread.join(); } catch (InterruptedException x) { ; } @SuppressWarnings("unchecked") Vector<String> data = console.getData(); if (data != null && data.size() > 0) { for (String message : data) { if (message.startsWith(ProcessCapture.ERR_PREFIX) /*if get message from stadard err*/ || message.contains( "RC:") /*some staf error message will be printed to standard out, not standard err*/) { throw new SAFSException( " Fail to execute command: " + stafCommand + " \n due to " + message); } //These are only STAF Response message, not interesting //IndependantLog.debug(message); } } serverStarted = true; } catch (Exception e) { IndependantLog.warn(debugmsg + StringUtils.debugmsg(e)); } finally { if (console != null) console.shutdown(); } } // if(!serverStarted){ // //TODO maybe try to launch the server on remote machine if there a "rshd" running there. // try { // Runtime.getRuntime().exec("rsh "+seleniumhost+launchServerCommand); // } catch (IOException e) { // IndependantLog.warn(debugmsg+StringUtils.debugmsg(e)); // } // } } return serverStarted; } /** * params[0] browser id (default {@link #DEFAULT_BROWSER_ID})<br> */ private void useWebBrowser() { String debugmsg = StringUtils.debugmsg(this.getClass(), "useWebBrowser"); Iterator iterator = params.iterator(); String id = ""; try { id = (String) iterator.next(); Log.info(debugmsg + "received browser id: " + id); } catch (Exception badvalue) { Log.info(debugmsg + "received browser id: " + id); } try { WDLibrary.useBrowser(id); testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage( testRecordData.getFac(), genericText.convert(GENKEYS.SUCCESS_2, testRecordData.getCommand() + id + " successful.", testRecordData.getCommand(), id), GENERIC_MESSAGE); return; } catch (Throwable th) { String thmsg = "WebDriver swithcing error."; Log.error(debugmsg + thmsg, th); testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); issueUnknownErrorFailure(thmsg); } } /** * params[0] browser id (default {@link #DEFAULT_BROWSER_ID})<br> */ private void stopWebBrowser() { String debugmsg = StringUtils.debugmsg(this.getClass(), "stopWebBrowser"); Iterator iterator = params.iterator(); String id = ""; try { id = (String) iterator.next(); Log.info(debugmsg + "received browser id: " + id); } catch (Exception badvalue) { Log.info(debugmsg + "received browser id: " + id); } try { WDLibrary.stopBrowser(id); } catch (Throwable th) { String thmsg = "WebDriver stopping error: " + th.getMessage(); Log.error(debugmsg + thmsg, th); testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); issueUnknownErrorFailure(thmsg); return; } testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage( testRecordData.getFac(), genericText.convert(GENKEYS.SUCCESS_2, testRecordData.getCommand() + id + " successful.", testRecordData.getCommand(), id), GENERIC_MESSAGE); } /** * Turn the highlight-switch on/off. * If the highlight-switch is turned on, the test component will be highlighted during runtime. */ private void highlight() { if (params.size() < 1) { issueParameterCountFailure(); return; } WebDriverGUIUtilities.HIGHLIGHT = StringUtilities.convertBool(params.iterator().next()); testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage( testRecordData.getFac(), genericText.convert(GENKEYS.SUCCESS_2, testRecordData.getCommand() + " successful.", testRecordData.getCommand()), GENERIC_MESSAGE); } /** <br><em>Purpose:</em> waitForGui **/ private void waitForGui() { if (params.size() < 2) { issueParameterCountFailure(); return; } Iterator<?> iterator = params.iterator(); final String DEFAULT_SECONDS_STR = "15"; final String DEFAULT_WEBPAGE_STR = "30"; boolean isWeb = testRecordData.getCommand().equalsIgnoreCase(DDDriverCommands.WAITFORWEBPAGE_KEYWORD); String DEFAULT_TIMEOUT = isWeb ? DEFAULT_WEBPAGE_STR : DEFAULT_SECONDS_STR; // get the window, comp String windowName = (String) iterator.next(); String compName = (String) iterator.next(); String command = testRecordData.getCommand().toLowerCase(); String seconds = null; int secii = 0; try { // optional param seconds = (String) iterator.next(); if (seconds.length() == 0) seconds = DEFAULT_TIMEOUT; secii = Integer.parseInt(seconds); Log.debug(command + " optional parameter '" + "TIMEOUT" + "' set to '" + seconds + "'."); } catch (Exception e) { Log.warn(command + " optional parameter timeout '" + seconds + "' is not valid: " + e.getMessage() + ". Use the default timeout " + DEFAULT_TIMEOUT); seconds = DEFAULT_TIMEOUT; secii = Integer.parseInt(seconds); } if (secii < 0) secii = 0; Log.info("............................." + command + ": window:" + windowName + ", component:" + compName + ", seconds:" + seconds); String msg = ""; try { // wait for the window/component int status = wdgu.waitForObject(testRecordData.getAppMapName(), windowName, compName, secii); //if it cannot be found within timeout if (status == 0) { WebElement winObject = ((WDTestRecordHelper) testRecordData).getWindowTestObject(); WebElement compObject = ((WDTestRecordHelper) testRecordData).getCompTestObject(); WebDriverGUIUtilities.highlightThenClear((compObject == null ? winObject : compObject), 1000); } else if (status == StatusCodes.SCRIPT_NOT_EXECUTED) { testRecordData.setStatusCode(StatusCodes.SCRIPT_NOT_EXECUTED); Log.debug(command + " was not handled by Selenium WebDriver. It will be handled by other engine later."); return; } else { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); msg = failedText.convert("not_found_timeout", compName + " was not found within timeout " + seconds, compName, seconds); standardFailureMessage(msg, testRecordData.getInputRecord()); return; } testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage(testRecordData.getFac(), genericText.convert("found_timeout", compName + " was found within timeout " + seconds, compName, seconds), GENERIC_MESSAGE); } catch (SAFSException se) { //se.printStackTrace(); testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); msg = failedText.convert("not_found_timeout", compName + " was not found within timeout " + seconds, compName, seconds); /** String semsg = se.getMessage(); if (semsg.length()==0) semsg = se.getClass().getName(); standardFailureMessage(msg, "SAFSException:"+ semsg); */ standardFailureMessage(msg, ""); } } protected boolean checkGUIExistence(boolean expectedExist, String mapNam, String window, String component, int timeoutInSeconds) throws SAFSException { boolean exist; if (expectedExist) {//Expect the component to be present exist = false; try { exist = (wdgu.waitForObject(mapNam, window, component, timeoutInSeconds) == 0); } catch (SAFSObjectNotFoundException sonf) { /*ignore*/} } else {//Expect the component to be not present exist = true; long endTime = System.currentTimeMillis() + timeoutInSeconds * 1000; while (exist && (System.currentTimeMillis() < endTime)) { try { exist = (wdgu.waitForObject(mapNam, window, component, 0) == 0); } catch (SAFSObjectNotFoundException sonf) { exist = false; } } } //if it exists, then highlight it and clear the highlight if (exist) { WebElement winObject = ((WDTestRecordHelper) testRecordData).getWindowTestObject(); WebElement compObject = ((WDTestRecordHelper) testRecordData).getCompTestObject(); WebDriverGUIUtilities.highlightThenClear((compObject == null ? winObject : compObject), 1000); } return (expectedExist == exist); } private void waitForGuiGone() { if (params.size() < 2) { issueParameterCountFailure(); return; } Log.info(".............................params= " + params); Iterator<?> iterator = params.iterator(); String DEFAULT_TIMEOUT = "15"; // get the window, comp String windowName = (String) iterator.next(); String compName = (String) iterator.next(); String seconds = iterator.hasNext() ? (String) iterator.next() : DEFAULT_TIMEOUT; int timeoutInMillis = 0; try { // optional param timeoutInMillis = Integer.parseInt(seconds) * 1000; } catch (Exception e) { seconds = DEFAULT_TIMEOUT; timeoutInMillis = Integer.parseInt(seconds) * 1000; } if (timeoutInMillis < 0) timeoutInMillis = 0; Log.info("............................. timeoutInMillis=" + timeoutInMillis); String winCompName = windowName + ":" + compName; int status = 0; boolean exist = false; boolean didExist = false; boolean isDisplayed = false; long endTime = System.currentTimeMillis() + timeoutInMillis; try { //wait for the GUI to show up: didExist = true while (!didExist) { try { status = wdgu.waitForObject(testRecordData.getAppMapName(), windowName, compName, 0); if (status == StatusCodes.SCRIPT_NOT_EXECUTED) { testRecordData.setStatusCode(StatusCodes.SCRIPT_NOT_EXECUTED); Log.debug(command + " was not handled by Selenium WebDriver. It will be handled by other engine later."); return; } exist = (status == 0); if (exist) { try { WebElement e = ((WDTestRecordHelper) wdgu.getTestRecordData()).getCompTestObject(); try { WebDriverGUIUtilities.highlightThenClear(e, 1000); isDisplayed = WDLibrary.isDisplayed(e); Log.info("............................. " + winCompName + " is Displayed = " + isDisplayed); } catch (SeleniumPlusException stale) { exist = false; didExist = true; } } catch (Exception fallback) { Log.debug("..........." + fallback.getClass().getName() + ", " + fallback.getMessage()); Log.info("............................. skipping initial visibility check."); } } } catch (SAFSObjectNotFoundException ignore) { } if (exist) didExist = true; // set once to show we did see it at least once. if (!didExist) { if (System.currentTimeMillis() > endTime) break; // give the app some computing time to play with try { Thread.sleep(20); } catch (InterruptedException x) { } } } // now wait for it to go away. while (exist && System.currentTimeMillis() < endTime) { // give the app some computing time to play with try { Thread.sleep(20); } catch (InterruptedException x) { } try { exist = (wdgu.waitForObject(testRecordData.getAppMapName(), windowName, compName, 0) == 0); if (exist) { try { WebElement e = ((WDTestRecordHelper) wdgu.getTestRecordData()).getCompTestObject(); try { exist = WDLibrary.isDisplayed(e); Log.info("............................. " + winCompName + " is still Displayed = " + exist); } catch (SeleniumPlusException stale) { exist = false; } } catch (Exception fallback) { Log.debug("..........." + fallback.getClass().getName() + ", " + fallback.getMessage()); Log.info("............................. skipping final visibility check."); } } } catch (SAFSObjectNotFoundException nf) { exist = false; } } //if it is not gone within timeout if (exist) { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); String msg = failedText.convert(FAILKEYS.NOT_GONE_TIMEOUT, winCompName + " was not gone within timeout " + seconds, winCompName, seconds); standardFailureMessage(msg, testRecordData.getInputRecord()); return; } if (didExist) { testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.GONE_TIMEOUT, winCompName + " was gone within timeout " + seconds, winCompName, seconds), GENERIC_MESSAGE); } else { // log a warning that we never saw it. Recognition could be bad. testRecordData.setStatusCode(StatusCodes.SCRIPT_WARNING); log.logMessage(testRecordData.getFac(), failedText.convert(FAILKEYS.NOT_FOUND_TIMEOUT, winCompName + " was not found in timeout " + seconds, winCompName, seconds), WARNING_MESSAGE); } } catch (SAFSObjectNotFoundException se) { if (didExist) { testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.GONE_TIMEOUT, winCompName + " was gone within timeout " + seconds, winCompName, seconds), GENERIC_MESSAGE); } else { testRecordData.setStatusCode(StatusCodes.SCRIPT_WARNING); log.logMessage(testRecordData.getFac(), failedText.convert(FAILKEYS.NOT_FOUND_TIMEOUT, winCompName + " was not found in timeout " + seconds, winCompName, seconds), WARNING_MESSAGE); } } catch (Exception e) { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); standardFailureMessage(command + " Fail.", "Met " + StringUtils.debugmsg(e)); } } private void setFocus() { String debugmsg = StringUtils.debugmsg(false); if (params.size() < 2) { issueParameterCountFailure(); return; } Iterator<?> iterator = params.iterator(); String window = (String) iterator.next(); String component = (String) iterator.next(); IndependantLog.debug(debugmsg + " Setting focus to " + window + ":" + component); testRecordData.setWindowName(window); testRecordData.setCompName(component); boolean focused = false; boolean isWindow = window.equalsIgnoreCase(component); String winCompString = isWindow ? window : window + ":" + component; //wait for window and component object try { WebDriver webdriver = WDLibrary.getWebDriver(); //wait for window and component object long timeout = isWindow ? getSecsWaitForWindow() : getSecsWaitForComponent(); int status = wdgu.waitForObject(testRecordData.getAppMapName(), window, component, timeout); if (status == 0) { //TODO focus the window, How to??? focusWindow(webdriver); if (!isWindow) { //focus the component WebElement element = WDLibrary.getObject(testRecordData.getCompGuiId()); Actions focusAction = new Actions(webdriver).moveToElement(element); if ("EditBox".equalsIgnoreCase(WebDriverGUIUtilities.getCompType(element))) focusAction = focusAction.click(); focusAction.perform(); } focused = true; } else { IndependantLog.error(debugmsg + " cannot find " + winCompString); } } catch (Exception e) { IndependantLog.error( debugmsg + " cannot set focus to " + winCompString + " due to " + StringUtils.debugmsg(e)); } if (focused) { testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); String msg = genericText.convert(TXT_SUCCESS_2, winCompString + " " + testRecordData.getCommand() + " successful.", winCompString, testRecordData.getCommand()); log.logMessage(testRecordData.getFac(), msg, GENERIC_MESSAGE); } else { issueErrorPerformingAction(FAILStrings.convert(FAILStrings.SOMETHING_NOT_FOUND, winCompString + " was not focused.", winCompString)); } } /** * TODO Need to move to class WDLibrary, this doesn't work yet!!! * @param webdriver * @throws SeleniumPlusException */ static void focusWindow(WebDriver webdriver) throws SeleniumPlusException { try { org.openqa.selenium.Point position = webdriver.manage().window().getPosition(); org.openqa.selenium.Dimension dim = webdriver.manage().window().getSize(); webdriver.manage().window().maximize(); webdriver.manage().window().setPosition(position); webdriver.manage().window().setSize(dim); webdriver.switchTo().window(webdriver.getWindowHandle()); WDLibrary.executeScript("window.focus();"); } catch (Exception e) { throw new SeleniumPlusException("Failed to minimize current browser window" + e.getMessage()); } } /** clear the cache of the test objects maintained by the appmap class, ** plus return the new TestObject for the windowName anc compName ** <br> this version is the worker, and does not set status or log a message ** @param windowName, String, if null then uses a dummy name ** @param compName, String, if null then uses a dummy name ** @return, if windowName or compName are null or not fould, then return null, else ** after clearing the cache, returns the new TestObject if found **/ private Object localClearAppMapCache(String windowName, String compName) { if (windowName == null) windowName = "___any"; if (compName == null) compName = "___comp"; String mapname = testRecordData.getAppMapName(); Object obj = wdgu.getTestObject(mapname, windowName, compName, true); return obj; } /** * <br><em>Purpose:</em> Helper function for waitForPropertyValue and waitForPropertyValueGone <br> * @param propertyStatus boolean, if it is true, it means wait for property matching expected values; <br> * if it is false, it means wait for property gone, i.e. NOT matching expected values. * @author SCNTAX */ private void waitForPropertyValueStatus(boolean propertyStatus) { String dbgmsg = StringUtils.debugmsg(DCDriverCommand.class, "waitForPropertyValueStatus"); if (params.size() < 4) { issueParameterCountFailure(); return; } final String DEFAULT_TIMEOUT = "15"; final String DEFAULT_CASE_INSENSITIVE = "False"; String seconds = ""; String caseInsensitive = ""; iterator = params.iterator(); // get the window, component, property, expected value. String windowName = (String) iterator.next(); String compName = (String) iterator.next(); String propertyName = (String) iterator.next(); String expectedValue = (String) iterator.next(); testRecordData.setWindowName(windowName); testRecordData.setCompName(compName); // get timeout, case sensitive parameters if (params.size() > 4) { seconds = (String) iterator.next(); if (params.size() > 5) caseInsensitive = (String) iterator.next(); } // timeout parsing int secii = 0; if (0 == seconds.length()) seconds = DEFAULT_TIMEOUT; try { secii = Integer.parseInt(seconds); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.DEFAULT_MISSING_PARAM, command + " optional parameter '" + "TIMEOUT" + "' set to '" + seconds + "'.", command, "TIMEOUT", seconds), GENERIC_MESSAGE); } catch (NumberFormatException e) { seconds = DEFAULT_TIMEOUT; secii = Integer.parseInt(seconds); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.DEFAULT_BAD_PARAM, command + " invalid optional parameter '" + "TIMEOUT" + "' set to '" + seconds + "'.", command, "TIMEOUT", seconds), GENERIC_MESSAGE); } catch (Exception e) { seconds = DEFAULT_TIMEOUT; secii = Integer.parseInt(seconds); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.DEFAULT_MISSING_PARAM, command + " optional parameter '" + "TIMEOUT" + "' set to '" + seconds + "'.", command, "TIMEOUT", seconds), GENERIC_MESSAGE); } if (secii < 0) secii = 0; // case sensitive parsing if (0 == caseInsensitive.length()) caseInsensitive = DEFAULT_CASE_INSENSITIVE; boolean booleanCaseInsensitive = Boolean.parseBoolean(caseInsensitive); log.logMessage(testRecordData.getFac(), genericText.convert( GENKEYS.DEFAULT_MISSING_PARAM, command + " optional parameter '" + "CASEINSENSITIVE" + "' set to '" + caseInsensitive + "'.", command, "CASEINSENSITIVE", caseInsensitive), GENERIC_MESSAGE); Log.debug(dbgmsg + "......" + command + ": window:" + windowName + ", component:" + compName + ", property name:" + propertyName + ", expected value:" + expectedValue + ", seconds:" + seconds + ", caseInsensitive:" + caseInsensitive); // compare with expected value String msg = ""; try { // wait for the window/component int status = wdgu.waitForPropertyStatus(windowName, compName, propertyName, expectedValue, secii, booleanCaseInsensitive, propertyStatus); //if it is not match with expected value if (status != 0) { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); msg = failedText.convert(FAILKEYS.SELECTION_NOT_MATCH, "Selection '" + propertyName + "' does not match expected value '" + expectedValue + "'", propertyName, expectedValue); standardFailureMessage(msg, testRecordData.getInputRecord()); return; } testRecordData.setStatusCode(StatusCodes.NO_SCRIPT_FAILURE); log.logMessage(testRecordData.getFac(), genericText.convert(GENKEYS.FOUND_TIMEOUT, compName + " was found within timeout " + seconds, compName, seconds), GENERIC_MESSAGE); } catch (SAFSException se) { testRecordData.setStatusCode(StatusCodes.GENERAL_SCRIPT_FAILURE); msg = failedText.convert(FAILKEYS.NOT_FOUND_TIMEOUT, compName + " was not found within timeout " + seconds, compName, seconds); standardFailureMessage(msg, testRecordData.getInputRecord()); } } }