Skip to content

Commit

Permalink
Merge pull request #32 from WhiteOrganization/31-create-a-notfoundtab…
Browse files Browse the repository at this point in the history
…leexception

Multiple fixes on WebDriverUtils
  • Loading branch information
obed-vazquez authored Dec 18, 2022
2 parents 6f0c491 + d30e006 commit 16318ee
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 27 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -48,7 +48,7 @@ by including it in your POM](https://maven.pkg.github.com/whiteorganization/whit
<dependency>
<groupId>io.github.whiteorganization</groupId>
<artifactId>white-selenium-framework</artifactId>
<version>0.3.1</version>
<version>0.3.2</version>
</dependency>
```
If used on a long-term heavy-use project we recommend:
Expand All @@ -61,7 +61,7 @@ If used on a long-term heavy-use project we recommend:
<dependency>
<groupId>io.github.whiteorganization</groupId>
<artifactId>white-selenium-framework</artifactId>
<version>0.3.1</version>
<version>0.3.2</version>
<!-- You need to manually import this library due to lack of maintenance on White_SeleniumFramework -->
<exclusions>
<exclusion>
Expand Down Expand Up @@ -101,7 +101,7 @@ and import the dependency like this:
<dependency>
<groupId>com.github.WhiteOrganization</groupId>
<artifactId>White_SeleniumFramework</artifactId>
<version>white-selenium-framework-0.3.1</version>
<version>white-selenium-framework-0.3.2</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.whiteorganization</groupId>
<artifactId>white-selenium-framework</artifactId>
<version>0.3.1</version>
<version>0.3.2</version>
<name>${project.groupId}:${project.artifactId}</name>
<description>A Selenium Framework that will help to execute tests and custom scenarios faster and reduce the effort
to access many sections Selenium related.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,145 @@ public String getTextFrom(By locator, Collection<String> nestedFrameNamesStructu

//<editor-fold defaultstate="collapsed" desc="Table Data">


/**
* Extracts all the data from a {@code <table>} and it will transform the rows ({@code <td>}s) into {@link Map}s indicating their header and cell value into its
* pairs.
* For example, this table: <br/>
* <table>
* <thead>
* <tr>
* <th>First Name</th>
* <th>Email</th>
* </tr>
* </thead>
* <tbody id="usersBody">
* <tr>
* <td>baz</td>
* <td>[email protected]</td>
* </tr>
* <tr>
* <td>bar</td>
* <td>[email protected]</td>
* </tr>
* <tr>
* <td>foo</td>
* <td>[email protected]</td>
* </tr>
* </tbody>
* </table> <br/>
* will be transformed into {@link List} objects with this format:
* {@code [{First Name=baz, [email protected]}, {First Name=bar, [email protected]}, {First Name=foo, [email protected]}]}.
* <p>
* This method will use the first table if any is found.
* </p>
*
* @return {@link List} of {@link Map} representing the rows and cells of the table.
* @throws White_SeleniumFrameworkException When an error is found.
* @author <a href="mailto:[email protected]">Obed Vazquez</a>
*/
public Optional<List<LinkedHashMap<String, String>>> getTableDataWithTag() {
return getTableDataWithTag("table", null);
}

private Optional<List<LinkedHashMap<String, String>>> getTableDataWithTag(String tagName) {
return getTableDataWithTag(tagName, null);
}


/**
* Extracts all the data from a {@code <table>} and it will transform the rows ({@code <td>}s) into {@link Map}s indicating their header and cell value into its
* pairs.
* For example, this table: <br/>
* <table>
* <thead>
* <tr>
* <th>First Name</th>
* <th>Email</th>
* </tr>
* </thead>
* <tbody id="usersBody">
* <tr>
* <td>baz</td>
* <td>[email protected]</td>
* </tr>
* <tr>
* <td>bar</td>
* <td>[email protected]</td>
* </tr>
* <tr>
* <td>foo</td>
* <td>[email protected]</td>
* </tr>
* </tbody>
* </table> <br/>
* will be transformed into {@link List} objects with this format:
* {@code [{First Name=baz, [email protected]}, {First Name=bar, [email protected]}, {First Name=foo, [email protected]}]}.
* <p>
* This method will use the first table if any is found.
* </p>
*
* @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 <a href="mailto:[email protected]">Obed Vazquez</a>
*/
public Optional<List<LinkedHashMap<String, String>>> getTableDataWithTag(Integer secsToWait) {
return getTableDataWithTag("table", secsToWait);
}

/**
* Extracts all the data from a {@code <table>} and it will transform the rows ({@code <td>}s) into {@link Map}s indicating their header and cell value into its
* pairs.
* For example, this table: <br/>
* <table>
* <thead>
* <tr>
* <th>First Name</th>
* <th>Email</th>
* </tr>
* </thead>
* <tbody id="usersBody">
* <tr>
* <td>baz</td>
* <td>[email protected]</td>
* </tr>
* <tr>
* <td>bar</td>
* <td>[email protected]</td>
* </tr>
* <tr>
* <td>foo</td>
* <td>[email protected]</td>
* </tr>
* </tbody>
* </table> <br/>
* will be transformed into {@link List} objects with this format:
* {@code [{First Name=baz, [email protected]}, {First Name=bar, [email protected]}, {First Name=foo, [email protected]}]}.
* <p>
* This method will use the first table if any is found.
* </p>
*
* @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 <a href="mailto:[email protected]">Obed Vazquez</a>
*/
public Optional<List<LinkedHashMap<String, String>>> 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 <table>} and it will transform the rows ({@code <td>}s) into {@link Map}s indicating their header and cell value into its
* pairs.
Expand Down Expand Up @@ -874,24 +1013,24 @@ public Optional<List<LinkedHashMap<String, String>>> getTableDataWithId(String i
}

public Optional<List<LinkedHashMap<String, String>>> getTableDataWithId(String id, Collection<String> 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);
return getTableData(By.id(id), secsToWait);
} 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);
}
}

Expand All @@ -909,12 +1048,12 @@ public Optional<List<LinkedHashMap<String, String>>> 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);
Expand Down Expand Up @@ -953,7 +1092,7 @@ public Optional<List<LinkedHashMap<String, String>>> 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);
}
Expand Down Expand Up @@ -1081,8 +1220,12 @@ public Optional<List<LinkedHashMap<String, String>>> 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);
}
Expand Down Expand Up @@ -1192,7 +1335,7 @@ public Optional<List<LinkedHashMap<String, String>>> 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);
}
Expand Down Expand Up @@ -1230,23 +1373,31 @@ public Optional<List<LinkedHashMap<String, String>>> 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<LinkedHashMap<String, String>> getTableData(WebElement table) {
public Optional<List<LinkedHashMap<String, String>>> getTableData(WebElement table) {
String logID = "::getTable([driver, table]): ";
log.trace("{}Start - Obtaining table data", logID);
if (table == null) return Optional.empty();
try {
List<String> tableHeaders = table.findElements(By.xpath(".//tr//th"))
.stream().map(WebElement::getText).collect(Collectors.toList());

List<String> headers = !tableHeaders.isEmpty() ? tableHeaders :
table.findElements(By.xpath(".//tbody/tr")).get(0).findElements(By.tagName("td"))
List<String> headers;
if (!tableHeaders.isEmpty()) {
headers = tableHeaders;
} else {
List<WebElement> 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<WebElement> 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);
}
Expand Down Expand Up @@ -1489,18 +1640,39 @@ public WebElement getElementByText(String text) {

public WebElement getElementByText(String text, Collection<String> 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);
}
}
}

Expand Down Expand Up @@ -1862,7 +2034,7 @@ public WebElement getElementBy(By locator, Collection<String> 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.
* <i>If you don't know what does this "focus change" is, will probably mean that it won't have an impact on your scenario</i>.
*
* <p>
* {@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.
*
Expand Down

0 comments on commit 16318ee

Please sign in to comment.