From e85253c91a23091d2d92c8ae5f9c2aec222669cb Mon Sep 17 00:00:00 2001 From: amandeepsingh333 Date: Fri, 28 Mar 2025 10:30:47 +0530 Subject: [PATCH 1/6] added regions --- README.md | 62 ++++++++++++++++ src/main/java/io/percy/selenium/Percy.java | 76 ++++++++++++++++++++ src/test/java/io/percy/selenium/SdkTest.java | 47 ++++++++++++ 3 files changed, 185 insertions(+) diff --git a/README.md b/README.md index d36d74b..0b336c7 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,68 @@ public class Example { - `bottom` (int): Bottom coordinate of the consider region. - `left` (int): Left coordinate of the consider region. - `right` (int): Right coordinate of the consider region. + - `regions` parameter that allows users to apply snapshot options to specific areas of the page. This parameter is an array where each object defines a custom region with configurations. + - Parameters: + - `elementSelector` (mandatory, only one of the following must be provided) + - `boundingBox` (object): Defines the coordinates and size of the region. + - `x` (number): X-coordinate of the region. + - `y` (number): Y-coordinate of the region. + - `width` (number): Width of the region. + - `height` (number): Height of the region. + - `elementXpath` (string): The XPath selector for the element. + - `elementCSS` (string): The CSS selector for the element. + - `padding` (optional) + - Specifies additional padding around the selected region. + - Properties: + - `top` (number): Padding from the top. + - `left` (number): Padding from the left. + - `right` (number): Padding from the right. + - `bottom` (number): Padding from the bottom. + - `algorithm` (mandatory) + - Specifies the snapshot comparison algorithm. + - Allowed values: `standard`, `layout`, `ignore`, `intelliignore`. + - `configuration` (required for `standard` and `intelliignore` algorithms, ignored otherwise) + - `diffSensitivity` (number): Sensitivity level for detecting differences. + - `imageIgnoreThreshold` (number): Threshold for ignoring minor image differences. + - `carouselsEnabled` (boolean): Whether to enable carousel detection. + - `bannersEnabled` (boolean): Whether to enable banner detection. + - `adsEnabled` (boolean): Whether to enable ad detection. + - `assertion` (optional) + - Defines assertions to apply to the region. + - `diffIgnoreThreshold` (number): The threshold for ignoring minor differences. +### Example Usage for regions +``` + Map elementSelector = new HashMap<>(); + elementSelector.put("elementCSS", ".ad-banner"); + + Map padding = new HashMap<>(); + padding.put("top", 10); + padding.put("left", 20); + padding.put("right", 15); + padding.put("bottom", 10); + + Map configuration = new HashMap<>(); + configuration.put("diffSensitivity", 2); + configuration.put("imageIgnoreThreshold", 0.2); + configuration.put("carouselsEnabled", true); + configuration.put("bannersEnabled", true); + configuration.put("adsEnabled", true); + + Map assertion = new HashMap<>(); + assertion.put("diffIgnoreThreshold", 0.4); + + Map obj1 = new HashMap<>(); + obj1.put("elementSelector", elementSelector); + obj1.put("padding", padding); + obj1.put("algorithm", "intelliignore"); + obj1.put("configuration", configuration); + obj1.put("assertion", assertion); + + List> regions = Collections.singletonList(obj1); + + percy.snapshot("Homepage", regions); + +``` ### Creating Percy on automate build Note: Automate Percy Token starts with `auto` keyword. The command can be triggered using `exec` keyword. diff --git a/src/main/java/io/percy/selenium/Percy.java b/src/main/java/io/percy/selenium/Percy.java index 7fe919b..76a9283 100644 --- a/src/main/java/io/percy/selenium/Percy.java +++ b/src/main/java/io/percy/selenium/Percy.java @@ -28,6 +28,9 @@ import java.util.stream.Collectors; +import javax.swing.text.html.CSS; +import javax.xml.xpath.XPath; + /** * Percy client for visual testing. */ @@ -75,6 +78,79 @@ public Percy(WebDriver driver) { this.env = new Environment(driver); } + /** + * Creates a region configuration based on the provided parameters. + * + * @param boundingBox The bounding box of the region, or null. + * @param elementXpath The XPath of the element, or null. + * @param elementCSS The CSS selector of the element, or null. + * @param padding The padding around the region, or null. + * @param algorithm The algorithm to be used (default 'ignore'). + * @param diffSensitivity The sensitivity for diffing, or null. + * @param imageIgnoreThreshold The image ignore threshold, or null. + * @param carouselsEnabled Flag for enabling carousels, or null. + * @param bannersEnabled Flag for enabling banners, or null. + * @param adsEnabled Flag for enabling ads, or null. + * @param diffIgnoreThreshold The diff ignore threshold, or null. + * @return A map representing the region configuration. + */ + + public Map createRegion(Map params) { + Map elementSelector = new HashMap<>(); + if (params.containsKey("boundingBox")) { + elementSelector.put("boundingBox", params.get("boundingBox")); + } + if (params.containsKey("elementXpath")) { + elementSelector.put("elementXpath", params.get("elementXpath")); + } + if (params.containsKey("elementCSS")) { + elementSelector.put("elementCSS", params.get("elementCSS")); + } + + Map region = new HashMap<>(); + region.put("algorithm", params.getOrDefault("algorithm", "ignore")); + region.put("elementSelector", elementSelector); + + if (params.containsKey("padding")) { + region.put("padding", params.get("padding")); + } + + Map configuration = new HashMap<>(); + String algorithm = (String) params.getOrDefault("algorithm", "ignore"); + if (algorithm.equals("standard") || algorithm.equals("intelliignore")) { + if (params.containsKey("diffSensitivity")) { + configuration.put("diffSensitivity", params.get("diffSensitivity")); + } + if (params.containsKey("imageIgnoreThreshold")) { + configuration.put("imageIgnoreThreshold", params.get("imageIgnoreThreshold")); + } + if (params.containsKey("carouselsEnabled")) { + configuration.put("carouselsEnabled", params.get("carouselsEnabled")); + } + if (params.containsKey("bannersEnabled")) { + configuration.put("bannersEnabled", params.get("bannersEnabled")); + } + if (params.containsKey("adsEnabled")) { + configuration.put("adsEnabled", params.get("adsEnabled")); + } + } + + if (!configuration.isEmpty()) { + region.put("configuration", configuration); + } + + Map assertion = new HashMap<>(); + if (params.containsKey("diffIgnoreThreshold")) { + assertion.put("diffIgnoreThreshold", params.get("diffIgnoreThreshold")); + } + + if (!assertion.isEmpty()) { + region.put("assertion", assertion); + } + + return region; + } + /** * Take a snapshot and upload it to Percy. * diff --git a/src/test/java/io/percy/selenium/SdkTest.java b/src/test/java/io/percy/selenium/SdkTest.java index 9619c8d..d7c6b6f 100644 --- a/src/test/java/io/percy/selenium/SdkTest.java +++ b/src/test/java/io/percy/selenium/SdkTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -207,4 +208,50 @@ public void takeScreenshotThrowErrorForWeb() { Throwable exception = assertThrows(RuntimeException.class, () -> mockedPercy.screenshot("Test")); assertEquals("Invalid function call - screenshot(). Please use snapshot() function for taking screenshot. screenshot() should be used only while using Percy with Automate. For more information on usage of snapshot(), refer doc for your language https://www.browserstack.com/docs/percy/integrate/overview", exception.getMessage()); } + + @Test + public void createRegionTest() { + // Setup the parameters for the region + Map params = new HashMap<>(); + params.put("boundingBox", "100,100,200,200"); + params.put("elementXpath", "//div[@id='test']"); + params.put("elementCSS", ".test-class"); + params.put("padding", 10); + params.put("algorithm", "standard"); + params.put("diffSensitivity", 0.5); + params.put("imageIgnoreThreshold", 0.2); + params.put("carouselsEnabled", true); + params.put("bannersEnabled", false); + params.put("adsEnabled", true); + params.put("diffIgnoreThreshold", 0.1); + + // Call the method to create the region + Map region = percy.createRegion(params); + + // Validate the returned region + assertNotNull(region); + + // Check if elementSelector was added correctly + Map elementSelector = (Map) region.get("elementSelector"); + assertNotNull(elementSelector); + assertEquals("100,100,200,200", elementSelector.get("boundingBox")); + assertEquals("//div[@id='test']", elementSelector.get("elementXpath")); + assertEquals(".test-class", elementSelector.get("elementCSS")); + + // Validate algorithm and configuration + assertEquals("standard", region.get("algorithm")); + + Map configuration = (Map) region.get("configuration"); + assertNotNull(configuration); + assertEquals(0.5, configuration.get("diffSensitivity")); + assertEquals(0.2, configuration.get("imageIgnoreThreshold")); + assertTrue((Boolean) configuration.get("carouselsEnabled")); + assertFalse((Boolean) configuration.get("bannersEnabled")); + assertTrue((Boolean) configuration.get("adsEnabled")); + + // Validate assertion + Map assertion = (Map) region.get("assertion"); + assertNotNull(assertion); + assertEquals(0.1, assertion.get("diffIgnoreThreshold")); + } } From 62ba70d6e969a15ac697e64f1798b3a2e8722e6b Mon Sep 17 00:00:00 2001 From: amandeepsingh333 Date: Fri, 28 Mar 2025 10:33:23 +0530 Subject: [PATCH 2/6] version fix --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b165439..29151f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ jobs: - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn cache dir)" - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} key: v1/${{ runner.os }}/java-${{ matrix.java }}/${{ hashFiles('**/yarn.lock') }} From e735ff800da06b404739807eec0aae0be8a19e40 Mon Sep 17 00:00:00 2001 From: amandeepsingh333 Date: Tue, 8 Apr 2025 17:06:12 +0530 Subject: [PATCH 3/6] cli version upgrade to 1.30.9 --- README.md | 14 ------------ package.json | 2 +- src/main/java/io/percy/selenium/Percy.java | 25 ++++++++++++---------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 0b336c7..50e15f2 100644 --- a/README.md +++ b/README.md @@ -230,13 +230,6 @@ public class Example { - `height` (number): Height of the region. - `elementXpath` (string): The XPath selector for the element. - `elementCSS` (string): The CSS selector for the element. - - `padding` (optional) - - Specifies additional padding around the selected region. - - Properties: - - `top` (number): Padding from the top. - - `left` (number): Padding from the left. - - `right` (number): Padding from the right. - - `bottom` (number): Padding from the bottom. - `algorithm` (mandatory) - Specifies the snapshot comparison algorithm. - Allowed values: `standard`, `layout`, `ignore`, `intelliignore`. @@ -254,12 +247,6 @@ public class Example { Map elementSelector = new HashMap<>(); elementSelector.put("elementCSS", ".ad-banner"); - Map padding = new HashMap<>(); - padding.put("top", 10); - padding.put("left", 20); - padding.put("right", 15); - padding.put("bottom", 10); - Map configuration = new HashMap<>(); configuration.put("diffSensitivity", 2); configuration.put("imageIgnoreThreshold", 0.2); @@ -272,7 +259,6 @@ public class Example { Map obj1 = new HashMap<>(); obj1.put("elementSelector", elementSelector); - obj1.put("padding", padding); obj1.put("algorithm", "intelliignore"); obj1.put("configuration", configuration); obj1.put("assertion", assertion); diff --git a/package.json b/package.json index f33e97a..4711c51 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,6 @@ "test": "npx percy exec --testing -- mvn test" }, "devDependencies": { - "@percy/cli": "1.29.5-beta.0" + "@percy/cli": "1.30.9" } } diff --git a/src/main/java/io/percy/selenium/Percy.java b/src/main/java/io/percy/selenium/Percy.java index 76a9283..b66bf21 100644 --- a/src/main/java/io/percy/selenium/Percy.java +++ b/src/main/java/io/percy/selenium/Percy.java @@ -81,17 +81,20 @@ public Percy(WebDriver driver) { /** * Creates a region configuration based on the provided parameters. * - * @param boundingBox The bounding box of the region, or null. - * @param elementXpath The XPath of the element, or null. - * @param elementCSS The CSS selector of the element, or null. - * @param padding The padding around the region, or null. - * @param algorithm The algorithm to be used (default 'ignore'). - * @param diffSensitivity The sensitivity for diffing, or null. - * @param imageIgnoreThreshold The image ignore threshold, or null. - * @param carouselsEnabled Flag for enabling carousels, or null. - * @param bannersEnabled Flag for enabling banners, or null. - * @param adsEnabled Flag for enabling ads, or null. - * @param diffIgnoreThreshold The diff ignore threshold, or null. + * @param params A map containing the region configuration options. Expected keys: + *
    + *
  • boundingBox - The bounding box of the region, or null.
  • + *
  • elementXpath - The XPath of the element, or null.
  • + *
  • elementCSS - The CSS selector of the element, or null.
  • + *
  • padding - The padding around the region, or null.
  • + *
  • algorithm - The algorithm to be used (default: 'ignore').
  • + *
  • diffSensitivity - The sensitivity for diffing, or null.
  • + *
  • imageIgnoreThreshold - The image ignore threshold, or null.
  • + *
  • carouselsEnabled - Flag for enabling carousels, or null.
  • + *
  • bannersEnabled - Flag for enabling banners, or null.
  • + *
  • adsEnabled - Flag for enabling ads, or null.
  • + *
  • diffIgnoreThreshold - The diff ignore threshold, or null.
  • + *
* @return A map representing the region configuration. */ From 7ad8613d72be3e9e6d6c2581a02e1bef9cb14876 Mon Sep 17 00:00:00 2001 From: amandeepsingh333 Date: Wed, 9 Apr 2025 17:57:23 +0530 Subject: [PATCH 4/6] updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50e15f2..cddee46 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ public class Example { - `right` (int): Right coordinate of the consider region. - `regions` parameter that allows users to apply snapshot options to specific areas of the page. This parameter is an array where each object defines a custom region with configurations. - Parameters: - - `elementSelector` (mandatory, only one of the following must be provided) + - `elementSelector` (optional, only one of the following must be provided, if this is not provided then full page will be considered as region) - `boundingBox` (object): Defines the coordinates and size of the region. - `x` (number): X-coordinate of the region. - `y` (number): Y-coordinate of the region. From 92532995f20d04dadbf65a51ae70831a2fb94d0e Mon Sep 17 00:00:00 2001 From: amandeepsingh333 Date: Thu, 17 Apr 2025 09:09:31 +0530 Subject: [PATCH 5/6] readme --- README.md | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index cddee46..e2eca62 100644 --- a/README.md +++ b/README.md @@ -244,28 +244,23 @@ public class Example { - `diffIgnoreThreshold` (number): The threshold for ignoring minor differences. ### Example Usage for regions ``` - Map elementSelector = new HashMap<>(); - elementSelector.put("elementCSS", ".ad-banner"); - - Map configuration = new HashMap<>(); - configuration.put("diffSensitivity", 2); - configuration.put("imageIgnoreThreshold", 0.2); - configuration.put("carouselsEnabled", true); - configuration.put("bannersEnabled", true); - configuration.put("adsEnabled", true); - - Map assertion = new HashMap<>(); - assertion.put("diffIgnoreThreshold", 0.4); - - Map obj1 = new HashMap<>(); - obj1.put("elementSelector", elementSelector); - obj1.put("algorithm", "intelliignore"); - obj1.put("configuration", configuration); - obj1.put("assertion", assertion); - + Map params = new HashMap<>(); + params.put("elementXpath", "//div[@id='test']"); + params.put("algorithm", "standard"); + params.put("diffSensitivity", 3); + params.put("imageIgnoreThreshold", 0.2); + params.put("carouselsEnabled", true); + params.put("bannersEnabled", false); + params.put("adsEnabled", true); + params.put("diffIgnoreThreshold", 0.1); + + // Call the method to create the region + Map regions2 = percy.createRegion(params); List> regions = Collections.singletonList(obj1); + Map options = new HashMap<>(); + options.put("regions", regions); - percy.snapshot("Homepage", regions); + percy.snapshot("Homepage", options); ``` From 49a19adfa396796954adc98bc4f32d97e29bea84 Mon Sep 17 00:00:00 2001 From: amandeepsingh333 Date: Fri, 18 Apr 2025 12:15:27 +0530 Subject: [PATCH 6/6] resolved comment --- src/main/java/io/percy/selenium/Percy.java | 26 ++++++++++------------ 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/percy/selenium/Percy.java b/src/main/java/io/percy/selenium/Percy.java index b66bf21..0cf20f0 100644 --- a/src/main/java/io/percy/selenium/Percy.java +++ b/src/main/java/io/percy/selenium/Percy.java @@ -121,20 +121,18 @@ public Map createRegion(Map params) { Map configuration = new HashMap<>(); String algorithm = (String) params.getOrDefault("algorithm", "ignore"); if (algorithm.equals("standard") || algorithm.equals("intelliignore")) { - if (params.containsKey("diffSensitivity")) { - configuration.put("diffSensitivity", params.get("diffSensitivity")); - } - if (params.containsKey("imageIgnoreThreshold")) { - configuration.put("imageIgnoreThreshold", params.get("imageIgnoreThreshold")); - } - if (params.containsKey("carouselsEnabled")) { - configuration.put("carouselsEnabled", params.get("carouselsEnabled")); - } - if (params.containsKey("bannersEnabled")) { - configuration.put("bannersEnabled", params.get("bannersEnabled")); - } - if (params.containsKey("adsEnabled")) { - configuration.put("adsEnabled", params.get("adsEnabled")); + List keys = Arrays.asList( + "diffSensitivity", + "imageIgnoreThreshold", + "carouselsEnabled", + "bannersEnabled", + "adsEnabled" + ); + + for (String key : keys) { + if (params.containsKey(key)) { + configuration.put(key, params.get(key)); + } } }