From 19e1be400654bda949d7973bcf9ee259e6027cab Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Mon, 5 Oct 2026 09:21:47 +0800 Subject: [PATCH 1/2] test(schedule): pin task-page relative time assertions --- .../ui-schedule/tests/task-manager-page.client.spec.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx b/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx index 48a6afe19e..c559307d37 100644 --- a/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx +++ b/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx @@ -116,9 +116,9 @@ function sessionsWithTitles(titles: Partial>): Session afterEach(() => { try { cleanup() - vi.restoreAllMocks() localStorage.clear() } finally { + vi.restoreAllMocks() installedStyles?.remove() installedStyles = undefined } @@ -139,10 +139,13 @@ function pinSystemZone(timeZone: string): void { // the open clock panel calls to bring the staged value into view. /** Device zone the cases pin: a rule without a stored zone seeds its clock in it. */ const DEVICE_ZONE = 'Asia/Shanghai' +/** Reference instant for static schedule assertions; timers retain their real scheduling. */ +const FIXTURE_NOW = Date.parse('2026-09-18T12:00:00.000Z') /** Elements whose `scrollIntoView` the open pickers called, in call order. */ const scrolledIntoView: Element[] = [] const scrollIntoView = vi.fn(function (this: Element) { scrolledIntoView.push(this) }) beforeEach(() => { + vi.spyOn(Date, 'now').mockReturnValue(FIXTURE_NOW) pinSystemZone(DEVICE_ZONE) Element.prototype.scrollIntoView = scrollIntoView scrollIntoView.mockClear() @@ -278,9 +281,7 @@ function relativeText(root: HTMLElement): string | null { /** * The relative next-run text both the row and the detail render for one instant. * - * The components sample their reference clock once per mount, so the assertion - * reads the same clock at assert time; every fixture instant is days away, where - * one unit of drift cannot change the rendered value. + * Expected durations use the same pinned clock as component renders. * @param scheduledAt - stored target instant. * @param dictionary - active locale dictionary. * @returns the localized time remaining, or overdue text. From 8a532bc5a56d6ca9591ba343f59584f5c3a4b00e Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Mon, 5 Oct 2026 09:51:35 +0800 Subject: [PATCH 2/2] test(schedule): remove stale wall-clock drift comment --- .../ui-schedule/tests/task-manager-page.client.spec.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx b/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx index c559307d37..52158d0ed2 100644 --- a/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx +++ b/packages/client/ui-schedule/tests/task-manager-page.client.spec.tsx @@ -760,9 +760,7 @@ describe('Task manager catalog', () => { it('states the time remaining until the next run in each locale', () => { // The row and the detail state a duration, not a date: zh reads `2小时后` - // and en reads `in 2 hours`, and neither renders a clock time for it. The - // fixture is two hours out, where a few milliseconds of clock drift cannot - // change the rendered unit. + // and en reads `in 2 hours`, and neither renders a clock time for it. const soon: ScheduleCatalogEntry = { ...at, title: 'Two hours out', prompt: 'Two hours out', scheduledAt: new Date(Date.now() + 2 * 3_600_000).toISOString(),