Promium 3.7.1__tar.gz → 3.7.3__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.
- {promium-3.7.1 → promium-3.7.3}/PKG-INFO +1 -1
- {promium-3.7.1 → promium-3.7.3}/Promium.egg-info/PKG-INFO +1 -1
- {promium-3.7.1 → promium-3.7.3}/promium/_diag.py +26 -4
- {promium-3.7.1 → promium-3.7.3}/promium/base.py +5 -5
- {promium-3.7.1 → promium-3.7.3}/promium/plugin.py +31 -10
- {promium-3.7.1 → promium-3.7.3}/setup.py +1 -1
- {promium-3.7.1 → promium-3.7.3}/LICENSE +0 -0
- {promium-3.7.1 → promium-3.7.3}/Promium.egg-info/SOURCES.txt +0 -0
- {promium-3.7.1 → promium-3.7.3}/Promium.egg-info/dependency_links.txt +0 -0
- {promium-3.7.1 → promium-3.7.3}/Promium.egg-info/entry_points.txt +0 -0
- {promium-3.7.1 → promium-3.7.3}/Promium.egg-info/requires.txt +0 -0
- {promium-3.7.1 → promium-3.7.3}/Promium.egg-info/top_level.txt +0 -0
- {promium-3.7.1 → promium-3.7.3}/README.rst +0 -0
- {promium-3.7.1 → promium-3.7.3}/doc/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/doc/conf.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/assertions.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/browsers.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/common.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/device_config.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/checkbox.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/drop_downs.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/frame.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/input_field.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/link.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/multiselect_listbox.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/radio_button.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/textarea_field.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/elements/upload_button.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/exceptions.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/expected_conditions.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/helpers.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/logger.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/support/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/support/settings.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/test_case.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/promium/waits.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/pyproject.toml +0 -0
- {promium-3.7.1 → promium-3.7.3}/setup.cfg +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/config.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/conftest.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/pages/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/pages/catalog_404_page.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/pages/catalog_gallery_page.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/__init__.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/test_base.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/test_chrome.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/test_edge.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/test_firefox.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/test_ie.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/settings/test_opera.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/test_catalog_404.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/test_catalog_gallery.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/test_enviroment.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/test_requests.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/test_soft_asserts.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/test_waits.py +0 -0
- {promium-3.7.1 → promium-3.7.3}/tests/urls.py +0 -0
|
@@ -12,8 +12,17 @@ from typing import Any
|
|
|
12
12
|
STEP_BUFFER = int(os.getenv("PROMIUM_STEP_BUFFER", "50"))
|
|
13
13
|
|
|
14
14
|
LOCATORS_TO_SHOW = int(
|
|
15
|
-
os.getenv("PROMIUM_LOCATORS_TO_SHOW", os.getenv("LOC_CHAIN_LEN", "
|
|
15
|
+
os.getenv("PROMIUM_LOCATORS_TO_SHOW", os.getenv("LOC_CHAIN_LEN", "3"))
|
|
16
16
|
)
|
|
17
|
+
# PROMIUM_ACTIONS_STYLE controls how the “Actions” chain is rendered:
|
|
18
|
+
# - "stair" (default): multi-line staircase with indentation
|
|
19
|
+
# - "line" : single-line with arrows
|
|
20
|
+
ACTIONS_STYLE_DEFAULT = os.getenv("PROMIUM_ACTIONS_STYLE", "stair").lower()
|
|
21
|
+
ACTIONS_STAIR_INDENT = int(os.getenv("PROMIUM_ACTIONS_STAIR_INDENT", "4"))
|
|
22
|
+
ACTIONS_TOTAL_LIMIT = int(
|
|
23
|
+
os.getenv("PROMIUM_ACTIONS_TOTAL_LIMIT", str(LOCATORS_TO_SHOW))
|
|
24
|
+
)
|
|
25
|
+
|
|
17
26
|
|
|
18
27
|
STEPS_EXCLUDE = [
|
|
19
28
|
s
|
|
@@ -228,7 +237,20 @@ def _format_actions_chain(
|
|
|
228
237
|
parts = _dedup_consecutive(parts)
|
|
229
238
|
if not parts:
|
|
230
239
|
return None
|
|
231
|
-
|
|
240
|
+
|
|
241
|
+
total_limit = max(1, int(ACTIONS_TOTAL_LIMIT or LOCATORS_TO_SHOW))
|
|
242
|
+
if len(parts) > total_limit:
|
|
243
|
+
parts = parts[-total_limit:]
|
|
244
|
+
|
|
245
|
+
style = ACTIONS_STYLE_DEFAULT
|
|
246
|
+
if style != "stair" or len(parts) == 1:
|
|
247
|
+
return " \u2192 ".join(parts)
|
|
248
|
+
|
|
249
|
+
indent_step = max(0, int(ACTIONS_STAIR_INDENT))
|
|
250
|
+
lines: list[str] = [parts[0]]
|
|
251
|
+
for i, p in enumerate(parts[1:], start=1):
|
|
252
|
+
lines.append(f"{' ' * (indent_step * i)}\u2192 {p}")
|
|
253
|
+
return "\n" + "\n".join(lines)
|
|
232
254
|
|
|
233
255
|
|
|
234
256
|
def _read_source_line(path: str, lineno: int, max_len: int) -> str | None:
|
|
@@ -283,7 +305,7 @@ def build_digest(
|
|
|
283
305
|
|
|
284
306
|
actions = _format_actions_chain(context_prefix)
|
|
285
307
|
if actions:
|
|
286
|
-
blocks.append("— Actions: " + actions)
|
|
308
|
+
blocks.append("— Actions: \n" + actions)
|
|
287
309
|
|
|
288
310
|
if SHOW_CALLSITE:
|
|
289
311
|
cs = _user_callsite()
|
|
@@ -300,4 +322,4 @@ def build_digest(
|
|
|
300
322
|
if origin and origin[0]:
|
|
301
323
|
blocks.append(f"↳ locator at {_rel(origin[0])}:{origin[1] or '?'}")
|
|
302
324
|
|
|
303
|
-
return "\n
|
|
325
|
+
return "\n\n".join(blocks)
|
|
@@ -940,12 +940,12 @@ class ElementBase(Base):
|
|
|
940
940
|
digest = f"{digest}\n{msg}"
|
|
941
941
|
raise ElementLocationException(digest) from None
|
|
942
942
|
|
|
943
|
-
def wait_to_disappear(self,
|
|
943
|
+
def wait_to_disappear(self, timeout: int = 10, msg: str = "") -> bool | None:
|
|
944
944
|
"""
|
|
945
945
|
Wait until element disappears from DOM or is hidden.
|
|
946
946
|
|
|
947
947
|
Args:
|
|
948
|
-
|
|
948
|
+
timeout: Maximum wait time in seconds.
|
|
949
949
|
msg: Optional extra message for error context.
|
|
950
950
|
|
|
951
951
|
Raises:
|
|
@@ -956,7 +956,7 @@ class ElementBase(Base):
|
|
|
956
956
|
"""
|
|
957
957
|
css = self._fmt_locator()
|
|
958
958
|
css_probe = self.locator if self.by == By.CSS_SELECTOR else None
|
|
959
|
-
push_step(f'wait_to_disappear("{css}", {
|
|
959
|
+
push_step(f'wait_to_disappear("{css}", {timeout}s)')
|
|
960
960
|
|
|
961
961
|
def _gone(_self: Self) -> bool:
|
|
962
962
|
obj = _self._get_current_driver()
|
|
@@ -972,7 +972,7 @@ class ElementBase(Base):
|
|
|
972
972
|
return True
|
|
973
973
|
|
|
974
974
|
try:
|
|
975
|
-
return WebDriverWait(self.driver,
|
|
975
|
+
return WebDriverWait(self.driver, timeout).until(
|
|
976
976
|
lambda driver: _gone(self)
|
|
977
977
|
)
|
|
978
978
|
except TimeoutException:
|
|
@@ -980,7 +980,7 @@ class ElementBase(Base):
|
|
|
980
980
|
self.driver,
|
|
981
981
|
title="Element(s) did not disappear",
|
|
982
982
|
locator=css,
|
|
983
|
-
wait_seconds=
|
|
983
|
+
wait_seconds=timeout,
|
|
984
984
|
css_for_probe=css_probe,
|
|
985
985
|
**self._digest_ctx(),
|
|
986
986
|
)
|
|
@@ -19,6 +19,8 @@ from promium.logger import Logger
|
|
|
19
19
|
from promium.test_case import create_driver
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
mono_color = os.getenv("PROMIUM_ASSERTION_PANEL_MONO_COLOR", False) # noqa: PLW1508
|
|
23
|
+
|
|
22
24
|
log = logging.getLogger(__name__)
|
|
23
25
|
|
|
24
26
|
|
|
@@ -269,12 +271,19 @@ def logger(request: pytest.FixtureRequest) -> logging.Logger:
|
|
|
269
271
|
return logging.getLogger()
|
|
270
272
|
|
|
271
273
|
|
|
274
|
+
def color_msg(msg: str, color: str = "bold red") -> str:
|
|
275
|
+
if mono_color:
|
|
276
|
+
return msg
|
|
277
|
+
return f"[{color}]{msg}[/{color}]"
|
|
278
|
+
|
|
279
|
+
|
|
272
280
|
@pytest.mark.trylast
|
|
273
281
|
def pytest_runtest_call(item: pytest.Item) -> None:
|
|
274
282
|
separator = "-" * 46
|
|
275
283
|
if PANEL_WIDTH := os.getenv("PROMIUM_ASSERTION_PANEL_WIDTH"):
|
|
276
284
|
from rich.console import Console # noqa: PLC0415
|
|
277
285
|
from rich.panel import Panel # noqa: PLC0415
|
|
286
|
+
from rich.syntax import Syntax # noqa: PLC0415
|
|
278
287
|
from rich.text import Text # noqa: PLC0415
|
|
279
288
|
|
|
280
289
|
try:
|
|
@@ -288,6 +297,10 @@ def pytest_runtest_call(item: pytest.Item) -> None:
|
|
|
288
297
|
PANEL_WIDTH = terminal_width
|
|
289
298
|
except Exception:
|
|
290
299
|
PANEL_WIDTH = terminal_width
|
|
300
|
+
if mono_color:
|
|
301
|
+
border_style = "none"
|
|
302
|
+
else:
|
|
303
|
+
border_style = "red"
|
|
291
304
|
|
|
292
305
|
if hasattr(item.config, "assertion_errors"):
|
|
293
306
|
if item.config.assertion_errors:
|
|
@@ -299,11 +312,16 @@ def pytest_runtest_call(item: pytest.Item) -> None:
|
|
|
299
312
|
width=PANEL_WIDTH - 5,
|
|
300
313
|
)
|
|
301
314
|
for error_text in item.config.assertion_errors:
|
|
315
|
+
text = error_text.strip()
|
|
316
|
+
if mono_color:
|
|
317
|
+
msg = Text(text, justify="left")
|
|
318
|
+
else:
|
|
319
|
+
msg = Syntax(text, "sql", word_wrap=True)
|
|
302
320
|
rich_panel = Panel(
|
|
303
|
-
|
|
304
|
-
title="
|
|
305
|
-
border_style=
|
|
306
|
-
padding=(1,
|
|
321
|
+
renderable=msg,
|
|
322
|
+
title=color_msg("Soft Assertion Error"),
|
|
323
|
+
border_style=border_style,
|
|
324
|
+
padding=(1, 1),
|
|
307
325
|
)
|
|
308
326
|
console.print(rich_panel)
|
|
309
327
|
rich_output = string_io.getvalue()
|
|
@@ -326,13 +344,16 @@ def pytest_runtest_call(item: pytest.Item) -> None:
|
|
|
326
344
|
width=PANEL_WIDTH - 5,
|
|
327
345
|
)
|
|
328
346
|
for error_text in console_errors:
|
|
347
|
+
text = error_text.strip()
|
|
348
|
+
if mono_color:
|
|
349
|
+
msg = Text(text, justify="left")
|
|
350
|
+
else:
|
|
351
|
+
msg = Syntax(text, "sql", word_wrap=True)
|
|
329
352
|
rich_panel = Panel(
|
|
330
|
-
|
|
331
|
-
title="
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
border_style="red",
|
|
335
|
-
padding=(1, 2),
|
|
353
|
+
renderable=msg,
|
|
354
|
+
title=color_msg("Browser console js errors found"),
|
|
355
|
+
border_style=border_style,
|
|
356
|
+
padding=(1, 1),
|
|
336
357
|
)
|
|
337
358
|
console.print(rich_panel)
|
|
338
359
|
rich_output = string_io.getvalue()
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|