Repository navigation
fix(e2e): select a farm-local expense range across month boundaries - #1011
Merged
Merged
Conversation
Owner
Author
Review record — Claude Opus 5.5 (local agent, read-only), 2 roundsReviewed at the owner's request. CodeRabbit was not triggered. Round 1 —
|
Merged
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Expense specs fail at the start of a farm month because the default range excludes the seeded rows. The phone optical-size test has the same cause: an empty month renders
EmptyStateinstead of the expense ledger.openSeededExpensesopens the page and fills both date filters from 30 days before farm-local today through today. It uses the existing farm clock, translated labels, and the phone filter dialog. It waits for the expense response carrying the requested dates, then for the rendered ledger. Listening before navigation also handles a 31-day month-end when the default range already matches. The window assumes a fresh simulation seed and covers its named expenses, dated 2–7 days before the UTC seed anchor. The preflight checks recent eggs, not expenses; an old database can still pass that check while these expense rows have aged out. The seeder and application are unchanged.The review identified a possible mid-month race where a caller could use the old ledger before the range reload remounted it. I did not reproduce that flake; the helper now owns the response and rendering waits instead of relying on callers.
I checked every
/expensesreference. The other callers measure the desktop summary and category controls, which do not require expense rows.Closes #1009
Verification
ab284d7fon the same real date; CI is the authoritative clean-runner result.1880d761: all three E2E smoke shards passed on the real October 1 Chicago date, including the response wait and immediate rejection handler. CodeQL and every other non-image check passed, including integration and web coverage/build. The CI run is red only because amd64 found ci: move image vulnerability scanning out of CI to a weekly scan of published images #1006’s existing OpenSSL CVE-2026-84782; fail-fast cancelled arm64 and image publishing was skipped.83b153ac, before the final promise-handling line.83b153ac(before the final promise-handling line): 134 passed, 1 intentionally skipped, 0 failed (6.3 minutes). No reruns. Host one-minute load fell from about 5.6 to 2.2 during the observed run.ab284d7f: 133 passed, 1 skipped, 1 timeout (13.3 minutes), with host load around 50–58 on 12 CPUs. The unrelated desktopday-readout-placement.spec.ts:173English day-strip visibility assertion timed out. An immediate sequential rerun of that case and its phone counterpart passed in 2.2 and 2.1 seconds; no code or deadline changes. Both also passed in the final fresh suite. The skip is the opt-in real token-lifetime test.await loadedstill propagates response failures. A disposable three-case Playwright probe forced navigation to fail before that await. Before the fix, the broken case reported both the navigation error andpage.waitForResponse: Test ended; afterward it reported only the intended navigation error. The following two cases passed in both runs, so this probe reproduced the extra rejection, not the wider file cascade.git diff --checkpass. The unrelated image-scan failure is tracked in ci: move image vulnerability scanning out of CI to a weekly scan of published images #1006; this PR does not change or suppress it.Repeat the month-boundary proof on any day
I executed these setup, before/after, and browser-probe commands as written on an Ubuntu 26.04 host. The host-downloaded library loaded successfully in the Ubuntu 24.04 app image, including its seeder. These Linux commands use an isolated
cw-1009-fixedcompose project on ports 18092 and 18900, in a dedicated checkout of this PR. They create only disposable, untracked files. Do not run them while another user is driving that same project. Prerequisites are Docker, Node/npm, Python, and Debian/Ubuntu'saptanddpkg-deb.FAKETIME='@2026-02-01 12:00:00'starts an advancing wall clock at February 1, not a stopped clock. The API and every one-shot process, including the seeder, inherit it from the app service. The Playwright runner and its Chromium children get the same setting below. All see February 1 in the farm's America/Chicago zone.FAKETIME_DONT_FAKE_MONOTONIC=1preserves real monotonic timers;FAKETIME_DONT_RESET=1keeps the runner's child processes on its advancing timeline.Both stopped-clock and advancing-clock trials reproduced the original failures. The first recipe let libfaketime enable its automatic monotonic workaround, which caused CPU spinning and dialog timeouts on this host.
FAKETIME_FORCE_MONOTONIC_FIX=0removed that overhead: the same desktop correction case passed in 4.3 seconds with the normal 45-second deadline. The recipe below includes this setting in both the app container and the runner. No spec timeout or assertion was relaxed. No clock interception becomes part of the application, simulation harness, or CI.To verify the browser clock itself, run this in the same shell.
page.evaluateexecutes in Chromium's renderer, not Node. The suite uses Playwright's default launch with--no-sandbox; this does not claim coverage of sandboxed Chromium.The advancing probe returned runner
2026-02-01T12:00:00.454Zand renderer2026-02-01T12:00:00.459Z, then12:00:01.462Zand12:00:01.463Z. Both advanced on the same timeline. In the stopped-clock diagnostic, runner and renderer both returned exactly2026-02-01T12:00:00Z; the API minted a JWT expiring at12:15:00Z, the seed manifest recordedgeneratedAtAnchor=2026-02-01, and the UI range was February 1–28. CDP confirmed the ledger was absent from the accessibility tree as well as the DOM.After the proof, remove the disposable specs and stop only this isolated project: