Skip to content

Commit 16045d2

Browse files
added region changes (#54)
* added region changes * lint * lint * test fix * test fix * python v fix * updated cli to 1.30.9 * updated cli to 1.30.9 * resolved comments * resolved comments
1 parent 674e9bf commit 16045d2

5 files changed

Lines changed: 221 additions & 2 deletions

File tree

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
strategy:
1515
matrix:
1616
python: [3.7, 3.8, 3.9]
17-
runs-on: ${{ matrix.python == 3.6 && 'ubuntu-20.04' || 'ubuntu-latest' }}
17+
runs-on: ${{ matrix.python == 3.7 && 'ubuntu-20.04' || 'ubuntu-latest' }}
1818

1919
steps:
2020
- uses: actions-ecosystem/action-regex-match@v2

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,54 @@ percy_screenshot(page, name = 'Screenshot 1')
122122
- `bottom` (int): Bottom coordinate of the consider region.
123123
- `left` (int): Left coordinate of the consider region.
124124
- `right` (int): Right coordinate of the consider region.
125+
- `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.
126+
- Parameters:
127+
- `elementSelector` (optional)
128+
- `boundingBox` (object): Defines the coordinates and size of the region.
129+
- `x` (number): X-coordinate of the region.
130+
- `y` (number): Y-coordinate of the region.
131+
- `width` (number): Width of the region.
132+
- `height` (number): Height of the region.
133+
- `elementXpath` (string): The XPath selector for the element.
134+
- `elementCSS` (string): The CSS selector for the element.
135+
136+
- `algorithm` (mandatory)
137+
- Specifies the snapshot comparison algorithm.
138+
- Allowed values: `standard`, `layout`, `ignore`, `intelliignore`.
139+
140+
- `configuration` (required for `standard` and `intelliignore` algorithms, ignored otherwise)
141+
- `diffSensitivity` (number): Sensitivity level for detecting differences.
142+
- `imageIgnoreThreshold` (number): Threshold for ignoring minor image differences.
143+
- `carouselsEnabled` (boolean): Whether to enable carousel detection.
144+
- `bannersEnabled` (boolean): Whether to enable banner detection.
145+
- `adsEnabled` (boolean): Whether to enable ad detection.
146+
147+
- `assertion` (optional)
148+
- Defines assertions to apply to the region.
149+
- `diffIgnoreThreshold` (number): The threshold for ignoring minor differences.
150+
151+
### Example Usage for regions
152+
153+
```
154+
obj1 = {
155+
"elementSelector": {
156+
"elementCSS": ".ad-banner"
157+
},
158+
"algorithm": "intelliignore",
159+
"configuration": {
160+
"diffSensitivity": 2,
161+
"imageIgnoreThreshold": 0.2,
162+
"carouselsEnabled": true,
163+
"bannersEnabled": true,
164+
"adsEnabled": true
165+
},
166+
"assertion": {
167+
"diffIgnoreThreshold": 0.4,
168+
}
169+
};
170+
171+
percy_snapshot(page, name="Homepage", regions: [obj1]);
172+
```
125173

126174

127175
### Creating Percy on automate build

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
"test": "make test"
55
},
66
"devDependencies": {
7-
"@percy/cli": "1.28.7"
7+
"@percy/cli": "1.30.9"
88
}
99
}

percy/screenshot.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,62 @@ def fetch_percy_dom():
6161
response.raise_for_status()
6262
return response.text
6363

64+
# pylint: disable=too-many-arguments, too-many-branches
65+
def create_region(
66+
boundingBox=None,
67+
elementXpath=None,
68+
elementCSS=None,
69+
padding=None,
70+
algorithm="ignore",
71+
diffSensitivity=None,
72+
imageIgnoreThreshold=None,
73+
carouselsEnabled=None,
74+
bannersEnabled=None,
75+
adsEnabled=None,
76+
diffIgnoreThreshold=None
77+
):
78+
79+
element_selector = {}
80+
if boundingBox:
81+
element_selector["boundingBox"] = boundingBox
82+
if elementXpath:
83+
element_selector["elementXpath"] = elementXpath
84+
if elementCSS:
85+
element_selector["elementCSS"] = elementCSS
86+
87+
region = {
88+
"algorithm": algorithm,
89+
"elementSelector": element_selector
90+
}
91+
92+
if padding:
93+
region["padding"] = padding
94+
95+
configuration = {}
96+
if algorithm in ["standard", "intelliignore"]:
97+
if diffSensitivity is not None:
98+
configuration["diffSensitivity"] = diffSensitivity
99+
if imageIgnoreThreshold is not None:
100+
configuration["imageIgnoreThreshold"] = imageIgnoreThreshold
101+
if carouselsEnabled is not None:
102+
configuration["carouselsEnabled"] = carouselsEnabled
103+
if bannersEnabled is not None:
104+
configuration["bannersEnabled"] = bannersEnabled
105+
if adsEnabled is not None:
106+
configuration["adsEnabled"] = adsEnabled
107+
108+
if configuration:
109+
region["configuration"] = configuration
110+
111+
assertion = {}
112+
if diffIgnoreThreshold is not None:
113+
assertion["diffIgnoreThreshold"] = diffIgnoreThreshold
114+
115+
if assertion:
116+
region["assertion"] = assertion
117+
118+
return region
119+
64120

65121
# Take a DOM snapshot and post it to the snapshot endpoint
66122
def percy_snapshot(page, name, **kwargs):

tests/test_screenshot.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
fetch_percy_dom,
1616
percy_snapshot,
1717
percy_automate_screenshot,
18+
create_region
1819
)
1920
import percy.screenshot as local
2021

@@ -367,6 +368,120 @@ def test_percy_automate_screenshot_invalid_call(self, mock_is_percy_enabled):
367368

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

371+
class TestCreateRegion(unittest.TestCase):
372+
373+
def test_create_region_with_all_params(self):
374+
result = create_region(
375+
boundingBox={"x": 10, "y": 20, "width": 100, "height": 200},
376+
elementXpath="//*[@id='test']",
377+
elementCSS=".test-class",
378+
padding=10,
379+
algorithm="intelliignore",
380+
diffSensitivity=0.8,
381+
imageIgnoreThreshold=0.5,
382+
carouselsEnabled=True,
383+
bannersEnabled=False,
384+
adsEnabled=True,
385+
diffIgnoreThreshold=0.2
386+
)
387+
388+
expected_result = {
389+
"algorithm": "intelliignore",
390+
"elementSelector": {
391+
"boundingBox": {"x": 10, "y": 20, "width": 100, "height": 200},
392+
"elementXpath": "//*[@id='test']",
393+
"elementCSS": ".test-class"
394+
},
395+
"padding": 10,
396+
"configuration": {
397+
"diffSensitivity": 0.8,
398+
"imageIgnoreThreshold": 0.5,
399+
"carouselsEnabled": True,
400+
"bannersEnabled": False,
401+
"adsEnabled": True
402+
},
403+
"assertion": {
404+
"diffIgnoreThreshold": 0.2
405+
}
406+
}
407+
408+
self.assertEqual(result, expected_result)
409+
410+
def test_create_region_with_minimal_params(self):
411+
result = create_region(
412+
algorithm="standard",
413+
boundingBox={"x": 10, "y": 20, "width": 100, "height": 200}
414+
)
415+
416+
expected_result = {
417+
"algorithm": "standard",
418+
"elementSelector": {
419+
"boundingBox": {"x": 10, "y": 20, "width": 100, "height": 200}
420+
}
421+
}
422+
423+
self.assertEqual(result, expected_result)
424+
425+
def test_create_region_with_padding(self):
426+
result = create_region(
427+
algorithm="ignore",
428+
padding=15
429+
)
430+
431+
expected_result = {
432+
"algorithm": "ignore",
433+
"elementSelector": {},
434+
"padding": 15
435+
}
436+
437+
self.assertEqual(result, expected_result)
438+
439+
def test_create_region_with_configuration_only_for_valid_algorithms(self):
440+
result = create_region(
441+
algorithm="intelliignore",
442+
diffSensitivity=0.9,
443+
imageIgnoreThreshold=0.7
444+
)
445+
446+
expected_result = {
447+
"algorithm": "intelliignore",
448+
"elementSelector": {},
449+
"configuration": {
450+
"diffSensitivity": 0.9,
451+
"imageIgnoreThreshold": 0.7
452+
}
453+
}
454+
455+
self.assertEqual(result, expected_result)
456+
457+
def test_create_region_with_diffIgnoreThreshold_in_assertion(self):
458+
result = create_region(
459+
algorithm="standard",
460+
diffIgnoreThreshold=0.3
461+
)
462+
463+
expected_result = {
464+
"algorithm": "standard",
465+
"elementSelector": {},
466+
"assertion": {
467+
"diffIgnoreThreshold": 0.3
468+
}
469+
}
470+
471+
self.assertEqual(result, expected_result)
472+
473+
def test_create_region_with_invalid_algorithm(self):
474+
result = create_region(
475+
algorithm="invalid_algorithm"
476+
)
477+
478+
expected_result = {
479+
"algorithm": "invalid_algorithm",
480+
"elementSelector": {}
481+
}
482+
483+
self.assertEqual(result, expected_result)
484+
370485

371486
if __name__ == "__main__":
372487
unittest.main()

0 commit comments

Comments
 (0)