Skip to content

Commit add65ba

Browse files
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>
1 parent 9e9f744 commit add65ba

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

ui/src/pages/StatusCards/format.test.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,19 @@ function update(overrides: Partial<StatusCardUpdate>): StatusCardUpdate {
3030
};
3131
}
3232

33+
// A fixed instant rather than the real clock. `rollupUpdatesToday` filters on
34+
// the *UTC* day boundary, so a suite that builds its fixtures from `new Date()`
35+
// fails in two ways: it straddles midnight UTC if the run happens to cross it,
36+
// and in any zone east of UTC+12 "today at local noon" is already yesterday in
37+
// UTC, so the rows it means to count are filtered out. The function takes `now`
38+
// for exactly this reason — the sibling test below already passes one.
39+
const NOW = new Date("2026-07-23T12:00:00.000Z");
40+
3341
function iso(daysAgo: number): string {
34-
const d = new Date();
35-
d.setDate(d.getDate() - daysAgo);
36-
// Noon avoids DST/midnight edge cases in the local-day filter.
37-
d.setHours(12, 0, 0, 0);
42+
const d = new Date(NOW);
43+
d.setUTCDate(d.getUTCDate() - daysAgo);
44+
// Noon UTC, so a row is unambiguously inside the UTC day it belongs to.
45+
d.setUTCHours(12, 0, 0, 0);
3846
return d.toISOString();
3947
}
4048

@@ -61,7 +69,7 @@ describe("rollupUpdatesToday", () => {
6169
// yesterday + last week — must not be counted as "today"
6270
update({ kind: "full", inputTokens: 9999, outputTokens: 9999, costCents: 99, startedAt: iso(1) }),
6371
update({ kind: "incremental", inputTokens: 9999, outputTokens: 9999, costCents: 99, startedAt: iso(7) }),
64-
]);
72+
], NOW);
6573
// Only today's full rebuild counts as an update (compile excluded).
6674
expect(rollup.updateCount).toBe(1);
6775
// Today's tokens/cost include today's compile but not older days.

ui/vitest.config.ts

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

0 commit comments

Comments
 (0)