diff --git a/README.md b/README.md index 8a5664f..09f6e8b 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ WebDriver webDriver=util.driver; The framework will also take care of the entire configuration of the Drivers, you just need to specify what supported WebExplorers do you want to run your scenarios on. -* Version: [0.3.1](https://github.com/orgs/WhiteOrganization/packages) +* Version: [0.3.2](https://github.com/orgs/WhiteOrganization/packages) This is still in development and some methods are being constantly added as they are used. Please help us by requesting those you need or need more detailed documentation. @@ -48,7 +48,7 @@ by including it in your POM](https://maven.pkg.github.com/whiteorganization/whit io.github.whiteorganization white-selenium-framework - 0.3.1 + 0.3.2 ``` If used on a long-term heavy-use project we recommend: @@ -61,7 +61,7 @@ If used on a long-term heavy-use project we recommend: io.github.whiteorganization white-selenium-framework - 0.3.1 + 0.3.2 @@ -101,7 +101,7 @@ and import the dependency like this: com.github.WhiteOrganization White_SeleniumFramework - white-selenium-framework-0.3.1 + white-selenium-framework-0.3.2 ``` diff --git a/pom.xml b/pom.xml index 5d4f581..538d4b0 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.github.whiteorganization white-selenium-framework - 0.3.1 + 0.3.2 ${project.groupId}:${project.artifactId} A Selenium Framework that will help to execute tests and custom scenarios faster and reduce the effort to access many sections Selenium related. diff --git a/src/main/java/org/white_sdev/white_seleniumframework/framework/WebDriverUtils.java b/src/main/java/org/white_sdev/white_seleniumframework/framework/WebDriverUtils.java index a7da76d..97687a1 100644 --- a/src/main/java/org/white_sdev/white_seleniumframework/framework/WebDriverUtils.java +++ b/src/main/java/org/white_sdev/white_seleniumframework/framework/WebDriverUtils.java @@ -831,6 +831,145 @@ public String getTextFrom(By locator, Collection nestedFrameNamesStructu // + + /** + * Extracts all the data from a {@code } and it will transform the rows ({@code
}s) into {@link Map}s indicating their header and cell value into its + * pairs. + * For example, this table:
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
First NameEmail
bazbaz@zinga.com
barbar@dummy.com
foofoo@dummy.com

+ * will be transformed into {@link List} objects with this format: + * {@code [{First Name=baz, Email=baz@zinga.com}, {First Name=bar, Email=bar@dummy.com}, {First Name=foo, Email=foo@dummy.com}]}. + *

+ * This method will use the first table if any is found. + *

