ci: allow staging deploy from fix/analytics-tz-bucket-offset; move analytics tz test to vite/tests
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -26,7 +26,7 @@ env:
|
|||||||
# staging repo (autumn-staging) -> us-east-1
|
# staging repo (autumn-staging) -> us-east-1
|
||||||
# Branches allowed to deploy to staging via workflow_dispatch with tag=deploy-staging.
|
# Branches allowed to deploy to staging via workflow_dispatch with tag=deploy-staging.
|
||||||
# Add short-lived PR branches here when you need staging without merging to dev.
|
# Add short-lived PR branches here when you need staging without merging to dev.
|
||||||
STAGING_DEPLOY_BRANCH_ALLOWLIST: fix-health-check-redis-disabled-detection feat/track-rate-limit-redis feat/events-hourly-rollup
|
STAGING_DEPLOY_BRANCH_ALLOWLIST: fix-health-check-redis-disabled-detection feat/track-rate-limit-redis feat/events-hourly-rollup fix/analytics-tz-bucket-offset
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
checks:
|
checks:
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"includeEntryExports": false
|
"includeEntryExports": false
|
||||||
},
|
},
|
||||||
"vite": {
|
"vite": {
|
||||||
"entry": ["tests/**/*.{ts,tsx}", "src/**/*.test.{ts,tsx}"],
|
"entry": ["tests/**/*.{ts,tsx}"],
|
||||||
"project": ["src/**/*.{ts,tsx}", "tests/**/*.{ts,tsx}"],
|
"project": ["src/**/*.{ts,tsx}", "tests/**/*.{ts,tsx}"],
|
||||||
"ignore": ["src/components/ai-elements/**", "src/hooks/useControllableState.ts", "src/types/**/*.d.ts"],
|
"ignore": ["src/components/ai-elements/**", "src/hooks/useControllableState.ts", "src/types/**/*.d.ts"],
|
||||||
"ignoreDependencies": [
|
"ignoreDependencies": [
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
// Day buckets are in the viewer's local zone, so a non-UTC viewer's latest day
|
|
||||||
// must label as the local day, not a day behind. Run with a non-UTC zone:
|
|
||||||
// cd vite && TZ=America/New_York bun test <this file>
|
|
||||||
// Ref: tickets/ANALYTICS_TIMEZONE_BUCKET_OFFSET.md
|
|
||||||
|
|
||||||
import { expect, test } from "bun:test";
|
|
||||||
import { formatPeriodLabel } from "./parseTimestamp";
|
|
||||||
|
|
||||||
const guardTimezone = () => {
|
|
||||||
if (process.env.TZ !== "America/New_York") {
|
|
||||||
throw new Error(
|
|
||||||
`This test must run with TZ=America/New_York (got ${process.env.TZ ?? "unset"}).`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
test("day bucket labels as the viewer's local calendar day (not a day behind)", () => {
|
|
||||||
guardTimezone();
|
|
||||||
// Pipe-emitted local-midnight bucket for the viewer's Jun 4.
|
|
||||||
const label = formatPeriodLabel({
|
|
||||||
period: "2026-06-04 00:00:00",
|
|
||||||
interval: "30d",
|
|
||||||
});
|
|
||||||
expect(label).toBe("4 Jun");
|
|
||||||
});
|
|
||||||
|
|
||||||
test("hour bucket (24h view) stays on UTC and renders in local time", () => {
|
|
||||||
guardTimezone();
|
|
||||||
// Hour buckets are emitted by the pipe in UTC. 13:00 UTC -> 09:00 in
|
|
||||||
// America/New_York (EDT). This must not regress when day buckets go local.
|
|
||||||
const label = formatPeriodLabel({
|
|
||||||
period: "2026-06-04 13:00:00",
|
|
||||||
interval: "24h",
|
|
||||||
});
|
|
||||||
expect(label).toBe("09:00");
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Day buckets are emitted by the pipe in the viewer's local zone, so the chart
|
||||||
|
// label must read the bare string as local, not UTC (else it lands a day behind
|
||||||
|
// for non-UTC viewers). These assertions are timezone-independent so they pass
|
||||||
|
// under any CI runner zone.
|
||||||
|
// Ref: tickets/ANALYTICS_TIMEZONE_BUCKET_OFFSET.md
|
||||||
|
|
||||||
|
import { expect, test } from "bun:test";
|
||||||
|
import {
|
||||||
|
formatPeriodLabel,
|
||||||
|
parseLocalTimestamp,
|
||||||
|
parseUTCTimestamp,
|
||||||
|
} from "@/views/customers/customer/analytics/utils/parseTimestamp";
|
||||||
|
|
||||||
|
test("day bucket label round-trips the local calendar day in any timezone", () => {
|
||||||
|
// parseLocalTimestamp parses local and formatDateShort renders local, so the
|
||||||
|
// wall-clock day round-trips regardless of the runner's zone. Before the fix
|
||||||
|
// (parse-as-UTC) this was a day behind for west-of-UTC viewers.
|
||||||
|
const label = formatPeriodLabel({
|
||||||
|
period: "2026-06-04 00:00:00",
|
||||||
|
interval: "30d",
|
||||||
|
});
|
||||||
|
expect(label).toBe("4 Jun");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("parseLocalTimestamp keeps the bare string's wall-clock as local", () => {
|
||||||
|
const date = parseLocalTimestamp("2026-06-04 13:00:00");
|
||||||
|
expect(date.getFullYear()).toBe(2026);
|
||||||
|
expect(date.getMonth()).toBe(5); // June (0-indexed)
|
||||||
|
expect(date.getDate()).toBe(4);
|
||||||
|
expect(date.getHours()).toBe(13);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("parseUTCTimestamp still treats bare strings as UTC (hour view / raw events)", () => {
|
||||||
|
// Hour buckets and the raw-events table are genuine UTC and must not change.
|
||||||
|
const date = parseUTCTimestamp("2026-06-04 13:00:00");
|
||||||
|
expect(date.getUTCFullYear()).toBe(2026);
|
||||||
|
expect(date.getUTCMonth()).toBe(5);
|
||||||
|
expect(date.getUTCDate()).toBe(4);
|
||||||
|
expect(date.getUTCHours()).toBe(13);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user