From 2ceb2924f33515aa8e9c5939fc4c52476a408067 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Sat, 29 Jun 2019 12:35:28 +0300 Subject: [PATCH 01/19] added webdrivermanager of io.github.bonigarcia library interaction --- pom.xml | 5 + .../keywords/BrowserManagement.java | 127 +++++++++++------- .../seleniumlibrary/keywords/Cookie.java | 2 - .../seleniumlibrary/keywords/Element.java | 22 ++- .../seleniumlibrary/keywords/Logging.java | 1 - .../seleniumlibrary/keywords/Robot.java | 1 - .../seleniumlibrary/keywords/Screenshot.java | 1 - .../keywords/SelectElement.java | 1 - .../keywords/TableElement.java | 1 - .../seleniumlibrary/keywords/Waiting.java | 1 - .../locators/ElementFinder.java | 2 - 11 files changed, 108 insertions(+), 56 deletions(-) diff --git a/pom.xml b/pom.xml index ba697b4..50013c1 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,11 @@ 2.18.3 test + + io.github.bonigarcia + webdrivermanager + 3.4.0 + diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java index de09911..4b9232e 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java @@ -1,6 +1,8 @@ package com.github.markusbernhardt.seleniumlibrary.keywords; import io.appium.java_client.ios.IOSDriver; +import io.github.bonigarcia.wdm.DriverManagerType; +import io.github.bonigarcia.wdm.WebDriverManager; import io.selendroid.client.SelendroidDriver; import java.io.File; @@ -10,7 +12,6 @@ import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; @@ -184,13 +185,18 @@ public void closeBrowser() { "\r\n" + "If the provided configuration options are not enough, it is possible to use `Create Webdriver` to customize browser initialization even more.") @ArgumentNames({ "url", "browserName=firefox", "alias=None", "remoteUrl=None", "desiredCapabilities=None", - "browserOptions=None" }) - public String openBrowser(String url, String... args) throws Throwable { + "browserOptions=None", "webDriverManager=None" }) + public String openBrowser(String url, String... args) { String browserName = robot.getParamsValue(args, 0, "firefox"); String alias = robot.getParamsValue(args, 1, "None"); String remoteUrl = robot.getParamsValue(args, 2, "None"); String desiredCapabilities = robot.getParamsValue(args, 3, "None"); String browserOptions = robot.getParamsValue(args, 4, "None"); + String webDriverManager = robot.getParamsValue(args, 5, "None"); + + if (!webDriverManager.equals("None")) { + webDriverManagerSetup(browserName); + } try { logging.info("browserName: " + browserName); @@ -665,7 +671,7 @@ protected WebDriver createLocalWebDriver(String browserName, Capabilities desire case "ipad": case "iphone": try { - return new IOSDriver(new URL(""), desiredCapabilities); + return new IOSDriver<>(new URL(""), desiredCapabilities); } catch (Exception e) { throw new SeleniumLibraryFatalException("Creating " + browserName + " instance failed.", e); } @@ -674,6 +680,41 @@ protected WebDriver createLocalWebDriver(String browserName, Capabilities desire } } + @RobotKeyword("WebDriver Manager Setup") + @ArgumentNames({"browserName=firefox"}) + public void webDriverManagerSetup(String browserName) { + initWebDriver(browserName); + logging.info(String.format("Init WebDriver Manager for '%s' browser", browserName)); + } + + private void initWebDriver(String browserName) { + switch (browserName.toLowerCase()) { + case "ff": + case "firefox": + case "ffheadless": + case "firefoxheadless": + WebDriverManager.getInstance(DriverManagerType.FIREFOX).setup(); + break; + case "ie": + case "internetexplorer": + WebDriverManager.getInstance(DriverManagerType.IEXPLORER).setup(); + break; + case "edge": + WebDriverManager.getInstance(DriverManagerType.EDGE).setup(); + break; + case "gc": + case "chrome": + case "googlechrome": + case "gcheadless": + case "chromeheadless": + case "googlechromeheadless": + WebDriverManager.getInstance(DriverManagerType.CHROME).setup(); + break; + default: + throw new SeleniumLibraryFatalException(browserName + " is not a supported browser for WebDriver Manager."); + } + } + protected WebDriver createRemoteWebDriver(Capabilities desiredCapabilities, URL remoteUrl) { HttpCommandExecutor httpCommandExecutor = new HttpCommandExecutor(remoteUrl); setRemoteWebDriverProxy(httpCommandExecutor); @@ -682,7 +723,7 @@ protected WebDriver createRemoteWebDriver(Capabilities desiredCapabilities, URL protected Capabilities createCapabilities(String browserName, String desiredCapabilitiesString, String browserOptions) { - Capabilities desiredCapabilities; + MutableCapabilities desiredCapabilities; switch (browserName.toLowerCase()) { case "ff": case "firefox": @@ -734,17 +775,16 @@ protected Capabilities createCapabilities(String browserName, String desiredCapa JSONObject jsonObject = (JSONObject) JSONValue.parse(desiredCapabilitiesString); if (jsonObject != null) { // Valid JSON - Iterator iterator = jsonObject.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry) iterator.next(); - ((MutableCapabilities) desiredCapabilities).setCapability(entry.getKey().toString(), entry.getValue()); + for (Object o : jsonObject.entrySet()) { + Entry entry = (Entry) o; + desiredCapabilities.setCapability(entry.getKey().toString(), entry.getValue()); } } else { // Invalid JSON. Old style key-value pairs for (String capability : desiredCapabilitiesString.split(",")) { String[] keyValue = capability.split(":"); if (keyValue.length == 2) { - ((MutableCapabilities) desiredCapabilities).setCapability(keyValue[0], keyValue[1]); + desiredCapabilities.setCapability(keyValue[0], keyValue[1]); } else { logging.warn("Invalid desiredCapabilities: " + desiredCapabilitiesString); } @@ -759,34 +799,34 @@ protected void parseBrowserOptionsChrome(String browserOptions, Capabilities des JSONObject jsonObject = (JSONObject) JSONValue.parse(browserOptions); if (jsonObject != null) { // Check all properties for translation to ChromeOptions - for (Iterator iterator = jsonObject.keySet().iterator(); iterator.hasNext(); ) { - String key = (String)iterator.next(); + for (Object o : jsonObject.keySet()) { + String key = (String) o; switch (key) { - case "args": { - // args is a list of strings - List args = new ArrayList<>(); - for (Object arg : (JSONArray)jsonObject.get(key)) { - args.add("--"+arg.toString().replace("--", "")); + case "args": { + // args is a list of strings + List args = new ArrayList<>(); + for (Object arg : (JSONArray) jsonObject.get(key)) { + args.add("--" + arg.toString().replace("--", "")); + } + ((ChromeOptions) desiredCapabilities).addArguments(args); + break; } - ((ChromeOptions) desiredCapabilities).addArguments(args); - break; - } - case "extensions": { - List extensions = new ArrayList<>(); - for (Object extension : (JSONArray)jsonObject.get(key)) { - extensions.add(new File(extension.toString().toString().replace('/', File.separatorChar))); + case "extensions": { + List extensions = new ArrayList<>(); + for (Object extension : (JSONArray) jsonObject.get(key)) { + extensions.add(new File(extension.toString().replace('/', File.separatorChar))); + } + ((ChromeOptions) desiredCapabilities).addExtensions(extensions); + break; } - ((ChromeOptions) desiredCapabilities).addExtensions(extensions); - break; - } - case "disable-extensions": - // change casing - ((ChromeOptions) desiredCapabilities).setExperimentalOption("useAutomationExtension", false); - break; - default: - // all unknonw properties are passed as is - ((ChromeOptions) desiredCapabilities).setExperimentalOption(key, jsonObject.get(key)); - break; + case "disable-extensions": + // change casing + ((ChromeOptions) desiredCapabilities).setExperimentalOption("useAutomationExtension", false); + break; + default: + // all unknonw properties are passed as is + ((ChromeOptions) desiredCapabilities).setExperimentalOption(key, jsonObject.get(key)); + break; } } } else { @@ -800,16 +840,14 @@ protected void parseBrowserOptionsFirefox(String browserOptions, Capabilities de JSONObject jsonObject = (JSONObject) JSONValue.parse(browserOptions); if (jsonObject != null) { FirefoxProfile firefoxProfile = new FirefoxProfile(); - Iterator iterator = jsonObject.entrySet().iterator(); - while (iterator.hasNext()) { - Entry entry = (Entry) iterator.next(); + for (Object o1 : jsonObject.entrySet()) { + Entry entry = (Entry) o1; String key = entry.getKey().toString(); if (key.equals("preferences")) { // Preferences JSONObject preferences = (JSONObject) entry.getValue(); - Iterator iteratorPreferences = preferences.entrySet().iterator(); - while (iteratorPreferences.hasNext()) { - Entry entryPreferences = (Entry) iteratorPreferences.next(); + for (Object o : preferences.entrySet()) { + Entry entryPreferences = (Entry) o; Object valuePreferences = entryPreferences.getValue(); logging.debug(String.format("Adding property: %s with value: %s", entryPreferences.getKey().toString(), valuePreferences)); @@ -818,7 +856,7 @@ protected void parseBrowserOptionsFirefox(String browserOptions, Capabilities de ((Number) valuePreferences).intValue()); } else if (valuePreferences instanceof Boolean) { firefoxProfile.setPreference(entryPreferences.getKey().toString(), - ((Boolean) valuePreferences).booleanValue()); + (Boolean) valuePreferences); } else { firefoxProfile.setPreference(entryPreferences.getKey().toString(), valuePreferences.toString()); @@ -827,9 +865,8 @@ protected void parseBrowserOptionsFirefox(String browserOptions, Capabilities de } else if (key.equals("extensions")) { // Extensions JSONArray extensions = (JSONArray) entry.getValue(); - Iterator iteratorExtensions = extensions.iterator(); - while (iteratorExtensions.hasNext()) { - File file = new File(iteratorExtensions.next().toString().replace('/', File.separatorChar)); + for (Object extension : extensions) { + File file = new File(extension.toString().replace('/', File.separatorChar)); firefoxProfile.addExtension(file); } } else { diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Cookie.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Cookie.java index cf11112..db21fc2 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Cookie.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Cookie.java @@ -1,13 +1,11 @@ package com.github.markusbernhardt.seleniumlibrary.keywords; -import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index cf33782..35907b0 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -15,7 +15,6 @@ import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; @@ -892,6 +891,27 @@ public void xpathShouldMatchXTimes(String xpath, int expectedXpathCount, String. logLevel); } + @RobotKeyword("Click to First Item from List Items by Locator.") + @ArgumentNames({"locator", "childLocator=NONE", "message=NONE"}) + public void clickToFirstItem(String locator, String... params) { + String child = robot.getParamsValue(params, 0, ""); + String message = robot.getParamsValue(params, 1, ""); + List elements = browserManagement.getCurrentWebDriver().findElements(By.xpath(locator)); + if (elements.size() == 0) { + if (message == null || message.equals("")) { + message = String.format("The Element was not found by locator '%s' and child locator '%s'.", + locator, child); + } + throw new SeleniumLibraryNonFatalException(message); + } + WebElement element = elements.get(0); + if (!child.isEmpty()) { + element.findElements(By.xpath(child)).get(0).click(); + } else { + element.click(); + } + } + // ############################## // Internal Methods // ############################## diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Logging.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Logging.java index 2ecead7..3047fba 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Logging.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Logging.java @@ -12,7 +12,6 @@ import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java index 818baa8..40023dd 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java @@ -5,7 +5,6 @@ import java.util.Map; import org.python.util.PythonInterpreter; -import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeywords; import com.google.gson.Gson; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Screenshot.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Screenshot.java index d2a4ac2..4645957 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Screenshot.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Screenshot.java @@ -11,7 +11,6 @@ import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/SelectElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/SelectElement.java index ae20fb4..43b2b8c 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/SelectElement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/SelectElement.java @@ -9,7 +9,6 @@ import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/TableElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/TableElement.java index 5d66441..507c3d6 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/TableElement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/TableElement.java @@ -7,7 +7,6 @@ import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Waiting.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Waiting.java index c5a44a2..06842e9 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Waiting.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Waiting.java @@ -5,7 +5,6 @@ import org.robotframework.javalib.annotation.ArgumentNames; import org.robotframework.javalib.annotation.Autowired; import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywordOverload; import org.robotframework.javalib.annotation.RobotKeywords; import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/locators/ElementFinder.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/locators/ElementFinder.java index d658248..2566cf0 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/locators/ElementFinder.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/locators/ElementFinder.java @@ -13,11 +13,9 @@ import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.python.util.PythonInterpreter; -import org.robotframework.javalib.annotation.Autowired; import com.github.markusbernhardt.seleniumlibrary.SeleniumLibraryNonFatalException; import com.github.markusbernhardt.seleniumlibrary.keywords.Element; -import com.github.markusbernhardt.seleniumlibrary.keywords.Logging; import com.github.markusbernhardt.seleniumlibrary.utils.Python; public class ElementFinder { From b14c678729f1a0e6eba9b2ad494f8bb961f26e8e Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Sat, 29 Jun 2019 13:19:05 +0300 Subject: [PATCH 02/19] clickToFirstItem method refactoring --- .../seleniumlibrary/keywords/Element.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index 35907b0..229d38d 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -880,7 +880,7 @@ public void xpathShouldMatchXTimes(String xpath, int expectedXpathCount, String. int actualXpathCount = elements.size(); if (actualXpathCount != expectedXpathCount) { - if (message == null || message.equals("")) { + if (message.isEmpty()) { message = String.format("Xpath %s should have matched %s times but matched %s times.", xpath, expectedXpathCount, actualXpathCount); } @@ -894,19 +894,19 @@ public void xpathShouldMatchXTimes(String xpath, int expectedXpathCount, String. @RobotKeyword("Click to First Item from List Items by Locator.") @ArgumentNames({"locator", "childLocator=NONE", "message=NONE"}) public void clickToFirstItem(String locator, String... params) { - String child = robot.getParamsValue(params, 0, ""); + String childLocator = robot.getParamsValue(params, 0, ""); String message = robot.getParamsValue(params, 1, ""); List elements = browserManagement.getCurrentWebDriver().findElements(By.xpath(locator)); - if (elements.size() == 0) { - if (message == null || message.equals("")) { + if (elements.isEmpty()) { + if (message.isEmpty()) { message = String.format("The Element was not found by locator '%s' and child locator '%s'.", - locator, child); + locator, childLocator); } throw new SeleniumLibraryNonFatalException(message); } WebElement element = elements.get(0); - if (!child.isEmpty()) { - element.findElements(By.xpath(child)).get(0).click(); + if (!childLocator.isEmpty()) { + element.findElements(By.xpath(childLocator)).get(0).click(); } else { element.click(); } From d7c69cc6659040ffe78a70fca9519f3efbc8f277 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Sun, 30 Jun 2019 00:09:39 +0300 Subject: [PATCH 03/19] added RobotString class for working with system properties and strings and created class for working with custom keywords of WebDriver --- .../CustomRobotDriverElement.java | 48 +++++++++++++++++++ .../seleniumlibrary/keywords/RobotString.java | 37 ++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java create mode 100644 src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java new file mode 100644 index 0000000..9072366 --- /dev/null +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java @@ -0,0 +1,48 @@ +package com.github.markusbernhardt.seleniumlibrary; + +import com.github.markusbernhardt.seleniumlibrary.keywords.BrowserManagement; +import com.github.markusbernhardt.seleniumlibrary.keywords.Robot; +import org.openqa.selenium.WebDriver; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.lang.reflect.Field; + +/** + * For extends of custom keywords of WebDriver actions + */ +public class CustomRobotDriverElement { + + private static SeleniumLibrary s; + private static BrowserManagement b; + private Robot robot = new Robot(); + + public CustomRobotDriverElement() throws NoSuchFieldException, IllegalAccessException { + try { + CustomRobotDriverElement.s = getLibraryInstance(); + } catch (javax.script.ScriptException e) { + e.printStackTrace(); + } + Field bmField = SeleniumLibrary.class.getDeclaredField("bm"); + bmField.setAccessible(true); + b = (BrowserManagement) bmField.get(s); + } + + private static SeleniumLibrary getLibraryInstance() throws ScriptException { + ScriptEngine engine = new ScriptEngineManager().getEngineByName("python"); + engine.put("library", "SeleniumLibrary"); + engine.eval("from robot.libraries.BuiltIn import BuiltIn"); + engine.eval("instance = BuiltIn().get_library_instance(library)"); + return (SeleniumLibrary) engine.get("instance"); + } + + protected static WebDriver getCurrentBrowser() { + return b.getCurrentWebDriver(); + } + + protected Robot getRobot() { + return robot; + } + +} diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java new file mode 100644 index 0000000..936da0c --- /dev/null +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java @@ -0,0 +1,37 @@ +package com.github.markusbernhardt.seleniumlibrary.keywords; + +import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; +import org.apache.commons.lang3.StringUtils; +import org.robotframework.javalib.annotation.ArgumentNames; +import org.robotframework.javalib.annotation.Autowired; +import org.robotframework.javalib.annotation.RobotKeyword; +import org.robotframework.javalib.annotation.RobotKeywords; + +@RobotKeywords +public class RobotString extends RunOnFailureKeywordsAdapter { + + /** + * Instantiated Logging keyword bean + */ + @Autowired + protected Logging logging; + + @RobotKeyword("Set System Property") + @ArgumentNames({"key", "value"}) + public void setSystemProperty(String key, String value) { + System.setProperty(key, value); + } + + @RobotKeyword("Get System Property") + @ArgumentNames({"key"}) + public String getSystemProperty(String key) { + return System.getProperty(key); + } + + @RobotKeyword("Is Contain String Ignore Case") + @ArgumentNames({"str", "searchStr"}) + public boolean isContainStringIgnoreCase(String str, String searchStr) { + logging.info(String.format("Is Contain String Ignore Case: Value - '%s'; String - '%s'", str, searchStr)); + return StringUtils.containsIgnoreCase(str, searchStr); + } +} From 562d59fc735e759a4487419dd87369ffc7fcfd09 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Mon, 1 Jul 2019 00:38:58 +0300 Subject: [PATCH 04/19] Added SeleniumLibraryNonFatalException to catch block in the CustomRobotDriverElement constr. --- .../seleniumlibrary/CustomRobotDriverElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java index 9072366..5136743 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java @@ -22,7 +22,7 @@ public CustomRobotDriverElement() throws NoSuchFieldException, IllegalAccessExce try { CustomRobotDriverElement.s = getLibraryInstance(); } catch (javax.script.ScriptException e) { - e.printStackTrace(); + throw new SeleniumLibraryNonFatalException("Cannot create SeleniumLibrary instance: " + e.getMessage()); } Field bmField = SeleniumLibrary.class.getDeclaredField("bm"); bmField.setAccessible(true); From 47c60dbefd094e90a445abb884a181ea38c8e3f3 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Mon, 1 Jul 2019 15:40:22 +0300 Subject: [PATCH 05/19] Corrected by review comments - updated constructor issues of CustomRobotDriverElement class --- .../seleniumlibrary/CustomRobotDriverElement.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java index 5136743..36f720d 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java @@ -2,6 +2,7 @@ import com.github.markusbernhardt.seleniumlibrary.keywords.BrowserManagement; import com.github.markusbernhardt.seleniumlibrary.keywords.Robot; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.openqa.selenium.WebDriver; import javax.script.ScriptEngine; @@ -21,12 +22,14 @@ public class CustomRobotDriverElement { public CustomRobotDriverElement() throws NoSuchFieldException, IllegalAccessException { try { CustomRobotDriverElement.s = getLibraryInstance(); - } catch (javax.script.ScriptException e) { - throw new SeleniumLibraryNonFatalException("Cannot create SeleniumLibrary instance: " + e.getMessage()); + } catch (ScriptException e) { + throw new SeleniumLibraryNonFatalException("Cannot create SeleniumLibrary instance: \n" + + ExceptionUtils.getStackTrace(e)); } Field bmField = SeleniumLibrary.class.getDeclaredField("bm"); bmField.setAccessible(true); b = (BrowserManagement) bmField.get(s); + bmField.setAccessible(false); } private static SeleniumLibrary getLibraryInstance() throws ScriptException { From 6b3b3ec5b035cc12ce2e5d465f979787d46c6456 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Mon, 1 Jul 2019 16:05:25 +0300 Subject: [PATCH 06/19] Corrected by review comments - updated constructor issues of CustomRobotDriverElement class --- .../seleniumlibrary/CustomRobotDriverElement.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java index 36f720d..6b54c6f 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java @@ -2,7 +2,6 @@ import com.github.markusbernhardt.seleniumlibrary.keywords.BrowserManagement; import com.github.markusbernhardt.seleniumlibrary.keywords.Robot; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.openqa.selenium.WebDriver; import javax.script.ScriptEngine; @@ -23,8 +22,7 @@ public CustomRobotDriverElement() throws NoSuchFieldException, IllegalAccessExce try { CustomRobotDriverElement.s = getLibraryInstance(); } catch (ScriptException e) { - throw new SeleniumLibraryNonFatalException("Cannot create SeleniumLibrary instance: \n" - + ExceptionUtils.getStackTrace(e)); + throw new SeleniumLibraryNonFatalException("Cannot create SeleniumLibrary instance.", e); } Field bmField = SeleniumLibrary.class.getDeclaredField("bm"); bmField.setAccessible(true); From 68e00e107caed4832b06bda9252a6cfda45d175f Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Mon, 1 Jul 2019 16:15:56 +0300 Subject: [PATCH 07/19] remover 'static' of getCurrentBrowser method --- .../seleniumlibrary/CustomRobotDriverElement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java index 6b54c6f..2f2d194 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/CustomRobotDriverElement.java @@ -38,7 +38,7 @@ private static SeleniumLibrary getLibraryInstance() throws ScriptException { return (SeleniumLibrary) engine.get("instance"); } - protected static WebDriver getCurrentBrowser() { + protected WebDriver getCurrentBrowser() { return b.getCurrentWebDriver(); } From 36eb5d8b2bb81332d0a725be44d433cd88684226 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Tue, 2 Jul 2019 23:29:01 +0300 Subject: [PATCH 08/19] Updated openBrowser method of BrowserManagement class and Robot class for working with boolean parameters --- .../keywords/BrowserManagement.java | 22 ++++++++++--------- .../seleniumlibrary/keywords/Robot.java | 2 ++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java index 4b9232e..f38c2ab 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java @@ -103,7 +103,7 @@ public class BrowserManagement extends RunOnFailureKeywordsAdapter { protected Element element; @Autowired - private Robot robot; + private Robot robot = new Robot(); // ############################## // Getter / Setter @@ -170,7 +170,9 @@ public void closeBrowser() { "| Iphone | iphone |\r\n" + "| JBrowser | jbrowser |\r\n" + "\r\n" + - "To be able to actually use one of these browsers, you need to have a matching Selenium browser driver available. See the [https://github.com/Hi-Fi/robotframework-seleniumlibrary-java#browser-drivers|project documentation] for more details.\r\n" + + "To be able to actually use one of these browsers, you need to have a matching Selenium browser driver available. See the [https://github.com/Hi-Fi/robotframework-seleniumlibrary-java#browser-drivers|project documentation] for more details.\r\n" + + "\r\n" + + "Optional ``isWebDriverManager`` is a flag of using automation download driver of browser and setting system variable for driver path.\r\n" + "\r\n" + "Optional ``alias`` is an alias given for this browser instance and it can be used for switching between browsers. An alternative approach for switching is using an index returned by this keyword. These indices start from 1, are incremented when new browsers are opened, and reset back to 1 when `Close All Browsers` is called. See `Switch Browser` for more information and examples.\r\n" + "\r\n" + @@ -184,17 +186,17 @@ public void closeBrowser() { "| `Open Browser` | http://example.com | Edge | remote_url=http://127.0.0.1:4444/wd/hub |\r\n" + "\r\n" + "If the provided configuration options are not enough, it is possible to use `Create Webdriver` to customize browser initialization even more.") - @ArgumentNames({ "url", "browserName=firefox", "alias=None", "remoteUrl=None", "desiredCapabilities=None", - "browserOptions=None", "webDriverManager=None" }) + @ArgumentNames({ "url", "browserName=firefox", "isWebDriverManager=false", "alias=None", "remoteUrl=None", + "desiredCapabilities=None", "browserOptions=None" }) public String openBrowser(String url, String... args) { String browserName = robot.getParamsValue(args, 0, "firefox"); - String alias = robot.getParamsValue(args, 1, "None"); - String remoteUrl = robot.getParamsValue(args, 2, "None"); - String desiredCapabilities = robot.getParamsValue(args, 3, "None"); - String browserOptions = robot.getParamsValue(args, 4, "None"); - String webDriverManager = robot.getParamsValue(args, 5, "None"); + boolean isWebDriverManager = robot.getParamsValue(args, 1, false); + String alias = robot.getParamsValue(args, 2, "None"); + String remoteUrl = robot.getParamsValue(args, 3, "None"); + String desiredCapabilities = robot.getParamsValue(args, 4, "None"); + String browserOptions = robot.getParamsValue(args, 5, "None"); - if (!webDriverManager.equals("None")) { + if (isWebDriverManager) { webDriverManagerSetup(browserName); } diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java index 40023dd..987be24 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Robot.java @@ -30,6 +30,8 @@ public T getParamsValue(String[] params, int index, T defaultValue) { value = (T) givenValue; } else if (defaultValue instanceof List) { value = (T) parseRobotList(givenValue); + } else if (Boolean.valueOf(givenValue)) { + value = (T) Boolean.valueOf(givenValue); } } return value; From fe5b8bb1d3fce3919c4e0b9f04b2e54083663a83 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Thu, 4 Jul 2019 22:58:03 +0300 Subject: [PATCH 09/19] Corrected by review comments --- .../keywords/BrowserManagement.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java index f38c2ab..21949d5 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/BrowserManagement.java @@ -103,7 +103,7 @@ public class BrowserManagement extends RunOnFailureKeywordsAdapter { protected Element element; @Autowired - private Robot robot = new Robot(); + private Robot robot; // ############################## // Getter / Setter @@ -171,14 +171,14 @@ public void closeBrowser() { "| JBrowser | jbrowser |\r\n" + "\r\n" + "To be able to actually use one of these browsers, you need to have a matching Selenium browser driver available. See the [https://github.com/Hi-Fi/robotframework-seleniumlibrary-java#browser-drivers|project documentation] for more details.\r\n" + - "\r\n" + - "Optional ``isWebDriverManager`` is a flag of using automation download driver of browser and setting system variable for driver path.\r\n" + "\r\n" + "Optional ``alias`` is an alias given for this browser instance and it can be used for switching between browsers. An alternative approach for switching is using an index returned by this keyword. These indices start from 1, are incremented when new browsers are opened, and reset back to 1 when `Close All Browsers` is called. See `Switch Browser` for more information and examples.\r\n" + "\r\n" + - "Optional ``remote_url`` is the URL for a remote Selenium server. If you specify a value for a remote, you can also specify ``desired_capabilities`` to configure, for example, a proxy server for Internet Explorer or a browser and operating system when using [http://saucelabs.com|Sauce Labs]. Desired capabilities can be given as a dictionary. [https://github.com/SeleniumHQ/selenium/wiki/Capabilities| Selenium documentation] lists possible capabilities that can be enabled.\r\n" + + "Optional ``remote_url`` is the URL for a remote Selenium server. If you specify a value for a remote, you can also specify ``desired_capabilities`` to configure, for example, a proxy server for Internet Explorer or a browser and operating system when using [http://saucelabs.com|Sauce Labs]. Desired capabilities can be given as a dictionary. [https://github.com/SeleniumHQ/selenium/wiki/Capabilities| Selenium documentation] lists possible capabilities that can be enabled.\r\n" + "\r\n" + - "Optional ``ff_profile_dir`` is the path to the Firefox profile directory if you wish to overwrite the default profile Selenium uses. Notice that prior to SeleniumLibrary 3.0, the library contained its own profile that was used by default.\r\n" + + "Optional ``ff_profile_dir`` is the path to the Firefox profile directory if you wish to overwrite the default profile Selenium uses. Notice that prior to SeleniumLibrary 3.0, the library contained its own profile that was used by default.\r\n" + + "\r\n" + + "Optional ``isWebDriverManager`` is a flag of using automation download driver of browser and setting system variable for driver path.\r\n" + "\r\n" + "Examples:\r\n" + "| `Open Browser` | http://example.com | Chrome |\r\n" + @@ -186,15 +186,15 @@ public void closeBrowser() { "| `Open Browser` | http://example.com | Edge | remote_url=http://127.0.0.1:4444/wd/hub |\r\n" + "\r\n" + "If the provided configuration options are not enough, it is possible to use `Create Webdriver` to customize browser initialization even more.") - @ArgumentNames({ "url", "browserName=firefox", "isWebDriverManager=false", "alias=None", "remoteUrl=None", - "desiredCapabilities=None", "browserOptions=None" }) + @ArgumentNames({ "url", "browserName=firefox", "alias=None", "remoteUrl=None", "desiredCapabilities=None", + "browserOptions=None", "isWebDriverManager=false" }) public String openBrowser(String url, String... args) { String browserName = robot.getParamsValue(args, 0, "firefox"); - boolean isWebDriverManager = robot.getParamsValue(args, 1, false); - String alias = robot.getParamsValue(args, 2, "None"); - String remoteUrl = robot.getParamsValue(args, 3, "None"); - String desiredCapabilities = robot.getParamsValue(args, 4, "None"); - String browserOptions = robot.getParamsValue(args, 5, "None"); + String alias = robot.getParamsValue(args, 1, "None"); + String remoteUrl = robot.getParamsValue(args, 2, "None"); + String desiredCapabilities = robot.getParamsValue(args, 3, "None"); + String browserOptions = robot.getParamsValue(args, 4, "None"); + boolean isWebDriverManager = robot.getParamsValue(args, 5, false); if (isWebDriverManager) { webDriverManagerSetup(browserName); From 5cc545db43bb9455a60d4080e3cb526a89fcbfdc Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Thu, 4 Jul 2019 23:19:22 +0300 Subject: [PATCH 10/19] Removed RobotString class --- .../seleniumlibrary/keywords/RobotString.java | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java deleted file mode 100644 index 936da0c..0000000 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/RobotString.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.github.markusbernhardt.seleniumlibrary.keywords; - -import com.github.markusbernhardt.seleniumlibrary.RunOnFailureKeywordsAdapter; -import org.apache.commons.lang3.StringUtils; -import org.robotframework.javalib.annotation.ArgumentNames; -import org.robotframework.javalib.annotation.Autowired; -import org.robotframework.javalib.annotation.RobotKeyword; -import org.robotframework.javalib.annotation.RobotKeywords; - -@RobotKeywords -public class RobotString extends RunOnFailureKeywordsAdapter { - - /** - * Instantiated Logging keyword bean - */ - @Autowired - protected Logging logging; - - @RobotKeyword("Set System Property") - @ArgumentNames({"key", "value"}) - public void setSystemProperty(String key, String value) { - System.setProperty(key, value); - } - - @RobotKeyword("Get System Property") - @ArgumentNames({"key"}) - public String getSystemProperty(String key) { - return System.getProperty(key); - } - - @RobotKeyword("Is Contain String Ignore Case") - @ArgumentNames({"str", "searchStr"}) - public boolean isContainStringIgnoreCase(String str, String searchStr) { - logging.info(String.format("Is Contain String Ignore Case: Value - '%s'; String - '%s'", str, searchStr)); - return StringUtils.containsIgnoreCase(str, searchStr); - } -} From 38b2a5dcd30bdf5dfe33eb027b54c3bd2642daf5 Mon Sep 17 00:00:00 2001 From: YauheniPo Date: Sat, 6 Jul 2019 13:43:07 +0300 Subject: [PATCH 11/19] Updated clickToFirstItem to clickElementByIndex method --- .../seleniumlibrary/keywords/Element.java | 35 ++++++++----------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index 229d38d..706c841 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -891,26 +891,21 @@ public void xpathShouldMatchXTimes(String xpath, int expectedXpathCount, String. logLevel); } - @RobotKeyword("Click to First Item from List Items by Locator.") - @ArgumentNames({"locator", "childLocator=NONE", "message=NONE"}) - public void clickToFirstItem(String locator, String... params) { - String childLocator = robot.getParamsValue(params, 0, ""); - String message = robot.getParamsValue(params, 1, ""); - List elements = browserManagement.getCurrentWebDriver().findElements(By.xpath(locator)); - if (elements.isEmpty()) { - if (message.isEmpty()) { - message = String.format("The Element was not found by locator '%s' and child locator '%s'.", - locator, childLocator); - } - throw new SeleniumLibraryNonFatalException(message); - } - WebElement element = elements.get(0); - if (!childLocator.isEmpty()) { - element.findElements(By.xpath(childLocator)).get(0).click(); - } else { - element.click(); - } - } + @RobotKeyword("Click to element from list elements by locator ``xpath``.") + @ArgumentNames({"xpath", "index=0", "message=NONE"}) + public void clickElementByIndex(String xpath, String... params) { + String message = robot.getParamsValue(params, 0, ""); + int index = robot.getParamsValue(params, 1, 0); + List elements = elementFind(xpath, false, false); + if (elements.isEmpty()) { + if (message.isEmpty()) { + message = String.format("The Element was not found by locator '%s' with index '%d'", xpath, index); + } + throw new SeleniumLibraryNonFatalException(message); + } + WebElement element = elements.get(index); + element.click(); + } // ############################## // Internal Methods From 7012222837546382d70806d3e8c7975000b99250 Mon Sep 17 00:00:00 2001 From: ractoc Date: Mon, 15 Jul 2019 08:57:07 +0200 Subject: [PATCH 12/19] updated the elementShouldContain, elementShouldNotContain, elementTextShouldBe and elementText ShouldNotBe to support either case sensitive or case insensitive operation. This is in line with recent changes to the Python version of the selenium library. Unfortunately, along the way, the indentation has been changed from tabs to all spaces. --- .../seleniumlibrary/keywords/Element.java | 1927 +++++++++-------- 1 file changed, 973 insertions(+), 954 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index 706c841..d120aeb 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -5,6 +5,7 @@ import java.util.Iterator; import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.JavascriptExecutor; @@ -25,367 +26,373 @@ @RobotKeywords public class Element extends RunOnFailureKeywordsAdapter { - /** - * Instantiated BrowserManagement keyword bean - */ - @Autowired - protected BrowserManagement browserManagement; - - /** - * Instantiated FormElement keyword bean - */ - @Autowired - protected FormElement formElement; - - /** - * Instantiated Logging keyword bean - */ - @Autowired - protected Logging logging; - - @Autowired - protected Robot robot; - - // ############################## - // Keywords - Element Lookups - // ############################## - - @RobotKeyword("Verify the current frame contains ``text``.\n\r" - + "\n\r" - + "See `Introduction` for details about log levels.") - @ArgumentNames({ "text", "logLevel=INFO" }) - public void currentFrameContains(String text, String...params) { - String logLevel = robot.getParamsValue(params, 0, "INFO"); - if (!isTextPresent(text)) { - logging.log(String.format("Current Frame Contains: %s => FAILED", text), logLevel); - throw new SeleniumLibraryNonFatalException( - String.format("Page should have contained text '%s', but did not.", text)); - } else { - logging.log(String.format("Current Frame Contains: %s => OK", text), logLevel); - } - } + /** + * Instantiated BrowserManagement keyword bean + */ + @Autowired + protected BrowserManagement browserManagement; + + /** + * Instantiated FormElement keyword bean + */ + @Autowired + protected FormElement formElement; + + /** + * Instantiated Logging keyword bean + */ + @Autowired + protected Logging logging; + + @Autowired + protected Robot robot; + + // ############################## + // Keywords - Element Lookups + // ############################## + + @RobotKeyword("Verify the current frame contains ``text``.\n\r" + + "\n\r" + + "See `Introduction` for details about log levels.") + @ArgumentNames({ "text", "logLevel=INFO" }) + public void currentFrameContains(String text, String...params) { + String logLevel = robot.getParamsValue(params, 0, "INFO"); + if (!isTextPresent(text)) { + logging.log(String.format("Current Frame Contains: %s => FAILED", text), logLevel); + throw new SeleniumLibraryNonFatalException( + String.format("Page should have contained text '%s', but did not.", text)); + } else { + logging.log(String.format("Current Frame Contains: %s => OK", text), logLevel); + } + } @RobotKeyword("Verify the current frame does not contain ``text``.\n\r" + "\n\r" + "See `Introduction` for details about log levels.") - @ArgumentNames({ "text", "logLevel=INFO" }) - public void currentFrameShouldNotContain(String text, String...params) { - String logLevel = robot.getParamsValue(params, 0, "INFO"); - if (isTextPresent(text)) { - logging.log(String.format("Current Frame Should Not Contain: %s => FAILED", text), logLevel); - throw new SeleniumLibraryNonFatalException( - String.format("Page should have not contained text '%s', but did.", text)); - } else { - logging.log(String.format("Current Frame Should Not Contain: %s => OK", text), logLevel); - } - } - - @RobotKeyword("Verify the element identified by ``locator`` contains ``text``.\n\r" - + "\n\r" - + "See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "text", "message=NONE" }) - public void elementShouldContain(String locator, String text, String...params) { - String message = robot.getParamsValue(params, 0, ""); - String actual = getText(locator); - - if (!actual.toLowerCase().contains(text.toLowerCase())) { - logging.info(String.format("Element Should Contain: %s => FAILED", text)); - throw new SeleniumLibraryNonFatalException( - String.format("Element should have contained text '%s', but its text was %s.", text, actual)); - } else { - logging.info(String.format("Element Should Contain: %s => OK", text)); - } - } - - @RobotKeyword("Verify the element identified by ``locator`` does not contain ``text``.\r\n" - + "\r\n" - + "See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "text", "message=NONE" }) - public void elementShouldNotContain(String locator, String text, String...params) { - String message = robot.getParamsValue(params, 0, ""); - String actual = getText(locator); - - if (actual.toLowerCase().contains(text.toLowerCase())) { - logging.info(String.format("Element Should Not Contain: %s => FAILED", text)); - throw new SeleniumLibraryNonFatalException( - String.format("Element should not have contained text '%s', but its text was %s.", text, actual)); - } else { - logging.info(String.format("Element Should Not Contain: %s => OK", text)); - } - } - - @RobotKeyword("Verify the frame identified by ``locator`` contains ``text``.\n\r" - + "\n\r" - + "See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "text", "logLevel=INFO" }) - public void frameShouldContain(String locator, String text, String...params) { - String logLevel = robot.getParamsValue(params, 0, "INFO"); - if (!frameContains(locator, text)) { - logging.log(String.format("Frame Should Contain: %s => FAILED", text), logLevel); - throw new SeleniumLibraryNonFatalException( - String.format("Frame should have contained text '%s', but did not.", text)); - } else { - logging.log(String.format("Frame Should Contain: %s => OK", text), logLevel); - } - } - - @RobotKeyword("Verify the frame identified by ``locator`` does not contain ``text``.\n\r" - + "\n\r" - + "See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "text", "logLevel=INFO" }) - public void frameShouldNotContain(String locator, String text, String...params) { + @ArgumentNames({ "text", "logLevel=INFO" }) + public void currentFrameShouldNotContain(String text, String...params) { String logLevel = robot.getParamsValue(params, 0, "INFO"); - if (frameContains(locator, text)) { - logging.log(String.format("Frame Should Not Contain: %s => FAILED", text), logLevel); - throw new SeleniumLibraryNonFatalException( - String.format("Frame should not have contained text '%s', but did.", text)); - } else { - logging.log(String.format("Frame Should Not Contain: %s => OK", text), logLevel); - } - } - - @RobotKeyword("Verify the current page contains ``text``.\n\r" - + "\n\r" - + "See `Introduction` for details about log levels.") - @ArgumentNames({ "text", "logLevel=INFO" }) - public void pageShouldContain(String text, String...params) { + if (isTextPresent(text)) { + logging.log(String.format("Current Frame Should Not Contain: %s => FAILED", text), logLevel); + throw new SeleniumLibraryNonFatalException( + String.format("Page should have not contained text '%s', but did.", text)); + } else { + logging.log(String.format("Current Frame Should Not Contain: %s => OK", text), logLevel); + } + } + + @RobotKeyword("Verify the element identified by ``locator`` contains ``text``.\n\r" + + "\n\r" + + "See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "text", "message=NONE", "ignore_case=False" }) + public void elementShouldContain(String locator, String text, String...params) { + String message = robot.getParamsValue(params, 0, StringUtils.EMPTY); + Boolean ignoreCase = robot.getParamsValue(params, 1, Boolean.FALSE); + String actual = getText(locator); + + if (!textContains(actual, text, ignoreCase)) { + if (StringUtils.isEmpty(message)) { + message = String.format("Element should have contained text '%s', but its text was %s.", text, actual); + } + logging.info(String.format("Element Should Contain: %s => FAILED", text)); + throw new SeleniumLibraryNonFatalException(message); + } else { + logging.info(String.format("Element Should Contain: %s => OK", text)); + } + } + + @RobotKeyword("Verify the element identified by ``locator`` does not contain ``text``.\r\n" + + "\r\n" + + "See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "text", "message=NONE", "ignore_case=False" }) + public void elementShouldNotContain(String locator, String text, String...params) { + String message = robot.getParamsValue(params, 0, StringUtils.EMPTY); + Boolean ignoreCase = robot.getParamsValue(params, 1, Boolean.FALSE); + String actual = getText(locator); + + if (textContains(actual, text, ignoreCase)) { + if (StringUtils.isEmpty(message)) { + message = String.format("Element should not have contained text '%s', but its text was %s.", text, actual); + } + logging.info(String.format("Element Should Not Contain: %s => FAILED", text)); + throw new SeleniumLibraryNonFatalException(message); + } else { + logging.info(String.format("Element Should Not Contain: %s => OK", text)); + } + } + + @RobotKeyword("Verify the frame identified by ``locator`` contains ``text``.\n\r" + + "\n\r" + + "See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "text", "logLevel=INFO" }) + public void frameShouldContain(String locator, String text, String...params) { String logLevel = robot.getParamsValue(params, 0, "INFO"); - if (!pageContains(text)) { - logging.log(String.format("Page Should Contain: %s => FAILED", text), logLevel); - throw new SeleniumLibraryNonFatalException( - String.format("Page should have contained text '%s' but did not.", text)); - } else { - logging.log(String.format("Page Should Contain: %s => OK", text), logLevel); - } - } - - @RobotKeyword("Verify the current page does not contain ``text``.\n\r" - + "\n\r" - + "See `Introduction` for details about log levels.") - @ArgumentNames({ "text", "logLevel=INFO" }) - public void pageShouldNotContain(String text, String...params) { + if (!frameContains(locator, text)) { + logging.log(String.format("Frame Should Contain: %s => FAILED", text), logLevel); + throw new SeleniumLibraryNonFatalException( + String.format("Frame should have contained text '%s', but did not.", text)); + } else { + logging.log(String.format("Frame Should Contain: %s => OK", text), logLevel); + } + } + + @RobotKeyword("Verify the frame identified by ``locator`` does not contain ``text``.\n\r" + + "\n\r" + + "See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "text", "logLevel=INFO" }) + public void frameShouldNotContain(String locator, String text, String...params) { String logLevel = robot.getParamsValue(params, 0, "INFO"); - if (pageContains(text)) { - logging.log(String.format("Page Should Not Contain: %s => FAILED", text), logLevel); - throw new SeleniumLibraryNonFatalException( - String.format("Page should not have contained text '%s' but did.", text)); - } else { - logging.log(String.format("Page Should Not Contain: %s => OK", text), logLevel); - } - } - - @RobotKeyword("Verify the element identified by ``locator`` is found on the current page\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) - public void pageShouldContainElement(String locator, String...params) { - String message = robot.getParamsValue(params, 0, ""); - String logLevel = robot.getParamsValue(params, 1, "INFO"); - pageShouldContainElement(locator, null, message, logLevel); - } - - protected void pageShouldContainElement(String locator, String tag, String message, String logLevel) { - String name = tag != null ? tag : "element"; - if (!isElementPresent(locator, tag)) { - if (message == null || message.equals("")) { - message = String.format("Page should have contained %s '%s' but did not", name, locator); - } - logging.log(message, logLevel); - throw new SeleniumLibraryNonFatalException(message); - } else { - logging.log(String.format("Current page contains %s '%s'.", name, locator), logLevel); - } - } + if (frameContains(locator, text)) { + logging.log(String.format("Frame Should Not Contain: %s => FAILED", text), logLevel); + throw new SeleniumLibraryNonFatalException( + String.format("Frame should not have contained text '%s', but did.", text)); + } else { + logging.log(String.format("Frame Should Not Contain: %s => OK", text), logLevel); + } + } + + @RobotKeyword("Verify the current page contains ``text``.\n\r" + + "\n\r" + + "See `Introduction` for details about log levels.") + @ArgumentNames({ "text", "logLevel=INFO" }) + public void pageShouldContain(String text, String...params) { + String logLevel = robot.getParamsValue(params, 0, "INFO"); + if (!pageContains(text)) { + logging.log(String.format("Page Should Contain: %s => FAILED", text), logLevel); + throw new SeleniumLibraryNonFatalException( + String.format("Page should have contained text '%s' but did not.", text)); + } else { + logging.log(String.format("Page Should Contain: %s => OK", text), logLevel); + } + } + + @RobotKeyword("Verify the current page does not contain ``text``.\n\r" + + "\n\r" + + "See `Introduction` for details about log levels.") + @ArgumentNames({ "text", "logLevel=INFO" }) + public void pageShouldNotContain(String text, String...params) { + String logLevel = robot.getParamsValue(params, 0, "INFO"); + if (pageContains(text)) { + logging.log(String.format("Page Should Not Contain: %s => FAILED", text), logLevel); + throw new SeleniumLibraryNonFatalException( + String.format("Page should not have contained text '%s' but did.", text)); + } else { + logging.log(String.format("Page Should Not Contain: %s => OK", text), logLevel); + } + } + + @RobotKeyword("Verify the element identified by ``locator`` is found on the current page\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about log levels and locators.") + @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) + public void pageShouldContainElement(String locator, String...params) { + String message = robot.getParamsValue(params, 0, ""); + String logLevel = robot.getParamsValue(params, 1, "INFO"); + pageShouldContainElement(locator, null, message, logLevel); + } + + protected void pageShouldContainElement(String locator, String tag, String message, String logLevel) { + String name = tag != null ? tag : "element"; + if (!isElementPresent(locator, tag)) { + if (message == null || message.equals("")) { + message = String.format("Page should have contained %s '%s' but did not", name, locator); + } + logging.log(message, logLevel); + throw new SeleniumLibraryNonFatalException(message); + } else { + logging.log(String.format("Current page contains %s '%s'.", name, locator), logLevel); + } + } @RobotKeyword("Verify the element identified by ``locator`` is not found on the current page\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) - public void pageShouldNotContainElement(String locator, String...params) { + @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) + public void pageShouldNotContainElement(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); String logLevel = robot.getParamsValue(params, 1, "INFO"); - pageShouldNotContainElement(locator, null, message, logLevel); - } - - protected void pageShouldNotContainElement(String locator, String tag, String message, String logLevel) { - String name = tag != null ? tag : "element"; - if (isElementPresent(locator, tag)) { - if (message == null || message.equals("")) { - message = String.format("Page should not have contained %s '%s' but did", name, locator); - } - logging.log(message, logLevel); - throw new SeleniumLibraryNonFatalException(message); - } else { - logging.log(String.format("Current page does not contain %s '%s'.", name, locator), logLevel); - } - } - - // ############################## - // Keywords - Attributes - // ############################## - - @RobotKeyword("Assigns a temporary identifier to the element identified by ``locator``.\r\n" + - "\r\n" + - "This is mainly useful, when the locator is a complicated and slow XPath expression. The identifier expires when the page is reloaded.\r\n" + - "\r\n" + - "Example:\r\n" + - " | Assign ID to Element | xpath://div[@id=\\\"first_div\\\"] | my id | \r\n" + - " | Page Should Contain Element | my id |") - @ArgumentNames({ "locator", "id" }) - public void assignIdToElement(String locator, String id) { - logging.info(String.format("Assigning temporary id '%s' to element '%s'", id, locator)); - List elements = elementFind(locator, true, true); - - ((JavascriptExecutor) browserManagement.getCurrentWebDriver()) - .executeScript(String.format("arguments[0].id = '%s';", id), elements.get(0)); - } + pageShouldNotContainElement(locator, null, message, logLevel); + } + + protected void pageShouldNotContainElement(String locator, String tag, String message, String logLevel) { + String name = tag != null ? tag : "element"; + if (isElementPresent(locator, tag)) { + if (message == null || message.equals("")) { + message = String.format("Page should not have contained %s '%s' but did", name, locator); + } + logging.log(message, logLevel); + throw new SeleniumLibraryNonFatalException(message); + } else { + logging.log(String.format("Current page does not contain %s '%s'.", name, locator), logLevel); + } + } + + // ############################## + // Keywords - Attributes + // ############################## + + @RobotKeyword("Assigns a temporary identifier to the element identified by ``locator``.\r\n" + + "\r\n" + + "This is mainly useful, when the locator is a complicated and slow XPath expression. The identifier expires when the page is reloaded.\r\n" + + "\r\n" + + "Example:\r\n" + + " | Assign ID to Element | xpath://div[@id=\\\"first_div\\\"] | my id | \r\n" + + " | Page Should Contain Element | my id |") + @ArgumentNames({ "locator", "id" }) + public void assignIdToElement(String locator, String id) { + logging.info(String.format("Assigning temporary id '%s' to element '%s'", id, locator)); + List elements = elementFind(locator, true, true); + + ((JavascriptExecutor) browserManagement.getCurrentWebDriver()) + .executeScript(String.format("arguments[0].id = '%s';", id), elements.get(0)); + } @RobotKeyword("Verify the element identified by ``locator`` is found on the current page\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator" }) - public void elementShouldBeEnabled(String locator) { - if (!isEnabled(locator)) { - throw new SeleniumLibraryNonFatalException(String.format("Element %s is disabled.", locator)); - } - } + @ArgumentNames({ "locator" }) + public void elementShouldBeEnabled(String locator) { + if (!isEnabled(locator)) { + throw new SeleniumLibraryNonFatalException(String.format("Element %s is disabled.", locator)); + } + } @RobotKeyword("Verify the element identified by ``locator`` is disabled.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void elementShouldBeDisabled(String locator) { - if (isEnabled(locator)) { - throw new SeleniumLibraryNonFatalException(String.format("Element %s is enabled.", locator)); - } - } - - @RobotKeyword("Verify the element identified by ``locator`` is selected.\r\n" + + @ArgumentNames({ "locator" }) + public void elementShouldBeDisabled(String locator) { + if (isEnabled(locator)) { + throw new SeleniumLibraryNonFatalException(String.format("Element %s is enabled.", locator)); + } + } + + @RobotKeyword("Verify the element identified by ``locator`` is selected.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "message=NONE" }) - public void elementShouldBeSelected(String locator, String...params) { + @ArgumentNames({ "locator", "message=NONE" }) + public void elementShouldBeSelected(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); - logging.info(String.format("Verifying element '%s' is selected.", locator)); - boolean selected = isSelected(locator); - - if (!selected) { - if (message == null || message.equals("")) { - message = String.format("Element '%s' should be selected, but it is not.", locator); - } - throw new SeleniumLibraryNonFatalException(message); - } - } - - @RobotKeyword("Verify the element identified by ``locator`` is not selected.\r\n" + + logging.info(String.format("Verifying element '%s' is selected.", locator)); + boolean selected = isSelected(locator); + + if (!selected) { + if (message == null || message.equals("")) { + message = String.format("Element '%s' should be selected, but it is not.", locator); + } + throw new SeleniumLibraryNonFatalException(message); + } + } + + @RobotKeyword("Verify the element identified by ``locator`` is not selected.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "message=NONE" }) - public void elementShouldNotBeSelected(String locator, String...params) { + @ArgumentNames({ "locator", "message=NONE" }) + public void elementShouldNotBeSelected(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); - logging.info(String.format("Verifying element '%s' is not selected.", locator)); - boolean selected = isSelected(locator); - - if (selected) { - if (message == null || message.equals("")) { - message = String.format("Element '%s' should not be selected, but it is.", locator); - } - throw new SeleniumLibraryNonFatalException(message); - } - } - - @RobotKeyword("Verify the element identified by ``locator`` is visible.\r\n" + - "\r\n" + - "Herein, visible means that the element is logically visible, not optically visible in the current browser viewport. For example, an element that carries display:none is not logically visible, so using this keyword on that element would fail.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "message=NONE" }) - public void elementShouldBeVisible(String locator, String...params) { + logging.info(String.format("Verifying element '%s' is not selected.", locator)); + boolean selected = isSelected(locator); + + if (selected) { + if (message == null || message.equals("")) { + message = String.format("Element '%s' should not be selected, but it is.", locator); + } + throw new SeleniumLibraryNonFatalException(message); + } + } + + @RobotKeyword("Verify the element identified by ``locator`` is visible.\r\n" + + "\r\n" + + "Herein, visible means that the element is logically visible, not optically visible in the current browser viewport. For example, an element that carries display:none is not logically visible, so using this keyword on that element would fail.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "message=NONE" }) + public void elementShouldBeVisible(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); - logging.info(String.format("Verifying element '%s' is visible.", locator)); - boolean visible = isVisible(locator); + logging.info(String.format("Verifying element '%s' is visible.", locator)); + boolean visible = isVisible(locator); - if (!visible) { - if (message == null || message.equals("")) { - message = String.format("Element '%s' should be visible, but it is not.", locator); - } - throw new SeleniumLibraryNonFatalException(message); - } - } + if (!visible) { + if (message == null || message.equals("")) { + message = String.format("Element '%s' should be visible, but it is not.", locator); + } + throw new SeleniumLibraryNonFatalException(message); + } + } @RobotKeyword("Verify the element identified by ``locator`` is not visible.\r\n" + "\r\n" + "Herein, visible means that the element is logically visible, not optically visible in the current browser viewport. For example, an element that carries display:none is not logically visible, so using this keyword on that element would fail.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "message=NONE" }) - public void elementShouldNotBeVisible(String locator, String...params) { + @ArgumentNames({ "locator", "message=NONE" }) + public void elementShouldNotBeVisible(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); - logging.info(String.format("Verifying element '%s' is not visible.", locator)); - boolean visible = isVisible(locator); + logging.info(String.format("Verifying element '%s' is not visible.", locator)); + boolean visible = isVisible(locator); - if (visible) { - if (message == null || message.equals("")) { - message = String.format("Element '%s' should not be visible, but it is.", locator); - } - throw new SeleniumLibraryNonFatalException(message); - } - } + if (visible) { + if (message == null || message.equals("")) { + message = String.format("Element '%s' should not be visible, but it is.", locator); + } + throw new SeleniumLibraryNonFatalException(message); + } + } @RobotKeyword("Verify the element identified by ``locator`` is clickable.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "message=NONE" }) - public void elementShouldBeClickable(String locator, String...params) { + @ArgumentNames({ "locator", "message=NONE" }) + public void elementShouldBeClickable(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); - logging.info(String.format("Verifying element '%s' is clickable.", locator)); - boolean clickable = isClickable(locator); + logging.info(String.format("Verifying element '%s' is clickable.", locator)); + boolean clickable = isClickable(locator); - if (!clickable) { - if (message == null || message.equals("")) { - message = String.format("Element '%s' should be clickable, but it is not.", locator); - } - throw new SeleniumLibraryNonFatalException(message); - } - } + if (!clickable) { + if (message == null || message.equals("")) { + message = String.format("Element '%s' should be clickable, but it is not.", locator); + } + throw new SeleniumLibraryNonFatalException(message); + } + } @RobotKeyword("Verify the element identified by ``locator`` is not clickable.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "message=NONE" }) - public void elementShouldNotBeClickable(String locator, String...params) { + @ArgumentNames({ "locator", "message=NONE" }) + public void elementShouldNotBeClickable(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); - logging.info(String.format("Verifying element '%s' is not clickable.", locator)); - boolean clickable = isClickable(locator); - - if (clickable) { - if (message == null || message.equals("")) { - message = String.format("Element '%s' should not be clickable, but it is.", locator); - } - throw new SeleniumLibraryNonFatalException(message); - } - } - - @RobotKeyword("Verify the text of the element identified by ``locator`` is exactly ``text``.\r\n" + - "\r\n" + - "In contrast to `Element Should Contain`, this keyword does not try a substring match but an exact match on the element identified by locator.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "text", "message=NONE" }) - public void elementTextShouldBe(String locator, String text, String...params) { + logging.info(String.format("Verifying element '%s' is not clickable.", locator)); + boolean clickable = isClickable(locator); + + if (clickable) { + if (message == null || message.equals("")) { + message = String.format("Element '%s' should not be clickable, but it is.", locator); + } + throw new SeleniumLibraryNonFatalException(message); + } + } + + @RobotKeyword("Verify the text of the element identified by ``locator`` is exactly ``text``.\r\n" + + "\r\n" + + "In contrast to `Element Should Contain`, this keyword does not try a substring match but an exact match on the element identified by locator.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "text", "message=NONE", "ignore_case=False" }) + public void elementTextShouldBe(String locator, String text, String...params) { String message = robot.getParamsValue(params, 0, ""); - List elements = elementFind(locator, true, true); - String actual = elements.get(0).getText(); - - if (!text.equals(actual)) { - if (message == null || message.equals("")) { - message = String.format("The text of element '%s' should have been '%s', but it was '%s'.", locator, - text, actual); - } - throw new SeleniumLibraryNonFatalException(message); - } - } + Boolean ignoreCase = robot.getParamsValue(params, 1, Boolean.FALSE); + List elements = elementFind(locator, true, true); + String actual = elements.get(0).getText(); + if (!textIs(actual, text, ignoreCase)) { + if (StringUtils.isEmpty(message)) { + message = String.format("The text of element '%s' should have been '%s', but it was '%s'.", locator, + text, actual); + } + throw new SeleniumLibraryNonFatalException(message); + } + } @RobotKeyword("Verify the text of the element identified by ``locator`` is not exactly ``text``.\r\n" + @@ -393,707 +400,719 @@ public void elementTextShouldBe(String locator, String text, String...params) { "In contrast to `Element Should Not Contain`, this keyword does not try a substring match but an exact match on the element identified by locator.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "text", "message=NONE" }) - public void elementTextShouldNotBe(String locator, String text, String...params) { + @ArgumentNames({ "locator", "text", "message=NONE", "ignore_case=False" }) + public void elementTextShouldNotBe(String locator, String text, String...params) { String message = robot.getParamsValue(params, 0, ""); - List elements = elementFind(locator, true, true); - String actual = elements.get(0).getText(); - - if (text.equals(actual)) { - if (message == null || message.equals("")) { - message = String.format("The text of element '%s' should have been '%s', but it was '%s'.", locator, - text, actual); - } - throw new SeleniumLibraryNonFatalException(message); - } - } - - @RobotKeyword("Returns the value of an element attribute.\r\n" + - "\r\n" + - "The ``attribute_locator`` consists of element locator followed by an @ sign and attribute name. Example: element_id@class\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "attributeLocator" }) - public String getElementAttribute(String attributeLocator) { - String[] parts = parseAttributeLocator(attributeLocator); - - List elements = elementFind(parts[0], true, false); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("Element '%s' not found.", parts[0])); - } - - return elements.get(0).getAttribute(parts[1]); - } - - @RobotKeyword("Clears the text from element identified by ``locator``.\r\n" + - "\r\n" + - "This keyword does not execute any checks on whether or not the clear method has succeeded, so if any subsequent checks are needed, they should be executed using method `Element Text Should Be`.\r\n" + - "\r\n" + - "Also, this method will use WebDriver's internal _element.clear()_ method, i.e. it will not send any keypresses, and it will not have any effect whatsoever on elements other than input textfields or input textareas. Clients relying on keypresses should implement their own methods.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void clearElementText(String locator) { - List elements = elementFind(locator, true, true); - - elements.get(0).clear(); - } - - @RobotKeyword("Returns inner element id by index```` of element identified by ``locator`` which is matched by ``matchid``.\r\n" - + "\r\n" - + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "matchid", "index" }) - public String getInnerElementId(String locator, String matchid, int index) { - List elements = elementFind(locator, true, true); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("get Inner element '%s' not found.", locator)); - } - - String xpathId = ".//*[contains(@id," + matchid + ")]"; - - List tmpe = elements.get(0).findElements((By.xpath(xpathId))); - if (tmpe.size() == 0) { - throw new SeleniumLibraryNonFatalException( - String.format("No Inner element '%s' not found by '%s'", locator, matchid)); - } - String eId = tmpe.get(index).getAttribute("id"); - - logging.info(String.format("Found element ID: '%s'.", eId)); - - return eId; - - } - - @RobotKeyword("Returns horizontal position of element identified by ``locator``.\r\n" + - "\r\n" + - "The position is returned in pixels off the left side of the page, as an integer. Fails if the matching element is not found.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public int getHorizontalPosition(String locator) { - List elements = elementFind(locator, true, false); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException( - String.format("Could not determine position for '%s'.", locator)); - } - - return elements.get(0).getLocation().getX(); - } + List elements = elementFind(locator, true, true); + Boolean ignoreCase = robot.getParamsValue(params, 1, Boolean.FALSE); + String actual = elements.get(0).getText(); + if (textIs(actual, text, ignoreCase)) { + if (StringUtils.isEmpty(message)) { + message = String.format("The text of element '%s' should have been '%s', but it was '%s'.", locator, + text, actual); + } + throw new SeleniumLibraryNonFatalException(message); + } + } + + @RobotKeyword("Returns the value of an element attribute.\r\n" + + "\r\n" + + "The ``attribute_locator`` consists of element locator followed by an @ sign and attribute name. Example: element_id@class\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "attributeLocator" }) + public String getElementAttribute(String attributeLocator) { + String[] parts = parseAttributeLocator(attributeLocator); + + List elements = elementFind(parts[0], true, false); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException(String.format("Element '%s' not found.", parts[0])); + } + + return elements.get(0).getAttribute(parts[1]); + } + + @RobotKeyword("Clears the text from element identified by ``locator``.\r\n" + + "\r\n" + + "This keyword does not execute any checks on whether or not the clear method has succeeded, so if any subsequent checks are needed, they should be executed using method `Element Text Should Be`.\r\n" + + "\r\n" + + "Also, this method will use WebDriver's internal _element.clear()_ method, i.e. it will not send any keypresses, and it will not have any effect whatsoever on elements other than input textfields or input textareas. Clients relying on keypresses should implement their own methods.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void clearElementText(String locator) { + List elements = elementFind(locator, true, true); + + elements.get(0).clear(); + } + + @RobotKeyword("Returns inner element id by index```` of element identified by ``locator`` which is matched by ``matchid``.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "matchid", "index" }) + public String getInnerElementId(String locator, String matchid, int index) { + List elements = elementFind(locator, true, true); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException(String.format("get Inner element '%s' not found.", locator)); + } + + String xpathId = ".//*[contains(@id," + matchid + ")]"; + + List tmpe = elements.get(0).findElements((By.xpath(xpathId))); + if (tmpe.size() == 0) { + throw new SeleniumLibraryNonFatalException( + String.format("No Inner element '%s' not found by '%s'", locator, matchid)); + } + String eId = tmpe.get(index).getAttribute("id"); + + logging.info(String.format("Found element ID: '%s'.", eId)); + + return eId; + + } + + @RobotKeyword("Returns horizontal position of element identified by ``locator``.\r\n" + + "\r\n" + + "The position is returned in pixels off the left side of the page, as an integer. Fails if the matching element is not found.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public int getHorizontalPosition(String locator) { + List elements = elementFind(locator, true, false); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException( + String.format("Could not determine position for '%s'.", locator)); + } + + return elements.get(0).getLocation().getX(); + } @RobotKeyword("Returns the value attribute of the element identified by ``locator``..\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public String getValue(String locator) { - return getValue(locator, null); - } + @ArgumentNames({ "locator" }) + public String getValue(String locator) { + return getValue(locator, null); + } - protected String getValue(String locator, String tag) { - List elements = elementFind(locator, true, false, tag); + protected String getValue(String locator, String tag) { + List elements = elementFind(locator, true, false, tag); - if (elements.size() == 0) { - return null; - } + if (elements.size() == 0) { + return null; + } - return elements.get(0).getAttribute("value"); - } + return elements.get(0).getAttribute("value"); + } @RobotKeyword("Returns the text of the element identified by ``locator``..\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public String getText(String locator) { - List elements = elementFind(locator, true, true); + @ArgumentNames({ "locator" }) + public String getText(String locator) { + List elements = elementFind(locator, true, true); - if (elements.size() == 0) { - return null; - } + if (elements.size() == 0) { + return null; + } - return elements.get(0).getText(); - } + return elements.get(0).getText(); + } @RobotKeyword("Returns vertical position of element identified by ``locator``.\r\n" + "\r\n" + "The position is returned in pixels off the left side of the page, as an integer. Fails if the matching element is not found.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public int getVerticalPosition(String locator) { - List elements = elementFind(locator, true, false); + @ArgumentNames({ "locator" }) + public int getVerticalPosition(String locator) { + List elements = elementFind(locator, true, false); - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException( - String.format("Could not determine position for '%s'.", locator)); - } + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException( + String.format("Could not determine position for '%s'.", locator)); + } - return elements.get(0).getLocation().getY(); - } + return elements.get(0).getLocation().getY(); + } - // ############################## - // Keywords - Mouse Input/Events - // ############################## + // ############################## + // Keywords - Mouse Input/Events + // ############################## @RobotKeyword("Click on the element identified by ``locator``.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void clickElement(String locator) { - logging.info(String.format("Clicking element '%s'.", locator)); - List elements = elementFind(locator, true, true); + @ArgumentNames({ "locator" }) + public void clickElement(String locator) { + logging.info(String.format("Clicking element '%s'.", locator)); + List elements = elementFind(locator, true, true); - elements.get(0).click(); - } + elements.get(0).click(); + } @RobotKeyword("Click on the element identified by locator at the coordinates ``xOffset`` and ``yOffset``.\r\n" + "\r\n" + "The cursor is moved at the center of the element and the to the given x/y offset from that point. Both offsets are specified as negative (left/up) or positive (right/down) number.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "xOffset", "yOffset" }) - public void clickElementAtCoordinates(String locator, String xOffset, String yOffset) { - logging.info(String.format("Clicking element '%s'in coordinates '%s', '%s'.", locator, xOffset, yOffset)); - List elements = elementFind(locator, true, true); + @ArgumentNames({ "locator", "xOffset", "yOffset" }) + public void clickElementAtCoordinates(String locator, String xOffset, String yOffset) { + logging.info(String.format("Clicking element '%s'in coordinates '%s', '%s'.", locator, xOffset, yOffset)); + List elements = elementFind(locator, true, true); - WebElement element = elements.get(0); - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.moveToElement(element).moveByOffset(Integer.parseInt(xOffset), Integer.parseInt(yOffset)).perform(); - } + WebElement element = elements.get(0); + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.moveToElement(element).moveByOffset(Integer.parseInt(xOffset), Integer.parseInt(yOffset)).perform(); + } @RobotKeyword("Double-Click on the element identified by ``locator``.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void doubleClickElement(String locator) { - logging.info(String.format("Double clicking element '%s'.", locator)); + @ArgumentNames({ "locator" }) + public void doubleClickElement(String locator) { + logging.info(String.format("Double clicking element '%s'.", locator)); - List elements = elementFind(locator, true, true); - Actions action = new Actions(browserManagement.getCurrentWebDriver()); + List elements = elementFind(locator, true, true); + Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.doubleClick(elements.get(0)).perform(); - } + action.doubleClick(elements.get(0)).perform(); + } @RobotKeyword("Set the focus to the element identified by ``locator``.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void focus(String locator) { - List elements = elementFind(locator, true, true); - ((JavascriptExecutor) browserManagement.getCurrentWebDriver()).executeScript("arguments[0].focus();", - elements.get(0)); - } - - @RobotKeyword("Drag the element identified by the locator ``source`` and move it on top of the element identified by the locator ``target``.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + - "\r\n" + - "Example:\r\n" + - " | Drag And Drop | elem1 | elem2 | # Move elem1 over elem2 |") - @ArgumentNames({ "source", "target" }) - public void dragAndDrop(String source, String target) { - List sourceElements = elementFind(source, true, true); - List targetElements = elementFind(target, true, true); - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.dragAndDrop(sourceElements.get(0), targetElements.get(0)).perform(); - } - - @RobotKeyword("Drag the element identified by the locator ``source`` and move it on top of the element identified by the locator ``target``.\r\n" + - "\r\n" + - "Both offsets are specified as negative (left/up) or positive (right/down) number.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + - "\r\n" + - "Example:\r\n" + - " | Drag And Drop By Offset | elem1 | 50 | 35 | # Move elem1 50px right and 35px down. |") - @ArgumentNames({ "source", "xOffset", "yOffset" }) - public void dragAndDropByOffset(String source, int xOffset, int yOffset) { - List elements = elementFind(source, true, true); - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.dragAndDropBy(elements.get(0), xOffset, yOffset).perform(); - } - - @RobotKeyword("Simulates pressing the left mouse button on the element identified by ``locator``.\r\n" + - "\r\n" + - "The element is pressed without releasing the mouse button.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void mouseDown(String locator) { - logging.info(String.format("Simulating Mouse Down on element '%s'.", locator)); - List elements = elementFind(locator, true, false); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); - } - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.clickAndHold(elements.get(0)).perform(); - } + @ArgumentNames({ "locator" }) + public void focus(String locator) { + List elements = elementFind(locator, true, true); + ((JavascriptExecutor) browserManagement.getCurrentWebDriver()).executeScript("arguments[0].focus();", + elements.get(0)); + } + + @RobotKeyword("Drag the element identified by the locator ``source`` and move it on top of the element identified by the locator ``target``.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + + "\r\n" + + "Example:\r\n" + + " | Drag And Drop | elem1 | elem2 | # Move elem1 over elem2 |") + @ArgumentNames({ "source", "target" }) + public void dragAndDrop(String source, String target) { + List sourceElements = elementFind(source, true, true); + List targetElements = elementFind(target, true, true); + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.dragAndDrop(sourceElements.get(0), targetElements.get(0)).perform(); + } + + @RobotKeyword("Drag the element identified by the locator ``source`` and move it on top of the element identified by the locator ``target``.\r\n" + + "\r\n" + + "Both offsets are specified as negative (left/up) or positive (right/down) number.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + + "\r\n" + + "Example:\r\n" + + " | Drag And Drop By Offset | elem1 | 50 | 35 | # Move elem1 50px right and 35px down. |") + @ArgumentNames({ "source", "xOffset", "yOffset" }) + public void dragAndDropByOffset(String source, int xOffset, int yOffset) { + List elements = elementFind(source, true, true); + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.dragAndDropBy(elements.get(0), xOffset, yOffset).perform(); + } + + @RobotKeyword("Simulates pressing the left mouse button on the element identified by ``locator``.\r\n" + + "\r\n" + + "The element is pressed without releasing the mouse button.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void mouseDown(String locator) { + logging.info(String.format("Simulating Mouse Down on element '%s'.", locator)); + List elements = elementFind(locator, true, false); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); + } + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.clickAndHold(elements.get(0)).perform(); + } @RobotKeyword("Simulates moving the mouse away from the element identified by ``locator``.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void mouseOut(String locator) { - logging.info(String.format("Simulating Mouse Out on element '%s'.", locator)); - List elements = elementFind(locator, true, false); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); - } - - WebElement element = elements.get(0); - Dimension size = element.getSize(); - int offsetX = size.getWidth() / 2 + 1; - int offsetY = size.getHeight() / 2 + 1; - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.moveToElement(element).moveByOffset(offsetX, offsetY).perform(); - } - - @RobotKeyword("Simulates moving the mouse over the element identified by ``locator``.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void mouseOver(String locator) { - logging.info(String.format("Simulating Mouse Over on element '%s'.", locator)); - List elements = elementFind(locator, true, false); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); - } - - WebElement element = elements.get(0); - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.moveToElement(element).perform(); - } - - @RobotKeyword("Simulates releasing the left mouse button on the element identified by ``locator``.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void mouseUp(String locator) { - logging.info(String.format("Simulating Mouse Up on element '%s'.", locator)); - List elements = elementFind(locator, true, false); - - if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); - } - - WebElement element = elements.get(0); - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.release(element).perform(); - } - - @RobotKeyword("Opens the context menu on the element identified by ``locator``.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void openContextMenu(String locator) { - List elements = elementFind(locator, true, true); - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.contextClick(elements.get(0)).perform(); - } - - @RobotKeyword("Simulates the given ``event`` on the element identified by ``locator``.\r\n" + - "\r\n" + - "This keyword is especially useful, when the element has an OnEvent handler that needs to be explicitly invoked.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") - @ArgumentNames({ "locator", "event" }) - public void simulate(String locator, String event) { - List elements = elementFind(locator, true, true); - String script = "element = arguments[0];" + "eventName = arguments[1];" + "if (document.createEventObject) {" - + "return element.fireEvent('on' + eventName, document.createEventObject());" + "}" - + "var evt = document.createEvent(\"HTMLEvents\");" + "evt.initEvent(eventName, true, true);" - + "return !element.dispatchEvent(evt);"; - - ((JavascriptExecutor) browserManagement.getCurrentWebDriver()).executeScript(script, elements.get(0), event); - } - - @RobotKeyword("Simulates pressing key on the element identified by ``locator``.\r\n" + - "\r\n" + - "Key is either a single character, or a numerical ASCII code of the key lead by '\\\\'.\r\n" + - "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + - "\r\n" + - "Example:\r\n" + - " | Press Key | text_field | q | # Press 'q' | \r\n" + - " | Press Key | login_button | \\\\13 | # ASCII code for enter key |") - @ArgumentNames({ "locator", "key" }) - public void pressKey(String locator, String key) { - if (key.startsWith("\\") && key.length() > 1) { - key = mapAsciiKeyCodeToKey(Integer.parseInt(key.substring(1))).toString(); - } - List element = elementFind(locator, true, true); - element.get(0).sendKeys(key); - } - - // ############################## - // Keywords - Links - // ############################## - - - @RobotKeyword("Click on the link identified by ``locator``.\r\n" + - "\r\n" + - "Key attributes for links are id, name, href and link text. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void clickLink(String locator) { - logging.info(String.format("Clicking link '%s'.", locator)); - List elements = elementFind(locator, true, true, "a"); - - elements.get(0).click(); - } - - @RobotKeyword("Returns a list containing ids of all links found in current page.\r\n" + - "\r\n" + - "If a link has no id, an empty string will be in the list instead.") - public ArrayList getAllLinks() { - ArrayList ret = new ArrayList(); - - List elements = elementFind("tag:a", false, false, "a"); - for (WebElement element : elements) { - ret.add(element.getAttribute("id")); - } - - return ret; - } - - @RobotKeyword("Simulates pressing the left mouse button on the link identified by ``locator``.\r\n" + - "\r\n" + - "The element is pressed without releasing the mouse button.\r\n" + - "\r\n" + - "Key attributes for links are id, name, href and link text. See `Introduction` for details about locators.\r\n" + - "\r\n") - @ArgumentNames({ "locator" }) - public void mouseDownOnLink(String locator) { - List elements = elementFind(locator, true, true, "link"); - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.clickAndHold(elements.get(0)).perform(); - } - - @RobotKeyword("Verify the link identified by ``locator`` is found on the current page.\r\n" + - "\r\n" + - "Key attributes for links are id, name, href and link text. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) - public void pageShouldContainLink(String locator, String...params) { + @ArgumentNames({ "locator" }) + public void mouseOut(String locator) { + logging.info(String.format("Simulating Mouse Out on element '%s'.", locator)); + List elements = elementFind(locator, true, false); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); + } + + WebElement element = elements.get(0); + Dimension size = element.getSize(); + int offsetX = size.getWidth() / 2 + 1; + int offsetY = size.getHeight() / 2 + 1; + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.moveToElement(element).moveByOffset(offsetX, offsetY).perform(); + } + + @RobotKeyword("Simulates moving the mouse over the element identified by ``locator``.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void mouseOver(String locator) { + logging.info(String.format("Simulating Mouse Over on element '%s'.", locator)); + List elements = elementFind(locator, true, false); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); + } + + WebElement element = elements.get(0); + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.moveToElement(element).perform(); + } + + @RobotKeyword("Simulates releasing the left mouse button on the element identified by ``locator``.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void mouseUp(String locator) { + logging.info(String.format("Simulating Mouse Up on element '%s'.", locator)); + List elements = elementFind(locator, true, false); + + if (elements.size() == 0) { + throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s not found.", locator)); + } + + WebElement element = elements.get(0); + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.release(element).perform(); + } + + @RobotKeyword("Opens the context menu on the element identified by ``locator``.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void openContextMenu(String locator) { + List elements = elementFind(locator, true, true); + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.contextClick(elements.get(0)).perform(); + } + + @RobotKeyword("Simulates the given ``event`` on the element identified by ``locator``.\r\n" + + "\r\n" + + "This keyword is especially useful, when the element has an OnEvent handler that needs to be explicitly invoked.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator", "event" }) + public void simulate(String locator, String event) { + List elements = elementFind(locator, true, true); + String script = "element = arguments[0];" + "eventName = arguments[1];" + "if (document.createEventObject) {" + + "return element.fireEvent('on' + eventName, document.createEventObject());" + "}" + + "var evt = document.createEvent(\"HTMLEvents\");" + "evt.initEvent(eventName, true, true);" + + "return !element.dispatchEvent(evt);"; + + ((JavascriptExecutor) browserManagement.getCurrentWebDriver()).executeScript(script, elements.get(0), event); + } + + @RobotKeyword("Simulates pressing key on the element identified by ``locator``.\r\n" + + "\r\n" + + "Key is either a single character, or a numerical ASCII code of the key lead by '\\\\'.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + + "\r\n" + + "Example:\r\n" + + " | Press Key | text_field | q | # Press 'q' | \r\n" + + " | Press Key | login_button | \\\\13 | # ASCII code for enter key |") + @ArgumentNames({ "locator", "key" }) + public void pressKey(String locator, String key) { + if (key.startsWith("\\") && key.length() > 1) { + key = mapAsciiKeyCodeToKey(Integer.parseInt(key.substring(1))).toString(); + } + List element = elementFind(locator, true, true); + element.get(0).sendKeys(key); + } + + // ############################## + // Keywords - Links + // ############################## + + + @RobotKeyword("Click on the link identified by ``locator``.\r\n" + + "\r\n" + + "Key attributes for links are id, name, href and link text. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void clickLink(String locator) { + logging.info(String.format("Clicking link '%s'.", locator)); + List elements = elementFind(locator, true, true, "a"); + + elements.get(0).click(); + } + + @RobotKeyword("Returns a list containing ids of all links found in current page.\r\n" + + "\r\n" + + "If a link has no id, an empty string will be in the list instead.") + public ArrayList getAllLinks() { + ArrayList ret = new ArrayList(); + + List elements = elementFind("tag:a", false, false, "a"); + for (WebElement element : elements) { + ret.add(element.getAttribute("id")); + } + + return ret; + } + + @RobotKeyword("Simulates pressing the left mouse button on the link identified by ``locator``.\r\n" + + "\r\n" + + "The element is pressed without releasing the mouse button.\r\n" + + "\r\n" + + "Key attributes for links are id, name, href and link text. See `Introduction` for details about locators.\r\n" + + "\r\n") + @ArgumentNames({ "locator" }) + public void mouseDownOnLink(String locator) { + List elements = elementFind(locator, true, true, "link"); + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.clickAndHold(elements.get(0)).perform(); + } + + @RobotKeyword("Verify the link identified by ``locator`` is found on the current page.\r\n" + + "\r\n" + + "Key attributes for links are id, name, href and link text. See `Introduction` for details about log levels and locators.") + @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) + public void pageShouldContainLink(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); String logLevel = robot.getParamsValue(params, 1, "INFO"); - pageShouldContainElement(locator, "link", message, logLevel); - } - - @RobotKeyword("Verify the link identified by ``locator`` is not found on the current page.\r\n" + - "\r\n" + - "Key attributes for links are id, name, href and link text. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) - public void pageShouldNotContainLink(String locator, String...params) { + pageShouldContainElement(locator, "link", message, logLevel); + } + + @RobotKeyword("Verify the link identified by ``locator`` is not found on the current page.\r\n" + + "\r\n" + + "Key attributes for links are id, name, href and link text. See `Introduction` for details about log levels and locators.") + @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) + public void pageShouldNotContainLink(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); String logLevel = robot.getParamsValue(params, 1, "INFO"); - pageShouldNotContainElement(locator, "link", message, logLevel); - } - - // ############################## - // Keywords - Images - // ############################## - - @RobotKeyword("Click on the image identified by ``locator``.\r\n" + - "\r\n" + - "Key attributes for images are id, src and alt. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void clickImage(String locator) { - logging.info(String.format("Clicking image '%s'.", locator)); - - List elements = elementFind(locator, true, false, "image"); - - if (elements.size() == 0) { - elements = elementFind(locator, true, true, "input"); - } - WebElement element = elements.get(0); - element.click(); - } - - @RobotKeyword("Simulates pressing the left mouse button on the image identified by ``locator``.\r\n" + - "\r\n" + - "The element is pressed without releasing the mouse button.\r\n" + - "\r\n" + - "Key attributes for images are id, src and alt. See `Introduction` for details about locators.") - @ArgumentNames({ "locator" }) - public void mouseDownOnImage(String locator) { - List elements = elementFind(locator, true, true, "image"); - - Actions action = new Actions(browserManagement.getCurrentWebDriver()); - action.clickAndHold(elements.get(0)).perform(); - } - - @RobotKeyword("Verify the image identified by ``locator`` is found on the current page.\r\n" + - "\r\n" + - "Key attributes for images are id, src and alt. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) - public void pageShouldContainImage(String locator, String...params) { + pageShouldNotContainElement(locator, "link", message, logLevel); + } + + // ############################## + // Keywords - Images + // ############################## + + @RobotKeyword("Click on the image identified by ``locator``.\r\n" + + "\r\n" + + "Key attributes for images are id, src and alt. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void clickImage(String locator) { + logging.info(String.format("Clicking image '%s'.", locator)); + + List elements = elementFind(locator, true, false, "image"); + + if (elements.size() == 0) { + elements = elementFind(locator, true, true, "input"); + } + WebElement element = elements.get(0); + element.click(); + } + + @RobotKeyword("Simulates pressing the left mouse button on the image identified by ``locator``.\r\n" + + "\r\n" + + "The element is pressed without releasing the mouse button.\r\n" + + "\r\n" + + "Key attributes for images are id, src and alt. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void mouseDownOnImage(String locator) { + List elements = elementFind(locator, true, true, "image"); + + Actions action = new Actions(browserManagement.getCurrentWebDriver()); + action.clickAndHold(elements.get(0)).perform(); + } + + @RobotKeyword("Verify the image identified by ``locator`` is found on the current page.\r\n" + + "\r\n" + + "Key attributes for images are id, src and alt. See `Introduction` for details about log levels and locators.") + @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) + public void pageShouldContainImage(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); String logLevel = robot.getParamsValue(params, 1, "INFO"); - pageShouldContainElement(locator, "image", message, logLevel); - } - - @RobotKeyword("Verify the image identified by ``locator`` is not found on the current page.\r\n" + - "\r\n" + - "Key attributes for images are id, src and alt. See `Introduction` for details about log levels and locators.") - @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) - public void pageShouldNotContainImage(String locator, String...params) { + pageShouldContainElement(locator, "image", message, logLevel); + } + + @RobotKeyword("Verify the image identified by ``locator`` is not found on the current page.\r\n" + + "\r\n" + + "Key attributes for images are id, src and alt. See `Introduction` for details about log levels and locators.") + @ArgumentNames({ "locator", "message=NONE", "logLevel=INFO" }) + public void pageShouldNotContainImage(String locator, String...params) { String message = robot.getParamsValue(params, 0, ""); String logLevel = robot.getParamsValue(params, 1, "INFO"); - pageShouldNotContainElement(locator, "image", message, logLevel); - } - - // ############################## - // Keywords - Xpath - // ############################## - - @RobotKeyword("Returns the number of elements located the given ``xpath``.\r\n" + - " \r\n" + - "If you wish to assert the number of located elements, use `Xpath Should Match X Times`.") - @ArgumentNames({ "xpath" }) - public int getMatchingXpathCount(String xpath) { - if (!xpath.startsWith("xpath=") && !xpath.startsWith("xpath:")) { - xpath = "xpath:" + xpath; - } - List elements = elementFind(xpath, false, false); - - return elements.size(); - } - - @RobotKeyword("Verify that the page contains the ``expectedXpathCount`` of elements located by the given ``xpath``.") - @ArgumentNames({ "xpath", "expectedXpathCount", "message=NONE", "logLevel=INFO" }) - public void xpathShouldMatchXTimes(String xpath, int expectedXpathCount, String...params) { + pageShouldNotContainElement(locator, "image", message, logLevel); + } + + // ############################## + // Keywords - Xpath + // ############################## + + @RobotKeyword("Returns the number of elements located the given ``xpath``.\r\n" + + " \r\n" + + "If you wish to assert the number of located elements, use `Xpath Should Match X Times`.") + @ArgumentNames({ "xpath" }) + public int getMatchingXpathCount(String xpath) { + if (!xpath.startsWith("xpath=") && !xpath.startsWith("xpath:")) { + xpath = "xpath:" + xpath; + } + List elements = elementFind(xpath, false, false); + + return elements.size(); + } + + @RobotKeyword("Verify that the page contains the ``expectedXpathCount`` of elements located by the given ``xpath``.") + @ArgumentNames({ "xpath", "expectedXpathCount", "message=NONE", "logLevel=INFO" }) + public void xpathShouldMatchXTimes(String xpath, int expectedXpathCount, String...params) { String message = robot.getParamsValue(params, 0, ""); String logLevel = robot.getParamsValue(params, 1, "INFO"); - if (!xpath.startsWith("xpath=") && !xpath.startsWith("xpath:")) { - xpath = "xpath:" + xpath; - } - List elements = elementFind(xpath, false, false); - int actualXpathCount = elements.size(); - - if (actualXpathCount != expectedXpathCount) { - if (message.isEmpty()) { - message = String.format("Xpath %s should have matched %s times but matched %s times.", xpath, - expectedXpathCount, actualXpathCount); - } - throw new SeleniumLibraryNonFatalException(message); - } - - logging.log(String.format("Current page contains %s elements matching '%s'.", actualXpathCount, xpath), - logLevel); - } - - @RobotKeyword("Click to element from list elements by locator ``xpath``.") - @ArgumentNames({"xpath", "index=0", "message=NONE"}) - public void clickElementByIndex(String xpath, String... params) { - String message = robot.getParamsValue(params, 0, ""); - int index = robot.getParamsValue(params, 1, 0); - List elements = elementFind(xpath, false, false); - if (elements.isEmpty()) { - if (message.isEmpty()) { - message = String.format("The Element was not found by locator '%s' with index '%d'", xpath, index); - } - throw new SeleniumLibraryNonFatalException(message); - } - WebElement element = elements.get(index); - element.click(); - } - - // ############################## - // Internal Methods - // ############################## - - protected List elementFind(String locator, boolean firstOnly, boolean required) { - return elementFind(locator, firstOnly, required, null); - } - - protected List elementFind(String locator, boolean firstOnly, boolean required, String tag) { - List elements = ElementFinder.find(browserManagement.getCurrentWebDriver(), locator, tag); - - if (required && elements.size() == 0) { - throw new SeleniumLibraryNonFatalException( - String.format("Element locator '%s' did not match any elements.", locator)); - } - - if (firstOnly) { - if (elements.size() > 1) { - List tmp = new ArrayList(); - tmp.add(elements.get(0)); - elements = tmp; - } - } - - return elements; - } - - protected boolean frameContains(String locator, String text) { - WebDriver current = browserManagement.getCurrentWebDriver(); - List elements = elementFind(locator, true, true); - - current.switchTo().frame(elements.get(0)); - logging.info(String.format("Searching for text from frame '%s'.", locator)); - boolean found = isTextPresent(text); - current.switchTo().defaultContent(); - - return found; - } - - protected boolean isTextPresent(String text) { - String locator = String.format("xpath://*[contains(., %s)]", escapeXpathValue(text)); - - return isElementPresent(locator); - } - - protected boolean isEnabled(String locator) { - List elements = elementFind(locator, true, true); - WebElement element = elements.get(0); - - if (!formElement.isFormElement(element)) { - throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s is not an input.", locator)); - } - if (!element.isEnabled()) { - return false; - } - String readonly = element.getAttribute("readonly"); - if (readonly != null && (readonly.equals("readonly") || readonly.equals("true"))) { - return false; - } - - return true; - } - - protected boolean isVisible(String locator) { - List elements = elementFind(locator, true, false); - if (elements.size() == 0) { - return false; - } - WebElement element = elements.get(0); - return element.isDisplayed(); - } - - protected boolean isClickable(String locator) { - List webElements = elementFind(locator, true, false); - if (webElements.size() == 0) { - return false; - } - WebElement element = webElements.get(0); - return element.isDisplayed() && element.isEnabled(); - } - - protected boolean isSelected(String locator) { - List webElements = elementFind(locator, true, false); - if (webElements.size() == 0) { - return false; - } - WebElement element = webElements.get(0); - return element.isSelected(); - } - - protected String[] parseAttributeLocator(String attributeLocator) { - int index = attributeLocator.lastIndexOf('@'); - if (index <= 0) { - throw new SeleniumLibraryNonFatalException( - String.format("Attribute locator '%s' does not contain an element locator.", attributeLocator)); - } - if (index + 1 == attributeLocator.length()) { - throw new SeleniumLibraryNonFatalException( - String.format("Attribute locator '%s' does not contain an attribute name.", attributeLocator)); - } - String[] parts = new String[2]; - parts[0] = attributeLocator.substring(0, index); - parts[1] = attributeLocator.substring(index + 1); - - return parts; - } - - protected boolean isElementPresent(String locator) { - return isElementPresent(locator, null); - } - - protected boolean isElementPresent(String locator, String tag) { - return elementFind(locator, true, false, tag).size() != 0; - } - - protected boolean pageContains(String text) { - WebDriver current = browserManagement.getCurrentWebDriver(); - current.switchTo().defaultContent(); - - if (isTextPresent(text)) { - return true; - } - - List elements = elementFind("xpath://frame|//iframe", false, false); - Iterator it = elements.iterator(); - while (it.hasNext()) { - current.switchTo().frame(it.next()); - boolean found = isTextPresent(text); - current.switchTo().defaultContent(); - if (found) { - return true; - } - } - - return false; - } - - protected CharSequence mapAsciiKeyCodeToKey(int keyCode) { - switch (keyCode) { - case 0: - return Keys.NULL; - case 8: - return Keys.BACK_SPACE; - case 9: - return Keys.TAB; - case 10: - return Keys.RETURN; - case 13: - return Keys.ENTER; - case 24: - return Keys.CANCEL; - case 27: - return Keys.ESCAPE; - case 32: - return Keys.SPACE; - case 42: - return Keys.MULTIPLY; - case 43: - return Keys.ADD; - case 44: - return Keys.SEPARATOR; - case 45: - return Keys.SUBTRACT; - case 56: - return Keys.DECIMAL; - case 57: - return Keys.DIVIDE; - case 59: - return Keys.SEMICOLON; - case 61: - return Keys.EQUALS; - case 127: - return Keys.DELETE; - default: - return new StringBuffer((char) keyCode); - } - } - - public static String escapeXpathValue(String value) { - if (value.contains("\"") && value.contains("'")) { - String[] partsWoApos = value.split("'"); - return String.format("concat('%s')", Python.join("', \"'\", '", Arrays.asList(partsWoApos))); - } - if (value.contains("'")) { - return String.format("\"%s\"", value); - } - return String.format("'%s'", value); - } + if (!xpath.startsWith("xpath=") && !xpath.startsWith("xpath:")) { + xpath = "xpath:" + xpath; + } + List elements = elementFind(xpath, false, false); + int actualXpathCount = elements.size(); + + if (actualXpathCount != expectedXpathCount) { + if (message.isEmpty()) { + message = String.format("Xpath %s should have matched %s times but matched %s times.", xpath, + expectedXpathCount, actualXpathCount); + } + throw new SeleniumLibraryNonFatalException(message); + } + + logging.log(String.format("Current page contains %s elements matching '%s'.", actualXpathCount, xpath), + logLevel); + } + + @RobotKeyword("Click to element from list elements by locator ``xpath``.") + @ArgumentNames({"xpath", "index=0", "message=NONE"}) + public void clickElementByIndex(String xpath, String... params) { + String message = robot.getParamsValue(params, 0, ""); + int index = robot.getParamsValue(params, 1, 0); + List elements = elementFind(xpath, false, false); + if (elements.isEmpty()) { + if (message.isEmpty()) { + message = String.format("The Element was not found by locator '%s' with index '%d'", xpath, index); + } + throw new SeleniumLibraryNonFatalException(message); + } + WebElement element = elements.get(index); + element.click(); + } + + // ############################## + // Internal Methods + // ############################## + + protected List elementFind(String locator, boolean firstOnly, boolean required) { + return elementFind(locator, firstOnly, required, null); + } + + protected List elementFind(String locator, boolean firstOnly, boolean required, String tag) { + List elements = ElementFinder.find(browserManagement.getCurrentWebDriver(), locator, tag); + + if (required && elements.size() == 0) { + throw new SeleniumLibraryNonFatalException( + String.format("Element locator '%s' did not match any elements.", locator)); + } + + if (firstOnly) { + if (elements.size() > 1) { + List tmp = new ArrayList(); + tmp.add(elements.get(0)); + elements = tmp; + } + } + + return elements; + } + + protected boolean frameContains(String locator, String text) { + WebDriver current = browserManagement.getCurrentWebDriver(); + List elements = elementFind(locator, true, true); + + current.switchTo().frame(elements.get(0)); + logging.info(String.format("Searching for text from frame '%s'.", locator)); + boolean found = isTextPresent(text); + current.switchTo().defaultContent(); + + return found; + } + + protected boolean isTextPresent(String text) { + String locator = String.format("xpath://*[contains(., %s)]", escapeXpathValue(text)); + + return isElementPresent(locator); + } + + protected boolean isEnabled(String locator) { + List elements = elementFind(locator, true, true); + WebElement element = elements.get(0); + + if (!formElement.isFormElement(element)) { + throw new SeleniumLibraryNonFatalException(String.format("ERROR: Element %s is not an input.", locator)); + } + if (!element.isEnabled()) { + return false; + } + String readonly = element.getAttribute("readonly"); + if (readonly != null && (readonly.equals("readonly") || readonly.equals("true"))) { + return false; + } + + return true; + } + + protected boolean isVisible(String locator) { + List elements = elementFind(locator, true, false); + if (elements.size() == 0) { + return false; + } + WebElement element = elements.get(0); + return element.isDisplayed(); + } + + protected boolean isClickable(String locator) { + List webElements = elementFind(locator, true, false); + if (webElements.size() == 0) { + return false; + } + WebElement element = webElements.get(0); + return element.isDisplayed() && element.isEnabled(); + } + + protected boolean isSelected(String locator) { + List webElements = elementFind(locator, true, false); + if (webElements.size() == 0) { + return false; + } + WebElement element = webElements.get(0); + return element.isSelected(); + } + + protected String[] parseAttributeLocator(String attributeLocator) { + int index = attributeLocator.lastIndexOf('@'); + if (index <= 0) { + throw new SeleniumLibraryNonFatalException( + String.format("Attribute locator '%s' does not contain an element locator.", attributeLocator)); + } + if (index + 1 == attributeLocator.length()) { + throw new SeleniumLibraryNonFatalException( + String.format("Attribute locator '%s' does not contain an attribute name.", attributeLocator)); + } + String[] parts = new String[2]; + parts[0] = attributeLocator.substring(0, index); + parts[1] = attributeLocator.substring(index + 1); + + return parts; + } + + protected boolean isElementPresent(String locator) { + return isElementPresent(locator, null); + } + + protected boolean isElementPresent(String locator, String tag) { + return elementFind(locator, true, false, tag).size() != 0; + } + + protected boolean pageContains(String text) { + WebDriver current = browserManagement.getCurrentWebDriver(); + current.switchTo().defaultContent(); + + if (isTextPresent(text)) { + return true; + } + + List elements = elementFind("xpath://frame|//iframe", false, false); + Iterator it = elements.iterator(); + while (it.hasNext()) { + current.switchTo().frame(it.next()); + boolean found = isTextPresent(text); + current.switchTo().defaultContent(); + if (found) { + return true; + } + } + + return false; + } + + protected CharSequence mapAsciiKeyCodeToKey(int keyCode) { + switch (keyCode) { + case 0: + return Keys.NULL; + case 8: + return Keys.BACK_SPACE; + case 9: + return Keys.TAB; + case 10: + return Keys.RETURN; + case 13: + return Keys.ENTER; + case 24: + return Keys.CANCEL; + case 27: + return Keys.ESCAPE; + case 32: + return Keys.SPACE; + case 42: + return Keys.MULTIPLY; + case 43: + return Keys.ADD; + case 44: + return Keys.SEPARATOR; + case 45: + return Keys.SUBTRACT; + case 56: + return Keys.DECIMAL; + case 57: + return Keys.DIVIDE; + case 59: + return Keys.SEMICOLON; + case 61: + return Keys.EQUALS; + case 127: + return Keys.DELETE; + default: + return new StringBuffer((char) keyCode); + } + } + + public static String escapeXpathValue(String value) { + if (value.contains("\"") && value.contains("'")) { + String[] partsWoApos = value.split("'"); + return String.format("concat('%s')", Python.join("', \"'\", '", Arrays.asList(partsWoApos))); + } + if (value.contains("'")) { + return String.format("\"%s\"", value); + } + return String.format("'%s'", value); + } + + private boolean textContains(String actual, String text, boolean ignoreCase) { + return ignoreCase + ? StringUtils.containsIgnoreCase(actual, text) + : StringUtils.contains(actual, text); + } + + private boolean textIs(String actual, String text, boolean ignoreCase) { + return ignoreCase + ? StringUtils.equalsIgnoreCase(actual, text) + : StringUtils.equals(actual, text); + } } From 65942affa8ce70c28502d930a09fa1d60807e3c8 Mon Sep 17 00:00:00 2001 From: Hi-Fi Date: Tue, 9 Jul 2019 11:15:28 +0300 Subject: [PATCH 13/19] Replaced Maven plugin for webdriver download with WebdriverManager (thanks to @YauheniPo) Suite setup to handle download in a way that tests doesn't need to be changed --- .gitignore | 3 +- README.md | 32 +++++- pom.xml | 103 +----------------- .../robotframework/settings/Settings.robot | 1 + .../testsuites/UnitTests/__init__.robot | 7 ++ 5 files changed, 46 insertions(+), 100 deletions(-) create mode 100644 src/test/robotframework/testsuites/UnitTests/__init__.robot diff --git a/.gitignore b/.gitignore index d6944f9..0b0dee8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .settings .classpath target -webdriver \ No newline at end of file +webdriver +/libspecs/ diff --git a/README.md b/README.md index 90c4e28..7b14403 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,36 @@ which contains all required libraries. Running of tests with this can be done wi [Library Specs](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.26/robotframework-seleniumlibrary-3.141.59.26.xml) and place it in your PYTHONPATH. +Usage, Selenium 4 (WIP) +----------------- + +If you are using the robotframework-maven-plugin you can +use this library by adding the following dependency to +your pom.xml: + + + com.github.hi-fi + robotframework-seleniumlibrary + 4.0.0-alpha-1.0 + test + + +If you cannot use the robotframework-maven-plugin you can use the +[jar-with-dependencies](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/4.0.0-alpha-1.0/robotframework-seleniumlibrary-4.0.0-alpha-1.0-jar-with-dependencies.jar), +which contains all required libraries. Running of tests with this can be done with command `java -jar robotframework-seleniumlibrary-4.0.0-alpha-1.0-jar-with-dependencies.jar `. + +* More information about this library can be found in the + [Keyword Documentation](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/4.0.0-alpha-1.0/robotframework-seleniumlibrary-4.0.0-alpha-1.0.html). +* For keyword completion in RIDE you can download this + [Library Specs](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/4.0.0-alpha-1.0/robotframework-seleniumlibrary-4.0.0-alpha-1.0.xml) + and place it in your PYTHONPATH. + Differences ----------- * Some keyword differences between this and [Python version](https://github.com/robotframework/SeleniumLibrary) exists. (Same) keywords should be aligned in upcoming versions. -* Older version of the library was imported as `Library Selenium2Library` (both Java and Python versions). Since 2.53.1.1 (and all 3.x versions) import is done as `Library SeleniumLibrary` +* Older version of the library was imported as `Library Selenium2Library` (both Java and Python versions). +Since 2.53.1.1 (and later major versions) import is done as `Library SeleniumLibrary` Browser drivers @@ -86,6 +111,8 @@ to know when to update drivers you use. Drivers can also be fetched with [https://github.com/Ardesco/selenium-standalone-server-plugin|Selenium Driver Binary Downloader plugin]. +With Selenium 4 [https://github.com/bonigarcia/webdrivermanager|WebdriverManager] is taken to use, so handling of drivers can also be done with standalone JAR from tests itself. + __ https://seleniumhq.github.io/selenium/docs/api/py/index.html#drivers __ https://en.wikipedia.org/wiki/PATH_(variable) @@ -96,7 +123,8 @@ This is a maven project. You can execute the integration tests (using [jBrowser] mvn integration-test -Other browsers are behind profiles (require browser installation with Firefox and Google Chrome, but not driver): +Other browsers are behind profiles +(require browser installation with Firefox and Google Chrome, but not driver. Driver downloaded directly from Internet, so runner needs to have access to it.): * Firefox: mvn integration-test -Pfirefox * Google Chrome: mvn integration-test -Pgooglechrome diff --git a/pom.xml b/pom.xml index 50013c1..487ca3d 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,7 @@ 3.141.59 SeleniumLibrary jbrowser + False @@ -203,27 +204,6 @@ - - com.lazerycode.selenium - driver-binary-downloader-maven-plugin - 1.0.16 - - - webdriver/binaries - - webdriver/zips - - src/test/resources/RepositoryMap.xml - - - - - selenium - - - - org.robotframework @@ -241,6 +221,7 @@ ${project.basedir}/src/test/robotframework/testsuites browser:${browser} + downloadWebDriver:${downloadWebDriver} target/robotframework-reports/${browser}_report.html target/robotframework-reports/${browser}_log.html @@ -384,101 +365,29 @@ firefox firefox + True - - - - com.lazerycode.selenium - driver-binary-downloader-maven-plugin - - - org.robotframework - robotframework-maven-plugin - - - - -Dwebdriver.gecko.driver=${webdriver.gecko.driver} - - - - - - firefoxheadless firefoxheadless + True - - - - com.lazerycode.selenium - driver-binary-downloader-maven-plugin - - - org.robotframework - robotframework-maven-plugin - - - - -Dwebdriver.gecko.driver=${webdriver.gecko.driver} - - - - - - googlechrome googlechrome + True - - - - com.lazerycode.selenium - driver-binary-downloader-maven-plugin - - - org.robotframework - robotframework-maven-plugin - - - - -Dwebdriver.chrome.driver=${webdriver.chrome.driver} - - - - - - googlechromeheadless googlechromeheadless + True - - - - com.lazerycode.selenium - driver-binary-downloader-maven-plugin - - - org.robotframework - robotframework-maven-plugin - - - - -Dwebdriver.chrome.driver=${webdriver.chrome.driver} - - - - - - release diff --git a/src/test/robotframework/settings/Settings.robot b/src/test/robotframework/settings/Settings.robot index 85b3c03..5881611 100644 --- a/src/test/robotframework/settings/Settings.robot +++ b/src/test/robotframework/settings/Settings.robot @@ -6,6 +6,7 @@ Library SeleniumLibrary *** Variables *** ${Profile} Local ${browser} jbrowser +${downloadWebDriver} ${False} ${Selenium.Browser.Name} ${browser} ${Selenium.Browser.Version} 17 ${Selenium.Timeout} 30.0 diff --git a/src/test/robotframework/testsuites/UnitTests/__init__.robot b/src/test/robotframework/testsuites/UnitTests/__init__.robot new file mode 100644 index 0000000..4127098 --- /dev/null +++ b/src/test/robotframework/testsuites/UnitTests/__init__.robot @@ -0,0 +1,7 @@ +*** Settings *** +Resource ../../settings/Settings.robot +Suite Setup Handle WebDriver + +*** Keywords *** +Handle WebDriver + Run Keyword If ${downloadWebDriver} WebDriver Manager Setup ${browser} \ No newline at end of file From 15e0540bd54026fc971b8e21c336fd634f0f0cad Mon Sep 17 00:00:00 2001 From: Hi-Fi Date: Tue, 16 Jul 2019 11:06:05 +0300 Subject: [PATCH 14/19] Release 3.141.59.265 --- README.md | 26 +------------------------- pom.xml | 2 +- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 7b14403..a457322 100644 --- a/README.md +++ b/README.md @@ -59,30 +59,6 @@ which contains all required libraries. Running of tests with this can be done wi [Library Specs](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.26/robotframework-seleniumlibrary-3.141.59.26.xml) and place it in your PYTHONPATH. -Usage, Selenium 4 (WIP) ------------------ - -If you are using the robotframework-maven-plugin you can -use this library by adding the following dependency to -your pom.xml: - - - com.github.hi-fi - robotframework-seleniumlibrary - 4.0.0-alpha-1.0 - test - - -If you cannot use the robotframework-maven-plugin you can use the -[jar-with-dependencies](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/4.0.0-alpha-1.0/robotframework-seleniumlibrary-4.0.0-alpha-1.0-jar-with-dependencies.jar), -which contains all required libraries. Running of tests with this can be done with command `java -jar robotframework-seleniumlibrary-4.0.0-alpha-1.0-jar-with-dependencies.jar `. - -* More information about this library can be found in the - [Keyword Documentation](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/4.0.0-alpha-1.0/robotframework-seleniumlibrary-4.0.0-alpha-1.0.html). -* For keyword completion in RIDE you can download this - [Library Specs](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/4.0.0-alpha-1.0/robotframework-seleniumlibrary-4.0.0-alpha-1.0.xml) - and place it in your PYTHONPATH. - Differences ----------- @@ -111,7 +87,7 @@ to know when to update drivers you use. Drivers can also be fetched with [https://github.com/Ardesco/selenium-standalone-server-plugin|Selenium Driver Binary Downloader plugin]. -With Selenium 4 [https://github.com/bonigarcia/webdrivermanager|WebdriverManager] is taken to use, so handling of drivers can also be done with standalone JAR from tests itself. +With At 3.141.59.265 [https://github.com/bonigarcia/webdrivermanager|WebdriverManager] is taken to use, so handling of drivers can also be done with standalone JAR from tests itself. __ https://seleniumhq.github.io/selenium/docs/api/py/index.html#drivers __ https://en.wikipedia.org/wiki/PATH_(variable) diff --git a/pom.xml b/pom.xml index 487ca3d..e56820f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.hi-fi robotframework-seleniumlibrary - 3.141.59.265-SNAPSHOT + 3.141.59.265 jar Robot Framework :: SeleniumLibrary From ae6c18f6b8b9afc38a9a6d6072fdaad36bb48be3 Mon Sep 17 00:00:00 2001 From: Hi-Fi Date: Tue, 16 Jul 2019 11:35:41 +0300 Subject: [PATCH 15/19] Next 3.x version to POM --- README.md | 10 +++++----- pom.xml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a457322..e05745c 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,18 @@ your pom.xml: com.github.hi-fi robotframework-seleniumlibrary - 3.141.59.26 + 3.141.59.265 test If you cannot use the robotframework-maven-plugin you can use the -[jar-with-dependencies](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.26/robotframework-seleniumlibrary-3.141.59.26-jar-with-dependencies.jar), -which contains all required libraries. Running of tests with this can be done with command `java -jar robotframework-seleniumlibrary-3.141.59.26-jar-with-dependencies.jar `. +[jar-with-dependencies](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.265/robotframework-seleniumlibrary-3.141.59.265-jar-with-dependencies.jar), +which contains all required libraries. Running of tests with this can be done with command `java -jar robotframework-seleniumlibrary-3.141.59.265-jar-with-dependencies.jar `. * More information about this library can be found in the - [Keyword Documentation](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.26/robotframework-seleniumlibrary-3.141.59.26.html). + [Keyword Documentation](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.265/robotframework-seleniumlibrary-3.141.59.265.html). * For keyword completion in RIDE you can download this - [Library Specs](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.26/robotframework-seleniumlibrary-3.141.59.26.xml) + [Library Specs](http://central.maven.org/maven2/com/github/hi-fi/robotframework-seleniumlibrary/3.141.59.265/robotframework-seleniumlibrary-3.141.59.265.xml) and place it in your PYTHONPATH. Differences diff --git a/pom.xml b/pom.xml index e56820f..03ded72 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.hi-fi robotframework-seleniumlibrary - 3.141.59.265 + 3.141.59.2653-SNAPSHOT jar Robot Framework :: SeleniumLibrary From a3c66509301b701cb96377f1cd28e3c42abf8a89 Mon Sep 17 00:00:00 2001 From: ractoc Date: Tue, 16 Jul 2019 15:19:09 +0200 Subject: [PATCH 16/19] Added setFocusToElement. This keyword should eventually replace the Focus keyword. For backwards compatibilty the Focus keyword has been deprecated and just forwards all calls to the new SetFocusToElement keyword. Added the ElementShouldBeFocused keyword. This is the companion keyword to the SetFocusToElement. It retreives the element identified by the locator and the currently active element. Then does an equals to see if it's the same element. --- .../seleniumlibrary/keywords/Element.java | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index d120aeb..636e601 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -247,8 +247,8 @@ public void assignIdToElement(String locator, String id) { .executeScript(String.format("arguments[0].id = '%s';", id), elements.get(0)); } - @RobotKeyword("Verify the element identified by ``locator`` is found on the current page\r\n" + - "\r\n" + + @RobotKeyword("Verify the element identified by ``locator`` is enabled\r\n" + + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about log levels and locators.") @ArgumentNames({ "locator" }) public void elementShouldBeEnabled(String locator) { @@ -257,7 +257,7 @@ public void elementShouldBeEnabled(String locator) { } } - @RobotKeyword("Verify the element identified by ``locator`` is disabled.\r\n" + + @RobotKeyword("Verify the element identified by ``locator`` is disabled.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") @ArgumentNames({ "locator" }) @@ -267,6 +267,16 @@ public void elementShouldBeDisabled(String locator) { } } + @RobotKeyword("Verify the element identified by ``locator`` is focused\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about log levels and locators.") + @ArgumentNames({ "locator" }) + public void elementShouldBeFocused(String locator) { + if (!isFocused(locator)) { + throw new SeleniumLibraryNonFatalException(String.format("Element %s is disabled.", locator)); + } + } + @RobotKeyword("Verify the element identified by ``locator`` is selected.\r\n" + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") @@ -582,11 +592,20 @@ public void doubleClickElement(String locator) { action.doubleClick(elements.get(0)).perform(); } - @RobotKeyword("Set the focus to the element identified by ``locator``.\r\n" + - "\r\n" + + @RobotKeyword("Set the focus to the element identified by ``locator``.\r\n" + + "\r\n" + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") @ArgumentNames({ "locator" }) + @Deprecated public void focus(String locator) { + setFocusToElement(locator); + } + + @RobotKeyword("Set the focus to the element identified by ``locator``.\r\n" + + "\r\n" + + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + @ArgumentNames({ "locator" }) + public void setFocusToElement(String locator) { List elements = elementFind(locator, true, true); ((JavascriptExecutor) browserManagement.getCurrentWebDriver()).executeScript("arguments[0].focus();", elements.get(0)); @@ -977,6 +996,14 @@ protected boolean isEnabled(String locator) { return true; } + protected boolean isFocused(String locator) { + List elements = elementFind(locator, true, true); + WebElement element = elements.get(0); + WebDriver current = browserManagement.getCurrentWebDriver(); + WebElement focused = current.switchTo().activeElement(); + return element.equals(focused); + } + protected boolean isVisible(String locator) { List elements = elementFind(locator, true, false); if (elements.size() == 0) { From cc61a10797064aa1d32952a7671749cc7b60d194 Mon Sep 17 00:00:00 2001 From: ractoc Date: Wed, 17 Jul 2019 08:03:40 +0200 Subject: [PATCH 17/19] small copy paste error in the error message --- .../markusbernhardt/seleniumlibrary/keywords/Element.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index 636e601..8370d97 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -273,7 +273,7 @@ public void elementShouldBeDisabled(String locator) { @ArgumentNames({ "locator" }) public void elementShouldBeFocused(String locator) { if (!isFocused(locator)) { - throw new SeleniumLibraryNonFatalException(String.format("Element %s is disabled.", locator)); + throw new SeleniumLibraryNonFatalException(String.format("Element %s is not focused.", locator)); } } From aaba73b2d4ffb9c3a1e4e3b32b7835bc2321bbe8 Mon Sep 17 00:00:00 2001 From: ractoc Date: Mon, 22 Jul 2019 15:38:31 +0200 Subject: [PATCH 18/19] added the new version of Get Element Attribute which uses 2 parameters instead of just 1. --- .../seleniumlibrary/keywords/Element.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java index 8370d97..a8c3ac4 100644 --- a/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java +++ b/src/main/java/com/github/markusbernhardt/seleniumlibrary/keywords/Element.java @@ -429,18 +429,32 @@ public void elementTextShouldNotBe(String locator, String text, String...params) "\r\n" + "The ``attribute_locator`` consists of element locator followed by an @ sign and attribute name. Example: element_id@class\r\n" + "\r\n" + - "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.") + "Key attributes for arbitrary elements are id and name. See `Introduction` for details about locators.\r\n" + + "\r\n" + + "Passing attribute name as part of the locator was removed in SeleniumLibrary 3.2. The explicit attribute argument should be used instead.") @ArgumentNames({ "attributeLocator" }) + @Deprecated public String getElementAttribute(String attributeLocator) { String[] parts = parseAttributeLocator(attributeLocator); + return getElementAttribute(parts[0], parts[1]); + } - List elements = elementFind(parts[0], true, false); + @RobotKeyword("Returns value of attribute from element locator.\r\n" + + "\r\n" + + "See the `Locating elements` section for details about the locator syntax.\r\n" + + "\r\n" + + "Example: ${id}= Get Element Attribute css:h1 id\r\n" + + "\r\n" + + "Passing attribute name as part of the locator was removed in SeleniumLibrary 3.2. The explicit attribute argument should be used instead.") + @ArgumentNames({ "locator", "attribute" }) + public String getElementAttribute(String locator, String attribute) { + + List elements = elementFind(locator, true, false); if (elements.size() == 0) { - throw new SeleniumLibraryNonFatalException(String.format("Element '%s' not found.", parts[0])); + throw new SeleniumLibraryNonFatalException(String.format("Element '%s' not found.", locator)); } - - return elements.get(0).getAttribute(parts[1]); + return elements.get(0).getAttribute(attribute); } @RobotKeyword("Clears the text from element identified by ``locator``.\r\n" + From 265e2b18a025c2c14009e31ea34bc1015f72a171 Mon Sep 17 00:00:00 2001 From: Hi-Fi Date: Thu, 25 Jul 2019 21:49:18 +0300 Subject: [PATCH 19/19] Removed headfull browsers from testing Forcing to use Trusty that has OracleJDK8 available --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f23414..728b516 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,11 @@ language: java +dist: trusty + jdk: - oraclejdk8 env: - PROFILE=build - - PROFILE=build,googlechrome - - PROFILE=build,firefox - PROFILE=build,googlechromeheadless - PROFILE=build,firefoxheadless