@molecule/app-e2e-preview 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,405 @@
1
+ /**
2
+ * The driver: connects to the hub from inside the sandbox (or any machine
3
+ * running the dev server), picks a connected preview page, and exposes it as
4
+ * an `E2ETransport` for the core's `createEvaluatePage()`.
5
+ *
6
+ * @module
7
+ */
8
+ import { randomUUID } from 'node:crypto';
9
+ import { existsSync, readFileSync } from 'node:fs';
10
+ import process from 'node:process';
11
+ import WebSocket from 'ws';
12
+ import { E2ETimeoutError, } from '@molecule/app-e2e';
13
+ import { createEvaluatePage } from '@molecule/app-e2e-fixtures-default';
14
+ import { E2E_WS_PATH, tokenFilePath, } from './types.js';
15
+ const BOND_NAME = 'the preview bond (@molecule/app-e2e-preview)';
16
+ const DEFAULT_CONNECT_TIMEOUT = 30_000;
17
+ const noPageMessage = (url) => `No preview page is connected to the dev server at ${url}. ${BOND_NAME} drives the page a browser is showing: ` +
18
+ `open this project's preview in the molecule.dev IDE (or the preview URL in any browser tab) and keep that tab open, then run again. ` +
19
+ `If the tab is asleep, wake it — the IDE keeps the screen awake while a build runs.`;
20
+ const candidatePorts = (options) => {
21
+ const raw = [
22
+ options.port,
23
+ Number(process.env['MOL_E2E_PREVIEW_PORT']),
24
+ 5173,
25
+ Number(process.env['VITE_PORT']),
26
+ 3000,
27
+ ];
28
+ const out = [];
29
+ for (const p of raw)
30
+ if (p && Number.isFinite(p) && !out.includes(p))
31
+ out.push(p);
32
+ return out;
33
+ };
34
+ const readToken = (port, options) => {
35
+ if (options.token)
36
+ return options.token;
37
+ const fromEnv = process.env['MOL_E2E_TOKEN'];
38
+ if (fromEnv)
39
+ return fromEnv;
40
+ try {
41
+ const file = tokenFilePath(port);
42
+ if (!existsSync(file))
43
+ return null;
44
+ const parsed = JSON.parse(readFileSync(file, 'utf8'));
45
+ return parsed.token ?? null;
46
+ }
47
+ catch (_error) {
48
+ return null;
49
+ }
50
+ };
51
+ /** A driver connection to one hub. */
52
+ class HubClient {
53
+ url;
54
+ ws;
55
+ pages = new Map();
56
+ current = null;
57
+ lastHref = '';
58
+ pending = new Map();
59
+ listeners = new Map();
60
+ closed = false;
61
+ constructor(url, ws) {
62
+ this.url = url;
63
+ this.ws = ws;
64
+ ws.on('message', (data) => this.onMessage(String(data)));
65
+ ws.on('close', () => {
66
+ this.closed = true;
67
+ for (const [id, p] of this.pending) {
68
+ this.pending.delete(id);
69
+ clearTimeout(p.timer);
70
+ p.reject(new Error(`the connection to the preview hub at ${url} closed (did the dev server restart?)`));
71
+ }
72
+ this.emit({ event: 'hub-closed' });
73
+ });
74
+ ws.on('error', () => {
75
+ /* close follows */
76
+ });
77
+ }
78
+ /** Connect to a hub as a driver and learn the pages already connected. */
79
+ static open(url, token, timeout) {
80
+ return new Promise((resolve, reject) => {
81
+ const ws = new WebSocket(`${url}?role=driver&token=${encodeURIComponent(token)}`);
82
+ const timer = setTimeout(() => {
83
+ ws.terminate();
84
+ reject(new Error(`timed out connecting to the preview hub at ${url}`));
85
+ }, timeout);
86
+ ws.once('open', () => {
87
+ clearTimeout(timer);
88
+ const client = new HubClient(url, ws);
89
+ client.seed().then(() => resolve(client), reject);
90
+ });
91
+ ws.once('error', (error) => {
92
+ clearTimeout(timer);
93
+ reject(error);
94
+ });
95
+ ws.once('unexpected-response', (_req, res) => {
96
+ clearTimeout(timer);
97
+ reject(new Error(`the preview hub at ${url} refused the driver connection (HTTP ${res.statusCode}) — wrong token, or not connecting from the machine that runs the dev server`));
98
+ });
99
+ });
100
+ }
101
+ /** Whether the socket has closed. */
102
+ get isClosed() {
103
+ return this.closed;
104
+ }
105
+ /** Subscribe to hub events (`page-hello`, `page-closed`, `navigated`, `console`, `pageerror`, `hub-closed`, or `*`); returns an unsubscribe function. */
106
+ on(event, fn) {
107
+ if (!this.listeners.has(event))
108
+ this.listeners.set(event, new Set());
109
+ this.listeners.get(event).add(fn);
110
+ return () => this.listeners.get(event)?.delete(fn);
111
+ }
112
+ /** Fan an event out to its listeners and to the wildcard listeners. */
113
+ emit(event) {
114
+ for (const fn of this.listeners.get(event.event) ?? [])
115
+ fn(event);
116
+ for (const fn of this.listeners.get('*') ?? [])
117
+ fn(event);
118
+ }
119
+ /** Route a hub frame: a reply to a pending request, or a page event that updates the bookkeeping. */
120
+ onMessage(raw) {
121
+ let msg;
122
+ try {
123
+ msg = JSON.parse(raw);
124
+ }
125
+ catch (_error) {
126
+ return;
127
+ }
128
+ if (typeof msg.id === 'string' && this.pending.has(msg.id)) {
129
+ const p = this.pending.get(msg.id);
130
+ this.pending.delete(msg.id);
131
+ clearTimeout(p.timer);
132
+ if (typeof msg.href === 'string' && msg.pageId === this.current)
133
+ this.lastHref = msg.href;
134
+ p.resolve(msg);
135
+ return;
136
+ }
137
+ if (typeof msg.event !== 'string')
138
+ return;
139
+ const pageId = typeof msg.pageId === 'string' ? msg.pageId : undefined;
140
+ if (msg.event === 'page-hello' && pageId) {
141
+ this.pages.set(pageId, {
142
+ id: pageId,
143
+ href: String(msg.href ?? ''),
144
+ title: String(msg.title ?? ''),
145
+ hidden: Boolean(msg.hidden),
146
+ framed: Boolean(msg.framed),
147
+ connectedAt: Number(msg.connectedAt ?? Date.now()),
148
+ lastSeen: Date.now(),
149
+ });
150
+ }
151
+ else if (msg.event === 'page-closed' && pageId) {
152
+ this.pages.delete(pageId);
153
+ if (this.current === pageId)
154
+ this.current = null;
155
+ }
156
+ else if (pageId && this.pages.has(pageId)) {
157
+ const peer = this.pages.get(pageId);
158
+ peer.lastSeen = Date.now();
159
+ if (msg.event === 'navigated' && typeof msg.href === 'string') {
160
+ peer.href = msg.href;
161
+ if (pageId === this.current)
162
+ this.lastHref = msg.href;
163
+ }
164
+ if (msg.event === 'visibility')
165
+ peer.hidden = Boolean(msg.hidden);
166
+ }
167
+ this.emit(msg);
168
+ }
169
+ /** Learn about pages that connected BEFORE this driver did (the hub only broadcasts new hellos). */
170
+ async seed() {
171
+ const reply = await this.request('list', {}, 5_000);
172
+ for (const peer of reply.value ?? []) {
173
+ if (!this.pages.has(peer.id))
174
+ this.pages.set(peer.id, { ...peer, lastSeen: peer.lastSeen || Date.now() });
175
+ }
176
+ }
177
+ /** Send one driver request and await its reply within `timeout`. */
178
+ request(op, payload, timeout) {
179
+ if (this.closed)
180
+ return Promise.reject(new Error(`the connection to the preview hub at ${this.url} is closed`));
181
+ const id = randomUUID();
182
+ return new Promise((resolve, reject) => {
183
+ const timer = setTimeout(() => {
184
+ this.pending.delete(id);
185
+ reject(new E2ETimeoutError(`the preview page did not answer within ${timeout}ms (${op}). Is the preview tab open and awake?`));
186
+ }, timeout);
187
+ this.pending.set(id, { resolve, reject, timer });
188
+ this.ws.send(JSON.stringify({ id, op, ...payload }));
189
+ });
190
+ }
191
+ /** Wait for a page to be connected; resolves with its id. */
192
+ waitForPage(options) {
193
+ const pick = () => {
194
+ if (options.preferred && this.pages.has(options.preferred))
195
+ return options.preferred;
196
+ const all = Array.from(this.pages.values()).filter((p) => p.id !== options.exclude);
197
+ const visible = all.filter((p) => !p.hidden);
198
+ const pool = visible.length ? visible : all;
199
+ pool.sort((a, b) => b.lastSeen - a.lastSeen);
200
+ return pool[0]?.id ?? null;
201
+ };
202
+ const now = pick();
203
+ if (now)
204
+ return Promise.resolve(now);
205
+ return new Promise((resolve, reject) => {
206
+ const timer = setTimeout(() => {
207
+ off();
208
+ reject(new E2ETimeoutError(noPageMessage(this.url)));
209
+ }, options.timeout);
210
+ const off = this.on('page-hello', () => {
211
+ const id = pick();
212
+ if (!id)
213
+ return;
214
+ clearTimeout(timer);
215
+ off();
216
+ resolve(id);
217
+ });
218
+ });
219
+ }
220
+ /** Close the driver socket. */
221
+ close() {
222
+ this.closed = true;
223
+ this.ws.close();
224
+ }
225
+ }
226
+ const openHub = async (options) => {
227
+ const timeout = options.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT;
228
+ const tried = [];
229
+ if (options.url) {
230
+ const port = Number(new URL(options.url).port) || 80;
231
+ const token = readToken(port, options);
232
+ if (!token)
233
+ throw new Error(`no driver token for the preview hub at ${options.url}: set MOL_E2E_TOKEN or start the dev server with the preview plugin (it writes ${tokenFilePath(port)})`);
234
+ return HubClient.open(options.url, token, timeout);
235
+ }
236
+ for (const port of candidatePorts(options)) {
237
+ const url = `ws://127.0.0.1:${port}${E2E_WS_PATH}`;
238
+ const token = readToken(port, options);
239
+ if (!token) {
240
+ tried.push(`${url} (no token file — is the dev server on :${port} running with the preview plugin?)`);
241
+ continue;
242
+ }
243
+ try {
244
+ return await HubClient.open(url, token, Math.min(timeout, 5_000));
245
+ }
246
+ catch (error) {
247
+ tried.push(`${url} (${String(error.message ?? error)})`);
248
+ }
249
+ }
250
+ throw new Error(`could not reach a preview hub. Tried:\n ${tried.join('\n ')}\nStart the app's dev server (it carries the preview plugin) and open its preview in the IDE.`);
251
+ };
252
+ /** Open a transport over the hub: one connected preview page, navigations followed across documents. */
253
+ const openTransport = async (options) => {
254
+ const hub = await openHub(options);
255
+ const connectTimeout = options.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT;
256
+ const navigationTimeout = options.navigationTimeout ?? 15_000;
257
+ hub.current = await hub.waitForPage({ timeout: connectTimeout, preferred: options.pageId });
258
+ hub.lastHref = hub.pages.get(hub.current)?.href ?? '';
259
+ const listeners = new Map();
260
+ const emit = (event, payload) => {
261
+ for (const fn of listeners.get(event) ?? [])
262
+ fn(payload);
263
+ };
264
+ hub.on('console', (e) => {
265
+ if (e.pageId === hub.current)
266
+ emit('console', { type: String(e.type ?? 'log'), text: String(e.text ?? '') });
267
+ });
268
+ hub.on('pageerror', (e) => {
269
+ if (e.pageId === hub.current)
270
+ emit('pageerror', {
271
+ message: String(e.message ?? 'Error'),
272
+ stack: typeof e.stack === 'string' ? e.stack : undefined,
273
+ });
274
+ });
275
+ hub.on('hub-closed', () => emit('close', undefined));
276
+ const ensurePage = async () => {
277
+ if (hub.current && hub.pages.has(hub.current))
278
+ return hub.current;
279
+ hub.current = await hub.waitForPage({ timeout: connectTimeout });
280
+ hub.lastHref = hub.pages.get(hub.current)?.href ?? hub.lastHref;
281
+ return hub.current;
282
+ };
283
+ const cmd = async (command, timeout) => {
284
+ const pageId = await ensurePage();
285
+ const reply = await hub.request('cmd', { pageId, cmd: command }, timeout);
286
+ if (reply.noPage) {
287
+ hub.current = null;
288
+ const next = await ensurePage();
289
+ return hub.request('cmd', { pageId: next, cmd: command }, timeout);
290
+ }
291
+ return reply;
292
+ };
293
+ const settle = async (timeout) => {
294
+ const deadline = Date.now() + timeout;
295
+ for (;;) {
296
+ const reply = await cmd({ op: 'evaluate', source: '() => document.readyState' }, Math.max(1_000, deadline - Date.now()));
297
+ if (reply.ok && reply.value === 'complete')
298
+ return;
299
+ if (Date.now() > deadline)
300
+ return;
301
+ await new Promise((r) => setTimeout(r, 100));
302
+ }
303
+ };
304
+ /** Resolve when the current page is replaced by a new document (or changed its URL in place). */
305
+ const awaitNavigation = (previous, timeout, graceForNoop) => new Promise((resolve, reject) => {
306
+ let done = false;
307
+ const finish = (fn) => {
308
+ if (done)
309
+ return;
310
+ done = true;
311
+ clearTimeout(timer);
312
+ if (grace)
313
+ clearTimeout(grace);
314
+ offHello();
315
+ offNav();
316
+ fn();
317
+ };
318
+ const timer = setTimeout(() => finish(() => reject(new E2ETimeoutError(`navigation did not complete within ${timeout}ms (the previous page ${previous} never handed over to a new document)`))), timeout);
319
+ const grace = graceForNoop === null ? null : setTimeout(() => finish(resolve), graceForNoop);
320
+ const offHello = hub.on('page-hello', (e) => {
321
+ if (e.pageId === previous)
322
+ return;
323
+ hub.current = String(e.pageId);
324
+ hub.lastHref = String(e.href ?? '');
325
+ finish(resolve);
326
+ });
327
+ const offNav = hub.on('navigated', (e) => {
328
+ if (e.pageId !== previous)
329
+ return;
330
+ hub.lastHref = String(e.href ?? hub.lastHref);
331
+ finish(resolve);
332
+ });
333
+ });
334
+ const transport = {
335
+ async evaluate(source, arg, opts) {
336
+ const timeout = opts?.timeout ?? 12_000;
337
+ const reply = await cmd({ op: 'evaluate', source, arg }, timeout);
338
+ if (reply.pageClosed) {
339
+ // The action navigated the page away before it could answer (a link click, a form submit).
340
+ await awaitNavigation(String(reply.pageId ?? hub.current ?? ''), navigationTimeout, null).catch(() => undefined);
341
+ return { ok: true, navigated: true };
342
+ }
343
+ if (reply.ok === false)
344
+ throw new Error(String(reply.error ?? 'evaluate failed'));
345
+ return reply.value;
346
+ },
347
+ async navigate(kind, url, opts) {
348
+ const timeout = opts?.timeout ?? navigationTimeout;
349
+ const previous = await ensurePage();
350
+ const command = kind === 'goto'
351
+ ? { op: 'goto', url }
352
+ : kind === 'reload'
353
+ ? { op: 'reload' }
354
+ : { op: 'history', delta: kind === 'back' ? -1 : 1 };
355
+ const pending = awaitNavigation(previous, timeout, kind === 'back' || kind === 'forward' ? 1_500 : null);
356
+ const reply = await cmd(command, Math.min(timeout, 5_000)).catch((error) => ({ ok: false, error: error.message }));
357
+ if (reply.ok === false && !reply.pageClosed) {
358
+ await pending.catch(() => undefined);
359
+ throw new Error(`page.${kind === 'goto' ? 'goto' : kind}(): ${String(reply.error)}`);
360
+ }
361
+ await pending;
362
+ await settle(timeout);
363
+ },
364
+ async viewport(width, height) {
365
+ const reply = await cmd({ op: 'viewport', width, height }, 5_000);
366
+ if (reply.ok === false)
367
+ throw new Error(String(reply.error ?? 'viewport failed'));
368
+ const v = reply.value;
369
+ return { width: v.width, height: v.height };
370
+ },
371
+ url: () => hub.lastHref,
372
+ on(event, listener) {
373
+ if (!listeners.has(event))
374
+ listeners.set(event, new Set());
375
+ listeners.get(event).add(listener);
376
+ return () => listeners.get(event)?.delete(listener);
377
+ },
378
+ async close() {
379
+ hub.close();
380
+ },
381
+ };
382
+ return transport;
383
+ };
384
+ /** The bond: `setProvider(provider)` in your `e2e/bonds.ts`. */
385
+ export const provider = {
386
+ name: 'preview',
387
+ async connect(options = {}) {
388
+ const transport = await openTransport(options);
389
+ return createEvaluatePage(transport, { ...options, bondName: BOND_NAME });
390
+ },
391
+ };
392
+ /** Open the live preview as a Playwright-shaped page from any script (`node scripts/check.mjs`). */
393
+ export const connectPreview = (options = {}) => provider.connect(options);
394
+ /** The preview pages currently connected to the hub. */
395
+ export const listPreviewPages = async (options = {}) => {
396
+ const hub = await openHub(options);
397
+ try {
398
+ const reply = await hub.request('list', {}, 5_000);
399
+ return reply.value ?? [];
400
+ }
401
+ finally {
402
+ hub.close();
403
+ }
404
+ };
405
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The hub: a WebSocket endpoint attached to the dev server's HTTP server.
3
+ * Preview pages connect as `role=page` (from the browser, same origin through
4
+ * whatever proxy serves the preview); the test runner connects as
5
+ * `role=driver` (loopback only, with the hub's token). The hub forwards each
6
+ * driver command to a page and the page's reply back, and broadcasts page
7
+ * events (hello, navigated, console, pageerror, dialog, closed) to drivers.
8
+ *
9
+ * @module
10
+ */
11
+ import type { IncomingMessage } from 'node:http';
12
+ import type { AddressInfo } from 'node:net';
13
+ import type { Duplex } from 'node:stream';
14
+ import { type PagePeer } from './types.js';
15
+ type UpgradeListener = (req: IncomingMessage, socket: Duplex, head: Buffer) => void;
16
+ /**
17
+ * The slice of `http.Server` / `http2.Http2SecureServer` the hub uses — Vite
18
+ * hands over either, and both emit `upgrade` with the same arguments.
19
+ */
20
+ export interface UpgradeCapableServer {
21
+ on(event: 'upgrade', listener: UpgradeListener): unknown;
22
+ off(event: 'upgrade', listener: UpgradeListener): unknown;
23
+ once(event: 'listening' | 'close', listener: () => void): unknown;
24
+ address(): AddressInfo | string | null;
25
+ readonly listening: boolean;
26
+ }
27
+ /** A running hub. */
28
+ export interface E2EHub {
29
+ /** The driver token (also written to the token file once the server listens). */
30
+ readonly token: string;
31
+ /** Pages currently connected. */
32
+ pages(): PagePeer[];
33
+ /** Detach from the server and close every socket. */
34
+ close(): void;
35
+ }
36
+ /**
37
+ * Attach the hub to an HTTP server (Vite's `server.httpServer`). Safe next to
38
+ * Vite's own HMR upgrade listener: each ignores the other's path.
39
+ */
40
+ export declare const attachE2EHub: (httpServer: UpgradeCapableServer, options?: {
41
+ token?: string;
42
+ path?: string;
43
+ }) => E2EHub;
44
+ export {};
45
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAIzC,OAAO,EAAe,KAAK,QAAQ,EAAiB,MAAM,YAAY,CAAA;AAItE,KAAK,eAAe,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAEnF;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAA;IACxD,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAA;IACzD,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAA;IACjE,OAAO,IAAI,WAAW,GAAG,MAAM,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAOD,qBAAqB;AACrB,MAAM,WAAW,MAAM;IACrB,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iCAAiC;IACjC,KAAK,IAAI,QAAQ,EAAE,CAAA;IACnB,qDAAqD;IACrD,KAAK,IAAI,IAAI,CAAA;CACd;AAKD;;;GAGG;AACH,eAAO,MAAM,YAAY,GACvB,YAAY,oBAAoB,EAChC,UAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,KAC9C,MAwMF,CAAA"}