percy-selenium 2.2.1b2__tar.gz → 2.2.2b0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/PKG-INFO +8 -1
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/README.md +7 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy/cache.py +18 -12
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy/snapshot.py +45 -6
- percy_selenium-2.2.2b0/percy/version.py +1 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/PKG-INFO +8 -1
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/tests/test_cache.py +29 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/tests/test_snapshot_units.py +105 -1
- percy_selenium-2.2.1b2/percy/version.py +0 -1
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/LICENSE +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy/__init__.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy/driver_metadata.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy/exception.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy/robot_library.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/SOURCES.txt +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/dependency_links.txt +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/not-zip-safe +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/requires.txt +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/top_level.txt +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/setup.cfg +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/setup.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/tests/test_driver_metadata.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/tests/test_init.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/tests/test_robot_library.py +0 -0
- {percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/tests/test_snapshot.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: percy-selenium
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2b0
|
|
4
4
|
Summary: Python client for visual testing with Percy
|
|
5
5
|
Home-page: https://github.com/percy/percy-selenium-python
|
|
6
6
|
Author: Perceptual Inc.
|
|
@@ -95,6 +95,13 @@ $ percy exec -- [python test command]
|
|
|
95
95
|
- `name` (**required**) - The snapshot name; must be unique to each snapshot
|
|
96
96
|
- `**kwargs` - [See per-snapshot configuration options](https://www.browserstack.com/docs/percy/take-percy-snapshots/overview#per-snapshot-configuration)
|
|
97
97
|
|
|
98
|
+
### Cookies
|
|
99
|
+
|
|
100
|
+
By default the SDK sends the browser's cookies with each snapshot so Percy can load pages and
|
|
101
|
+
assets that need a logged-in session during asset discovery. To stop sending cookies, set
|
|
102
|
+
`PERCY_DO_NOT_USE_CAPTURED_COOKIES=true`. Assets behind authentication may then fail to load
|
|
103
|
+
and snapshots can render incorrectly; the SDK logs a warning once when this is enabled.
|
|
104
|
+
|
|
98
105
|
### Migrating Config
|
|
99
106
|
|
|
100
107
|
If you have a previous Percy configuration file, migrate it to the newest version with the
|
|
@@ -60,6 +60,13 @@ $ percy exec -- [python test command]
|
|
|
60
60
|
- `name` (**required**) - The snapshot name; must be unique to each snapshot
|
|
61
61
|
- `**kwargs` - [See per-snapshot configuration options](https://www.browserstack.com/docs/percy/take-percy-snapshots/overview#per-snapshot-configuration)
|
|
62
62
|
|
|
63
|
+
### Cookies
|
|
64
|
+
|
|
65
|
+
By default the SDK sends the browser's cookies with each snapshot so Percy can load pages and
|
|
66
|
+
assets that need a logged-in session during asset discovery. To stop sending cookies, set
|
|
67
|
+
`PERCY_DO_NOT_USE_CAPTURED_COOKIES=true`. Assets behind authentication may then fail to load
|
|
68
|
+
and snapshots can render incorrectly; the SDK logs a warning once when this is enabled.
|
|
69
|
+
|
|
63
70
|
### Migrating Config
|
|
64
71
|
|
|
65
72
|
If you have a previous Percy configuration file, migrate it to the newest version with the
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import threading
|
|
1
2
|
import time
|
|
2
3
|
|
|
3
4
|
class Cache:
|
|
4
5
|
CACHE = {}
|
|
5
6
|
CACHE_TIMEOUT = 5 * 60 # 300 seconds
|
|
6
7
|
TIMEOUT_KEY = 'last_access_time'
|
|
8
|
+
# Guards CACHE so parallel runners sharing a process can't mutate it mid-iteration
|
|
9
|
+
LOCK = threading.RLock()
|
|
7
10
|
|
|
8
11
|
# Caching Keys
|
|
9
12
|
capabilities = 'capabilities'
|
|
@@ -19,24 +22,27 @@ class Cache:
|
|
|
19
22
|
@classmethod
|
|
20
23
|
def set_cache(cls, session_id, property, value):
|
|
21
24
|
cls.check_types(session_id, property)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
with cls.LOCK:
|
|
26
|
+
session = cls.CACHE.get(session_id, {})
|
|
27
|
+
session[cls.TIMEOUT_KEY] = time.time()
|
|
28
|
+
session[property] = value
|
|
29
|
+
cls.CACHE[session_id] = session
|
|
26
30
|
|
|
27
31
|
@classmethod
|
|
28
32
|
def get_cache(cls, session_id, property):
|
|
29
33
|
cls.cleanup_cache()
|
|
30
34
|
cls.check_types(session_id, property)
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
with cls.LOCK:
|
|
36
|
+
session = cls.CACHE.get(session_id, {})
|
|
37
|
+
return session.get(property, None)
|
|
33
38
|
|
|
34
39
|
@classmethod
|
|
35
40
|
def cleanup_cache(cls):
|
|
36
41
|
now = time.time()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
with cls.LOCK:
|
|
43
|
+
session_ids = [
|
|
44
|
+
session_id for session_id, session in cls.CACHE.items()
|
|
45
|
+
if now - session[cls.TIMEOUT_KEY] >= cls.CACHE_TIMEOUT
|
|
46
|
+
]
|
|
47
|
+
for session_id in session_ids:
|
|
48
|
+
cls.CACHE.pop(session_id, None)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import os
|
|
3
3
|
import platform
|
|
4
4
|
import json
|
|
5
|
+
import tempfile
|
|
5
6
|
from contextlib import contextmanager
|
|
6
7
|
from functools import lru_cache
|
|
7
8
|
from time import sleep
|
|
@@ -35,6 +36,9 @@ try:
|
|
|
35
36
|
RESIZE_SETTLE_SECONDS = float(os.environ.get('PERCY_RESIZE_SETTLE_SECONDS') or 0.5)
|
|
36
37
|
except (TypeError, ValueError):
|
|
37
38
|
RESIZE_SETTLE_SECONDS = 0.5
|
|
39
|
+
# Set to true to stop sending browser cookies to the CLI (read per snapshot)
|
|
40
|
+
DO_NOT_USE_CAPTURED_COOKIES_ENV = 'PERCY_DO_NOT_USE_CAPTURED_COOKIES'
|
|
41
|
+
_cookie_opt_out_warned = False
|
|
38
42
|
# for logging
|
|
39
43
|
LABEL = '[\u001b[35m' + ('percy:python' if PERCY_DEBUG else 'percy') + '\u001b[39m]'
|
|
40
44
|
CDP_SUPPORT_SELENIUM = (str(SELENIUM_VERSION)[0].isdigit() and int(
|
|
@@ -52,6 +56,25 @@ def log(message, lvl = 'info'):
|
|
|
52
56
|
if lvl != 'debug' or PERCY_DEBUG:
|
|
53
57
|
print(message)
|
|
54
58
|
|
|
59
|
+
def get_cookies_for_snapshot(driver):
|
|
60
|
+
"""Collect browser cookies so the CLI can load authenticated assets during
|
|
61
|
+
discovery. Honours the PERCY_DO_NOT_USE_CAPTURED_COOKIES opt-out and never
|
|
62
|
+
raises: a cookie read failure only means no cookies are forwarded."""
|
|
63
|
+
global _cookie_opt_out_warned # pylint: disable=global-statement
|
|
64
|
+
if _get_bool_env(DO_NOT_USE_CAPTURED_COOKIES_ENV):
|
|
65
|
+
if not _cookie_opt_out_warned:
|
|
66
|
+
_cookie_opt_out_warned = True
|
|
67
|
+
log('Not sending browser cookies to Percy because '
|
|
68
|
+
f'{DO_NOT_USE_CAPTURED_COOKIES_ENV} is set. Pages or assets that need a '
|
|
69
|
+
'logged-in session may fail to load during asset discovery, so snapshots '
|
|
70
|
+
'can render incorrectly.', 'warn')
|
|
71
|
+
return []
|
|
72
|
+
try:
|
|
73
|
+
return driver.get_cookies()
|
|
74
|
+
except Exception as e: # pylint: disable=broad-except
|
|
75
|
+
log(f'Could not read browser cookies, continuing without them: {e}', 'debug')
|
|
76
|
+
return []
|
|
77
|
+
|
|
55
78
|
# Check if Percy is enabled, caching the result so it is only checked once
|
|
56
79
|
@lru_cache(maxsize=None)
|
|
57
80
|
def is_percy_enabled():
|
|
@@ -991,11 +1014,7 @@ def capture_responsive_dom(driver, cookies, config, percy_dom_script=None, **kwa
|
|
|
991
1014
|
dom_snapshots.append(dom_snapshot)
|
|
992
1015
|
# Optional debug dump — gated to avoid polluting the user's CWD on every CI run.
|
|
993
1016
|
if PERCY_DEBUG:
|
|
994
|
-
|
|
995
|
-
with open("output_file.json", "w", encoding="utf-8") as file_handle:
|
|
996
|
-
json.dump(dom_snapshots, file_handle, indent=4)
|
|
997
|
-
except Exception as e: # pylint: disable=broad-except
|
|
998
|
-
log(f"Could not write debug snapshot dump: {type(e).__name__}: {e}", "debug")
|
|
1017
|
+
_write_responsive_debug_dump(dom_snapshots)
|
|
999
1018
|
# Restore the original window size after capture. No snapshot follows, so
|
|
1000
1019
|
# skip the resize-event poll (wait_for_resize=False) — it serves no purpose
|
|
1001
1020
|
# here and is the call that hangs geckodriver in CI.
|
|
@@ -1003,6 +1022,26 @@ def capture_responsive_dom(driver, cookies, config, percy_dom_script=None, **kwa
|
|
|
1003
1022
|
driver, current_width, current_height, resize_count + 1, wait_for_resize=False)
|
|
1004
1023
|
return dom_snapshots
|
|
1005
1024
|
|
|
1025
|
+
def _write_responsive_debug_dump(dom_snapshots):
|
|
1026
|
+
# Owner-only temp file with an unpredictable name; cookies are left out
|
|
1027
|
+
# because they're not needed to debug the captured DOM.
|
|
1028
|
+
try:
|
|
1029
|
+
redacted = [
|
|
1030
|
+
{k: v for k, v in snap.items() if k != 'cookies'} if isinstance(snap, dict) else snap
|
|
1031
|
+
for snap in dom_snapshots
|
|
1032
|
+
]
|
|
1033
|
+
fd, path = tempfile.mkstemp(prefix='percy-responsive-dom-', suffix='.json')
|
|
1034
|
+
try:
|
|
1035
|
+
with os.fdopen(fd, "w", encoding="utf-8") as file_handle:
|
|
1036
|
+
json.dump(redacted, file_handle, indent=4)
|
|
1037
|
+
except Exception:
|
|
1038
|
+
# Don't leave a partially written dump behind
|
|
1039
|
+
os.remove(path)
|
|
1040
|
+
raise
|
|
1041
|
+
log(f"Wrote responsive snapshot debug dump to {path}", "debug")
|
|
1042
|
+
except Exception as e: # pylint: disable=broad-except
|
|
1043
|
+
log(f"Could not write debug snapshot dump: {type(e).__name__}: {e}", "debug")
|
|
1044
|
+
|
|
1006
1045
|
def is_responsive_snapshot_capture(config, **kwargs):
|
|
1007
1046
|
# Don't run resposive snapshot capture when defer uploads is enabled
|
|
1008
1047
|
if 'percy' in config and config['percy'].get('deferUploads', False): return False
|
|
@@ -1028,7 +1067,7 @@ def percy_snapshot(driver, name, **kwargs):
|
|
|
1028
1067
|
# Expose closed shadow roots via CDP before serialization so PercyDOM
|
|
1029
1068
|
# can find them through the WeakMap (Chromium-only; non-Chromium no-ops).
|
|
1030
1069
|
expose_closed_shadow_roots(driver)
|
|
1031
|
-
cookies = driver
|
|
1070
|
+
cookies = get_cookies_for_snapshot(driver)
|
|
1032
1071
|
|
|
1033
1072
|
# Serialize and capture the DOM
|
|
1034
1073
|
if is_responsive_snapshot_capture(data['config'], **kwargs):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.2-beta.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: percy-selenium
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2b0
|
|
4
4
|
Summary: Python client for visual testing with Percy
|
|
5
5
|
Home-page: https://github.com/percy/percy-selenium-python
|
|
6
6
|
Author: Perceptual Inc.
|
|
@@ -95,6 +95,13 @@ $ percy exec -- [python test command]
|
|
|
95
95
|
- `name` (**required**) - The snapshot name; must be unique to each snapshot
|
|
96
96
|
- `**kwargs` - [See per-snapshot configuration options](https://www.browserstack.com/docs/percy/take-percy-snapshots/overview#per-snapshot-configuration)
|
|
97
97
|
|
|
98
|
+
### Cookies
|
|
99
|
+
|
|
100
|
+
By default the SDK sends the browser's cookies with each snapshot so Percy can load pages and
|
|
101
|
+
assets that need a logged-in session during asset discovery. To stop sending cookies, set
|
|
102
|
+
`PERCY_DO_NOT_USE_CAPTURED_COOKIES=true`. Assets behind authentication may then fail to load
|
|
103
|
+
and snapshots can render incorrectly; the SDK logs a warning once when this is enabled.
|
|
104
|
+
|
|
98
105
|
### Migrating Config
|
|
99
106
|
|
|
100
107
|
If you have a previous Percy configuration file, migrate it to the newest version with the
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# . # pylint: disable=[arguments-differ, protected-access]
|
|
2
|
+
import threading
|
|
2
3
|
import time
|
|
3
4
|
import unittest
|
|
4
5
|
from unittest.mock import patch
|
|
@@ -57,3 +58,31 @@ class TestCache(unittest.TestCase):
|
|
|
57
58
|
self.assertIn(self.session_id, self.cache.CACHE)
|
|
58
59
|
self.cache.cleanup_cache()
|
|
59
60
|
self.assertNotIn(self.session_id, self.cache.CACHE)
|
|
61
|
+
|
|
62
|
+
def test_cleanup_cache_blocks_concurrent_writers_while_iterating(self):
|
|
63
|
+
cache = self.cache
|
|
64
|
+
writer_blocked = []
|
|
65
|
+
writers = []
|
|
66
|
+
|
|
67
|
+
class InterleavingDict(dict):
|
|
68
|
+
# Simulates another thread writing to the cache mid-iteration
|
|
69
|
+
def items(self):
|
|
70
|
+
writer = threading.Thread(
|
|
71
|
+
target=cache.set_cache,
|
|
72
|
+
args=('other_session', Cache.capabilities, {}))
|
|
73
|
+
writer.start()
|
|
74
|
+
writers.append(writer)
|
|
75
|
+
writer.join(timeout=0.2)
|
|
76
|
+
writer_blocked.append(writer.is_alive())
|
|
77
|
+
for item in list(super().items()):
|
|
78
|
+
yield item
|
|
79
|
+
|
|
80
|
+
original = cache.CACHE
|
|
81
|
+
cache.CACHE = InterleavingDict(original)
|
|
82
|
+
try:
|
|
83
|
+
cache.cleanup_cache() # must not raise "dictionary changed size during iteration"
|
|
84
|
+
writers[0].join(timeout=5)
|
|
85
|
+
self.assertEqual(writer_blocked, [True])
|
|
86
|
+
self.assertIn('other_session', cache.CACHE)
|
|
87
|
+
finally:
|
|
88
|
+
cache.CACHE = original
|
|
@@ -5,6 +5,9 @@ target branches the end-to-end suite in test_snapshot.py does not reach."""
|
|
|
5
5
|
import importlib
|
|
6
6
|
import json
|
|
7
7
|
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import stat
|
|
10
|
+
import tempfile
|
|
8
11
|
import unittest
|
|
9
12
|
from unittest.mock import patch, MagicMock, Mock
|
|
10
13
|
|
|
@@ -471,6 +474,13 @@ class TestGetSerializedDomPageUrlFailure(unittest.TestCase):
|
|
|
471
474
|
|
|
472
475
|
|
|
473
476
|
class TestResponsiveDebugDump(unittest.TestCase):
|
|
477
|
+
def setUp(self):
|
|
478
|
+
self.tmpdir = tempfile.mkdtemp()
|
|
479
|
+
patcher = patch('percy.snapshot.tempfile.tempdir', self.tmpdir)
|
|
480
|
+
patcher.start()
|
|
481
|
+
self.addCleanup(patcher.stop)
|
|
482
|
+
self.addCleanup(shutil.rmtree, self.tmpdir, True)
|
|
483
|
+
|
|
474
484
|
def tearDown(self):
|
|
475
485
|
if os.path.exists('output_file.json'):
|
|
476
486
|
os.remove('output_file.json')
|
|
@@ -489,7 +499,32 @@ class TestResponsiveDebugDump(unittest.TestCase):
|
|
|
489
499
|
result = local.capture_responsive_dom(
|
|
490
500
|
self._driver(), {}, {}, percy_dom_script='PERCY_DOM')
|
|
491
501
|
self.assertEqual(result, [])
|
|
492
|
-
self.
|
|
502
|
+
self.assertEqual(len(os.listdir(self.tmpdir)), 1)
|
|
503
|
+
|
|
504
|
+
@patch('percy.snapshot.PERCY_DEBUG', True)
|
|
505
|
+
@patch('percy.snapshot.change_window_dimension_and_wait', MagicMock())
|
|
506
|
+
@patch('percy.snapshot._wait_for_ready', MagicMock(return_value=None))
|
|
507
|
+
@patch('percy.snapshot.get_responsive_widths',
|
|
508
|
+
MagicMock(return_value=[{'width': 375}]))
|
|
509
|
+
@patch('percy.snapshot.get_serialized_dom')
|
|
510
|
+
def test_debug_dump_is_private_temp_file_without_cookies(self, mock_dom):
|
|
511
|
+
mock_dom.return_value = {'html': '<p/>', 'cookies': [{'name': 'sid', 'value': 's3cr3t'}]}
|
|
512
|
+
result = local.capture_responsive_dom(
|
|
513
|
+
self._driver(), [{'name': 'sid', 'value': 's3cr3t'}], {},
|
|
514
|
+
percy_dom_script='PERCY_DOM')
|
|
515
|
+
# The snapshot sent to the CLI still carries its cookies
|
|
516
|
+
self.assertEqual(result[0]['cookies'], [{'name': 'sid', 'value': 's3cr3t'}])
|
|
517
|
+
# No predictable file is dropped into the working directory
|
|
518
|
+
self.assertFalse(os.path.exists('output_file.json'))
|
|
519
|
+
files = os.listdir(self.tmpdir)
|
|
520
|
+
self.assertEqual(len(files), 1)
|
|
521
|
+
path = os.path.join(self.tmpdir, files[0])
|
|
522
|
+
if os.name == 'posix':
|
|
523
|
+
self.assertEqual(stat.S_IMODE(os.stat(path).st_mode), 0o600)
|
|
524
|
+
with open(path, encoding='utf-8') as file_handle:
|
|
525
|
+
content = file_handle.read()
|
|
526
|
+
self.assertNotIn('s3cr3t', content)
|
|
527
|
+
self.assertEqual(json.loads(content), [{'html': '<p/>', 'width': 375}])
|
|
493
528
|
|
|
494
529
|
@patch('percy.snapshot.PERCY_DEBUG', True)
|
|
495
530
|
@patch('percy.snapshot.change_window_dimension_and_wait', MagicMock())
|
|
@@ -500,6 +535,75 @@ class TestResponsiveDebugDump(unittest.TestCase):
|
|
|
500
535
|
result = local.capture_responsive_dom(
|
|
501
536
|
self._driver(), {}, {}, percy_dom_script='PERCY_DOM')
|
|
502
537
|
self.assertEqual(result, [])
|
|
538
|
+
# The partially written dump is removed
|
|
539
|
+
self.assertEqual(os.listdir(self.tmpdir), [])
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
class TestCookieForwarding(unittest.TestCase):
|
|
543
|
+
SESSION_COOKIES = [
|
|
544
|
+
{'name': 'session_id', 'value': 'abc', 'domain': 'example.com', 'secure': True},
|
|
545
|
+
{'name': 'auth_token', 'value': 'xyz', 'domain': 'example.com', 'secure': True},
|
|
546
|
+
]
|
|
547
|
+
|
|
548
|
+
def setUp(self):
|
|
549
|
+
patcher = patch('percy.snapshot._cookie_opt_out_warned', False)
|
|
550
|
+
patcher.start()
|
|
551
|
+
self.addCleanup(patcher.stop)
|
|
552
|
+
|
|
553
|
+
def _driver(self):
|
|
554
|
+
driver = MagicMock()
|
|
555
|
+
driver.get_cookies.return_value = list(self.SESSION_COOKIES)
|
|
556
|
+
driver.current_url = 'https://example.com/'
|
|
557
|
+
return driver
|
|
558
|
+
|
|
559
|
+
@patch('percy.snapshot.is_percy_enabled',
|
|
560
|
+
MagicMock(return_value={'session_type': 'web', 'config': {}, 'widths': {}}))
|
|
561
|
+
@patch('percy.snapshot.fetch_percy_dom', MagicMock(return_value='PERCY_DOM'))
|
|
562
|
+
@patch('percy.snapshot.expose_closed_shadow_roots', MagicMock())
|
|
563
|
+
@patch('percy.snapshot.get_serialized_dom')
|
|
564
|
+
@patch('percy.snapshot.requests.post')
|
|
565
|
+
def _take_snapshots(self, mock_post, mock_dom, count=1):
|
|
566
|
+
mock_dom.side_effect = lambda _d, cookies, **_k: {'html': '<p/>', 'cookies': cookies}
|
|
567
|
+
mock_post.return_value.json.return_value = {'success': True}
|
|
568
|
+
for i in range(count):
|
|
569
|
+
local.percy_snapshot(self._driver(), f'snap {i}')
|
|
570
|
+
return [c for c in mock_post.call_args_list if c.args[0].endswith('/percy/snapshot')]
|
|
571
|
+
|
|
572
|
+
@patch.dict(os.environ, {}, clear=False)
|
|
573
|
+
def test_default_forwards_session_cookies_unchanged(self):
|
|
574
|
+
os.environ.pop('PERCY_DO_NOT_USE_CAPTURED_COOKIES', None)
|
|
575
|
+
posts = self._take_snapshots()
|
|
576
|
+
self.assertEqual(posts[0].kwargs['json']['dom_snapshot']['cookies'],
|
|
577
|
+
self.SESSION_COOKIES)
|
|
578
|
+
|
|
579
|
+
@patch.dict(os.environ, {'PERCY_DO_NOT_USE_CAPTURED_COOKIES': 'true'})
|
|
580
|
+
@patch('percy.snapshot.log')
|
|
581
|
+
def test_opt_out_sends_no_cookies_and_warns_once(self, mock_log):
|
|
582
|
+
posts = self._take_snapshots(count=2) # pylint: disable=unexpected-keyword-arg
|
|
583
|
+
self.assertEqual(len(posts), 2)
|
|
584
|
+
for post in posts:
|
|
585
|
+
self.assertEqual(post.kwargs['json']['dom_snapshot']['cookies'], [])
|
|
586
|
+
warnings = [c for c in mock_log.call_args_list
|
|
587
|
+
if len(c.args) > 1 and c.args[1] == 'warn']
|
|
588
|
+
self.assertEqual(len(warnings), 1)
|
|
589
|
+
self.assertEqual(
|
|
590
|
+
warnings[0].args[0],
|
|
591
|
+
'Not sending browser cookies to Percy because PERCY_DO_NOT_USE_CAPTURED_COOKIES '
|
|
592
|
+
'is set. Pages or assets that need a logged-in session may fail to load during '
|
|
593
|
+
'asset discovery, so snapshots can render incorrectly.')
|
|
594
|
+
|
|
595
|
+
@patch.dict(os.environ, {'PERCY_DO_NOT_USE_CAPTURED_COOKIES': 'false'})
|
|
596
|
+
def test_opt_out_false_still_forwards(self):
|
|
597
|
+
driver = self._driver()
|
|
598
|
+
self.assertEqual(local.get_cookies_for_snapshot(driver), self.SESSION_COOKIES)
|
|
599
|
+
|
|
600
|
+
@patch.dict(os.environ, {}, clear=False)
|
|
601
|
+
@patch('percy.snapshot.log')
|
|
602
|
+
def test_cookie_read_failure_is_not_raised(self, _mock_log):
|
|
603
|
+
os.environ.pop('PERCY_DO_NOT_USE_CAPTURED_COOKIES', None)
|
|
604
|
+
driver = self._driver()
|
|
605
|
+
driver.get_cookies.side_effect = Exception('no cookies for you')
|
|
606
|
+
self.assertEqual(local.get_cookies_for_snapshot(driver), [])
|
|
503
607
|
|
|
504
608
|
|
|
505
609
|
if __name__ == '__main__':
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.2.1-beta.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{percy_selenium-2.2.1b2 → percy_selenium-2.2.2b0}/percy_selenium.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|