live-browser-session.test.mjs

 1import { describe, it } from 'node:test';
 2import assert from 'node:assert/strict';
 3import { readFileSync } from 'node:fs';
 4import { join } from 'node:path';
 5import vm from 'node:vm';
 6
 7const REPO_ROOT = process.cwd();
 8const SCRIPT = join(REPO_ROOT, 'skill/scripts/live-browser-session.js');
 9
10function createMemoryStorage() {
11  const values = new Map();
12  return {
13    getItem(key) { return values.has(key) ? values.get(key) : null; },
14    setItem(key, value) { values.set(key, String(value)); },
15    removeItem(key) { values.delete(key); },
16  };
17}
18
19function loadFactory() {
20  const context = { window: {}, globalThis: {}, console };
21  context.window = context;
22  context.globalThis = context;
23  vm.createContext(context);
24  vm.runInContext(readFileSync(SCRIPT, 'utf-8'), context, { filename: SCRIPT });
25  return context.__IMPECCABLE_LIVE_SESSION__.createLiveBrowserSessionState;
26}
27
28describe('live-browser-session state helper', () => {
29  it('persists session, handled state, and scroll independently', () => {
30    const createState = loadFactory();
31    const storage = createMemoryStorage();
32    const state = createState({ prefix: 'impeccable-live', storage, idFactory: () => 'owner-a' });
33
34    state.writeScrollY(420);
35    state.saveSession({ id: 'session-a', state: 'CYCLING', visible: 2 });
36    state.markHandled('session-a');
37
38    assert.equal(state.readScrollY(), 420);
39    assert.equal(state.loadSession().visible, 2);
40    assert.equal(state.isHandled('session-a'), true);
41
42    state.clearSession();
43    assert.equal(state.loadSession(), null);
44    assert.equal(state.readScrollY(), 420, 'scroll key is deliberately independent from session key');
45  });
46
47  it('carries checkpoint revision across reload-equivalent helper instances', () => {
48    const createState = loadFactory();
49    const storage = createMemoryStorage();
50    const first = createState({ prefix: 'impeccable-live', storage, idFactory: () => 'owner-a' });
51    first.saveSession({ id: 'session-b', state: 'CYCLING', visible: 1 });
52    assert.equal(first.nextCheckpointRevision(), 1);
53    assert.equal(first.nextCheckpointRevision(), 2);
54
55    const second = createState({ prefix: 'impeccable-live', storage, idFactory: () => 'owner-b' });
56    const restored = second.loadSession();
57    assert.equal(restored.checkpointRevision, 2);
58    assert.equal(
59      second.nextCheckpointRevision(),
60      3,
61      'event=live_browser_session.revision_resume actor=browser operation=reload_checkpoint risk=durable_store_ignores_stale_checkpoint expected=3 actual=' + second.currentCheckpointRevision(),
62    );
63  });
64});