CI: FT stages run in parallel, --parallel dropped intra-stage — bud-btn click sites bypass scroll-into-view ; .woodpecker/main.yaml restructures the FT split — test-FTs-non-room + test-FTs-room now both depends_on: test-two-browser-FTs (instead of room serially depending on non-room) so they fan out + run concurrently, each w. its own DATABASE_URL: sqlite:////tmp/test_db_{non_room,room}.sqlite3 outside the shared workspace mount so the two stages can't see each other's SQLite file + the #296 EOFError-on-half-created-test-db blocker is gone; --parallel flag dropped from both manage.py test invocations because the empirical wall-clock from #302-304 (151 tests in ~42 min, 83 tests in ~16 min — ~16-17s/test avg either way) shows ~1-1.5x speedup at best — Firefox spawn cost (~3-5s cold-start × 38 tests/worker) + RAM pressure (4 headless Firefoxes ≈ 1.5-2GB working set on a quadcore DO droplet) + SQLite file-lock contention eat most of the gain the cores would otherwise give, while the contention amplifies every transient-DOM flake we've spent the last 2 days chasing (login-race in #300/303 → 054b0aa + ad0041d, gecko-perms in #302/303 → ad0041d, ElementNotInteractable in #304 → this commit, Jasmine-timeout in #303 → ad0041d); stage-level parallelism gets back the wall-clock reduction (~16min savings vs serial stages) w.o. amplifying within-stage contention — net wall clock should be ~60-65min for both FT stages running concurrently vs ~58min today, but flake exposure drops dramatically; downstream screendumps + build-and-push already list both FT steps in their depends_on so they naturally gate on the slower of the two ; test_core_bud_btn.py wraps 4 unwrapped find_element(...).click() sites in wait_for(execute_script("arguments[0].click()", btn)) — the _open_panel_and_invite helper feeding 6 GatekeeperBudBtnAsyncInviteTest tests + the standalone GatekeeperBudBtnDuplicateInviteErrorTest test_duplicate_invite_shows_error_brief_and_fyi_flashes_slot click + both .note-banner--duplicate .note-banner__fyi clicks (one on the share-flow at line 433, one on the gatekeeper-invite-flow at line 622) — pipeline #304 errored on the OK button click w. ElementNotInteractableException: Element <button id="id_bud_ok"> could not be scrolled into view because the post-send_keys autocomplete dropdown on _bud_invite_panel.html briefly overlapped the OK button under CI contention so Firefox refused the scroll-into-view; same pattern + same fix shape as confirm_guard in base.py — execute_script bypasses Selenium's scroll-into-view gate entirely + wait_for absorbs any leftover transient state via WebDriverException retry ; commit only ships the test-side fix + CI restructure; if the CI changes work as intended (green pipeline #305) the docker-rebuild option for python-tdd-ci:latest still stands as the next ~5min/pipeline win, separately filed in project_ci_remove_pip_install_deferred.md — TDD
Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -427,9 +427,12 @@ class BudBtnDuplicateShareErrorTest(FunctionalTest):
|
||||
self.assertNotIn("bud-duplicate-flash", chip.get_attribute("class") or "")
|
||||
|
||||
# FYI dismisses + applies flash class
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__fyi"
|
||||
).click()
|
||||
self.wait_for(lambda: self.browser.execute_script(
|
||||
"arguments[0].click()",
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__fyi"
|
||||
),
|
||||
))
|
||||
self.wait_for(lambda: self.assertEqual(
|
||||
self.browser.find_elements(By.CSS_SELECTOR, ".note-banner--duplicate"),
|
||||
[],
|
||||
@@ -503,9 +506,17 @@ class GatekeeperBudBtnAsyncInviteTest(FunctionalTest):
|
||||
lambda: self.browser.find_element(By.ID, "id_recipient")
|
||||
)
|
||||
recipient_input.send_keys(recipient)
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, "#id_bud_panel .btn.btn-confirm"
|
||||
).click()
|
||||
# wait_for + execute_script bypasses Selenium's scroll-into-view
|
||||
# gate — under CI contention the post-send_keys autocomplete dropdown
|
||||
# can briefly overlap the OK button + Firefox refuses the click w.
|
||||
# ElementNotInteractableException (pipeline #304). Same shape as
|
||||
# confirm_guard in base.py.
|
||||
self.wait_for(lambda: self.browser.execute_script(
|
||||
"arguments[0].click()",
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, "#id_bud_panel .btn.btn-confirm"
|
||||
),
|
||||
))
|
||||
return bud_btn
|
||||
|
||||
def test_invite_creates_room_invite(self):
|
||||
@@ -579,7 +590,13 @@ class GatekeeperBudBtnDuplicateInviteErrorTest(FunctionalTest):
|
||||
btn.click()
|
||||
recipient = self.wait_for(lambda: self.browser.find_element(By.ID, "id_recipient"))
|
||||
recipient.send_keys("alice@test.io")
|
||||
self.browser.find_element(By.CSS_SELECTOR, "#id_bud_panel .btn.btn-confirm").click()
|
||||
# See _open_panel_and_invite (above) for the bypass rationale.
|
||||
self.wait_for(lambda: self.browser.execute_script(
|
||||
"arguments[0].click()",
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, "#id_bud_panel .btn.btn-confirm"
|
||||
),
|
||||
))
|
||||
|
||||
title = self.wait_for(lambda: self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__title"
|
||||
@@ -600,9 +617,12 @@ class GatekeeperBudBtnDuplicateInviteErrorTest(FunctionalTest):
|
||||
)
|
||||
self.assertNotIn("bud-duplicate-flash", slot.get_attribute("class") or "")
|
||||
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__fyi"
|
||||
).click()
|
||||
self.wait_for(lambda: self.browser.execute_script(
|
||||
"arguments[0].click()",
|
||||
self.browser.find_element(
|
||||
By.CSS_SELECTOR, ".note-banner--duplicate .note-banner__fyi"
|
||||
),
|
||||
))
|
||||
self.wait_for(lambda: self.assertEqual(
|
||||
self.browser.find_elements(By.CSS_SELECTOR, ".note-banner--duplicate"),
|
||||
[],
|
||||
|
||||
Reference in New Issue
Block a user