Skip to content

Commit a2d50c4

Browse files
committed
[java] Add hooks around getScreenshotAs in WebDriverListener #16232
WebDriverListener has now default methods for both WebDriver and WebElement for clients to be notified before and after a screenshot is being taken. Fixes #16232
1 parent 6a8f6c6 commit a2d50c4

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

java/src/org/openqa/selenium/support/events/WebDriverListener.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
import org.openqa.selenium.Cookie;
3131
import org.openqa.selenium.Dimension;
3232
import org.openqa.selenium.JavascriptExecutor;
33+
import org.openqa.selenium.OutputType;
3334
import org.openqa.selenium.Point;
3435
import org.openqa.selenium.ScriptKey;
36+
import org.openqa.selenium.TakesScreenshot;
3537
import org.openqa.selenium.WebDriver;
3638
import org.openqa.selenium.WebElement;
3739
import org.openqa.selenium.WindowType;
@@ -330,6 +332,26 @@ default void beforeResetInputState(WebDriver driver) {}
330332
*/
331333
default void afterResetInputState(WebDriver driver) {}
332334

335+
/**
336+
* This method will be called before {@link TakesScreenshot#getScreenshotAs(OutputType)} is
337+
* called.
338+
*
339+
* @param driver - decorated WebDriver instance
340+
* @param target - target type, @see OutputType
341+
* @param <X> - return type for getScreenshotAs.
342+
*/
343+
default <X> void beforeGetScreenshotAs(WebDriver driver, OutputType<X> target) {}
344+
345+
/**
346+
* This method will be called after {@link TakesScreenshot#getScreenshotAs(OutputType)} is called.
347+
*
348+
* @param driver - decorated WebDriver instance
349+
* @param target - target type, @see OutputType
350+
* @param result - object in which is stored information about the screenshot.
351+
* @param <X> - return type for getScreenshotAs.
352+
*/
353+
default <X> void afterGetScreenshotAs(WebDriver driver, OutputType<X> target, X result) {}
354+
333355
// WebElement
334356

335357
/**
@@ -581,6 +603,24 @@ default void beforeGetCssValue(WebElement element, String propertyName) {}
581603
*/
582604
default void afterGetCssValue(WebElement element, String propertyName, String result) {}
583605

606+
/**
607+
* @param element - decorated WebElement instance
608+
* @param target - target type, @see OutputType
609+
* @param <X> - return type for getScreenshotAs.
610+
*/
611+
default <X> void beforeGetScreenshotAs(WebElement element, OutputType<X> target) {}
612+
613+
/**
614+
* This action will be performed each time after {@link WebDriver.TargetLocator#alert()} is
615+
* called.
616+
*
617+
* @param element - decorated WebElement instance
618+
* @param target - target type, @see OutputType
619+
* @param result - object in which is stored information about the screenshot.
620+
* @param <X> - return type for getScreenshotAs.
621+
*/
622+
default <X> void afterGetScreenshotAs(WebElement element, OutputType<X> target, X result) {}
623+
584624
// Navigation (WebDriver.Navigation)
585625

