Skip to content

Commit

Permalink
Fixes tests for firefox
Browse files Browse the repository at this point in the history
  • Loading branch information
Jiwari committed Mar 9, 2020
1 parent 4c26ac3 commit 3c616af
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 19 deletions.
51 changes: 45 additions & 6 deletions java/client/src/org/openqa/selenium/ShadowElementFinder.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package org.openqa.selenium;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
* Helper to to verify if some element has a Shadow Root attached to it and allow further querying to locate nested elements attached to it.
Expand Down Expand Up @@ -34,10 +36,47 @@ public boolean hasShadowElement(WebElement element) {
* @return A WebElement if there is a Shadow Root attached to the element, null otherwise
*/
@SuppressWarnings("unchecked")
public List<WebElement> extractShadowElementOf(WebElement element, By by) {
String cssSelector = getCssSelectorOfBy(by);
final String SHADOW_ROOT_SCRIPT = String.format("return arguments[0].shadowRoot.querySelectorAll('%s')", cssSelector);
return (List<WebElement>) jsExecutor.executeScript(SHADOW_ROOT_SCRIPT, element);
public Optional<List<WebElement>> extractShadowElementsOf(WebElement element, By by) {
try {
String cssSelector = getCssSelectorOfBy(by);
final String SHADOW_ROOT_SCRIPT = String.format("return arguments[0].shadowRoot.querySelectorAll('%s')", cssSelector);
List<WebElement> webElements = (List<WebElement>) jsExecutor.executeScript(SHADOW_ROOT_SCRIPT, element);
return Optional.ofNullable(webElements);
} catch (Exception e) {
throw new InvalidSelectorException("It was not possible to locate the elements inside the Shadow Root. Locator " + by.toString());
}
}

/**
* Safely locates elements from the element using the {@link By}
*
* @param element An element with a shadow root
* @param by A {@link org.openqa.selenium.By.ByCssSelector}
* @return A list of the found elements, or an empty list if there is an error
*/
public List<WebElement> safeLocateElementsFromShadow(WebElement element, By by) {
try {
Optional<List<WebElement>> optional = extractShadowElementsOf(element, by);
return optional.orElseGet(ArrayList::new);
} catch (Exception e) {
return Collections.singletonList(element);
}
}

/**
* Safely locates elements from the element using the {@link By}, and returns the first found element
*
* @param element An element with a shadow root
* @param by A {@link org.openqa.selenium.By.ByCssSelector}
* @return The first element of the list, or the element provided if nothing is found
*/
public WebElement safeLocateElementFromShadow(WebElement element, By by) {
Optional<List<WebElement>> optional = extractShadowElementsOf(element, by);
if (optional.isPresent()) {
return optional.get().get(0);
} else {
return element;
}
}

/**
Expand All @@ -47,7 +86,7 @@ public List<WebElement> extractShadowElementOf(WebElement element, By by) {
* @param by A {@link org.openqa.selenium.By.ByCssSelector}
* @return The css
*/
private String getCssSelectorOfBy(By by) {
protected String getCssSelectorOfBy(By by) {
if (by instanceof By.ByCssSelector) {
By.ByCssSelector byCssSelector = (By.ByCssSelector) by;
return byCssSelector.getCssSelector();
Expand All @@ -65,7 +104,7 @@ private String getCssSelectorOfBy(By by) {
public List<WebElement> extractShadowElementsWithBy(List<WebElement> elements, By by) {
List<WebElement> extractedElements = new ArrayList<>();
for (WebElement element : elements) {
extractedElements.addAll(extractShadowElementOf(element, by));
extractedElements.addAll(safeLocateElementsFromShadow(element, by));
}
return extractedElements;
}
Expand Down
80 changes: 67 additions & 13 deletions java/client/test/org/openqa/selenium/ShadowElementFinderTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.openqa.selenium;

import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.Test;
import org.openqa.selenium.testing.Ignore;
import org.openqa.selenium.testing.JUnit4TestBase;

import java.util.Arrays;
Expand All @@ -10,8 +10,7 @@
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;
import static org.openqa.selenium.testing.drivers.Browser.FIREFOX;
import static org.openqa.selenium.testing.drivers.Browser.MARIONETTE;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class ShadowElementFinderTest extends JUnit4TestBase {

Expand All @@ -36,32 +35,35 @@ public void testShadowElementDoesNotExist() {
}

@Test
public void testShadowElementUnsafeExtractionIsReturned() {
public void testShadowElementExtractionReturnsList() {
driver.get(pages.shadowElementsPage);

WebElement element = driver.findElement(By.id("outside_shadow"));
Optional<WebElement> result = new ShadowElementFinder(driver).extractShadowElementOf(element);
By by = By.cssSelector("nested-element");
Optional<List<WebElement>> result = new ShadowElementFinder(driver).extractShadowElementsOf(element, by);

assertThat(result.isPresent()).isTrue();
assertThat(result).isPresent();
assertThat(result.get()).hasSize(1);
}

@Test
@Ignore(MARIONETTE)
public void testShadowElementUnsafeExtractionIsNull() {
public void testShadowElementInvalidSelectorReturnsEmpty() {
driver.get(pages.shadowElementsPage);

WebElement element = driver.findElement(By.id("no_shadow"));
Optional<WebElement> result = new ShadowElementFinder(driver).extractShadowElementOf(element);
By by = By.cssSelector("invalid");
Optional<List<WebElement>> result = new ShadowElementFinder(driver).extractShadowElementsOf(element, by);

assertThat(result.isPresent()).isFalse();
assertThat(result).isNotPresent();
}

@Test
public void testShadowElementSafeExtractionIsReturned() {
driver.get(pages.shadowElementsPage);

WebElement element = driver.findElement(By.id("outside_shadow"));
WebElement extractedElement = new ShadowElementFinder(driver).safeExtractShadowElementOf(element);
By by = By.cssSelector("nested-element");
WebElement extractedElement = new ShadowElementFinder(driver).safeLocateElementFromShadow(element, by);

assertThat(extractedElement).isNotNull();
assertThat(extractedElement).isNotEqualTo(element);
Expand All @@ -72,7 +74,8 @@ public void testSafeExtractReturnsSameElementWhenElementIsNotShadow() {
driver.get(pages.shadowElementsPage);

WebElement element = driver.findElement(By.id("no_shadow"));
WebElement extractedElement = new ShadowElementFinder(driver).safeExtractShadowElementOf(element);
By by = By.cssSelector("invalid");
WebElement extractedElement = new ShadowElementFinder(driver).safeLocateElementFromShadow(element, by);

assertThat(extractedElement).isNotNull();
assertThat(extractedElement).isEqualTo(element);
Expand All @@ -85,12 +88,63 @@ public void testExtractShadowElementsFromList() {
WebElement noShadow = driver.findElement(By.id("no_shadow"));
WebElement outsideShadow = driver.findElement(By.id("outside_shadow"));
List<WebElement> list = Arrays.asList(noShadow, outsideShadow);
List<WebElement> extractedElements = new ShadowElementFinder(driver).extractShadowElements(list);
By by = By.cssSelector("nested-element");
List<WebElement> extractedElements = new ShadowElementFinder(driver).extractShadowElementsWithBy(list, by);

assertThat(extractedElements).isNotNull();
assertThat(extractedElements).hasSize(2);
assertThat(extractedElements).allMatch(Objects::nonNull);
assertThat(extractedElements).contains(noShadow);
assertThat(extractedElements).doesNotContain(outsideShadow);
}

@Test
public void testShadowElementsSafeExtractionIsReturned() {
driver.get(pages.shadowElementsPage);

WebElement element = driver.findElement(By.id("outside_shadow"));
By by = By.cssSelector("nested-element");
List<WebElement> extractedElement = new ShadowElementFinder(driver).safeLocateElementsFromShadow(element, by);

assertThat(extractedElement).isNotNull();
assertThat(extractedElement).hasSize(1);
assertThat(extractedElement).isNotEqualTo(element);
}

@Test
public void testSafeExtractReturnsSameElementWhenElementsIsNotShadow() {
driver.get(pages.shadowElementsPage);

WebElement element = driver.findElement(By.id("no_shadow"));
By by = By.cssSelector("invalid");
List<WebElement> extractedElement = new ShadowElementFinder(driver).safeLocateElementsFromShadow(element, by);

assertThat(extractedElement).isNotNull();
assertThat(extractedElement).hasSize(1);
assertThat(extractedElement).isEqualTo(element);
}

@Test
public void testGetCssSelectorByReturnsCorrectString() {
driver.get(pages.shadowElementsPage);

String cssString = "someSelector";
By by = By.cssSelector(cssString);
String actualCssSelector = new ShadowElementFinder(driver).getCssSelectorOfBy(by);

assertThat(actualCssSelector).isNotNull();
assertThat(actualCssSelector).isEqualTo(cssString);
}

@Test
public void testGetCssSelectorByThrowsExceptionForNonCss() {
driver.get(pages.shadowElementsPage);

List<By> bys = Arrays.asList(By.xpath("xpath"), By.id("id"), By.linkText("linkText"), By.className("className"),
By.tagName("tagName"), By.name("name"), By.partialLinkText("partiaLinkText"));
bys.forEach(by -> {
ThrowingCallable callable = () -> new ShadowElementFinder(driver).getCssSelectorOfBy(by);
assertThatThrownBy(callable).hasCauseInstanceOf(InvalidSelectorException.class);
});
}
}

0 comments on commit 3c616af

Please sign in to comment.