From fb4df665ab89638abaff63bc1c838b51e5fbf07f Mon Sep 17 00:00:00 2001 From: Valery Yatsynovich Date: Wed, 6 Jul 2022 14:19:35 +0200 Subject: [PATCH] [java] Add ability to decorate child classes of `WebDriver` (#10737) Co-authored-by: Puja Jagani Co-authored-by: Diego Molina --- .../support/decorators/DefaultDecorated.java | 6 ++--- .../decorators/WebDriverDecorator.java | 27 +++++++++++++------ .../support/events/EventFiringDecorator.java | 2 +- .../openqa/selenium/remote/AugmenterTest.java | 2 +- .../decorators/DecoratedAlertTest.java | 2 +- .../decorators/DecoratedNavigationTest.java | 2 +- .../decorators/DecoratedOptionsTest.java | 2 +- .../DecoratedRemoteWebDriverTest.java | 15 +++++------ .../decorators/DecoratedSwitchToTest.java | 2 +- .../decorators/DecoratedTimeoutsTest.java | 2 +- .../decorators/DecoratedWebDriverTest.java | 8 +++--- .../decorators/DecoratedWebElementTest.java | 2 +- .../decorators/DecoratedWindowTest.java | 2 +- .../support/decorators/IntegrationTest.java | 2 +- .../support/decorators/InterfacesTest.java | 4 +-- 15 files changed, 45 insertions(+), 35 deletions(-) diff --git a/java/src/org/openqa/selenium/support/decorators/DefaultDecorated.java b/java/src/org/openqa/selenium/support/decorators/DefaultDecorated.java index 0eace50a2e200..cc5735a776f1f 100644 --- a/java/src/org/openqa/selenium/support/decorators/DefaultDecorated.java +++ b/java/src/org/openqa/selenium/support/decorators/DefaultDecorated.java @@ -23,9 +23,9 @@ public class DefaultDecorated implements Decorated { 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; } @@ -34,7 +34,7 @@ public final T getOriginal() { return original; } - public final WebDriverDecorator getDecorator() { + public final WebDriverDecorator getDecorator() { return decorator; } diff --git a/java/src/org/openqa/selenium/support/decorators/WebDriverDecorator.java b/java/src/org/openqa/selenium/support/decorators/WebDriverDecorator.java index 1a832ce37300b..e7c45eab2b552 100644 --- a/java/src/org/openqa/selenium/support/decorators/WebDriverDecorator.java +++ b/java/src/org/openqa/selenium/support/decorators/WebDriverDecorator.java @@ -179,22 +179,33 @@ * */ @Beta -public class WebDriverDecorator { +public class WebDriverDecorator { - private Decorated decorated; + private final Class targetWebDriverClass; - public final WebDriver decorate(WebDriver original) { + private Decorated decorated; + + @SuppressWarnings("unchecked") + public WebDriverDecorator() { + this((Class) WebDriver.class); + } + + public WebDriverDecorator(Class 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 getDecoratedDriver() { + public Decorated getDecoratedDriver() { return decorated; } - public Decorated createDecorated(WebDriver driver) { + public Decorated createDecorated(T driver) { return new DefaultDecorated<>(driver, this); } @@ -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); @@ -316,7 +327,7 @@ protected final Z createProxy(final Decorated decorated, Class clazz) Class[] allInterfacesArray = allInterfaces.toArray(new Class[0]); Class proxy = new ByteBuddy() - .subclass(Object.class) + .subclass(clazz.isInterface() ? Object.class : clazz) .implement(allInterfacesArray) .method(ElementMatchers.any()) .intercept(InvocationHandlerAdapter.of(handler)) diff --git a/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java b/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java index f0f2cd63ecc62..df1f16348b90d 100644 --- a/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java +++ b/java/src/org/openqa/selenium/support/events/EventFiringDecorator.java @@ -155,7 +155,7 @@ * extending {@link WebDriverDecorator}, not by creating sophisticated listeners. */ @Beta -public class EventFiringDecorator extends WebDriverDecorator { +public class EventFiringDecorator extends WebDriverDecorator { private static final Logger logger = Logger.getLogger(EventFiringDecorator.class.getName()); diff --git a/java/test/org/openqa/selenium/remote/AugmenterTest.java b/java/test/org/openqa/selenium/remote/AugmenterTest.java index 998f36043ace9..ce57034fff424 100644 --- a/java/test/org/openqa/selenium/remote/AugmenterTest.java +++ b/java/test/org/openqa/selenium/remote/AugmenterTest.java @@ -440,7 +440,7 @@ public Capabilities getCapabilities() { } } - private static class ModifyTitleWebDriverDecorator extends WebDriverDecorator { + private static class ModifyTitleWebDriverDecorator extends WebDriverDecorator { @Override public Object call(Decorated target, Method method, Object[] args) throws Throwable { diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedAlertTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedAlertTest.java index 17aedb6456427..cc4288851ee8a 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedAlertTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedAlertTest.java @@ -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(); } } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedNavigationTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedNavigationTest.java index e2b2bd4c43388..db2572673938b 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedNavigationTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedNavigationTest.java @@ -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(); } } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedOptionsTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedOptionsTest.java index fb1b886d6f516..a013576a15b68 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedOptionsTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedOptionsTest.java @@ -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(); } } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedRemoteWebDriverTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedRemoteWebDriverTest.java index 98fa66bcdd467..8d54724e7bb93 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedRemoteWebDriverTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedRemoteWebDriverTest.java @@ -48,12 +48,11 @@ 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); } @@ -61,7 +60,7 @@ void shouldImplementWrapsDriverToProvideAccessToUnderlyingDriver() { void cannotConvertDecoratedToRemoteWebDriver() { RemoteWebDriver originalDriver = mock(RemoteWebDriver.class); - WebDriver decorated = new WebDriverDecorator().decorate(originalDriver); + WebDriver decorated = new WebDriverDecorator<>().decorate(originalDriver); assertThat(decorated).isNotInstanceOf(RemoteWebDriver.class); } @@ -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); } @@ -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); @@ -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")); diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedSwitchToTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedSwitchToTest.java index 5339305c0be34..da29e660d2699 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedSwitchToTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedSwitchToTest.java @@ -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(); } } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedTimeoutsTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedTimeoutsTest.java index c564cb02deb26..bf869dce51bfa 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedTimeoutsTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedTimeoutsTest.java @@ -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(); } } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedWebDriverTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedWebDriverTest.java index 8bf3351273369..f3f7b8251e4ba 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedWebDriverTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedWebDriverTest.java @@ -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); @@ -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()); } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedWebElementTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedWebElementTest.java index d389bb19cb525..a8019858bfa9b 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedWebElementTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedWebElementTest.java @@ -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")); } } diff --git a/java/test/org/openqa/selenium/support/decorators/DecoratedWindowTest.java b/java/test/org/openqa/selenium/support/decorators/DecoratedWindowTest.java index f96abfdbf3012..bb7ce669e95db 100644 --- a/java/test/org/openqa/selenium/support/decorators/DecoratedWindowTest.java +++ b/java/test/org/openqa/selenium/support/decorators/DecoratedWindowTest.java @@ -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(); } } diff --git a/java/test/org/openqa/selenium/support/decorators/IntegrationTest.java b/java/test/org/openqa/selenium/support/decorators/IntegrationTest.java index aec409baa5ca6..e0dee79f892c6 100644 --- a/java/test/org/openqa/selenium/support/decorators/IntegrationTest.java +++ b/java/test/org/openqa/selenium/support/decorators/IntegrationTest.java @@ -34,7 +34,7 @@ @Tag("UnitTests") class IntegrationTest { - static class CountCalls extends WebDriverDecorator { + static class CountCalls extends WebDriverDecorator { int counterBefore = 0; int counterAfter = 0; diff --git a/java/test/org/openqa/selenium/support/decorators/InterfacesTest.java b/java/test/org/openqa/selenium/support/decorators/InterfacesTest.java index ee63e40e3f4fa..2c4b56f7259ee 100644 --- a/java/test/org/openqa/selenium/support/decorators/InterfacesTest.java +++ b/java/test/org/openqa/selenium/support/decorators/InterfacesTest.java @@ -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); } @@ -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); } }