test(ui): make the suite pass outside UTC (#11480)

The ui suite was green in CI and red on a clean checkout in any other
timezone. GitHub's runners default to UTC, so nothing ever reported it. A
contributor elsewhere sees two failures on their first run, which reads as
"this project is broken" rather than "your clock differs from the runner's".

Two independent causes.

`IssueProperties` supplies a UTC instant and asserts on the local-time string
the UI renders from it - "2026-07-17T16:08:00.000Z" is expected to read
"Today, 4:08 PM". That holds only where local time is UTC. Pinned with
`env: { TZ: "UTC" }` rather than rewritten: those assertions are about what a
person sees, and "4:08 PM" is worth more to a reader than an expectation
computed from the same formatter the component uses, which would pass whatever
that formatter did.

`StatusCards/format` was wrong in two ways at once, and the pin hides only one,
so it is fixed directly. `rollupUpdatesToday` filters on the *UTC* day
boundary, while the test built fixtures from local noon on the real clock.
East of UTC+12, "today at local noon" is already yesterday in UTC and the rows
the test means to count are filtered out; and any run crossing midnight UTC
lands `iso(0)` and the function's default `now` on different days. The
fixtures now come from a fixed instant, passed as `now` - the parameter exists
for this, and the sibling test already used it.

Each fix was confirmed load-bearing by removing it under TZ=Pacific/Auckland.
Without the pin, IssueProperties fails; without the fixed instant, StatusCards
fails even with the pin removed, so neither rides on the other.

Full ui suite 4017 pass, 0 fail, in UTC, Pacific/Auckland and Asia/Kolkata.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tonio 2026-08-16 10:15:38 -07:00 committed by GitHub
parent 9e9f744f58
commit add65ba4a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 5 deletions

View File

@ -30,11 +30,19 @@ function update(overrides: Partial<StatusCardUpdate>): StatusCardUpdate {
};
}
// A fixed instant rather than the real clock. `rollupUpdatesToday` filters on
// the *UTC* day boundary, so a suite that builds its fixtures from `new Date()`
// fails in two ways: it straddles midnight UTC if the run happens to cross it,
// and in any zone east of UTC+12 "today at local noon" is already yesterday in
// UTC, so the rows it means to count are filtered out. The function takes `now`
// for exactly this reason — the sibling test below already passes one.
const NOW = new Date("2026-07-23T12:00:00.000Z");
function iso(daysAgo: number): string {
const d = new Date();
d.setDate(d.getDate() - daysAgo);
// Noon avoids DST/midnight edge cases in the local-day filter.
d.setHours(12, 0, 0, 0);
const d = new Date(NOW);
d.setUTCDate(d.getUTCDate() - daysAgo);
// Noon UTC, so a row is unambiguously inside the UTC day it belongs to.
d.setUTCHours(12, 0, 0, 0);
return d.toISOString();
}
@ -61,7 +69,7 @@ describe("rollupUpdatesToday", () => {
// yesterday + last week — must not be counted as "today"
update({ kind: "full", inputTokens: 9999, outputTokens: 9999, costCents: 99, startedAt: iso(1) }),
update({ kind: "incremental", inputTokens: 9999, outputTokens: 9999, costCents: 99, startedAt: iso(7) }),
]);
], NOW);
// Only today's full rebuild counts as an update (compile excluded).
expect(rollup.updateCount).toBe(1);
// Today's tokens/cost include today's compile but not older days.

View File

@ -11,5 +11,14 @@ export default defineConfig({
test: {
environment: "node",
setupFiles: ["./vitest.setup.ts"],
// Pin the clock's timezone so date rendering is the same everywhere.
//
// Several suites supply a UTC instant and assert on the local-time string
// the UI renders from it — "2026-07-17T16:08:00.000Z" is expected to read
// "Today, 4:08 PM". That only holds where local time is UTC. CI passes
// because GitHub's runners happen to default to UTC; a contributor in any
// other zone sees those tests fail on a clean checkout, which reads as
// "the suite is broken" rather than "your clock differs".
env: { TZ: "UTC" },
},
});