Skip to content

Commit 36b826a

Browse files
adding regions support for sdk (#297)
* added regions * version fix * cli version upgrade to 1.30.9 * updated readme * readme * resolved comment
1 parent 79d3ef3 commit 36b826a

File tree

5 files changed

+169
-2
lines changed

5 files changed

+169
-2
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Get yarn cache directory path
3333
id: yarn-cache-dir-path
3434
run: echo "::set-output name=dir::$(yarn cache dir)"
35-
- uses: actions/cache@v2
35+
- uses: actions/cache@v3
3636
with:
3737
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
3838
key: v1/${{ runner.os }}/java-${{ matrix.java }}/${{ hashFiles('**/yarn.lock') }}

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,49 @@ public class Example {
220220
- `bottom` (int): Bottom coordinate of the consider region.
221221
- `left` (int): Left coordinate of the consider region.
222222
- `right` (int): Right coordinate of the consider region.
223+
- `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.
224+
- Parameters:
225+
- `elementSelector` (optional, only one of the following must be provided, if this is not provided then full page will be considered as region)
226+
- `boundingBox` (object): Defines the coordinates and size of the region.
227+
- `x` (number): X-coordinate of the region.
228+
- `y` (number): Y-coordinate of the region.
229+
- `width` (number): Width of the region.
230+
- `height` (number): Height of the region.
231+
- `elementXpath` (string): The XPath selector for the element.
232+
- `elementCSS` (string): The CSS selector for the element.
233+
- `algorithm` (mandatory)
234+
- Specifies the snapshot comparison algorithm.
235+
- Allowed values: `standard`, `layout`, `ignore`, `intelliignore`.
236+
- `configuration` (required for `standard` and `intelliignore` algorithms, ignored otherwise)
237+
- `diffSensitivity` (number): Sensitivity level for detecting differences.
238+
- `imageIgnoreThreshold` (number): Threshold for ignoring minor image differences.
239+
- `carouselsEnabled` (boolean): Whether to enable carousel detection.
240+
- `bannersEnabled` (boolean): Whether to enable banner detection.
241+
- `adsEnabled` (boolean): Whether to enable ad detection.
242+
- `assertion` (optional)
243+
- Defines assertions to apply to the region.
244+
- `diffIgnoreThreshold` (number): The threshold for ignoring minor differences.
245+
### Example Usage for regions
246+
```
247+
Map<String, Object> params = new HashMap<>();
248+
params.put("elementXpath", "//div[@id='test']");
249+
params.put("algorithm", "standard");
250+
params.put("diffSensitivity", 3);
251+
params.put("imageIgnoreThreshold", 0.2);
252+
params.put("carouselsEnabled", true);
253+
params.put("bannersEnabled", false);
254+
params.put("adsEnabled", true);
255+
params.put("diffIgnoreThreshold", 0.1);
256+
257+
// Call the method to create the region
258+
Map<String, Object> regions2 = percy.createRegion(params);
259+
List<Map<String, Object>> regions = Collections.singletonList(obj1);
260+
Map<String, Object> options = new HashMap<>();
261+
options.put("regions", regions);
262+
263+
percy.snapshot("Homepage", options);
264+
265+
```
223266
224267
### Creating Percy on automate build
225268
Note: Automate Percy Token starts with `auto` keyword. The command can be triggered using `exec` keyword.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
"test": "npx percy exec --testing -- mvn test"
55
},
66
"devDependencies": {
7-
"@percy/cli": "1.29.5-beta.0"
7+
"@percy/cli": "1.30.9"
88
}
99
}

src/main/java/io/percy/selenium/Percy.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828

2929
import java.util.stream.Collectors;
3030

31+
import javax.swing.text.html.CSS;
32+
import javax.xml.xpath.XPath;
33+
3134
/**
3235
* Percy client for visual testing.
3336
*/
@@ -75,6 +78,80 @@ public Percy(WebDriver driver) {
7578
this.env = new Environment(driver);
7679
}
7780

81+
/**
82+
* Creates a region configuration based on the provided parameters.
83+
*
84+
* @param params A map containing the region configuration options. Expected keys:
85+
* <ul>
86+
* <li>boundingBox - The bounding box of the region, or null.</li>
87+
* <li>elementXpath - The XPath of the element, or null.</li>
88+
* <li>elementCSS - The CSS selector of the element, or null.</li>
89+
* <li>padding - The padding around the region, or null.</li>
90+
* <li>algorithm - The algorithm to be used (default: 'ignore').</li>
91+
* <li>diffSensitivity - The sensitivity for diffing, or null.</li>
92+
* <li>imageIgnoreThreshold - The image ignore threshold, or null.</li>
93+
* <li>carouselsEnabled - Flag for enabling carousels, or null.</li>
94+
* <li>bannersEnabled - Flag for enabling banners, or null.</li>
95+
* <li>adsEnabled - Flag for enabling ads, or null.</li>
96+
* <li>diffIgnoreThreshold - The diff ignore threshold, or null.</li>
97+
* </ul>
98+
* @return A map representing the region configuration.
99+
*/
100+
101+
public Map<String, Object> createRegion(Map<String, Object> params) {
102+
Map<String, Object> elementSelector = new HashMap<>();
103+
if (params.containsKey("boundingBox")) {
104+
elementSelector.put("boundingBox", params.get("boundingBox"));
105+
}
106+
if (params.containsKey("elementXpath")) {
107+
elementSelector.put("elementXpath", params.get("elementXpath"));
108+
}
109+
if (params.containsKey("elementCSS")) {
110+
elementSelector.put("elementCSS", params.get("elementCSS"));
111+
}
112+
113+
Map<String, Object> region = new HashMap<>();
114+
region.put("algorithm", params.getOrDefault("algorithm", "ignore"));
115+
region.put("elementSelector", elementSelector);
116+
117+
if (params.containsKey("padding")) {
118+
region.put("padding", params.get("padding"));
119+
}
120+
121+
Map<String, Object> configuration = new HashMap<>();
122+
String algorithm = (String) params.getOrDefault("algorithm", "ignore");
123+
if (algorithm.equals("standard") || algorithm.equals("intelliignore")) {
124+
List<String> keys = Arrays.asList(
125+
"diffSensitivity",
126+
"imageIgnoreThreshold",
127+
"carouselsEnabled",
128+
"bannersEnabled",
129+
"adsEnabled"
130+
);
131+
132+
for (String key : keys) {
133+
if (params.containsKey(key)) {
134+
configuration.put(key, params.get(key));
135+
}
136+
}
137+
}
138+
139+
if (!configuration.isEmpty()) {
140+
region.put("configuration", configuration);
141+
}
142+
143+
Map<String, Object> assertion = new HashMap<>();
144+
if (params.containsKey("diffIgnoreThreshold")) {
145+
assertion.put("diffIgnoreThreshold", params.get("diffIgnoreThreshold"));
146+
}
147+
148+
if (!assertion.isEmpty()) {
149+
region.put("assertion", assertion);
150+
}
151+
152+
return region;
153+
}
154+
78155
/**
79156
* Take a snapshot and upload it to Percy.
80157
*

src/test/java/io/percy/selenium/SdkTest.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import org.junit.jupiter.api.AfterAll;
99
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Order;
1011
import org.junit.jupiter.api.BeforeAll;
1112
import org.junit.jupiter.api.Test;
1213
import static org.junit.jupiter.api.Assertions.*;
@@ -207,4 +208,50 @@ public void takeScreenshotThrowErrorForWeb() {
207208
Throwable exception = assertThrows(RuntimeException.class, () -> mockedPercy.screenshot("Test"));
208209
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());
209210
}
211+
212+
@Test
213+
public void createRegionTest() {
214+
// Setup the parameters for the region
215+
Map<String, Object> params = new HashMap<>();
216+
params.put("boundingBox", "100,100,200,200");
217+
params.put("elementXpath", "//div[@id='test']");
218+
params.put("elementCSS", ".test-class");
219+
params.put("padding", 10);
220+
params.put("algorithm", "standard");
221+
params.put("diffSensitivity", 0.5);
222+
params.put("imageIgnoreThreshold", 0.2);
223+
params.put("carouselsEnabled", true);
224+
params.put("bannersEnabled", false);
225+
params.put("adsEnabled", true);
226+
params.put("diffIgnoreThreshold", 0.1);
227+
228+
// Call the method to create the region
229+
Map<String, Object> region = percy.createRegion(params);
230+
231+
// Validate the returned region
232+
assertNotNull(region);
233+
234+
// Check if elementSelector was added correctly
235+
Map<String, Object> elementSelector = (Map<String, Object>) region.get("elementSelector");
236+
assertNotNull(elementSelector);
237+
assertEquals("100,100,200,200", elementSelector.get("boundingBox"));
238+
assertEquals("//div[@id='test']", elementSelector.get("elementXpath"));
239+
assertEquals(".test-class", elementSelector.get("elementCSS"));
240+
241+
// Validate algorithm and configuration
242+
assertEquals("standard", region.get("algorithm"));
243+
244+
Map<String, Object> configuration = (Map<String, Object>) region.get("configuration");
245+
assertNotNull(configuration);
246+
assertEquals(0.5, configuration.get("diffSensitivity"));
247+
assertEquals(0.2, configuration.get("imageIgnoreThreshold"));
248+
assertTrue((Boolean) configuration.get("carouselsEnabled"));
249+
assertFalse((Boolean) configuration.get("bannersEnabled"));
250+
assertTrue((Boolean) configuration.get("adsEnabled"));
251+
252+
// Validate assertion
253+
Map<String, Object> assertion = (Map<String, Object>) region.get("assertion");
254+
assertNotNull(assertion);
255+
assertEquals(0.1, assertion.get("diffIgnoreThreshold"));
256+
}
210257
}

0 commit comments

Comments
 (0)