Harden the offline e2e for slower CI timing (#38)
Some checks failed
CD / Build and push images (push) Successful in 54s
CI / Lint, typecheck, test (push) Successful in 1m59s
CI / Auth e2e pack (push) Failing after 2m12s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m11s
CD / Promote to Int (push) Successful in 11s

The offline pack passed locally but flaked in CI. Make its timing-sensitive
steps robust without changing the feature:

- Before going offline, wait until the service worker not only controls the
  page but has actually populated Cache Storage (app-shell precache complete),
  so the offline reload is guaranteed to be servable from cache.
- After coming back online, wait for the reloaded tab to reconnect (so it has
  pushed its local state) before checking a second client converges.
- Raise the service-worker-ready and convergence timeouts, and the IndexedDB
  flush wait, for headroom on slower runners.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PGdhRiwU1WRL4XxJfZYipY
This commit is contained in:
Claude Opus 4.8 2026-07-08 22:24:29 +02:00
parent af81b50fa6
commit 41b259fae5

View File

@ -25,11 +25,23 @@ test('offline: edit, reload while offline, then reconnect converges (#38)', asyn
await expect(page.locator('.editor-connection')).toHaveAttribute('data-status', 'connected', {
timeout: 15000,
});
// The service worker must control the page before an offline reload can be
// served from the cached app shell.
await page.waitForFunction(() => navigator.serviceWorker?.controller != null, null, {
timeout: 20000,
});
// The service worker must control the page AND have finished precaching the
// app shell before an offline reload can be served from cache. Checking the
// Cache Storage is populated avoids a race where the SW controls the page but
// its install (precache) has not completed yet.
await page.waitForFunction(
async () => {
if (!navigator.serviceWorker?.controller) return false;
const names = await caches.keys();
for (const name of names) {
const cache = await caches.open(name);
if ((await cache.keys()).length > 0) return true;
}
return false;
},
null,
{ timeout: 30000 },
);
const editor = page.locator('.ProseMirror');
await editor.click();
@ -58,7 +70,7 @@ test('offline: edit, reload while offline, then reconnect converges (#38)', asyn
expect(apiResult).toBe('network-error');
// Give y-indexeddb a moment to flush the offline edit before the reload.
await page.waitForTimeout(1000);
await page.waitForTimeout(1500);
// Reload the tab while offline: the app shell loads from the service worker,
// the page resolves from the offline metadata cache, and its content comes
@ -68,13 +80,18 @@ test('offline: edit, reload while offline, then reconnect converges (#38)', asyn
await expect(reloaded).toContainText('offline extra', { timeout: 20000 });
await expect(reloaded).toContainText('online base');
// Back online: a second participant converges on the merged content.
// Back online: the reloaded tab reconnects and pushes its local state to the
// server; wait for that before checking a second participant converges.
await owner.setOffline(false);
await expect(page.locator('.editor-connection')).toHaveAttribute('data-status', 'connected', {
timeout: 30000,
});
const admin = await contextForUser(browser, BASE_URL, 'fixture-admin');
const adminPage = await admin.newPage();
await adminPage.goto(`/p/${pond.slug}/${slug}`);
await expect(adminPage.locator('.ProseMirror')).toContainText('offline extra', {
timeout: 25000,
timeout: 30000,
});
await owner.close();