From ae1586cde7a386ddee501e643ef67e10bf8d02f7 Mon Sep 17 00:00:00 2001 From: Florian Kostenzer Date: Mon, 13 Jul 2026 23:31:44 +0200 Subject: [PATCH] test: pin test timezone to UTC, document test commands --- CLAUDE.md | 6 ++++++ package.json | 6 +++--- src/lib/components/StatusBarCalendar.svelte.test.ts | 4 ++-- src/lib/server/tool.test.ts | 6 +++--- vite.config.ts | 5 +++-- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a5edd369..7486ca37 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,8 +16,14 @@ npm run check # Svelte + TypeScript type checking npm run prettify # Format all files with Prettier npm run migrate # Run database migrations via Knex npm run seed # Run database seeds (migrations run automatically first) +npm test # Run all tests (server unit + browser component projects) +npm run test:server # Server-side unit tests only (Node) +npm run test:client # Component tests only (headless Chromium via Playwright) +npm run test:watch # Watch mode ``` +Component tests need a one-time `npx playwright install chromium`. + ## Architecture ### Dual Process Model diff --git a/package.json b/package.json index ccc0e206..a4366688 100644 --- a/package.json +++ b/package.json @@ -49,10 +49,10 @@ "schedule": "vite-node src/lib/server/startup.ts", "seed": "npx knex seed:run", "start": "node build/main.js", - "test": "vitest run", + "test": "cross-env TZ=UTC vitest run", "test:client": "vitest run --project=client", - "test:server": "vitest run --project=server", - "test:watch": "vitest" + "test:server": "cross-env TZ=UTC vitest run --project=server", + "test:watch": "cross-env TZ=UTC vitest" }, "devDependencies": { "@internationalized/date": "^3.10.0", diff --git a/src/lib/components/StatusBarCalendar.svelte.test.ts b/src/lib/components/StatusBarCalendar.svelte.test.ts index 5540f66b..47fc548f 100644 --- a/src/lib/components/StatusBarCalendar.svelte.test.ts +++ b/src/lib/components/StatusBarCalendar.svelte.test.ts @@ -3,8 +3,8 @@ import { render } from "vitest-browser-svelte"; import StatusBarCalendar from "./StatusBarCalendar.svelte"; import type { TimestampStatusCount } from "$lib/server/types/db"; -// Noon UTC keeps the rendered calendar date stable for any machine timezone -// with an offset within ±11 hours (the timezone store defaults to browser TZ). +// The browser context is pinned to UTC (see vite.config.ts), so the timezone store +// (which defaults to browser TZ) is deterministic; noon UTC keeps fixtures safe too. const NOON_UTC = 1768478400; // 2026-01-15T12:00:00Z const day = (overrides: Partial): TimestampStatusCount => ({ diff --git a/src/lib/server/tool.test.ts b/src/lib/server/tool.test.ts index c574949b..6540ea45 100644 --- a/src/lib/server/tool.test.ts +++ b/src/lib/server/tool.test.ts @@ -32,9 +32,9 @@ import { } from "./tool"; import type { TimestampStatusCount } from "./types/db"; -// All fixed timestamps are at 12:00 UTC so that local-date-based functions -// (GetDayStartTimestampUTC mixes local date parts with Date.UTC) produce the -// same result on any machine with a UTC offset between -11 and +11 hours. +// The npm scripts pin TZ=UTC, so local-date-based functions (GetDayStartTimestampUTC +// mixes local date parts with Date.UTC) are deterministic here. Fixtures still use +// noon UTC so the tests stay safe even if vitest is run directly without the pin. const NOON_UTC = 1768478400; // 2026-01-15T12:00:00Z const DAY_START = 1768435200; // 2026-01-15T00:00:00Z diff --git a/vite.config.ts b/vite.config.ts index 17e7b377..9bdb25e0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,6 +5,7 @@ import version from "vite-plugin-package-version"; import { defineConfig } from "vite"; import devtoolsJson from "vite-plugin-devtools-json"; import { playwright } from "@vitest/browser-playwright"; +import { configDefaults } from "vitest/config"; import * as dotenv from "dotenv"; @@ -66,7 +67,7 @@ export default defineConfig(({ mode }) => { name: "server", environment: "node", include: ["src/**/*.{test,spec}.{js,ts}"], - exclude: ["src/**/*.svelte.{test,spec}.{js,ts}"], + exclude: [...configDefaults.exclude, "src/**/*.svelte.{test,spec}.{js,ts}"], }, }, { @@ -76,7 +77,7 @@ export default defineConfig(({ mode }) => { browser: { enabled: true, headless: true, - provider: playwright(), + provider: playwright({ contextOptions: { timezoneId: "UTC" } }), instances: [{ browser: "chromium" }], // Vitest's default browser API port (63315) can fall inside Windows // Hyper-V excluded TCP port ranges; pin below the ephemeral range.