import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' import { _electron as electron, expect, test } from '@playwright/test' const here = dirname(fileURLToPath(import.meta.url)) const MAIN = join(here, '..', 'out', 'main', 'index.js') // Opt-in (GITEA_LIVE=1). A real launch persists the snapshot; a second launch with // gitea unreachable must still show the board + real scheduler output from the // persisted cache (offline reads). No model needed. test.describe('live persistence', () => { test('offline: serves the persisted snapshot', async () => { test.skip(!process.env.GITEA_LIVE, 'GITEA_LIVE not set — opt-in live test') test.setTimeout(120_000) // launch 1 — real reconcile writes the snapshot to disk const app1 = await electron.launch({ args: [MAIN], env: { ...process.env } }) const w1 = await app1.firstWindow() await w1.waitForLoadState('domcontentloaded') // a scheduler-only phrase confirms real data reconciled (never emitted by fixtures) await expect(w1.getByText(/on the critical path|unblocks #|waits on #|· ready/).first()).toBeVisible({ timeout: 30000 }) await app1.close() // launch 2 — gitea unreachable; the reconcile must fall back to the persisted snapshot const app2 = await electron.launch({ args: [MAIN], env: { ...process.env, GITEA_BASE_URL: 'http://127.0.0.1:9' }, }) const w2 = await app2.firstWindow() await w2.waitForLoadState('domcontentloaded') // Focus still renders real scheduler output — proving it came from the cache, offline await expect(w2.getByText(/on the critical path|unblocks #|waits on #|· ready/).first()).toBeVisible({ timeout: 20000 }) await w2.screenshot({ path: join(here, '.artifacts', 'screens', 'live-offline.png'), fullPage: true, animations: 'disabled' }) await app2.close() }) })