Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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') }}
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,49 @@ 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` (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.
- `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.
- `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<String, Object> 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<String, Object> regions2 = percy.createRegion(params);
List<Map<String, Object>> regions = Collections.singletonList(obj1);
Map<String, Object> options = new HashMap<>();
options.put("regions", regions);

percy.snapshot("Homepage", options);

```

### Creating Percy on automate build
Note: Automate Percy Token starts with `auto` keyword. The command can be triggered using `exec` keyword.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"test": "npx percy exec --testing -- mvn test"
},
"devDependencies": {
"@percy/cli": "1.29.5-beta.0"
"@percy/cli": "1.30.9"
}
}
77 changes: 77 additions & 0 deletions src/main/java/io/percy/selenium/Percy.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -75,6 +78,80 @@ public Percy(WebDriver driver) {
this.env = new Environment(driver);
}

/**
* Creates a region configuration based on the provided parameters.
*
* @param params A map containing the region configuration options. Expected keys:
* <ul>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we have tags in comments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is for javaDoc
it's actually processed by tools that generate HTML documentation.

* <li>boundingBox - The bounding box of the region, or null.</li>
* <li>elementXpath - The XPath of the element, or null.</li>
* <li>elementCSS - The CSS selector of the element, or null.</li>
* <li>padding - The padding around the region, or null.</li>
* <li>algorithm - The algorithm to be used (default: 'ignore').</li>
* <li>diffSensitivity - The sensitivity for diffing, or null.</li>
* <li>imageIgnoreThreshold - The image ignore threshold, or null.</li>
* <li>carouselsEnabled - Flag for enabling carousels, or null.</li>
* <li>bannersEnabled - Flag for enabling banners, or null.</li>
* <li>adsEnabled - Flag for enabling ads, or null.</li>
* <li>diffIgnoreThreshold - The diff ignore threshold, or null.</li>
* </ul>
* @return A map representing the region configuration.
*/

public Map<String, Object> createRegion(Map<String, Object> params) {
Map<String, Object> 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<String, Object> 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<String, Object> configuration = new HashMap<>();
String algorithm = (String) params.getOrDefault("algorithm", "ignore");
if (algorithm.equals("standard") || algorithm.equals("intelliignore")) {
List<String> keys = Arrays.asList(
"diffSensitivity",
"imageIgnoreThreshold",
"carouselsEnabled",
"bannersEnabled",
"adsEnabled"
);

for (String key : keys) {
if (params.containsKey(key)) {
configuration.put(key, params.get(key));
}
}
}

if (!configuration.isEmpty()) {
region.put("configuration", configuration);
}

Map<String, Object> 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.
*
Expand Down
47 changes: 47 additions & 0 deletions src/test/java/io/percy/selenium/SdkTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand Down Expand Up @@ -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<String, Object> 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<String, Object> region = percy.createRegion(params);

// Validate the returned region
assertNotNull(region);

// Check if elementSelector was added correctly
Map<String, Object> elementSelector = (Map<String, Object>) 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<String, Object> configuration = (Map<String, Object>) 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<String, Object> assertion = (Map<String, Object>) region.get("assertion");
assertNotNull(assertion);
assertEquals(0.1, assertion.get("diffIgnoreThreshold"));
}
}
Loading