Test the clock where CI could not see it: the date field's time zone, a backwards date, a reopened panel

Three behaviours of the clock had no test that would fail without them:

- "jumps the clock to the date submitted, read as UTC" only told UTC from local time on a machine
  outside UTC. CI runs on ubuntu-latest, in UTC, where both readings are the same instant, so a
  field read as local time passed all 805 tests there. The test now sets TZ to Asia/Kolkata (UTC
  +5:30) itself, and afterEach unstubs it.
- Nothing checked that a negative rate moves the date backwards; the dock's test read only the
  rate's sign. The store now checks that at -86 400 s/s a second of wall clock is a day earlier.
- Nothing checked that reopening the Display panel fills the date field with the clock's date,
  rather than the one it held when the dock was built.

Controls, the suite run under TZ=UTC: the field read as local time fails "jumps the clock to the date
submitted, read as UTC"; the rate's size taken without its sign fails "runs the date backwards at a
negative rate"; toggleTab not refilling the field fails "fills the date field again with the clock's
date when the panel is opened again".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-29 19:30:38 +02:00
co-authored by Claude Opus 5.5
parent 34084c0eec
commit 56af5e3553
2 changed files with 24 additions and 1 deletions
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { DataLoaderService } from '../../core/data/data-loader.service'; import { DataLoaderService } from '../../core/data/data-loader.service';
import { BookmarksStore } from '../../shared/state/bookmarks.store'; import { BookmarksStore } from '../../shared/state/bookmarks.store';
@@ -378,6 +378,8 @@ describe('HudDockComponent', () => {
fixture.detectChanges(); fixture.detectChanges();
}); });
afterEach(() => vi.unstubAllEnvs());
function button(name: string): HTMLButtonElement { function button(name: string): HTMLButtonElement {
return [...host().querySelectorAll<HTMLButtonElement>('#dock-panel-display button')].find((b) => b.textContent?.trim() === name)!; return [...host().querySelectorAll<HTMLButtonElement>('#dock-panel-display button')].find((b) => b.textContent?.trim() === name)!;
} }
@@ -417,6 +419,9 @@ describe('HudDockComponent', () => {
}); });
it('jumps the clock to the date submitted, read as UTC', () => { it('jumps the clock to the date submitted, read as UTC', () => {
// Five and a half hours from UTC, so a field read as local time lands elsewhere: in UTC itself,
// where CI runs, the two readings are the same instant and this could not tell them apart.
vi.stubEnv('TZ', 'Asia/Kolkata');
const field = host().querySelector<HTMLInputElement>('#clock-date')!; const field = host().querySelector<HTMLInputElement>('#clock-date')!;
field.value = '2020-12-21T18:00'; field.value = '2020-12-21T18:00';
button('Go').click(); button('Go').click();
@@ -431,5 +436,15 @@ describe('HudDockComponent', () => {
expect(time.atNow()).toBe(true); expect(time.atNow()).toBe(true);
expect(host().querySelector<HTMLInputElement>('#clock-date')!.value).toBe(time.date().toISOString().slice(0, 16)); expect(host().querySelector<HTMLInputElement>('#clock-date')!.value).toBe(time.date().toISOString().slice(0, 16));
}); });
it('fills the date field again with the clock’s date when the panel is opened again', () => {
time.setDate(new Date('2020-12-21T18:00Z'));
fixture.componentInstance.toggleTab('display');
fixture.detectChanges();
fixture.componentInstance.toggleTab('display');
fixture.detectChanges();
expect(host().querySelector<HTMLInputElement>('#clock-date')!.value).toBe('2020-12-21T18:00');
});
}); });
}); });
+8
View File
@@ -48,6 +48,14 @@ describe('TimeStore', () => {
expect(time.julianDate() - afterTwoDays).toBeLessThan(1 / 24); expect(time.julianDate() - afterTwoDays).toBeLessThan(1 / 24);
}); });
it('runs the date backwards at a negative rate', () => {
time.setRate(-86_400);
const before = time.julianDate();
vi.advanceTimersByTime(1000);
expect(time.julianDate() - before).toBeCloseTo(-1, 9);
});
it('knows the map is away from now even once it is back at real time', () => { it('knows the map is away from now even once it is back at real time', () => {
expect(time.atNow()).toBe(true); expect(time.atNow()).toBe(true);
time.setRate(2_629_800); time.setRate(2_629_800);