586626
/**

java/test/org/openqa/selenium/support/events/EventFiringDecoratorTest.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@
4444
import org.openqa.selenium.Dimension;
4545
import org.openqa.selenium.ImmutableCapabilities;
4646
import org.openqa.selenium.JavascriptExecutor;
47+
import org.openqa.selenium.OutputType;
4748
import org.openqa.selenium.Point;
49+
import org.openqa.selenium.TakesScreenshot;
4850
import org.openqa.selenium.WebDriver;
4951
import org.openqa.selenium.WebDriverException;
5052
import org.openqa.selenium.WebElement;
@@ -285,9 +287,11 @@ public void afterPerform(WebDriver driver, Collection<Sequence> actions) {
285287

286288
@Test
287289
void shouldFireWebElementEvents() {
290+
String result = "result";
288291
WebDriver driver = mock(WebDriver.class);
289292
WebElement element = mock(WebElement.class);
290293
when(driver.findElement(any())).thenReturn(element);
294+
when(element.getScreenshotAs(OutputType.BASE64)).thenReturn(result);
291295

292296
CollectorListener listener =
293297
new CollectorListener() {
@@ -467,6 +471,16 @@ public void beforeGetCssValue(WebElement element, String propertyName) {
467471
public void afterGetCssValue(WebElement element, String propertyName, String result) {
468472
acc.append("afterGetCssValue").append("\n");
469473
}
474+
475+
@Override
476+
public <X> void beforeGetScreenshotAs(WebElement driver, OutputType<X> target) {
477+
acc.append("beforeGetScreenshotAs ").append(target).append("\n");
478+
}
479+
480+
@Override
481+
public <X> void afterGetScreenshotAs(WebElement driver, OutputType<X> target, X result) {
482+
acc.append("afterGetScreenshotAs ").append(target).append(" ").append(result).append("\n");
483+
}
470484
};
471485

472486
WebDriver decorated = new EventFiringDecorator<>(listener).decorate(driver);
@@ -485,6 +499,7 @@ public void afterGetCssValue(WebElement element, String propertyName, String res
485499
element1.getSize();
486500
element1.getCssValue("test");
487501
element1.clear();
502+
element1.getScreenshotAs(OutputType.BASE64);
488503

489504
assertThat(listener.acc.toString().trim())
490505
.isEqualTo(
@@ -545,7 +560,11 @@ public void afterGetCssValue(WebElement element, String propertyName, String res
545560
"beforeAnyWebElementCall clear",
546561
"beforeClear",
547562
"afterClear",
548-
"afterAnyWebElementCall clear"));
563+
"afterAnyWebElementCall clear",
564+
"beforeAnyWebElementCall getScreenshotAs",
565+
"beforeGetScreenshotAs OutputType.BASE64",
566+
"afterGetScreenshotAs OutputType.BASE64 " + result,
567+
"afterAnyWebElementCall getScreenshotAs"));
549568
}
550569

551570
@Test
@@ -973,6 +992,40 @@ public void afterAlert(WebDriver.TargetLocator targetLocator, Alert alert) {
973992
"afterAnyCall alert"));
974993
}
975994

995+
@Test
996+
void shouldFireWebDriverTakesScreenshotEvents() {
997+
String result = "result";
998+
WebDriver driver = mock(WebDriver.class, withSettings().extraInterfaces(TakesScreenshot.class));
999+
when(((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64)).thenReturn(result);
1000+
1001+
CollectorListener listener =
1002+
new CollectorListener() {
1003+
@Override
1004+
public <X> void beforeGetScreenshotAs(WebDriver driver, OutputType<X> target) {
1005+
acc.append("beforeGetScreenshotAs ").append(target).append("\n");
1006+
}
1007+
1008+
@Override
1009+
public <X> void afterGetScreenshotAs(WebDriver driver, OutputType<X> target, X result) {
1010+
acc.append("afterGetScreenshotAs ").append(target).append(" ").append(result).append("\n");
1011+
}
1012+
};
1013+
WebDriver decorated = new EventFiringDecorator<>(listener).decorate(driver);
1014+
1015+
((TakesScreenshot) decorated).getScreenshotAs(OutputType.BASE64);
1016+
1017+
assertThat(listener.acc.toString().trim())
1018+
.isEqualTo(
1019+
String.join(
1020+
"\n",
1021+
"beforeAnyCall getScreenshotAs",
1022+
"beforeAnyWebDriverCall getScreenshotAs",
1023+
"beforeGetScreenshotAs OutputType.BASE64",
1024+
"afterGetScreenshotAs OutputType.BASE64 " + result,
1025+
"afterAnyWebDriverCall getScreenshotAs",
1026+
"afterAnyCall getScreenshotAs"));
1027+
}
1028+
9761029
@Test
9771030
void shouldSuppressExceptionInBeforeAnyCall() {
9781031
WebDriver driver = mock(WebDriver.class);

0 commit comments

Comments
 (0)