import type { AddressInfo } from 'node:net'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { createNativeLoginGate } from '../src/native-login-gate.js'; const servers: Array> = []; afterEach(async () => { await Promise.all(servers.splice(0).map((server) => new Promise((resolve) => { server.close(() => resolve()); }))); }); describe('native Reddit login gate', () => { it('serves VNC guidance and completes only after the explicit handoff', async () => { const onComplete = vi.fn(); const server = createNativeLoginGate({ publicVncUrl: 'https://red-vnc.example/vnc.html', onComplete, }).listen(0); servers.push(server); await new Promise((resolve) => server.once('listening', resolve)); const { port } = server.address() as AddressInfo; const page = await fetch(`http://127.0.0.1:${port}/`); const html = await page.text(); expect(html).toContain('Chrome is running without automation'); expect(html).toContain('https://red-vnc.example/vnc.html'); expect(html).toContain("fetch('/complete', { method: 'POST' })"); expect(onComplete).not.toHaveBeenCalled(); const completed = await fetch(`http://127.0.0.1:${port}/complete`, { method: 'POST' }); expect(completed.status).toBe(202); expect(await completed.json()).toEqual({ ok: true, restarting: true }); expect(onComplete).toHaveBeenCalledOnce(); }); });