From be47703b59a7f60811ada4c05879e37674393bfa Mon Sep 17 00:00:00 2001 From: kevinjylin Date: Sat, 6 Jun 2026 17:28:45 -0700 Subject: [PATCH] Fix failing CI: schema contract test, calendar menu role, flaky e2e Three independent failures were red on main: - Pipeline unit test test_schema_contract expected _to_event_row to return a dict, but it now returns a (row, superseded_id) tuple. Unpack it. - E2E "Add to calendar"/"Add reminder" expected role=button, but the disclosure toggle exposed neither button nor link (Playwright sees the
as a group). Give the an explicit role="button" so the accessible role matches a disclosure toggle and the native toggle still works. - E2E "calendar shows loading state" failed deterministically on slow CI CPU: the calendar syncs its cursor to the feed's observed day on mount, firing a stray fetch that races the test's Next-month click. Wait for the calendar to settle on May 2026 before exercising the navigation fetch, matching the sibling tests. Drop the racy blockCalendarFetch band-aid. Verified locally: 83/83 pipeline tests, 12/12 e2e, lint clean. The calendar test now passes under 4x/8x/12x CPU throttle. Co-Authored-By: Claude Opus 4.8 --- pipeline/tests/test_schema_contract.py | 2 +- src/components/events/EventCalendarMenu.tsx | 1 + tests/e2e/events-browser-contract.spec.ts | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pipeline/tests/test_schema_contract.py b/pipeline/tests/test_schema_contract.py index 3a2304c..01d625a 100644 --- a/pipeline/tests/test_schema_contract.py +++ b/pipeline/tests/test_schema_contract.py @@ -78,7 +78,7 @@ def tearDownClass(cls) -> None: sys.modules[name] = mod def test_extract_stories_event_row_keys(self) -> None: - row = self.extract_stories._to_event_row( + row, _superseded_id = self.extract_stories._to_event_row( { "id": "3894795737410658765", "handle": "cyber_ucr", diff --git a/src/components/events/EventCalendarMenu.tsx b/src/components/events/EventCalendarMenu.tsx index bcc2ee0..faea7ae 100644 --- a/src/components/events/EventCalendarMenu.tsx +++ b/src/components/events/EventCalendarMenu.tsx @@ -94,6 +94,7 @@ export function EventCalendarMenu({ return (
diff --git a/tests/e2e/events-browser-contract.spec.ts b/tests/e2e/events-browser-contract.spec.ts index b7de9f1..04210ce 100644 --- a/tests/e2e/events-browser-contract.spec.ts +++ b/tests/e2e/events-browser-contract.spec.ts @@ -62,20 +62,22 @@ test("calendar shows loading state while month events refresh", async ({ const calendarRail = page.locator( 'aside[aria-label="Calendar and time filter"]' ); - await expect(calendarRail.getByRole("heading")).toBeVisible(); + const calendarHeading = calendarRail.getByRole("heading", { level: 2 }); + await expect(calendarRail).toBeVisible(); + // The calendar follows the feed's first visible day, so it settles on the + // observed month (May 2026) shortly after load. Wait for that initial sync to + // finish before testing a navigation fetch — otherwise the stray sync request + // races the click and the displayed month reads as already-loaded on slow CI. + await expect(calendarHeading).toHaveText(/may 2026/i); let releaseCalendarResponse!: () => void; const calendarResponse = new Promise((resolve) => { releaseCalendarResponse = resolve; }); - let blockCalendarFetch = false; + // Installed only after the initial sync settled, so the single request it holds + // open is the one triggered by the Next-month click below. await page.route("**/api/events/calendar**", async (route) => { - if (!blockCalendarFetch) { - await route.continue(); - return; - } - await calendarResponse; await route.fulfill({ status: 200, @@ -85,10 +87,8 @@ test("calendar shows loading state while month events refresh", async ({ }); const calendarGrid = calendarRail.locator("[aria-busy]").first(); - blockCalendarFetch = true; - const fetchStarted = page.waitForRequest("**/api/events/calendar**"); await calendarRail.getByRole("button", { name: "Next month" }).click(); - await fetchStarted; + await expect(calendarHeading).toHaveText(/june 2026/i); await expect(calendarGrid).toHaveAttribute("aria-busy", "true"); releaseCalendarResponse();