storebound/tests/browser/console-persist.browser.ts

60 lines
3.6 KiB
TypeScript

// storebound console fill, mode (c): a session cookie (no Expires / Max-Age) survives closing and relaunching
// storebound's own persistent profile (--restore-last-session plus a graceful close). Launched with the browser kind the
// product uses for that profile (cli/shots/browser.ts, kind "visible"): real Google Chrome, else Playwright's full
// Chromium, headless here so no window appears. Never the headless shell: it does not restore the last session, so the
// cookie is always lost there. Skips (with the reason) only when neither is installed. Slow (two real Chrome launches
// and graceful closes per store), so tools/ci-plan.ts lists it as HEAVY (the dedicated browser shard).
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { type ConsoleBrowser, openConsoleBrowser } from '../../cli/console/session';
import { installedBrowsers } from '../../cli/shots/browser';
import { capped, CLOSE_TIMEOUT_MS, LAUNCH_TIMEOUT_MS, persistentBrowser } from '../helpers/browser';
const real = await persistentBrowser();
if (!real.label) console.warn(`console-persist tests skipped: ${real.skipWhy}`);
const TEST_MS = 2 * LAUNCH_TIMEOUT_MS + 30_000; // two launches (each capped) plus the test itself
let server: ReturnType<typeof Bun.serve> | null = null;
let base = '';
beforeAll(() => {
server = Bun.serve({ hostname: '127.0.0.1', port: 0, fetch: req => {
const path = new URL(req.url).pathname;
if (path === '/session-set') return new Response('<p>set</p>', { headers: { 'content-type': 'text/html', 'set-cookie': 'sbsession=example; Path=/; HttpOnly' } });
if (path === '/session-echo') return new Response(`<p id="c">${/(?:^|; )sbsession=example(?:;|$)/.test(req.headers.get('cookie') ?? '') ? 'kept' : 'lost'}</p>`, { headers: { 'content-type': 'text/html' } });
return new Response('not found', { status: 404 });
} });
base = `http://127.0.0.1:${server.port}/`;
});
afterAll(() => { server?.stop(true); });
describe.skipIf(!real.label)(`storebound's own profile (${real.label ?? 'no real Chrome'})`, () => {
for (const store of ['apple', 'play'] as const) {
test.concurrent(`${store}: a session cookie survives closing and relaunching storebound's own profile`, async () => {
const dir = mkdtempSync(join(tmpdir(), `storebound-profile-${store}-`));
const root = join(import.meta.dir, '..', '..');
const { chromium } = await import('playwright');
// the resolver's own choice, without a STOREBOUND_CHROME from the environment
const installed = installedBrowsers(chromium, { ...process.env, STOREBOUND_CHROME: undefined });
const opts = { store, profileDir: dir, fresh: true, headless: true, say: () => {}, launchTimeoutMs: LAUNCH_TIMEOUT_MS, launchDeps: { installed } };
let b: ConsoleBrowser | null = null;
try {
b = await openConsoleBrowser(root, opts);
await b.page.goto(base + 'session-set');
await b.close(); // graceful: Chrome writes its cookie store
await b.closed;
b = await openConsoleBrowser(root, opts);
expect(b.pages()).toHaveLength(1); // the restored tab was closed again
await b.page.goto(base + 'session-echo');
expect(await b.page.textContent('#c')).toBe('kept');
await b.close();
await b.closed;
} finally {
// a failed assertion must not leave this Chrome running into the next test
if (b && !b.isClosed()) await capped(b.context.close(), CLOSE_TIMEOUT_MS);
rmSync(dir, { recursive: true, force: true });
}
}, TEST_MS);
}
});