Make the frontend tests independent of runner load #425

Merged
robbertbos merged 1 commit from ci-frozen-parse-clock into main 2026-09-23 23:21:43 +00:00
Owner

Closes #404.

frontend-test failed in 14 of the last 85 runs. The failed first attempts could still be read through the job view in the web UI (the raw log download returns a 500 for them). Here is what failed:

Test Runs
quoteBar.test.ts "marks a quote the initial parse did not reach" 12 (one of them together with hideMarkers.test.ts)
UnreadMessageList.test.ts "stops loading further unread at the window ceiling" (timeout at 5000ms) 1
Node download in setup-node (TLS disconnect) 1, fixed by #420

The failure was always an assertion or a timeout, never a crash, and always a test that depends on the clock.

CodeMirror parse budget. CodeMirror stops parsing when a Date.now() budget runs out: 20ms when a state is created, 50ms in ensureSyntaxTree. On a busy runner the tree stops short, and quoteLines sees no quote at line 400. A clock that jumps 30ms per call reproduces the exact CI error (expected [] to have a length of 1 but got +0); with a frozen clock the test passes. The seven test files that read a parse tree now freeze Date per test (vi.useFakeTimers({ toFake: ['Date'] })). Parsing then stops only on its character limits, so the test still exercises the "initial parse stops at 3000 characters" case it is named after.

UnreadMessageList.test.ts. The fixtures are timed against a NOW pinned at module load, but the component formats "40 min geleden" against the real clock. Once the file had run for more than a minute, the label read "41 min geleden"; setting the clock to NOW + 61s reproduces it. Date is now frozen at NOW. The window-ceiling test renders a full 200-message window (MAX_UNREAD_WINDOW) eight times: 3.1s at load 12, against the 5s default. It gets 20s instead of a smaller window, because hitting the real ceiling is the point of the test.

Test-only change, so no CHANGELOG entry.

Not fixed: in one local run at load 22, SortableSection.test.ts "scrolls a card hanging off the bottom back into view after an Alt-move" also failed once. It is not among the CI failures and I could not reproduce it (a 30ms stall around afterMove passes), so it is left alone. If it shows up in CI, its log is the place to start.