+ * + * @return {@link List} of {@link Map} representing the rows and cells of the table. + * @throws White_SeleniumFrameworkException When an error is found. + * @author Obed Vazquez + */ + public Optional>> getTableDataWithTag() { + return getTableDataWithTag("table", null); + } + + private Optional>> getTableDataWithTag(String tagName) { + return getTableDataWithTag(tagName, null); + } + + + /** + * Extracts all the data from a {@code } and it will transform the rows ({@code
}s) into {@link Map}s indicating their header and cell value into its + * pairs. + * For example, this table:
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
First NameEmail
bazbaz@zinga.com
barbar@dummy.com
foofoo@dummy.com

+ * will be transformed into {@link List} objects with this format: + * {@code [{First Name=baz, Email=baz@zinga.com}, {First Name=bar, Email=bar@dummy.com}, {First Name=foo, Email=foo@dummy.com}]}. + *

+ * This method will use the first table if any is found. + *

+ * + * @param secsToWait the seconds to waitFor for the element to show up in the page; uses the app default (specified in .properties with + * default-explicit-waitFor property) if null. + * @return {@link List} of {@link Map} representing the rows and cells of the table. + * @throws White_SeleniumFrameworkException When an error is found. + * @author Obed Vazquez + */ + public Optional>> getTableDataWithTag(Integer secsToWait) { + return getTableDataWithTag("table", secsToWait); + } + + /** + * Extracts all the data from a {@code } and it will transform the rows ({@code
}s) into {@link Map}s indicating their header and cell value into its + * pairs. + * For example, this table:
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
First NameEmail
bazbaz@zinga.com
barbar@dummy.com
foofoo@dummy.com

+ * will be transformed into {@link List} objects with this format: + * {@code [{First Name=baz, Email=baz@zinga.com}, {First Name=bar, Email=bar@dummy.com}, {First Name=foo, Email=foo@dummy.com}]}. + *

+ * This method will use the first table if any is found. + *

+ * + * @param tagName the tag to locate the element to perform the operation with. + * @param secsToWait the seconds to waitFor for the element to show up in the page; uses the app default (specified in .properties with + * default-explicit-waitFor property) if null. + * @return {@link List} of {@link Map} representing the rows and cells of the table. + * @throws White_SeleniumFrameworkException When an error is found. + * @author Obed Vazquez + */ + public Optional>> getTableDataWithTag(String tagName, Integer secsToWait) { + String logID = "::getTableDataWithTag([tagName, keys, secsToWait]): "; + log.trace("{}Start ", logID); + if (tagName == null) return Optional.empty(); + try { + return getTableData(By.tagName(tagName), secsToWait); + } catch (Exception ex) { + throw new White_SeleniumFrameworkException(String.format("Unable to obtain the data from table with tag :%s ", tagName), ex); + } + } + + /** * Extracts all the data from a {@code } and it will transform the rows ({@code
}s) into {@link Map}s indicating their header and cell value into its * pairs. @@ -874,8 +1013,8 @@ public Optional>> getTableDataWithId(String i } public Optional>> getTableDataWithId(String id, Collection nestedFrameNamesStructure, Integer secsToWait) { - String logID = "::clickId([id, nestedFrameNamesStructure, secsToWait]): "; - log.trace("{}Start Clicking", logID); + String logID = "::getTableDataWithId([id, nestedFrameNamesStructure, secsToWait]): "; + log.trace("{}Start ", logID); if (id == null) return Optional.empty(); try { if (nestedFrameNamesStructure != null) focus(nestedFrameNamesStructure, secsToWait); @@ -883,15 +1022,15 @@ public Optional>> getTableDataWithId(String i } catch (Exception ex) { if (!defaultContentFocused && (nestedFrameNamesStructure == null || nestedFrameNamesStructure.isEmpty())) { //is dirty and wasn't me who got it dirty? try { - log.warn("{}Couldn't click the element, switching to the main frame and trying again.", logID); + log.warn("{}Unable to obtain the data from table, switching to the main frame and trying again.", logID); driver.switchTo().defaultContent(); defaultContentFocused = true; return getTableDataWithId(id, secsToWait); } catch (Exception ex2) { - log.error("{}Impossible to to click the element, throwing exception", logID); + log.error("{}Unable to obtain the data from table, throwing exception", logID); } } - throw new White_SeleniumFrameworkException("Unable to click the Button or Link:" + id, ex); + throw new White_SeleniumFrameworkException(String.format("Unable to obtain the data from table with id :%s ", id), ex); } } @@ -909,12 +1048,12 @@ public Optional>> getTableDataWithName(String } catch (Exception ex) { if (!defaultContentFocused && (nestedFrameNamesStructure == null || nestedFrameNamesStructure.isEmpty())) { //is dirty and wasn't me who got it dirty? try { - log.warn("{}Couldn't click the element, switching to the main frame and trying again.", logID); + log.warn("{}Unable to obtain the data from table, switching to the main frame and trying again.", logID); driver.switchTo().defaultContent(); defaultContentFocused = true; return getTableDataWithName(name, secsToWait); } catch (Exception ex2) { - log.error("{}Impossible to to click the element, throwing exception", logID); + log.error("{}Unable to obtain the data from table, throwing exception", logID); } } throw new White_SeleniumFrameworkException(String.format("Unable to obtain the data from table with name :%s ", name), ex); @@ -953,7 +1092,7 @@ public Optional>> getTableDataWithClass(Strin log.trace("{}Start ", logID); try { WebElement table = getElementBy(By.className(cssClass), relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting); - return Optional.ofNullable(getTableData(table)); + return getTableData(table); } catch (Exception ex) { throw new White_SeleniumFrameworkException(String.format("Unable to obtain the data from table with css class :%s ", cssClass), ex); } @@ -1081,8 +1220,12 @@ public Optional>> getTableDataWithText(String String logID = "::getTableDataWithText([text, relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting]): "; log.trace("{}Start ", logID); try { - WebElement table = getElementByText(text, relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting); - return Optional.ofNullable(getTableData(table)); + WebElement table = getElementBy(By.xpath("//table[//*//text()[contains(., '" + text + "')]]"), + relativeNestedFrameNamesStructure, + skipRetryWithNoFrames, + secsToWait, + skipRetryWithoutWaiting); + return getTableData(table); } catch (Exception ex) { throw new White_SeleniumFrameworkException("Unable to obtain data from table", ex); } @@ -1192,7 +1335,7 @@ public Optional>> getTableData(By locator, Co if (table != null) if (scrollToElement) scrollToElement(table); log.trace("{} extracting", logID); - return Optional.ofNullable(getTableData(table)); + return getTableData(table); } catch (Exception ex) { throw new White_SeleniumFrameworkException(String.format("Impossible to extract the data from the table with locator %s", locator), ex); } @@ -1230,23 +1373,31 @@ public Optional>> getTableData(By locator, Co * @param table {@link WebElement table} to extract the data from. * @return {@link List} of {@link Map} representing the rows and cells of the table. */ - public List> getTableData(WebElement table) { + public Optional>> getTableData(WebElement table) { String logID = "::getTable([driver, table]): "; log.trace("{}Start - Obtaining table data", logID); + if (table == null) return Optional.empty(); try { List tableHeaders = table.findElements(By.xpath(".//tr//th")) .stream().map(WebElement::getText).collect(Collectors.toList()); - List headers = !tableHeaders.isEmpty() ? tableHeaders : - table.findElements(By.xpath(".//tbody/tr")).get(0).findElements(By.tagName("td")) + List headers; + if (!tableHeaders.isEmpty()) { + headers = tableHeaders; + } else { + List tableHeaderElements = table.findElements(By.xpath(".//tbody/tr")); + if (tableHeaderElements != null) + headers = tableHeaderElements.get(0).findElements(By.tagName("td")) .stream().map(WebElement::getText).collect(Collectors.toList()); - - return table.findElements(By.xpath(".//tbody/tr")).stream().map(tableRow -> { + else + return Optional.empty(); + } + return Optional.of(table.findElements(By.xpath(".//tbody/tr")).stream().map(tableRow -> { List tableCells = tableRow.findElements(By.tagName("td")); return tableCells.stream().collect(Collectors.toMap( (tableCell) -> headers.get(tableCells.indexOf(tableCell)), WebElement::getText, (x, y) -> x + ", " + y, LinkedHashMap::new)); - }).collect(Collectors.toList()); + }).collect(Collectors.toList())); } catch (Exception ex) { throw new White_SeleniumFrameworkException(String.format("Impossible to obtain data from Table %s", table), ex); } @@ -1489,18 +1640,39 @@ public WebElement getElementByText(String text) { public WebElement getElementByText(String text, Collection relativeNestedFrameNamesStructure, Boolean skipRetryWithNoFrames, Integer secsToWait, Boolean skipRetryWithoutWaiting) { - log.trace("getElementByText(text, relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting) - Start: "); + String logID = "::getElementByText([text, relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting]): "; + log.trace("{}Start ", logID); + WebElement element; try { - - WebElement element = + element = getElementBy(By.xpath("//*[text() = '" + text + "']"), relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting); + if (element == null) { + log.trace("{}Unable to obtain element by text by using first strategy, trying with a second one.", logID); + element = getElementBy(By.xpath("//*[text() = '" + text + "']]"), + relativeNestedFrameNamesStructure, + skipRetryWithNoFrames, + secsToWait, + skipRetryWithoutWaiting); + } log.trace("::getElementByText(text, relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting) - Finish: "); return element; } catch (Exception ex) { - throw new White_SeleniumFrameworkException("Unable to obtain element with text: " + text, ex); + log.warn("{}Unable to obtain element by text by using first strategy, trying with a second one.", logID); + try { + element = getElementBy(By.xpath("//*[text() = '" + text + "']]"), + relativeNestedFrameNamesStructure, + skipRetryWithNoFrames, + secsToWait, + skipRetryWithoutWaiting); + log.trace("::getElementByText(text, relativeNestedFrameNamesStructure, skipRetryWithNoFrames, secsToWait, skipRetryWithoutWaiting) - Finish: "); + return element; + + } catch (Exception e) { + throw new White_SeleniumFrameworkException(String.format("Unable to obtain element with text: [%s] by any methods.", text), ex); + } } } @@ -1862,7 +2034,7 @@ public WebElement getElementBy(By locator, Collection relativeNestedFram * of the page making effectively the {@code relativeNestedFrameNamesStructure} absolute instead of relative, you can skip this operation by setting * the {@code skipRetryWithNoFrames} parameter to {@code true}, This will help your script to not modify the driver's focus if there is an error. * If you don't know what does this "focus change" is, will probably mean that it won't have an impact on your scenario. - * + *

* {@link WebDriver#findElement(org.openqa.selenium.By) } vs {@link WebDriver#findElements(org.openqa.selenium.By) } and * {@link WebDriverWait#until(java.util.function.Function) } on a single and multiple instances. *