From a6630f112f5232d77225144469d0ff0602375e57 Mon Sep 17 00:00:00 2001 From: Craig Williams Date: Fri, 16 Oct 2026 16:46:08 +0100 Subject: [PATCH] Added tests for format and storage, run in UK time --- web/src/lib/format.test.ts | 28 ++++++++++++++++++++++++++++ web/src/lib/storage.test.ts | 36 ++++++++++++++++++++++++++++++++++++ web/vite.config.ts | 4 +++- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 web/src/lib/format.test.ts create mode 100644 web/src/lib/storage.test.ts diff --git a/web/src/lib/format.test.ts b/web/src/lib/format.test.ts new file mode 100644 index 0000000..24c96a4 --- /dev/null +++ b/web/src/lib/format.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from 'vitest'; + +import { formatDate, formatMoney, parseDate } from './format'; + +test.each([ + { name: 'null', value: null }, + { name: 'undefined', value: undefined }, + { name: 'empty', value: '' }, + { name: 'Go’s zero time', value: '0001-01-01T00:00:00Z' }, + { name: 'not a date', value: 'soon' }, +])('parseDate reads $name as no date', ({ value }) => { + expect(parseDate(value)).toBeNull(); + expect(formatDate(value)).toBe('—'); +}); + +test('dates are shown day, short month and year', () => { + // Tests run in UK time (vite.config.ts), as dates are shown in local time. + expect(parseDate('2026-03-03T12:00:00Z')?.toISOString()).toBe('2026-03-03T12:00:00.000Z'); + expect(formatDate('2026-03-03T12:00:00Z')).toBe('3 Mar 2026'); + // 23:30 UTC is already the next day in British Summer Time. + expect(formatDate('2026-07-01T23:30:00Z')).toBe('2 Jul 2026'); +}); + +test('money is shown in whole pounds, and nothing as a dash', () => { + expect(formatMoney(125000.5)).toBe('£125,001'); + expect(formatMoney(0)).toBe('—'); + expect(formatMoney(-5)).toBe('—'); +}); diff --git a/web/src/lib/storage.test.ts b/web/src/lib/storage.test.ts new file mode 100644 index 0000000..c1c2bc0 --- /dev/null +++ b/web/src/lib/storage.test.ts @@ -0,0 +1,36 @@ +import { afterEach, expect, test, vi } from 'vitest'; + +import { readStored, writeStored } from './storage'; + +afterEach(() => { + vi.unstubAllGlobals(); +}); + +test('reads and writes localStorage', () => { + const stored = new Map(); + vi.stubGlobal('window', { + localStorage: { + getItem: (key: string) => stored.get(key) ?? null, + setItem: (key: string, value: string) => stored.set(key, value), + }, + }); + + expect(readStored('job_search.theme')).toBeNull(); + writeStored('job_search.theme', 'dark'); + expect(readStored('job_search.theme')).toBe('dark'); +}); + +test('storage that throws reads as nothing stored and ignores writes', () => { + const refuse = (): never => { + throw new Error('storage is disabled'); + }; + vi.stubGlobal('window', { + localStorage: { + getItem: refuse, + setItem: refuse, + }, + }); + + expect(readStored('job_search.theme')).toBeNull(); + expect(() => writeStored('job_search.theme', 'dark')).not.toThrow(); +}); diff --git a/web/vite.config.ts b/web/vite.config.ts index 3ee4ce3..55981bf 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -26,9 +26,11 @@ export default defineConfig(({ mode }) => { }, // Vitest. vite-plugin-solid would run tests in jsdom, which isn't // installed: nothing tested yet renders, and Solid's reactivity works - // in Node as it is. + // in Node as it is. Dates are shown in local time, so tests run in UK + // time wherever they run. test: { environment: 'node', + env: { TZ: 'Europe/London' }, }, }; });