Closes #404. `frontend-test` failed in 14 of the last 85 runs. The failed first attempts could still be read through the job view in the web UI (the raw log download returns a 500 for them). Here is what failed: | Test | Runs | |---|---| | `quoteBar.test.ts` "marks a quote the initial parse did not reach" | 12 (one of them together with `hideMarkers.test.ts`) | | `UnreadMessageList.test.ts` "stops loading further unread at the window ceiling" (timeout at 5000ms) | 1 | | Node download in `setup-node` (TLS disconnect) | 1, fixed by #420 | The failure was always an assertion or a timeout, never a crash, and always a test that depends on the clock. **CodeMirror parse budget.** CodeMirror stops parsing when a `Date.now()` budget runs out: 20ms when a state is created, 50ms in `ensureSyntaxTree`. On a busy runner the tree stops short, and `quoteLines` sees no quote at line 400. A clock that jumps 30ms per call reproduces the exact CI error (`expected [] to have a length of 1 but got +0`); with a frozen clock the test passes. The seven test files that read a parse tree now freeze `Date` per test (`vi.useFakeTimers({ toFake: ['Date'] })`). Parsing then stops only on its character limits, so the test still exercises the "initial parse stops at 3000 characters" case it is named after. **`UnreadMessageList.test.ts`.** The fixtures are timed against a `NOW` pinned at module load, but the component formats "40 min geleden" against the real clock. Once the file had run for more than a minute, the label read "41 min geleden"; setting the clock to `NOW + 61s` reproduces it. `Date` is now frozen at `NOW`. The window-ceiling test renders a full 200-message window (`MAX_UNREAD_WINDOW`) eight times: 3.1s at load 12, against the 5s default. It gets 20s instead of a smaller window, because hitting the real ceiling is the point of the test. Test-only change, so no CHANGELOG entry. **Not fixed:** in one local run at load 22, `SortableSection.test.ts` "scrolls a card hanging off the bottom back into view after an Alt-move" also failed once. It is not among the CI failures and I could not reproduce it (a 30ms stall around `afterMove` passes), so it is left alone. If it shows up in CI, its log is the place to start.
Make the frontend tests independent of runner load
Some checks failed
CI / release-scripts (pull_request) Successful in 13s
security-scan / SBOM (trivy) (pull_request) Successful in 12s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 19s
security-scan / JS SCA (npm audit) (pull_request) Successful in 20s
security-scan / Python SAST (bandit) (pull_request) Successful in 23s
test-build / build (pull_request) Has been cancelled
security-scan / Python SCA (pip-audit) (pull_request) Has been cancelled
CI / frontend-test (pull_request) Has been cancelled
test-build / build (backend) (pull_request) Has been cancelled
CI / backend-test (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
CI / pre-commit (pull_request) Has been cancelled
test-build / build (frontend) (pull_request) Has been cancelled
3173f08749
frontend-test failed about one run in six and passed on a retry. Of
the 14 failures still in the Forgejo history, 12 were the CodeMirror
parser tests (11 of them quoteBar's "marks a quote the initial parse
did not reach"). CodeMirror stops parsing when a Date.now() budget
runs out (20ms on state creation, 50ms in ensureSyntaxTree), so on a
busy runner the tree stops short and the test sees no quote. The
tests that read a parse tree now freeze Date, which leaves only the
character limits in play.

UnreadMessageList.test.ts pinned NOW at module load, while the
component formats "40 min geleden" against the real clock: a file
that ran over a minute read "41 min geleden". Date is now frozen at
NOW. Its window-ceiling test renders a full 200-message window eight
times and timed out at the 5s default once; it gets 20s.
robbertbos force-pushed ci-frozen-parse-clock from 3173f08749
Some checks failed
CI / release-scripts (pull_request) Successful in 13s
security-scan / SBOM (trivy) (pull_request) Successful in 12s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 19s
security-scan / JS SCA (npm audit) (pull_request) Successful in 20s
security-scan / Python SAST (bandit) (pull_request) Successful in 23s
test-build / build (pull_request) Has been cancelled
security-scan / Python SCA (pip-audit) (pull_request) Has been cancelled
CI / frontend-test (pull_request) Has been cancelled
test-build / build (backend) (pull_request) Has been cancelled
CI / backend-test (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
CI / pre-commit (pull_request) Has been cancelled
test-build / build (frontend) (pull_request) Has been cancelled
to 4e1af240b3
Some checks failed
CI / release-scripts (pull_request) Successful in 18s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 20s
security-scan / JS SCA (npm audit) (pull_request) Successful in 21s
security-scan / Python SAST (bandit) (pull_request) Successful in 29s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 48s
test-build / build (frontend) (pull_request) Successful in 1m6s
test-build / build (backend) (pull_request) Successful in 1m11s
CI / frontend-test (pull_request) Successful in 1m13s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 2m5s
CI / backend-test (pull_request) Successful in 3m13s
CI / e2e (pull_request) Has been cancelled
2026-09-23 21:16:19 +00:00
Compare
robbertbos force-pushed ci-frozen-parse-clock from 4e1af240b3
Some checks failed
CI / release-scripts (pull_request) Successful in 18s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 20s
security-scan / JS SCA (npm audit) (pull_request) Successful in 21s
security-scan / Python SAST (bandit) (pull_request) Successful in 29s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 48s
test-build / build (frontend) (pull_request) Successful in 1m6s
test-build / build (backend) (pull_request) Successful in 1m11s
CI / frontend-test (pull_request) Successful in 1m13s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 2m5s
CI / backend-test (pull_request) Successful in 3m13s
CI / e2e (pull_request) Has been cancelled
to 0baf416258
All checks were successful
CI / release-scripts (pull_request) Successful in 18s
security-scan / SBOM (trivy) (pull_request) Successful in 25s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 30s
security-scan / Python SAST (bandit) (pull_request) Successful in 38s
security-scan / JS SCA (npm audit) (pull_request) Successful in 40s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 1m0s
test-build / build (frontend) (pull_request) Successful in 1m46s
test-build / build (backend) (pull_request) Successful in 1m54s
CI / frontend-test (pull_request) Successful in 1m55s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 2m0s
CI / backend-test (pull_request) Successful in 6m54s
CI / e2e (pull_request) Successful in 9m31s
2026-09-23 21:22:00 +00:00
Compare
robbertbos scheduled this pull request to auto merge when all checks succeed 2026-09-23 21:39:12 +00:00
robbertbos force-pushed ci-frozen-parse-clock from 0baf416258
All checks were successful
CI / release-scripts (pull_request) Successful in 18s
security-scan / SBOM (trivy) (pull_request) Successful in 25s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 30s
security-scan / Python SAST (bandit) (pull_request) Successful in 38s
security-scan / JS SCA (npm audit) (pull_request) Successful in 40s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 1m0s
test-build / build (frontend) (pull_request) Successful in 1m46s
test-build / build (backend) (pull_request) Successful in 1m54s
CI / frontend-test (pull_request) Successful in 1m55s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 2m0s
CI / backend-test (pull_request) Successful in 6m54s
CI / e2e (pull_request) Successful in 9m31s
to 1c63b3450c
All checks were successful
CI / release-scripts (pull_request) Successful in 16s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 20s
security-scan / JS SCA (npm audit) (pull_request) Successful in 30s
security-scan / Python SAST (bandit) (pull_request) Successful in 35s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 54s
CI / frontend-test (pull_request) Successful in 1m46s
test-build / build (frontend) (pull_request) Successful in 1m45s
test-build / build (backend) (pull_request) Successful in 1m50s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 2m18s
CI / e2e (pull_request) Successful in 9m1s
CI / backend-test (pull_request) Successful in 17m36s
2026-09-23 21:39:17 +00:00
Compare
robbertbos force-pushed ci-frozen-parse-clock from 1c63b3450c
All checks were successful
CI / release-scripts (pull_request) Successful in 16s
security-scan / SBOM (trivy) (pull_request) Successful in 15s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 20s
security-scan / JS SCA (npm audit) (pull_request) Successful in 30s
security-scan / Python SAST (bandit) (pull_request) Successful in 35s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 54s
CI / frontend-test (pull_request) Successful in 1m46s
test-build / build (frontend) (pull_request) Successful in 1m45s
test-build / build (backend) (pull_request) Successful in 1m50s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 2m18s
CI / e2e (pull_request) Successful in 9m1s
CI / backend-test (pull_request) Successful in 17m36s
to 2796f6fb86
Some checks failed
security-scan / SBOM (trivy) (pull_request) Successful in 13s
CI / release-scripts (pull_request) Successful in 13s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 19s
security-scan / JS SCA (npm audit) (pull_request) Successful in 19s
security-scan / Python SAST (bandit) (pull_request) Successful in 26s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 43s
test-build / build (frontend) (pull_request) Successful in 1m2s
test-build / build (backend) (pull_request) Successful in 1m8s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 1m58s
CI / frontend-test (pull_request) Successful in 4m6s
CI / backend-test (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
2026-09-23 22:03:11 +00:00
Compare
robbertbos force-pushed ci-frozen-parse-clock from 2796f6fb86
Some checks failed
security-scan / SBOM (trivy) (pull_request) Successful in 13s
CI / release-scripts (pull_request) Successful in 13s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 19s
security-scan / JS SCA (npm audit) (pull_request) Successful in 19s
security-scan / Python SAST (bandit) (pull_request) Successful in 26s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 43s
test-build / build (frontend) (pull_request) Successful in 1m2s
test-build / build (backend) (pull_request) Successful in 1m8s
test-build / build (pull_request) Successful in 0s
CI / pre-commit (pull_request) Successful in 1m58s
CI / frontend-test (pull_request) Successful in 4m6s
CI / backend-test (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
to 46921bf169
All checks were successful
CI / pre-commit (pull_request) Successful in 26m16s
CI / frontend-test (pull_request) Successful in 5m30s
CI / release-scripts (pull_request) Successful in 15s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 53s
security-scan / Python SAST (bandit) (pull_request) Successful in 33s
security-scan / JS SCA (npm audit) (pull_request) Successful in 31s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 24s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
test-build / build (backend) (pull_request) Successful in 2m7s
test-build / build (frontend) (pull_request) Successful in 2m5s
test-build / build (pull_request) Successful in 0s
CI / backend-test (pull_request) Successful in 22m54s
CI / e2e (pull_request) Successful in 13m41s
CI / pre-commit (push) Successful in 2m1s
CI / release-scripts (push) Successful in 15s
publish-and-stage / decide (push) Successful in 9s
security-scan / Python SCA (pip-audit) (push) Successful in 51s
security-scan / Python SAST (bandit) (push) Successful in 31s
CI / frontend-test (push) Successful in 4m21s
security-scan / JS SCA (npm audit) (push) Successful in 30s
security-scan / SBOM (trivy) (push) Successful in 16s
tag-release / release (push) Successful in 9s
security-scan / Filesystem scan (trivy fs) (push) Successful in 26s
publish-and-stage / build (backend) (push) Has been skipped
publish-and-stage / build (frontend) (push) Has been skipped
publish-and-stage / build (push) Successful in 0s
publish-and-stage / deploy-staging (push) Has been skipped
CI / e2e (push) Successful in 13m48s
CI / backend-test (push) Successful in 14m50s
2026-09-23 22:18:07 +00:00
Compare
robbertbos deleted branch ci-frozen-parse-clock 2026-09-23 23:21:43 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
robbertbos/waggle!425
No description provided.