From ddeb87cdba00832a049a2b92cf74ec126932a0ce Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Sun, 14 Jun 2026 23:07:36 -0400 Subject: [PATCH] test(18): make timezone e2e deterministic and align with WR-01 fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The timezone-verify spec assumed a first-run (unset) starting state, but e2e global-setup truncated only the list/event tables — never app_config — so a prior run's saved household_timezone leaked across runs. Clear that key in global-setup so the spec always starts from isExplicitlySet:false. Also repurpose the stale "Save disabled when unchanged" assertion: after the WR-01 fix, first-run Save is correctly ENABLED when the input matches the displayed default (saving confirms the detected zone). The disabled-when- unchanged-and-explicit case remains covered by the persist-across-reload test. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/pwa/e2e/global-setup.ts | 7 +++++++ apps/pwa/e2e/timezone-verify.spec.ts | 12 ++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/apps/pwa/e2e/global-setup.ts b/apps/pwa/e2e/global-setup.ts index e1cc78d..1d64a08 100644 --- a/apps/pwa/e2e/global-setup.ts +++ b/apps/pwa/e2e/global-setup.ts @@ -109,6 +109,13 @@ export default async function globalSetup(): Promise { await conn.execute('TRUNCATE TABLE calendar_events'); await conn.execute('SET FOREIGN_KEY_CHECKS=1'); + // Phase 18: clear any stored household timezone so the timezone spec always + // starts from the first-run (isExplicitlySet:false) state. app_config is NOT + // truncated above (it can hold other non-test config), so delete only this key. + // Without this, a prior run's saved value leaks across runs and makes the + // first-run / persist-across-reload timezone assertions non-deterministic. + await conn.execute("DELETE FROM app_config WHERE `key` = 'household_timezone'"); + // Seed the dev-bypass admin user row for id=1 (D-01 dev note, Phase 10). // DEV_USER (id=1) is injected by devBypass.ts WITHOUT a DB upsert, so the users table // has no row for id=1 by default. requireAdmin (Plan 02) does a DB lookup and would 403 diff --git a/apps/pwa/e2e/timezone-verify.spec.ts b/apps/pwa/e2e/timezone-verify.spec.ts index 1b4ac21..cbbfbe5 100644 --- a/apps/pwa/e2e/timezone-verify.spec.ts +++ b/apps/pwa/e2e/timezone-verify.spec.ts @@ -30,11 +30,19 @@ test.describe('Admin Timezone section — 18-04 round-trip', () => { expect(val.length, 'Input should have a non-empty timezone').toBeGreaterThan(0); }); - test('Save button is disabled when timezone is unchanged', async ({ page }) => { + test('Save is enabled on first run when timezone is not yet explicit (WR-01)', async ({ page }) => { + // On first run the GET returns isExplicitlySet:false with the detected zone + // pre-filled. Saving that value to make the choice explicit is a meaningful + // action, so Save must be ENABLED even though the input matches the displayed + // default. (The disabled-when-unchanged behaviour for an already-explicit + // value is covered by the "Save persists" test below, which re-disables Save + // after a successful save.) const tzSection = page.getByRole('region', { name: 'Timezone' }); + // Confirm we are in the first-run (system-default) state for this assertion. + await expect(tzSection.getByText('Using system default')).toBeVisible(); const saveBtn = tzSection.getByRole('button', { name: /Save|Saving/ }); await expect(saveBtn).toBeVisible(); - await expect(saveBtn).toBeDisabled(); + await expect(saveBtn).toBeEnabled(); }); test('Changing the input enables Save', async ({ page }) => {