From 9e8fe86dd248b60ce8365197b50972a7feaed0bf Mon Sep 17 00:00:00 2001 From: Kerem Date: Thu, 4 Jul 2024 15:17:22 +0000 Subject: [PATCH] [java] Support SAUCE_REGION (#83) --- .../java/com/saucelabs/visual/DataCenter.java | 18 +++++++++++++ .../java/com/saucelabs/visual/VisualApi.java | 27 +++++++++++++++++-- .../visual/graphql/GraphQLClient.java | 10 +++++++ .../visual/utils/EnvironmentVariables.java | 2 ++ .../visual/integration/LoginPageIT.java | 7 +---- 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/visual-java/src/main/java/com/saucelabs/visual/DataCenter.java b/visual-java/src/main/java/com/saucelabs/visual/DataCenter.java index d6faf052..107bdf22 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/DataCenter.java +++ b/visual-java/src/main/java/com/saucelabs/visual/DataCenter.java @@ -1,5 +1,7 @@ package com.saucelabs.visual; +import com.saucelabs.visual.exception.VisualApiException; + public enum DataCenter { US_WEST_1("https://api.us-west-1.saucelabs.com/v1/visual/graphql"), US_EAST_4("https://api.us-east-4.saucelabs.com/v1/visual/graphql"), @@ -10,4 +12,20 @@ public enum DataCenter { DataCenter(String endpoint) { this.endpoint = endpoint; } + + static DataCenter fromSauceRegion(String sauceRegion) { + if (sauceRegion == null) { + return US_WEST_1; + } + switch (sauceRegion) { + case "us-west-1": + return US_WEST_1; + case "eu-central-1": + return EU_CENTRAL_1; + case "us-east-4": + return US_EAST_4; + default: + throw new VisualApiException("Unknown region: " + sauceRegion); + } + } } 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 7be07318..02d9fca2 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/VisualApi.java +++ b/visual-java/src/main/java/com/saucelabs/visual/VisualApi.java @@ -25,6 +25,10 @@ public class VisualApi { private static final Logger log = LoggerFactory.getLogger(VisualApi.class); + private static String resolveEndpoint() { + return DataCenter.fromSauceRegion(EnvironmentVariables.SAUCE_REGION).endpoint; + } + /** Creates a VisualApi instance using builder style */ public static class Builder { private final RemoteWebDriver driver; @@ -39,7 +43,7 @@ public static class Builder { private FullPageScreenshotConfig fullPageScreenshotConfig; public Builder(RemoteWebDriver driver, String username, String accessKey) { - this(driver, username, accessKey, DataCenter.US_WEST_1.endpoint); + this(driver, username, accessKey, resolveEndpoint()); } public Builder(RemoteWebDriver driver, String username, String accessKey, DataCenter region) { @@ -112,6 +116,17 @@ public VisualApi build() { private FullPageScreenshotConfig fullPageScreenshotConfig; private String sessionMetadataBlob; + /** + * Creates a VisualApi instance for a given Visual Backend {@link DataCenter} + * + * @param driver The {@link org.openqa.selenium.WebDriver} instance where the tests should run at + * @param username SauceLabs username + * @param accessKey SauceLabs access key + */ + public VisualApi(RemoteWebDriver driver, String username, String accessKey) { + this(driver, resolveEndpoint(), username, accessKey); + } + /** * Creates a VisualApi instance for a given Visual Backend {@link DataCenter} * @@ -218,7 +233,15 @@ private WebdriverSessionInfoQuery.Result webdriverSessionInfo() { WebdriverSessionInfoQuery query = new WebdriverSessionInfoQuery( new WebdriverSessionInfoQuery.WebdriverSessionInfoIn(this.jobId, this.sessionId)); - return this.client.execute(query, WebdriverSessionInfoQuery.Data.class).result; + try { + WebdriverSessionInfoQuery.Data response = + this.client.execute(query, WebdriverSessionInfoQuery.Data.class); + return response.result; + } catch (VisualApiException e) { + log.error( + "Sauce Visual: No WebDriver session found. Please make sure WebDriver and Sauce Visual data centers are aligned."); + throw e; + } } /** diff --git a/visual-java/src/main/java/com/saucelabs/visual/graphql/GraphQLClient.java b/visual-java/src/main/java/com/saucelabs/visual/graphql/GraphQLClient.java index 69771f5d..45d7ca6a 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/graphql/GraphQLClient.java +++ b/visual-java/src/main/java/com/saucelabs/visual/graphql/GraphQLClient.java @@ -68,6 +68,16 @@ public D execute(GraphQLOperation operation, Class responseType) JsonNode rootNode = objectMapper.readTree(responseString); JsonNode dataField = rootNode.get("data"); + JsonNode errors = rootNode.get("errors"); + + if (errors != null) { + JsonNode message = errors.findValue("message"); + if (message != null) { + throw new VisualApiException(message.asText()); + } else { + throw new VisualApiException("Unexpected error"); + } + } return objectMapper.treeToValue(dataField, responseType); } catch (IOException e) { diff --git a/visual-java/src/main/java/com/saucelabs/visual/utils/EnvironmentVariables.java b/visual-java/src/main/java/com/saucelabs/visual/utils/EnvironmentVariables.java index f3e53c1d..3eed1b10 100644 --- a/visual-java/src/main/java/com/saucelabs/visual/utils/EnvironmentVariables.java +++ b/visual-java/src/main/java/com/saucelabs/visual/utils/EnvironmentVariables.java @@ -4,6 +4,8 @@ public class EnvironmentVariables { private EnvironmentVariables() {} + public static final String SAUCE_REGION = System.getenv("SAUCE_REGION"); + public static final String PROJECT_NAME = System.getenv("SAUCE_VISUAL_PROJECT"); public static final String BRANCH_NAME = System.getenv("SAUCE_VISUAL_BRANCH"); public static final String DEFAULT_BRANCH_NAME = System.getenv("SAUCE_VISUAL_DEFAULT_BRANCH"); 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 0fd362da..e334a669 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,7 +4,6 @@ import com.saucelabs.saucebindings.UnhandledPromptBehavior; import com.saucelabs.saucebindings.junit5.SauceBaseTest; import com.saucelabs.saucebindings.options.SauceOptions; -import com.saucelabs.visual.DataCenter; import com.saucelabs.visual.VisualApi; import com.saucelabs.visual.junit5.TestMetaInfoExtension; import org.junit.jupiter.api.Test; @@ -24,11 +23,7 @@ public SauceOptions createSauceOptions() { @Test void checkLoginPage() { VisualApi visual = - new VisualApi( - driver, - DataCenter.US_WEST_1, - System.getenv("SAUCE_USERNAME"), - System.getenv("SAUCE_ACCESS_KEY")); + new VisualApi(driver, System.getenv("SAUCE_USERNAME"), System.getenv("SAUCE_ACCESS_KEY")); driver.get("https://www.saucedemo.com"); visual.sauceVisualCheck("Login page"); System.out.println("Sauce Visual: " + visual.getBuild().getUrl());