From 8bfdb76e7e27ce3c044f88804a490c15d0072455 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 11 Sep 2026 18:39:06 +0530 Subject: [PATCH 1/2] fix: skip dev-only GA-absent checks when the target isn't a dev host HOME_URL_DEV is whichever site the suite targets. Pointed at prod, the two dev GA tests asserted GA is absent on prod, where it is correctly present (G-41CT4XZ341). They now skip unless the host starts with dev., matching the contract stated in the file header. --- tests/consumer/smoke/test_con_seo_analytics.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/consumer/smoke/test_con_seo_analytics.py b/tests/consumer/smoke/test_con_seo_analytics.py index d45ca71..4ed4c5a 100644 --- a/tests/consumer/smoke/test_con_seo_analytics.py +++ b/tests/consumer/smoke/test_con_seo_analytics.py @@ -17,6 +17,7 @@ import os import re import time +from urllib.parse import urlparse import pytest @@ -114,12 +115,18 @@ def test_prod_data_layer_has_config_call(driver): # ─── Dev: GA must be completely absent ───────────────────────────────────────── +def _require_dev_target(): + # HOME_URL_DEV is whichever site the suite targets; prod deploys point it at prod. + host = urlparse(DEV_URL or "").hostname or "" + if not host.startswith("dev."): + pytest.skip(f"HOME_URL_DEV targets '{host or 'nothing'}', not a dev host; GA-absent checks apply to dev only") + + @pytest.mark.smoke @pytest.mark.seo def test_dev_ga_script_tag_absent(driver): """Dev must not load any googletagmanager script (GA intentionally disabled).""" - if not DEV_URL: - pytest.skip("HOME_URL_DEV not set") + _require_dev_target() driver.get(DEV_URL) time.sleep(GA_SETTLE_SECONDS) @@ -131,8 +138,7 @@ def test_dev_ga_script_tag_absent(driver): @pytest.mark.seo def test_dev_gtag_is_undefined(driver): """window.gtag must be undefined on dev (GA intentionally disabled).""" - if not DEV_URL: - pytest.skip("HOME_URL_DEV not set") + _require_dev_target() driver.get(DEV_URL) time.sleep(GA_SETTLE_SECONDS) From 60e9935bc5a3a342d3b45a8954466d3895fdd85b Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 11 Sep 2026 18:39:06 +0530 Subject: [PATCH 2/2] fix: rerun on StaleElementReferenceException as a timing signature A React re-render between wait_and_capture returning an element and the caller's is_displayed() leaves a stale reference -- a race, not a logic failure, and the same shape across ~43 wait_and_capture callers. Seen on test_TC_SEC_02_search_bar against prod. --- pytest.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pytest.ini b/pytest.ini index 3469dec..d866ca6 100644 --- a/pytest.ini +++ b/pytest.ini @@ -6,8 +6,9 @@ minversion = 6.0 # -n/--numprocesses is passed. # # --reruns/--only-rerun: retry a test up to twice, but ONLY when it failed on a -# timing signature (Selenium's TimeoutException, or pytest-timeout's own -# "Failed: Timeout" wrapper) — the kind of failure this suite has repeatedly +# timing signature (Selenium's TimeoutException, pytest-timeout's own +# "Failed: Timeout" wrapper, or a StaleElementReferenceException from a React +# re-render between find and use) — the kind of failure this suite has repeatedly # turned out to be a race or a throttled backend rather than a real bug. # AssertionError is deliberately excluded: those are logic/data failures (e.g. # a hardcoded fixture that no longer exists) and rerunning them would only mask @@ -16,6 +17,7 @@ addopts = --json-report --json-report-file=report.json --dist loadfile --reruns 2 --reruns-delay 5 --only-rerun "TimeoutException" --only-rerun "Failed: Timeout" + --only-rerun "StaleElementReferenceException" testpaths = tests markers =