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 @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
python: [3.7, 3.8, 3.9]
runs-on: ${{ matrix.python == 3.6 && 'ubuntu-20.04' || 'ubuntu-latest' }}
runs-on: ${{ matrix.python == 3.7 && 'ubuntu-20.04' || 'ubuntu-latest' }}

steps:
- uses: actions-ecosystem/action-regex-match@v2
Expand Down
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,54 @@ percy_screenshot(page, name = 'Screenshot 1')
- `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)
- `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

```
obj1 = {
"elementSelector": {
"elementCSS": ".ad-banner"
},
"algorithm": "intelliignore",
"configuration": {
"diffSensitivity": 2,
"imageIgnoreThreshold": 0.2,
"carouselsEnabled": true,
"bannersEnabled": true,
"adsEnabled": true
},
"assertion": {
"diffIgnoreThreshold": 0.4,
}
};

percy_snapshot(page, name="Homepage", regions: [obj1]);
```


### Creating Percy on automate build
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": "make test"
},
"devDependencies": {
"@percy/cli": "1.28.7"
"@percy/cli": "1.30.9"
}
}
56 changes: 56 additions & 0 deletions percy/screenshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,62 @@ def fetch_percy_dom():
response.raise_for_status()
return response.text

# pylint: disable=too-many-arguments, too-many-branches
def create_region(
boundingBox=None,
elementXpath=None,
elementCSS=None,
padding=None,
algorithm="ignore",
diffSensitivity=None,
imageIgnoreThreshold=None,
carouselsEnabled=None,
bannersEnabled=None,
adsEnabled=None,
diffIgnoreThreshold=None
):

element_selector = {}
if boundingBox:
element_selector["boundingBox"] = boundingBox
if elementXpath:
element_selector["elementXpath"] = elementXpath
if elementCSS:
element_selector["elementCSS"] = elementCSS

region = {
"algorithm": algorithm,
"elementSelector": element_selector
}

if padding:
region["padding"] = padding

configuration = {}
if algorithm in ["standard", "intelliignore"]:
if diffSensitivity is not None:
configuration["diffSensitivity"] = diffSensitivity
if imageIgnoreThreshold is not None:
configuration["imageIgnoreThreshold"] = imageIgnoreThreshold
if carouselsEnabled is not None:
configuration["carouselsEnabled"] = carouselsEnabled
if bannersEnabled is not None:
configuration["bannersEnabled"] = bannersEnabled
if adsEnabled is not None:
configuration["adsEnabled"] = adsEnabled

if configuration:
region["configuration"] = configuration

assertion = {}
if diffIgnoreThreshold is not None:
assertion["diffIgnoreThreshold"] = diffIgnoreThreshold

if assertion:
region["assertion"] = assertion

return region


# Take a DOM snapshot and post it to the snapshot endpoint
def percy_snapshot(page, name, **kwargs):
Expand Down
115 changes: 115 additions & 0 deletions tests/test_screenshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
fetch_percy_dom,
percy_snapshot,
percy_automate_screenshot,
create_region
)
import percy.screenshot as local

Expand Down Expand Up @@ -367,6 +368,120 @@ def test_percy_automate_screenshot_invalid_call(self, mock_is_percy_enabled):

self.assertTrue("Invalid function call" in str(context.exception))

class TestCreateRegion(unittest.TestCase):

def test_create_region_with_all_params(self):
result = create_region(
boundingBox={"x": 10, "y": 20, "width": 100, "height": 200},
elementXpath="//*[@id='test']",
elementCSS=".test-class",
padding=10,
algorithm="intelliignore",
diffSensitivity=0.8,
imageIgnoreThreshold=0.5,
carouselsEnabled=True,
bannersEnabled=False,
adsEnabled=True,
diffIgnoreThreshold=0.2
)

expected_result = {
"algorithm": "intelliignore",
"elementSelector": {
"boundingBox": {"x": 10, "y": 20, "width": 100, "height": 200},
"elementXpath": "//*[@id='test']",
"elementCSS": ".test-class"
},
"padding": 10,
"configuration": {
"diffSensitivity": 0.8,
"imageIgnoreThreshold": 0.5,
"carouselsEnabled": True,
"bannersEnabled": False,
"adsEnabled": True
},
"assertion": {
"diffIgnoreThreshold": 0.2
}
}

self.assertEqual(result, expected_result)

def test_create_region_with_minimal_params(self):
result = create_region(
algorithm="standard",
boundingBox={"x": 10, "y": 20, "width": 100, "height": 200}
)

expected_result = {
"algorithm": "standard",
"elementSelector": {
"boundingBox": {"x": 10, "y": 20, "width": 100, "height": 200}
}
}

self.assertEqual(result, expected_result)

def test_create_region_with_padding(self):
result = create_region(
algorithm="ignore",
padding=15
)

expected_result = {
"algorithm": "ignore",
"elementSelector": {},
"padding": 15
}

self.assertEqual(result, expected_result)

def test_create_region_with_configuration_only_for_valid_algorithms(self):
result = create_region(
algorithm="intelliignore",
diffSensitivity=0.9,
imageIgnoreThreshold=0.7
)

expected_result = {
"algorithm": "intelliignore",
"elementSelector": {},
"configuration": {
"diffSensitivity": 0.9,
"imageIgnoreThreshold": 0.7
}
}

self.assertEqual(result, expected_result)

def test_create_region_with_diffIgnoreThreshold_in_assertion(self):
result = create_region(
algorithm="standard",
diffIgnoreThreshold=0.3
)

expected_result = {
"algorithm": "standard",
"elementSelector": {},
"assertion": {
"diffIgnoreThreshold": 0.3
}
}

self.assertEqual(result, expected_result)

def test_create_region_with_invalid_algorithm(self):
result = create_region(
algorithm="invalid_algorithm"
)

expected_result = {
"algorithm": "invalid_algorithm",
"elementSelector": {}
}

self.assertEqual(result, expected_result)


if __name__ == "__main__":
unittest.main()
Loading