Skip to content

Commit

Permalink
[java] Add ability to decorate child classes of WebDriver (#10737)
Browse files Browse the repository at this point in the history
Co-authored-by: Puja Jagani <puja.jagani93@gmail.com>
Co-authored-by: Diego Molina <diemol@users.noreply.github.com>
  • Loading branch information
3 people committed Jul 6, 2022
1 parent 09e296c commit fb4df66
Show file tree
Hide file tree
Showing 15 changed files with 45 additions and 35 deletions.
Expand Up @@ -23,9 +23,9 @@
public class DefaultDecorated<T> implements Decorated<T> {

private final T original;
private final WebDriverDecorator decorator;
private final WebDriverDecorator<?> decorator;

public DefaultDecorated(final T original, final WebDriverDecorator decorator) {
public DefaultDecorated(final T original, final WebDriverDecorator<?> decorator) {
this.original = original;
this.decorator = decorator;
}
Expand All @@ -34,7 +34,7 @@ public final T getOriginal() {
return original;
}

public final WebDriverDecorator getDecorator() {
public final WebDriverDecorator<?> getDecorator() {
return decorator;
}

Expand Down
Expand Up @@ -179,22 +179,33 @@
* </code></pre>
*/
@Beta
public class WebDriverDecorator {
public class WebDriverDecorator<T extends WebDriver> {

private Decorated<WebDriver> decorated;
private final Class<T> targetWebDriverClass;

public final WebDriver decorate(WebDriver original) {
private Decorated<T> decorated;

@SuppressWarnings("unchecked")
public WebDriverDecorator() {
this((Class<T>) WebDriver.class);
}

public WebDriverDecorator(Class<T> targetClass) {
this.targetWebDriverClass = targetClass;
}

public final T decorate(T original) {
Require.nonNull("WebDriver", original);

decorated = createDecorated(original);
return createProxy(decorated, WebDriver.class);
return createProxy(decorated, targetWebDriverClass);
}

public Decorated<WebDriver> getDecoratedDriver() {
public Decorated<T> getDecoratedDriver() {
return decorated;
}

public Decorated<WebDriver> createDecorated(WebDriver driver) {
public Decorated<T> createDecorated(T driver) {
return new DefaultDecorated<>(driver, this);
}

Expand Down Expand Up @@ -248,7 +259,7 @@ public Object onError(

private Object decorateResult(Object toDecorate) {
if (toDecorate instanceof WebDriver) {
return createProxy(getDecoratedDriver(), WebDriver.class);
return createProxy(getDecoratedDriver(), targetWebDriverClass);
}
if (toDecorate instanceof WebElement) {
return createProxy(createDecorated((WebElement) toDecorate), WebElement.class);
Expand Down Expand Up @@ -316,7 +327,7 @@ protected final <Z> Z createProxy(final Decorated<Z> decorated, Class<Z> clazz)
Class<?>[] allInterfacesArray = allInterfaces.toArray(new Class<?>[0]);

Class<? extends Z> proxy = new ByteBuddy()
.subclass(Object.class)
.subclass(clazz.isInterface() ? Object.class : clazz)
.implement(allInterfacesArray)
.method(ElementMatchers.any())
.intercept(InvocationHandlerAdapter.of(handler))
Expand Down
Expand Up @@ -155,7 +155,7 @@
* extending {@link WebDriverDecorator}, not by creating sophisticated listeners.
*/
@Beta
public class EventFiringDecorator extends WebDriverDecorator {
public class EventFiringDecorator<T extends WebDriver> extends WebDriverDecorator<T> {

private static final Logger logger = Logger.getLogger(EventFiringDecorator.class.getName());

Expand Down
2 changes: 1 addition & 1 deletion java/test/org/openqa/selenium/remote/AugmenterTest.java
Expand Up @@ -440,7 +440,7 @@ public Capabilities getCapabilities() {
}
}

private static class ModifyTitleWebDriverDecorator extends WebDriverDecorator {
private static class ModifyTitleWebDriverDecorator extends WebDriverDecorator<WebDriver> {

@Override
public Object call(Decorated<?> target, Method method, Object[] args) throws Throwable {
Expand Down
Expand Up @@ -49,7 +49,7 @@ public Fixture() {
originalDriver = mock(WebDriver.class);
when(originalSwitch.alert()).thenReturn(original);
when(originalDriver.switchTo()).thenReturn(originalSwitch);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.switchTo().alert();
}
}
Expand Down
Expand Up @@ -45,7 +45,7 @@ public Fixture() {
original = mock(WebDriver.Navigation.class);
originalDriver = mock(WebDriver.class);
when(originalDriver.navigate()).thenReturn(original);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.navigate();
}
}
Expand Down
Expand Up @@ -50,7 +50,7 @@ public Fixture() {
original = mock(WebDriver.Options.class);
originalDriver = mock(WebDriver.class);
when(originalDriver.manage()).thenReturn(original);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.manage();
}
}
Expand Down
Expand Up @@ -48,20 +48,19 @@ void shouldImplementWrapsDriverToProvideAccessToUnderlyingDriver() {
RemoteWebDriver originalDriver = mock(RemoteWebDriver.class);
when(originalDriver.getSessionId()).thenReturn(sessionId);

WebDriver decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
RemoteWebDriver decoratedDriver = new WebDriverDecorator<>(RemoteWebDriver.class).decorate(originalDriver);

RemoteWebDriver
underlying =
(RemoteWebDriver) ((WrapsDriver) decoratedDriver).getWrappedDriver();
assertThat(decoratedDriver.getSessionId()).isEqualTo(sessionId);

RemoteWebDriver underlying = (RemoteWebDriver) ((WrapsDriver) decoratedDriver).getWrappedDriver();
assertThat(underlying.getSessionId()).isEqualTo(sessionId);
}

@Test
void cannotConvertDecoratedToRemoteWebDriver() {
RemoteWebDriver originalDriver = mock(RemoteWebDriver.class);

WebDriver decorated = new WebDriverDecorator().decorate(originalDriver);
WebDriver decorated = new WebDriverDecorator<>().decorate(originalDriver);

assertThat(decorated).isNotInstanceOf(RemoteWebDriver.class);
}
Expand All @@ -70,7 +69,7 @@ void cannotConvertDecoratedToRemoteWebDriver() {
void decoratedDriversShouldImplementWrapsDriver() {
RemoteWebDriver originalDriver = mock(RemoteWebDriver.class);

WebDriver decorated = new WebDriverDecorator().decorate(originalDriver);
WebDriver decorated = new WebDriverDecorator<>().decorate(originalDriver);

assertThat(decorated).isInstanceOf(WrapsDriver.class);
}
Expand All @@ -85,7 +84,7 @@ void decoratedElementsShouldImplementWrapsElement() {

when(originalDriver.findElement(any())).thenReturn(originalElement);

WebDriver decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
WebDriver decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
WebElement element = decoratedDriver.findElement(By.id("test"));

assertThat(element).isInstanceOf(WrapsElement.class);
Expand All @@ -101,7 +100,7 @@ void canConvertDecoratedRemoteWebElementToJson() {

when(originalDriver.findElement(any())).thenReturn(originalElement);

WebDriver decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
WebDriver decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);

WebElement element = decoratedDriver.findElement(By.id("test"));

Expand Down
Expand Up @@ -48,7 +48,7 @@ public Fixture() {
original = mock(WebDriver.TargetLocator.class);
originalDriver = mock(WebDriver.class);
when(originalDriver.switchTo()).thenReturn(original);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.switchTo();
}
}
Expand Down
Expand Up @@ -48,7 +48,7 @@ public Fixture() {
originalDriver = mock(WebDriver.class);
when(originalOptions.timeouts()).thenReturn(original);
when(originalDriver.manage()).thenReturn(originalOptions);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.manage().timeouts();
}
}
Expand Down
Expand Up @@ -86,9 +86,9 @@ void canCompareDecorated() {
WebDriver original1 = mock(WebDriver.class);
WebDriver original2 = mock(WebDriver.class);

WebDriver decorated1 = new WebDriverDecorator().decorate(original1);
WebDriver decorated2 = new WebDriverDecorator().decorate(original1);
WebDriver decorated3 = new WebDriverDecorator().decorate(original2);
WebDriver decorated1 = new WebDriverDecorator<>().decorate(original1);
WebDriver decorated2 = new WebDriverDecorator<>().decorate(original1);
WebDriver decorated3 = new WebDriverDecorator<>().decorate(original2);
assertThat(decorated1).isEqualTo(decorated2);
assertThat(decorated1).isNotEqualTo(decorated3);

Expand All @@ -101,7 +101,7 @@ void canCompareDecorated() {
@Test
void testHashCode() {
WebDriver original = mock(WebDriver.class);
WebDriver decorated = new WebDriverDecorator().decorate(original);
WebDriver decorated = new WebDriverDecorator<>().decorate(original);
assertThat(decorated.hashCode()).isEqualTo(original.hashCode());
}

Expand Down
Expand Up @@ -56,7 +56,7 @@ public Fixture() {
original = mock(WebElement.class);
originalDriver = mock(WebDriver.class);
when(originalDriver.findElement(any())).thenReturn(original);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.findElement(By.id("test"));
}
}
Expand Down
Expand Up @@ -50,7 +50,7 @@ public Fixture() {
originalDriver = mock(WebDriver.class);
when(originalOptions.window()).thenReturn(original);
when(originalDriver.manage()).thenReturn(originalOptions);
decoratedDriver = new WebDriverDecorator().decorate(originalDriver);
decoratedDriver = new WebDriverDecorator<>().decorate(originalDriver);
decorated = decoratedDriver.manage().window();
}
}
Expand Down
Expand Up @@ -34,7 +34,7 @@
@Tag("UnitTests")
class IntegrationTest {

static class CountCalls extends WebDriverDecorator {
static class CountCalls extends WebDriverDecorator<WebDriver> {

int counterBefore = 0;
int counterAfter = 0;
Expand Down
Expand Up @@ -36,7 +36,7 @@ void shouldNotAddInterfacesNotAvailableInTheOriginalDriver() {
WebDriver driver = mock(WebDriver.class);
assertThat(driver).isNotInstanceOf(SomeOtherInterface.class);

WebDriver decorated = new WebDriverDecorator().decorate(driver);
WebDriver decorated = new WebDriverDecorator<>().decorate(driver);
assertThat(decorated).isNotInstanceOf(SomeOtherInterface.class);
}

Expand All @@ -45,7 +45,7 @@ void shouldRespectInterfacesAvailableInTheOriginalDriver() {
WebDriver driver = mock(ExtendedDriver.class);
assertThat(driver).isInstanceOf(SomeOtherInterface.class);

WebDriver decorated = new WebDriverDecorator().decorate(driver);
WebDriver decorated = new WebDriverDecorator<>().decorate(driver);
assertThat(decorated).isInstanceOf(SomeOtherInterface.class);
}
}

0 comments on commit fb4df66

Please sign in to comment.