diff --git a/visual-java/src/main/java/com/saucelabs/visual/CheckOptions.java b/visual-java/src/main/java/com/saucelabs/visual/CheckOptions.java index 7d5bdb4e..42ce9349 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/CheckOptions.java +++ b/visual-java/src/main/java/com/saucelabs/visual/CheckOptions.java @@ -30,6 +30,7 @@ public CheckOptions( DiffingOptionsIn diffingOptions, Boolean captureDom, String clipSelector, + WebElement clipElement, FullPageScreenshotConfig fullPageScreenshotConfig) { this.ignoreElements = ignoreElements; this.ignoreRegions = ignoreRegions; @@ -39,6 +40,7 @@ public CheckOptions( this.diffingMethod = diffingMethod; this.captureDom = captureDom; this.clipSelector = clipSelector; + this.clipElement = clipElement; this.fullPageScreenshotConfig = fullPageScreenshotConfig; this.diffingOptions = diffingOptions; } @@ -53,6 +55,7 @@ public CheckOptions( private DiffingOptionsIn diffingOptions; private Boolean captureDom; private String clipSelector; + private WebElement clipElement; private FullPageScreenshotConfig fullPageScreenshotConfig; public static class Builder { @@ -65,6 +68,7 @@ public static class Builder { private DiffingOptionsIn diffingOptions; private Boolean captureDom; private String clipSelector; + private WebElement clipElement; private FullPageScreenshotConfig fullPageScreenshotConfig; public Builder withIgnoreElements(List ignoreElements) { @@ -107,6 +111,11 @@ public Builder withFullPageConfig(FullPageScreenshotConfig fullPageScreenshotCon return this; } + public Builder withClipElement(WebElement clipElement) { + this.clipElement = clipElement; + return this; + } + public Builder disableOnly(EnumSet flags) { this.diffingOptions = new DiffingOptionsIn(); DiffingFlag.setAll(this.diffingOptions, true); @@ -144,6 +153,7 @@ public CheckOptions build() { diffingOptions, captureDom, clipSelector, + clipElement, fullPageScreenshotConfig); } } @@ -216,6 +226,14 @@ public void setClipSelector(String clipSelector) { this.clipSelector = clipSelector; } + public WebElement getClipElement() { + return clipElement; + } + + public void setClipElement(WebElement clipElement) { + this.clipElement = clipElement; + } + public FullPageScreenshotConfig getFullPageScreenshotConfig() { return fullPageScreenshotConfig; } diff --git a/visual-java/src/main/java/com/saucelabs/visual/VisualApi.java b/visual-java/src/main/java/com/saucelabs/visual/VisualApi.java index 02d9fca2..a40f555e 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/VisualApi.java +++ b/visual-java/src/main/java/com/saucelabs/visual/VisualApi.java @@ -16,6 +16,7 @@ import java.time.Duration; import java.util.*; import java.util.stream.Collectors; +import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.remote.RemoteWebElement; @@ -115,6 +116,7 @@ public VisualApi build() { private Boolean captureDom; private FullPageScreenshotConfig fullPageScreenshotConfig; private String sessionMetadataBlob; + private final RemoteWebDriver driver; /** * Creates a VisualApi instance for a given Visual Backend {@link DataCenter} @@ -181,11 +183,12 @@ public VisualApi( this.jobId = jobIdString == null ? sessionId : jobIdString; this.build = VisualBuild.getBuildOnce(this, buildAttributes); this.sessionMetadataBlob = this.webdriverSessionInfo().blob; + this.driver = driver; } VisualApi( String jobId, - String sessionId, + RemoteWebDriver driver, VisualBuild build, String sessionMetadataBlob, String url, @@ -201,7 +204,8 @@ public VisualApi( } this.build = build; this.jobId = jobId; - this.sessionId = sessionId; + this.sessionId = driver.getSessionId().toString(); + this.driver = driver; this.client = new GraphQLClient(url, username, accessKey); this.sessionMetadataBlob = sessionMetadataBlob; } @@ -403,9 +407,10 @@ public void sauceVisualCheck(String snapshotName, CheckOptions options) { input.setCaptureDom(captureDom); } - String clipSelector = options.getClipSelector(); - if (clipSelector != null) { - input.setClipSelector(clipSelector); + if (options.getClipElement() != null) { + input.setClipElement(options.getClipElement()); + } else if (options.getClipSelector() != null) { + input.setClipElement(this.driver.findElement(By.cssSelector(options.getClipSelector()))); } FullPageScreenshotConfig fullPageScreenshotConfig = diff --git a/visual-java/src/main/java/com/saucelabs/visual/graphql/CreateSnapshotFromWebDriverMutation.java b/visual-java/src/main/java/com/saucelabs/visual/graphql/CreateSnapshotFromWebDriverMutation.java index 4148e4e8..e8d65fda 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/graphql/CreateSnapshotFromWebDriverMutation.java +++ b/visual-java/src/main/java/com/saucelabs/visual/graphql/CreateSnapshotFromWebDriverMutation.java @@ -12,6 +12,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.remote.RemoteWebElement; public class CreateSnapshotFromWebDriverMutation implements GraphQLOperation { public static final String OPERATION_DOCUMENT = @@ -43,6 +45,8 @@ public static class CreateSnapshotFromWebDriverIn { public Optional clipSelector = Optional.empty(); + public Optional clipElement = Optional.empty(); + public Optional fullPageConfig = Optional.empty(); public Optional diffingOptions = Optional.empty(); @@ -84,6 +88,10 @@ public void setClipSelector(String clipSelector) { this.clipSelector = Optional.of(clipSelector); } + public void setClipElement(WebElement clipElement) { + this.clipElement = Optional.of(((RemoteWebElement) clipElement).getId()); + } + public void setFullPageConfig(FullPageScreenshotConfig fullPageConfig) { this.fullPageConfig = Optional.ofNullable(fullPageConfig); } diff --git a/visual-java/src/test/java/com/saucelabs/visual/VisualApiTest.java b/visual-java/src/test/java/com/saucelabs/visual/VisualApiTest.java index 7b921c69..5b374669 100644 --- a/visual-java/src/test/java/com/saucelabs/visual/VisualApiTest.java +++ b/visual-java/src/test/java/com/saucelabs/visual/VisualApiTest.java @@ -22,7 +22,7 @@ class VisualApiTest { void sauceVisualResultsTest() throws IllegalAccessException { VisualApi api = new VisualApi( - "", "", new VisualBuild(null, null, null, null, null, null), "", "", "u", "k"); + "", null, new VisualBuild(null, null, null, null, null, null), "", "", "u", "k"); GraphQLClient mockGraphQLClient = mock(GraphQLClient.class); when(mockGraphQLClient.execute(any(), any())) .thenReturn( diff --git a/visual-java/src/test/java/com/saucelabs/visual/integration/LoginPageIT.java b/visual-java/src/test/java/com/saucelabs/visual/integration/LoginPageIT.java index e334a669..b8e2fe34 100644 --- a/visual-java/src/test/java/com/saucelabs/visual/integration/LoginPageIT.java +++ b/visual-java/src/test/java/com/saucelabs/visual/integration/LoginPageIT.java @@ -4,10 +4,12 @@ import com.saucelabs.saucebindings.UnhandledPromptBehavior; import com.saucelabs.saucebindings.junit5.SauceBaseTest; import com.saucelabs.saucebindings.options.SauceOptions; +import com.saucelabs.visual.CheckOptions; import com.saucelabs.visual.VisualApi; import com.saucelabs.visual.junit5.TestMetaInfoExtension; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.openqa.selenium.By; @ExtendWith({TestMetaInfoExtension.class}) class LoginPageIT extends SauceBaseTest { @@ -25,7 +27,12 @@ void checkLoginPage() { VisualApi visual = new VisualApi(driver, System.getenv("SAUCE_USERNAME"), System.getenv("SAUCE_ACCESS_KEY")); driver.get("https://www.saucedemo.com"); - visual.sauceVisualCheck("Login page"); + visual.sauceVisualCheck( + "Login page", + new CheckOptions.Builder() + .withClipElement( + driver.findElement(By.cssSelector("input[data-test=\"login-button\"]"))) + .build()); System.out.println("Sauce Visual: " + visual.getBuild().getUrl()); } }