2026-05-12 16:40:15 -04:00
|
|
|
import re
|
|
|
|
|
|
2026-02-11 14:42:38 -05:00
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
|
from .base import FunctionalTest
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class JasmineTest(FunctionalTest):
|
|
|
|
|
def test_jasmine_specs_pass(self):
|
|
|
|
|
self.browser.get(self.live_server_url + "/static/tests/SpecRunner.html")
|
|
|
|
|
|
|
|
|
|
def check_results():
|
|
|
|
|
result = self.browser.find_element(By.CSS_SELECTOR, ".jasmine-overall-result")
|
2026-05-12 16:40:15 -04:00
|
|
|
# Word-boundary anchor — Jasmine 6 reports as "N specs, X failures".
|
|
|
|
|
# Plain `"0 failures" in text` matches "10 failures", "20 failures",
|
|
|
|
|
# etc., letting up to 99 failed specs slip past as green.
|
|
|
|
|
if not re.search(r"(?<!\d)0 failures\b", result.text):
|
2026-03-29 23:39:03 -04:00
|
|
|
failures = self.browser.find_elements(
|
|
|
|
|
By.CSS_SELECTOR, ".jasmine-failed .jasmine-description"
|
|
|
|
|
)
|
|
|
|
|
detail = "\n".join(f.text for f in failures) if failures else "(no detail)"
|
|
|
|
|
self.fail(f"{result.text}\nFailing specs:\n{detail}")
|
|
|
|
|
|
FT flake mitigations triggered by pipelines #302/#303 — three independent fixes consolidated in one commit; test_admin_tarot._login_to_admin now waits on `"Site administration"` body substring before returning, same shape as 054b0aa's test_admin.py fix — the helper used to click submit + return immediately, letting the three TarotAdminTest tests race their subsequent `browser.get(/admin/epic/tarotcard/)` against the in-flight POST → 302 → admin home navigation so on a slow CI runner the new GET cancelled the unfinished POST, the session cookie was never set, the browser landed back on `/admin/login/?next=…`, and the downstream assertion saw the login-page body (`'Earthman Deck' not found in 'Django administration\nEmail:\nPassword:'` in #303, plus a NoSuchElementException for "The Schiz" on test_admin_earthman_card_detail's link-text click) — wait_for w. assertIn retries til the post-login page actually renders so the rest of the helper's callers start from a settled state ; test_jasmine swaps `wait_for(check_results)` → `wait_for_slow(check_results, timeout=60)` — the spec suite has grown well past the 10s MAX_WAIT the default `wait_for` decorator affords + under CI contention (parallel Selenium workers competing for CPU on the same droplet) Jasmine's `.jasmine-overall-result` was still reporting `"Running..."` at 10s when the assertion fired w. `(no detail)` failure list (#303); check_results body is unchanged — `"Running..."` doesn't match the `0 failures` regex so it falls into the failure branch + raises AssertionError, which wait_for_slow naturally retries til the result settles or 60s elapses ; base._make_browser wraps `webdriver.Firefox(options=options)` in try/except WebDriverException w. one sleep+retry when `"geckodriver"` appears in the error message — covers the spawn race under --parallel where multiple workers hit the same binary mid-permission-set + one of them gets `'geckodriver' executable may have wrong permissions` (1 test in #302 + 1 test in #303, different test classes each time, confirming infra not test-logic); narrow filter on `"geckodriver"` so a genuine install fault still fails fast — both attempts would surface the same error in <1s ; deferred option filed to memory (project_ci_remove_pip_install_deferred.md) — dropping the `pip install -r requirements.dev.txt` line from each FT step would save ~5 min/pipeline (CI image drifted from requirements.dev.txt since a21e6aa so the install actually downloads 30+ packages every step instead of the intended "already satisfied" no-op verify) but loses the dep-drift safety net; declined for now, revisit when wall-clock pain > safety value — TDD
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 12:53:49 -04:00
|
|
|
# wait_for_slow w. 60s ceiling — the spec suite has grown well past the
|
|
|
|
|
# 10s MAX_WAIT the default wait_for affords. Under CI contention
|
|
|
|
|
# (parallel Selenium workers competing for CPU) Jasmine's still
|
|
|
|
|
# reporting "Running..." at 10s; pipeline #303 caught this. The
|
|
|
|
|
# check_results body keeps raising AssertionError ("Running..." doesn't
|
|
|
|
|
# match the 0-failures regex) so wait_for_slow naturally retries til
|
|
|
|
|
# the result settles or the timeout fires.
|
|
|
|
|
self.wait_for_slow(check_results, timeout=60)
|