@monoes/monobrowse 1.0.6 → 1.0.8
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.
- package/LICENSE +191 -0
- package/README.md +68 -0
- package/dist/src/__tests__/adapters.test.d.ts +2 -0
- package/dist/src/__tests__/adapters.test.d.ts.map +1 -0
- package/dist/src/__tests__/adapters.test.js +104 -0
- package/dist/src/__tests__/adapters.test.js.map +1 -0
- package/dist/src/__tests__/batch-eval-parsing.test.d.ts +0 -0
- package/dist/src/__tests__/batch-eval-parsing.test.d.ts.map +0 -0
- package/dist/src/__tests__/batch-eval-parsing.test.js +0 -0
- package/dist/src/__tests__/batch-eval-parsing.test.js.map +0 -0
- package/dist/src/__tests__/box-model.test.d.ts +0 -0
- package/dist/src/__tests__/box-model.test.d.ts.map +0 -0
- package/dist/src/__tests__/box-model.test.js +0 -0
- package/dist/src/__tests__/box-model.test.js.map +0 -0
- package/dist/src/__tests__/browser-launch.test.d.ts +0 -0
- package/dist/src/__tests__/browser-launch.test.d.ts.map +0 -0
- package/dist/src/__tests__/browser-launch.test.js +0 -0
- package/dist/src/__tests__/browser-launch.test.js.map +0 -0
- package/dist/src/__tests__/cdp-client.test.d.ts +2 -0
- package/dist/src/__tests__/cdp-client.test.d.ts.map +1 -0
- package/dist/src/__tests__/cdp-client.test.js +326 -0
- package/dist/src/__tests__/cdp-client.test.js.map +1 -0
- package/dist/src/__tests__/close-browser.test.d.ts +2 -0
- package/dist/src/__tests__/close-browser.test.d.ts.map +1 -0
- package/dist/src/__tests__/close-browser.test.js +188 -0
- package/dist/src/__tests__/close-browser.test.js.map +1 -0
- package/dist/src/__tests__/console-log.test.d.ts +2 -0
- package/dist/src/__tests__/console-log.test.d.ts.map +1 -0
- package/dist/src/__tests__/console-log.test.js +195 -0
- package/dist/src/__tests__/console-log.test.js.map +1 -0
- package/dist/src/__tests__/find.test.d.ts +2 -0
- package/dist/src/__tests__/find.test.d.ts.map +1 -0
- package/dist/src/__tests__/find.test.js +299 -0
- package/dist/src/__tests__/find.test.js.map +1 -0
- package/dist/src/__tests__/frame-command.test.d.ts +2 -0
- package/dist/src/__tests__/frame-command.test.d.ts.map +1 -0
- package/dist/src/__tests__/frame-command.test.js +85 -0
- package/dist/src/__tests__/frame-command.test.js.map +1 -0
- package/dist/src/__tests__/output.test.d.ts +0 -0
- package/dist/src/__tests__/output.test.d.ts.map +0 -0
- package/dist/src/__tests__/output.test.js +0 -0
- package/dist/src/__tests__/output.test.js.map +0 -0
- package/dist/src/__tests__/ref-cache.test.d.ts +0 -0
- package/dist/src/__tests__/ref-cache.test.d.ts.map +0 -0
- package/dist/src/__tests__/ref-cache.test.js +43 -2
- package/dist/src/__tests__/ref-cache.test.js.map +1 -1
- package/dist/src/__tests__/session-state.test.d.ts +2 -0
- package/dist/src/__tests__/session-state.test.d.ts.map +1 -0
- package/dist/src/__tests__/session-state.test.js +203 -0
- package/dist/src/__tests__/session-state.test.js.map +1 -0
- package/dist/src/__tests__/snapshot.test.d.ts +2 -0
- package/dist/src/__tests__/snapshot.test.d.ts.map +1 -0
- package/dist/src/__tests__/snapshot.test.js +262 -0
- package/dist/src/__tests__/snapshot.test.js.map +1 -0
- package/dist/src/__tests__/storage-eval.test.d.ts +2 -0
- package/dist/src/__tests__/storage-eval.test.d.ts.map +1 -0
- package/dist/src/__tests__/storage-eval.test.js +133 -0
- package/dist/src/__tests__/storage-eval.test.js.map +1 -0
- package/dist/src/__tests__/tabs.test.d.ts +2 -0
- package/dist/src/__tests__/tabs.test.d.ts.map +1 -0
- package/dist/src/__tests__/tabs.test.js +161 -0
- package/dist/src/__tests__/tabs.test.js.map +1 -0
- package/dist/src/browser/action-builder/analyzer.d.ts +0 -0
- package/dist/src/browser/action-builder/analyzer.d.ts.map +0 -0
- package/dist/src/browser/action-builder/analyzer.js +0 -0
- package/dist/src/browser/action-builder/analyzer.js.map +0 -0
- package/dist/src/browser/action-builder/types.d.ts +0 -0
- package/dist/src/browser/action-builder/types.d.ts.map +0 -0
- package/dist/src/browser/action-builder/types.js +0 -0
- package/dist/src/browser/action-builder/types.js.map +0 -0
- package/dist/src/browser/actions.d.ts +0 -0
- package/dist/src/browser/actions.d.ts.map +0 -0
- package/dist/src/browser/actions.js +0 -0
- package/dist/src/browser/actions.js.map +0 -0
- package/dist/src/browser/adapters/gemini.d.ts +0 -0
- package/dist/src/browser/adapters/gemini.d.ts.map +0 -0
- package/dist/src/browser/adapters/gemini.js +0 -0
- package/dist/src/browser/adapters/gemini.js.map +0 -0
- package/dist/src/browser/adapters/google.d.ts +0 -0
- package/dist/src/browser/adapters/google.d.ts.map +0 -0
- package/dist/src/browser/adapters/google.js +0 -0
- package/dist/src/browser/adapters/google.js.map +0 -0
- package/dist/src/browser/adapters/index.d.ts +0 -0
- package/dist/src/browser/adapters/index.d.ts.map +0 -0
- package/dist/src/browser/adapters/index.js +0 -0
- package/dist/src/browser/adapters/index.js.map +0 -0
- package/dist/src/browser/adapters/instagram.d.ts +0 -0
- package/dist/src/browser/adapters/instagram.d.ts.map +0 -0
- package/dist/src/browser/adapters/instagram.js +0 -0
- package/dist/src/browser/adapters/instagram.js.map +0 -0
- package/dist/src/browser/adapters/linkedin.d.ts +0 -0
- package/dist/src/browser/adapters/linkedin.d.ts.map +0 -0
- package/dist/src/browser/adapters/linkedin.js +0 -0
- package/dist/src/browser/adapters/linkedin.js.map +0 -0
- package/dist/src/browser/adapters/microsoft.d.ts +0 -0
- package/dist/src/browser/adapters/microsoft.d.ts.map +0 -0
- package/dist/src/browser/adapters/microsoft.js +0 -0
- package/dist/src/browser/adapters/microsoft.js.map +0 -0
- package/dist/src/browser/adapters/x.d.ts +0 -0
- package/dist/src/browser/adapters/x.d.ts.map +0 -0
- package/dist/src/browser/adapters/x.js +0 -0
- package/dist/src/browser/adapters/x.js.map +0 -0
- package/dist/src/browser/batch.d.ts +0 -0
- package/dist/src/browser/batch.d.ts.map +0 -0
- package/dist/src/browser/batch.js +0 -0
- package/dist/src/browser/batch.js.map +0 -0
- package/dist/src/browser/browser.d.ts +13 -0
- package/dist/src/browser/browser.d.ts.map +1 -1
- package/dist/src/browser/browser.js +99 -16
- package/dist/src/browser/browser.js.map +1 -1
- package/dist/src/browser/cdp.d.ts +4 -1
- package/dist/src/browser/cdp.d.ts.map +1 -1
- package/dist/src/browser/cdp.js +45 -16
- package/dist/src/browser/cdp.js.map +1 -1
- package/dist/src/browser/console-log.d.ts +0 -0
- package/dist/src/browser/console-log.d.ts.map +0 -0
- package/dist/src/browser/console-log.js +0 -0
- package/dist/src/browser/console-log.js.map +0 -0
- package/dist/src/browser/dashboard/api-types.d.ts +0 -0
- package/dist/src/browser/dashboard/api-types.d.ts.map +0 -0
- package/dist/src/browser/dashboard/api-types.js +0 -0
- package/dist/src/browser/dashboard/api-types.js.map +0 -0
- package/dist/src/browser/dashboard/server.d.ts +0 -0
- package/dist/src/browser/dashboard/server.d.ts.map +0 -0
- package/dist/src/browser/dashboard/server.js +0 -0
- package/dist/src/browser/dashboard/server.js.map +0 -0
- package/dist/src/browser/dashboard/ui.html +0 -0
- package/dist/src/browser/dialog.d.ts +0 -0
- package/dist/src/browser/dialog.d.ts.map +0 -0
- package/dist/src/browser/dialog.js +0 -0
- package/dist/src/browser/dialog.js.map +0 -0
- package/dist/src/browser/emulation.d.ts +0 -0
- package/dist/src/browser/emulation.d.ts.map +0 -0
- package/dist/src/browser/emulation.js +0 -0
- package/dist/src/browser/emulation.js.map +0 -0
- package/dist/src/browser/find.d.ts +0 -0
- package/dist/src/browser/find.d.ts.map +0 -0
- package/dist/src/browser/find.js +0 -0
- package/dist/src/browser/find.js.map +0 -0
- package/dist/src/browser/har.d.ts +0 -0
- package/dist/src/browser/har.d.ts.map +0 -0
- package/dist/src/browser/har.js +0 -0
- package/dist/src/browser/har.js.map +0 -0
- package/dist/src/browser/index.d.ts +0 -0
- package/dist/src/browser/index.d.ts.map +0 -0
- package/dist/src/browser/index.js +0 -0
- package/dist/src/browser/index.js.map +0 -0
- package/dist/src/browser/network.d.ts +0 -0
- package/dist/src/browser/network.d.ts.map +0 -0
- package/dist/src/browser/network.js +0 -0
- package/dist/src/browser/network.js.map +0 -0
- package/dist/src/browser/pdf.d.ts +0 -0
- package/dist/src/browser/pdf.d.ts.map +0 -0
- package/dist/src/browser/pdf.js +0 -0
- package/dist/src/browser/pdf.js.map +0 -0
- package/dist/src/browser/profiler.d.ts +0 -0
- package/dist/src/browser/profiler.d.ts.map +0 -0
- package/dist/src/browser/profiler.js +0 -0
- package/dist/src/browser/profiler.js.map +0 -0
- package/dist/src/browser/record.d.ts +0 -0
- package/dist/src/browser/record.d.ts.map +0 -0
- package/dist/src/browser/record.js +0 -0
- package/dist/src/browser/record.js.map +0 -0
- package/dist/src/browser/ref-cache.d.ts +6 -1
- package/dist/src/browser/ref-cache.d.ts.map +1 -1
- package/dist/src/browser/ref-cache.js +21 -3
- package/dist/src/browser/ref-cache.js.map +1 -1
- package/dist/src/browser/screenshot.d.ts +0 -0
- package/dist/src/browser/screenshot.d.ts.map +0 -0
- package/dist/src/browser/screenshot.js +0 -0
- package/dist/src/browser/screenshot.js.map +0 -0
- package/dist/src/browser/session.d.ts +0 -0
- package/dist/src/browser/session.d.ts.map +0 -0
- package/dist/src/browser/session.js +0 -0
- package/dist/src/browser/session.js.map +0 -0
- package/dist/src/browser/snapshot.d.ts +0 -0
- package/dist/src/browser/snapshot.d.ts.map +0 -0
- package/dist/src/browser/snapshot.js +0 -0
- package/dist/src/browser/snapshot.js.map +0 -0
- package/dist/src/browser/storage.d.ts +0 -0
- package/dist/src/browser/storage.d.ts.map +0 -0
- package/dist/src/browser/storage.js +0 -0
- package/dist/src/browser/storage.js.map +0 -0
- package/dist/src/browser/tabs.d.ts +5 -1
- package/dist/src/browser/tabs.d.ts.map +1 -1
- package/dist/src/browser/tabs.js +4 -3
- package/dist/src/browser/tabs.js.map +1 -1
- package/dist/src/browser/trace.d.ts +0 -0
- package/dist/src/browser/trace.d.ts.map +0 -0
- package/dist/src/browser/trace.js +0 -0
- package/dist/src/browser/trace.js.map +0 -0
- package/dist/src/browser/types.d.ts +4 -0
- package/dist/src/browser/types.d.ts.map +1 -1
- package/dist/src/browser/types.js +0 -0
- package/dist/src/browser/types.js.map +1 -1
- package/dist/src/browser/vitals.d.ts +0 -0
- package/dist/src/browser/vitals.d.ts.map +0 -0
- package/dist/src/browser/vitals.js +0 -0
- package/dist/src/browser/vitals.js.map +0 -0
- package/dist/src/browser/wait.d.ts +0 -0
- package/dist/src/browser/wait.d.ts.map +0 -0
- package/dist/src/browser/wait.js +0 -0
- package/dist/src/browser/wait.js.map +0 -0
- package/dist/src/cli/action.d.ts +0 -0
- package/dist/src/cli/action.d.ts.map +0 -0
- package/dist/src/cli/action.js +0 -0
- package/dist/src/cli/action.js.map +0 -0
- package/dist/src/cli/commands.d.ts +0 -0
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/commands.js +96 -4
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/output.d.ts +0 -0
- package/dist/src/cli/output.d.ts.map +0 -0
- package/dist/src/cli/output.js +0 -0
- package/dist/src/cli/output.js.map +0 -0
- package/dist/src/cli/platform.d.ts +0 -0
- package/dist/src/cli/platform.d.ts.map +0 -0
- package/dist/src/cli/platform.js +0 -0
- package/dist/src/cli/platform.js.map +0 -0
- package/dist/src/cli/types.d.ts +0 -0
- package/dist/src/cli/types.d.ts.map +0 -0
- package/dist/src/cli/types.js +0 -0
- package/dist/src/cli/types.js.map +0 -0
- package/dist/src/cli.d.ts +0 -0
- package/dist/src/cli.d.ts.map +0 -0
- package/dist/src/cli.js.map +0 -0
- package/dist/src/index.d.ts +0 -0
- package/dist/src/index.d.ts.map +0 -0
- package/dist/src/index.js +0 -0
- package/dist/src/index.js.map +0 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -8
- package/src/__tests__/adapters.test.ts +125 -0
- package/src/__tests__/batch-eval-parsing.test.ts +0 -0
- package/src/__tests__/box-model.test.ts +0 -0
- package/src/__tests__/browser-launch.test.ts +0 -0
- package/src/__tests__/cdp-client.test.ts +375 -0
- package/src/__tests__/close-browser.test.ts +205 -0
- package/src/__tests__/console-log.test.ts +250 -0
- package/src/__tests__/find.test.ts +354 -0
- package/src/__tests__/frame-command.test.ts +98 -0
- package/src/__tests__/output.test.ts +0 -0
- package/src/__tests__/ref-cache.test.ts +47 -2
- package/src/__tests__/session-state.test.ts +251 -0
- package/src/__tests__/snapshot.test.ts +331 -0
- package/src/__tests__/storage-eval.test.ts +171 -0
- package/src/__tests__/tabs.test.ts +183 -0
- package/src/browser/action-builder/analyzer.ts +0 -0
- package/src/browser/action-builder/types.ts +0 -0
- package/src/browser/actions.ts +0 -0
- package/src/browser/adapters/gemini.ts +0 -0
- package/src/browser/adapters/google.ts +0 -0
- package/src/browser/adapters/index.ts +0 -0
- package/src/browser/adapters/instagram.ts +0 -0
- package/src/browser/adapters/linkedin.ts +0 -0
- package/src/browser/adapters/microsoft.ts +0 -0
- package/src/browser/adapters/x.ts +0 -0
- package/src/browser/batch.ts +0 -0
- package/src/browser/browser.ts +101 -16
- package/src/browser/cdp.ts +52 -15
- package/src/browser/console-log.ts +0 -0
- package/src/browser/dashboard/api-types.ts +0 -0
- package/src/browser/dashboard/server.ts +0 -0
- package/src/browser/dashboard/ui.html +0 -0
- package/src/browser/dialog.ts +0 -0
- package/src/browser/emulation.ts +0 -0
- package/src/browser/find.ts +0 -0
- package/src/browser/har.ts +0 -0
- package/src/browser/index.ts +0 -0
- package/src/browser/network.ts +0 -0
- package/src/browser/pdf.ts +0 -0
- package/src/browser/profiler.ts +0 -0
- package/src/browser/record.ts +0 -0
- package/src/browser/ref-cache.ts +29 -6
- package/src/browser/screenshot.ts +0 -0
- package/src/browser/session.ts +0 -0
- package/src/browser/snapshot.ts +0 -0
- package/src/browser/storage.ts +0 -0
- package/src/browser/tabs.ts +12 -4
- package/src/browser/trace.ts +0 -0
- package/src/browser/types.ts +4 -0
- package/src/browser/vitals.ts +0 -0
- package/src/browser/wait.ts +0 -0
- package/src/cli/action.ts +0 -0
- package/src/cli/commands.ts +90 -4
- package/src/cli/output.ts +0 -0
- package/src/cli/platform.ts +0 -0
- package/src/cli/types.ts +0 -0
- package/src/cli.ts +0 -0
- package/src/index.ts +0 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CdpClient dispatch/guard logic and the two HTTP endpoint helpers.
|
|
3
|
+
*
|
|
4
|
+
* No browser and no WebSocket server: `connect()` is exercised against a fake
|
|
5
|
+
* `ws` module (so we can drive 'message'/'close'/'error' by hand), and
|
|
6
|
+
* fetchTargets/fetchNewTarget run against a stubbed global fetch.
|
|
7
|
+
*/
|
|
8
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
9
|
+
// --- fake `ws` -------------------------------------------------------------
|
|
10
|
+
// Captures the most recently constructed socket so tests can drive its events.
|
|
11
|
+
let lastSocket = null;
|
|
12
|
+
class FakeWs {
|
|
13
|
+
url;
|
|
14
|
+
handlers = new Map();
|
|
15
|
+
sent = [];
|
|
16
|
+
closed = false;
|
|
17
|
+
/** When set, the `send` callback receives this error instead of success. */
|
|
18
|
+
sendError = null;
|
|
19
|
+
constructor(url) {
|
|
20
|
+
this.url = url;
|
|
21
|
+
lastSocket = this;
|
|
22
|
+
}
|
|
23
|
+
on(event, fn) {
|
|
24
|
+
if (!this.handlers.has(event))
|
|
25
|
+
this.handlers.set(event, []);
|
|
26
|
+
this.handlers.get(event).push(fn);
|
|
27
|
+
}
|
|
28
|
+
emit(event, ...args) {
|
|
29
|
+
for (const fn of [...(this.handlers.get(event) ?? [])])
|
|
30
|
+
fn(...args);
|
|
31
|
+
}
|
|
32
|
+
send(data, cb) {
|
|
33
|
+
this.sent.push(data);
|
|
34
|
+
cb?.(this.sendError ?? undefined);
|
|
35
|
+
}
|
|
36
|
+
close() {
|
|
37
|
+
this.closed = true;
|
|
38
|
+
}
|
|
39
|
+
/** Convenience: deliver a CDP frame as the ws 'message' event does. */
|
|
40
|
+
deliver(msg) {
|
|
41
|
+
this.emit('message', Buffer.from(JSON.stringify(msg)));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
vi.mock('ws', () => ({ WebSocket: FakeWs }));
|
|
45
|
+
const { CdpClient, fetchTargets, fetchNewTarget } = await import('../browser/cdp.js');
|
|
46
|
+
/** Build a connected client plus its fake socket. */
|
|
47
|
+
async function connected() {
|
|
48
|
+
const client = new CdpClient();
|
|
49
|
+
const p = client.connect('ws://127.0.0.1:9222/devtools/page/ABC');
|
|
50
|
+
lastSocket.emit('open');
|
|
51
|
+
await p;
|
|
52
|
+
return { client, ws: lastSocket };
|
|
53
|
+
}
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
lastSocket = null;
|
|
56
|
+
});
|
|
57
|
+
describe('connect', () => {
|
|
58
|
+
it('resolves on open and reports connected', async () => {
|
|
59
|
+
const { client, ws } = await connected();
|
|
60
|
+
expect(ws.url).toBe('ws://127.0.0.1:9222/devtools/page/ABC');
|
|
61
|
+
expect(client.isConnected()).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('rejects when the socket errors before ever opening', async () => {
|
|
64
|
+
const client = new CdpClient();
|
|
65
|
+
const p = client.connect('ws://127.0.0.1:1/devtools');
|
|
66
|
+
lastSocket.emit('error', new Error('ECONNREFUSED'));
|
|
67
|
+
await expect(p).rejects.toThrow('ECONNREFUSED');
|
|
68
|
+
expect(client.isConnected()).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('send', () => {
|
|
72
|
+
it('rejects when not connected rather than queueing forever', async () => {
|
|
73
|
+
await expect(new CdpClient().send('Page.enable')).rejects.toThrow('CDP not connected');
|
|
74
|
+
});
|
|
75
|
+
it('serializes id/method/params and omits sessionId when not given', async () => {
|
|
76
|
+
const { client, ws } = await connected();
|
|
77
|
+
void client.send('Page.navigate', { url: 'https://x.test' });
|
|
78
|
+
expect(JSON.parse(ws.sent[0])).toEqual({
|
|
79
|
+
id: 1,
|
|
80
|
+
method: 'Page.navigate',
|
|
81
|
+
params: { url: 'https://x.test' },
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
it('attaches sessionId when supplied and increments ids monotonically', async () => {
|
|
85
|
+
const { client, ws } = await connected();
|
|
86
|
+
void client.send('A', {}, 'S1');
|
|
87
|
+
void client.send('B', {}, 'S1');
|
|
88
|
+
expect(JSON.parse(ws.sent[0]).id).toBe(1);
|
|
89
|
+
expect(JSON.parse(ws.sent[1])).toMatchObject({ id: 2, method: 'B', sessionId: 'S1' });
|
|
90
|
+
});
|
|
91
|
+
it('resolves with the response result matched by id', async () => {
|
|
92
|
+
const { client, ws } = await connected();
|
|
93
|
+
const a = client.send('A');
|
|
94
|
+
const b = client.send('B');
|
|
95
|
+
// Answer out of order to prove id matching, not FIFO.
|
|
96
|
+
ws.deliver({ id: 2, result: { v: 'second' } });
|
|
97
|
+
ws.deliver({ id: 1, result: { v: 'first' } });
|
|
98
|
+
expect(await a).toEqual({ v: 'first' });
|
|
99
|
+
expect(await b).toEqual({ v: 'second' });
|
|
100
|
+
});
|
|
101
|
+
it('resolves with {} when the response carries no result', async () => {
|
|
102
|
+
const { client, ws } = await connected();
|
|
103
|
+
const p = client.send('A');
|
|
104
|
+
ws.deliver({ id: 1 });
|
|
105
|
+
expect(await p).toEqual({});
|
|
106
|
+
});
|
|
107
|
+
it('rejects with the CDP error code and message', async () => {
|
|
108
|
+
const { client, ws } = await connected();
|
|
109
|
+
const p = client.send('Bad.method');
|
|
110
|
+
ws.deliver({ id: 1, error: { code: -32601, message: 'method not found' } });
|
|
111
|
+
await expect(p).rejects.toThrow('CDP error -32601: method not found');
|
|
112
|
+
});
|
|
113
|
+
it('rejects and forgets the command when the socket send callback errors', async () => {
|
|
114
|
+
const { client, ws } = await connected();
|
|
115
|
+
ws.sendError = new Error('socket write failed');
|
|
116
|
+
await expect(client.send('A')).rejects.toThrow('socket write failed');
|
|
117
|
+
// Not left pending: a later close() must not try to reject it a second time.
|
|
118
|
+
ws.sendError = null;
|
|
119
|
+
expect(() => client.close()).not.toThrow();
|
|
120
|
+
});
|
|
121
|
+
it('refuses to exceed the 1000 in-flight command cap', async () => {
|
|
122
|
+
const { client } = await connected();
|
|
123
|
+
const inflight = Array.from({ length: 1000 }, () => client.send('A').catch(() => { }));
|
|
124
|
+
await expect(client.send('A')).rejects.toThrow('CDP command queue full (>1000 in-flight commands)');
|
|
125
|
+
client.close();
|
|
126
|
+
await Promise.all(inflight);
|
|
127
|
+
});
|
|
128
|
+
describe('#115: default timeout (a response that never arrives must not hang forever)', () => {
|
|
129
|
+
beforeEach(() => vi.useFakeTimers());
|
|
130
|
+
afterEach(() => vi.useRealTimers());
|
|
131
|
+
it('rejects a command with no response after the default 30s timeout', async () => {
|
|
132
|
+
const { client } = await connected();
|
|
133
|
+
const p = client.send('Runtime.evaluate');
|
|
134
|
+
const assertion = expect(p).rejects.toThrow('CDP command "Runtime.evaluate" timed out after 30000ms');
|
|
135
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
136
|
+
await assertion;
|
|
137
|
+
});
|
|
138
|
+
it('honors a caller-supplied timeout shorter than the default', async () => {
|
|
139
|
+
const { client } = await connected();
|
|
140
|
+
const p = client.send('Runtime.evaluate', {}, undefined, 500);
|
|
141
|
+
const assertion = expect(p).rejects.toThrow('timed out after 500ms');
|
|
142
|
+
await vi.advanceTimersByTimeAsync(500);
|
|
143
|
+
await assertion;
|
|
144
|
+
});
|
|
145
|
+
it('timeoutMs: 0 disables the timeout entirely', async () => {
|
|
146
|
+
const { client, ws } = await connected();
|
|
147
|
+
const p = client.send('A', {}, undefined, 0);
|
|
148
|
+
await vi.advanceTimersByTimeAsync(60_000);
|
|
149
|
+
// Still pending — no timeout fired.
|
|
150
|
+
let settled = false;
|
|
151
|
+
void p.then(() => { settled = true; }).catch(() => { settled = true; });
|
|
152
|
+
await Promise.resolve();
|
|
153
|
+
expect(settled).toBe(false);
|
|
154
|
+
ws.deliver({ id: 1, result: {} });
|
|
155
|
+
await expect(p).resolves.toEqual({});
|
|
156
|
+
});
|
|
157
|
+
it('a response arriving before the timeout clears the timer (does not also reject later)', async () => {
|
|
158
|
+
const { client, ws } = await connected();
|
|
159
|
+
const p = client.send('A');
|
|
160
|
+
ws.deliver({ id: 1, result: { ok: true } });
|
|
161
|
+
await expect(p).resolves.toEqual({ ok: true });
|
|
162
|
+
// Advancing past the timeout window must not throw/reject anything further.
|
|
163
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
describe('#115: Target.targetCrashed / targetDestroyed flush pending commands', () => {
|
|
167
|
+
it('targetCrashed rejects in-flight commands instead of leaving them pending', async () => {
|
|
168
|
+
const { client, ws } = await connected();
|
|
169
|
+
const p = client.send('Runtime.evaluate');
|
|
170
|
+
ws.deliver({ method: 'Target.targetCrashed', params: {} });
|
|
171
|
+
await expect(p).rejects.toThrow('CDP target crashed');
|
|
172
|
+
expect(client.isConnected()).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
it('targetDestroyed rejects in-flight commands', async () => {
|
|
175
|
+
const { client, ws } = await connected();
|
|
176
|
+
const p = client.send('Runtime.evaluate');
|
|
177
|
+
ws.deliver({ method: 'Target.targetDestroyed', params: {} });
|
|
178
|
+
await expect(p).rejects.toThrow('CDP target destroyed');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
describe('event dispatch', () => {
|
|
183
|
+
it('routes events to listeners with params and sessionId', async () => {
|
|
184
|
+
const { client, ws } = await connected();
|
|
185
|
+
const seen = [];
|
|
186
|
+
client.on('Page.loadEventFired', (params, sid) => seen.push([params, sid]));
|
|
187
|
+
ws.deliver({ method: 'Page.loadEventFired', params: { timestamp: 5 }, sessionId: 'S1' });
|
|
188
|
+
expect(seen).toEqual([[{ timestamp: 5 }, 'S1']]);
|
|
189
|
+
});
|
|
190
|
+
it('passes {} when the event has no params', async () => {
|
|
191
|
+
const { client, ws } = await connected();
|
|
192
|
+
const seen = [];
|
|
193
|
+
client.on('E', (p) => seen.push(p));
|
|
194
|
+
ws.deliver({ method: 'E' });
|
|
195
|
+
expect(seen).toEqual([{}]);
|
|
196
|
+
});
|
|
197
|
+
it('the returned off() unsubscribes', async () => {
|
|
198
|
+
const { client, ws } = await connected();
|
|
199
|
+
let count = 0;
|
|
200
|
+
const off = client.on('E', () => count++);
|
|
201
|
+
ws.deliver({ method: 'E' });
|
|
202
|
+
off();
|
|
203
|
+
ws.deliver({ method: 'E' });
|
|
204
|
+
expect(count).toBe(1);
|
|
205
|
+
});
|
|
206
|
+
it('isolates a throwing listener so siblings still run', async () => {
|
|
207
|
+
const { client, ws } = await connected();
|
|
208
|
+
let reached = false;
|
|
209
|
+
client.on('E', () => {
|
|
210
|
+
throw new Error('listener blew up');
|
|
211
|
+
});
|
|
212
|
+
client.on('E', () => {
|
|
213
|
+
reached = true;
|
|
214
|
+
});
|
|
215
|
+
expect(() => ws.deliver({ method: 'E' })).not.toThrow();
|
|
216
|
+
expect(reached).toBe(true);
|
|
217
|
+
});
|
|
218
|
+
it('swallows malformed frames instead of crashing the socket', async () => {
|
|
219
|
+
const { client, ws } = await connected();
|
|
220
|
+
expect(() => ws.emit('message', Buffer.from('{not json'))).not.toThrow();
|
|
221
|
+
expect(client.isConnected()).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
it('caps listeners per event at 100', async () => {
|
|
224
|
+
const { client } = await connected();
|
|
225
|
+
for (let i = 0; i < 100; i++)
|
|
226
|
+
client.on('E', () => { });
|
|
227
|
+
expect(() => client.on('E', () => { })).toThrow('CDP event listener limit reached for event: E');
|
|
228
|
+
// The cap is per event name, not global.
|
|
229
|
+
expect(() => client.on('OtherEvent', () => { })).not.toThrow();
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
describe('once / onceWithOff', () => {
|
|
233
|
+
it('resolves on the first matching event and self-unsubscribes', async () => {
|
|
234
|
+
const { client, ws } = await connected();
|
|
235
|
+
const p = client.once('E');
|
|
236
|
+
ws.deliver({ method: 'E', params: { n: 1 } });
|
|
237
|
+
ws.deliver({ method: 'E', params: { n: 2 } });
|
|
238
|
+
expect(await p).toEqual({ n: 1 });
|
|
239
|
+
});
|
|
240
|
+
it('filters by sessionId when one is given', async () => {
|
|
241
|
+
const { client, ws } = await connected();
|
|
242
|
+
const p = client.once('E', 'S1');
|
|
243
|
+
ws.deliver({ method: 'E', params: { from: 'S2' }, sessionId: 'S2' });
|
|
244
|
+
ws.deliver({ method: 'E', params: { from: 'S1' }, sessionId: 'S1' });
|
|
245
|
+
expect(await p).toEqual({ from: 'S1' });
|
|
246
|
+
});
|
|
247
|
+
it('onceWithOff returns a canceller that stops the waiter from firing', async () => {
|
|
248
|
+
const { client, ws } = await connected();
|
|
249
|
+
let settled = false;
|
|
250
|
+
const [promise, off] = client.onceWithOff('E');
|
|
251
|
+
void promise.then(() => {
|
|
252
|
+
settled = true;
|
|
253
|
+
});
|
|
254
|
+
off();
|
|
255
|
+
ws.deliver({ method: 'E' });
|
|
256
|
+
await Promise.resolve();
|
|
257
|
+
expect(settled).toBe(false);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
describe('teardown paths', () => {
|
|
261
|
+
it('close() rejects every pending command, drops listeners and closes the socket', async () => {
|
|
262
|
+
const { client, ws } = await connected();
|
|
263
|
+
const pending = client.send('A');
|
|
264
|
+
let events = 0;
|
|
265
|
+
client.on('E', () => events++);
|
|
266
|
+
client.close();
|
|
267
|
+
await expect(pending).rejects.toThrow('CDP connection closed');
|
|
268
|
+
expect(ws.closed).toBe(true);
|
|
269
|
+
expect(client.isConnected()).toBe(false);
|
|
270
|
+
ws.deliver({ method: 'E' });
|
|
271
|
+
expect(events).toBe(0);
|
|
272
|
+
});
|
|
273
|
+
it('a socket "close" event rejects pending commands', async () => {
|
|
274
|
+
const { client, ws } = await connected();
|
|
275
|
+
const pending = client.send('A');
|
|
276
|
+
ws.emit('close');
|
|
277
|
+
await expect(pending).rejects.toThrow('CDP connection closed');
|
|
278
|
+
expect(client.isConnected()).toBe(false);
|
|
279
|
+
});
|
|
280
|
+
it('a post-connect "error" flushes pending commands with that error', async () => {
|
|
281
|
+
const { client, ws } = await connected();
|
|
282
|
+
const pending = client.send('A');
|
|
283
|
+
ws.emit('error', new Error('EPIPE'));
|
|
284
|
+
await expect(pending).rejects.toThrow('EPIPE');
|
|
285
|
+
expect(client.isConnected()).toBe(false);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
describe('fetchTargets / fetchNewTarget', () => {
|
|
289
|
+
const realFetch = globalThis.fetch;
|
|
290
|
+
afterEach(() => {
|
|
291
|
+
globalThis.fetch = realFetch;
|
|
292
|
+
});
|
|
293
|
+
function stubFetch(impl) {
|
|
294
|
+
const fn = vi.fn((url, init) => Promise.resolve(impl(url, init)));
|
|
295
|
+
globalThis.fetch = fn;
|
|
296
|
+
return fn;
|
|
297
|
+
}
|
|
298
|
+
it('fetchTargets hits /json/list on the given port', async () => {
|
|
299
|
+
const fn = stubFetch(() => new Response(JSON.stringify([{ id: 'T1', type: 'page' }]), { status: 200 }));
|
|
300
|
+
await expect(fetchTargets(9333)).resolves.toEqual([{ id: 'T1', type: 'page' }]);
|
|
301
|
+
expect(fn.mock.calls[0][0]).toBe('http://127.0.0.1:9333/json/list');
|
|
302
|
+
});
|
|
303
|
+
it('fetchTargets throws on a non-OK response', async () => {
|
|
304
|
+
stubFetch(() => new Response('nope', { status: 500, statusText: 'Internal Server Error' }));
|
|
305
|
+
await expect(fetchTargets(9222)).rejects.toThrow('Failed to fetch targets: Internal Server Error');
|
|
306
|
+
});
|
|
307
|
+
it('fetchNewTarget uses PUT and percent-encodes the URL', async () => {
|
|
308
|
+
const fn = stubFetch(() => new Response(JSON.stringify({ id: 'T2' }), { status: 200 }));
|
|
309
|
+
await expect(fetchNewTarget(9222, 'https://x.test/a?b=1&c=2')).resolves.toEqual({ id: 'T2' });
|
|
310
|
+
const [url, init] = fn.mock.calls[0];
|
|
311
|
+
expect(init.method).toBe('PUT');
|
|
312
|
+
expect(url).toBe('http://127.0.0.1:9222/json/new?' + encodeURIComponent('https://x.test/a?b=1&c=2'));
|
|
313
|
+
// The query separators of the target URL must not leak into Chrome's own query.
|
|
314
|
+
expect(url.split('?').length).toBe(2);
|
|
315
|
+
});
|
|
316
|
+
it('fetchNewTarget throws on a non-OK response', async () => {
|
|
317
|
+
stubFetch(() => new Response('', { status: 405, statusText: 'Method Not Allowed' }));
|
|
318
|
+
await expect(fetchNewTarget(9222, 'about:blank')).rejects.toThrow('Failed to create target: Method Not Allowed');
|
|
319
|
+
});
|
|
320
|
+
it('rejects responses over the 10 MB body cap instead of parsing them', async () => {
|
|
321
|
+
const huge = JSON.stringify([{ pad: 'x'.repeat(11 * 1024 * 1024) }]);
|
|
322
|
+
stubFetch(() => new Response(huge, { status: 200 }));
|
|
323
|
+
await expect(fetchTargets(9222)).rejects.toThrow(/CDP response too large: \d+ bytes/);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
//# sourceMappingURL=cdp-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdp-client.test.js","sourceRoot":"","sources":["../../../src/__tests__/cdp-client.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-browser.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/close-browser.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* closeBrowser()'s cross-process PID-kill fallback (browser.ts) — previously
|
|
3
|
+
* had zero test coverage anywhere in this package (found in a review pass
|
|
4
|
+
* after commit c4847e22). Covers:
|
|
5
|
+
* - using a persisted PID when the in-process launchedPids map is empty
|
|
6
|
+
* (the always-true case for a fresh CLI invocation)
|
|
7
|
+
* - rejecting a persisted PID that is too old to trust (staleness bound)
|
|
8
|
+
* - a liveness check (process.kill(pid, 0)) gating the SIGKILL itself
|
|
9
|
+
*
|
|
10
|
+
* No real Chrome or child process is spawned: Browser.close is driven via a
|
|
11
|
+
* fake `ws` socket (same pattern as cdp-client.test.ts), and process.kill is
|
|
12
|
+
* spied on rather than actually signaling anything.
|
|
13
|
+
*/
|
|
14
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
15
|
+
import { mkdtemp, rm, mkdir, writeFile } from 'fs/promises';
|
|
16
|
+
import { join } from 'path';
|
|
17
|
+
import { tmpdir } from 'os';
|
|
18
|
+
let lastSocket = null;
|
|
19
|
+
class FakeWs {
|
|
20
|
+
url;
|
|
21
|
+
handlers = new Map();
|
|
22
|
+
constructor(url) {
|
|
23
|
+
this.url = url;
|
|
24
|
+
lastSocket = this;
|
|
25
|
+
}
|
|
26
|
+
on(event, fn) {
|
|
27
|
+
if (!this.handlers.has(event))
|
|
28
|
+
this.handlers.set(event, []);
|
|
29
|
+
this.handlers.get(event).push(fn);
|
|
30
|
+
}
|
|
31
|
+
emit(event, ...args) {
|
|
32
|
+
for (const fn of [...(this.handlers.get(event) ?? [])])
|
|
33
|
+
fn(...args);
|
|
34
|
+
}
|
|
35
|
+
/** When true, send() acknowledges the CDP command by delivering a matching
|
|
36
|
+
* empty result — the GRACEFUL path. Default false leaves it hanging so
|
|
37
|
+
* closeBrowser's own BROWSER_CLOSE_TIMEOUT_MS race settles it (ungraceful). */
|
|
38
|
+
autoAck = false;
|
|
39
|
+
send(data, cb) {
|
|
40
|
+
void cb;
|
|
41
|
+
if (!this.autoAck)
|
|
42
|
+
return;
|
|
43
|
+
const { id } = JSON.parse(data);
|
|
44
|
+
queueMicrotask(() => this.deliver({ id, result: {} }));
|
|
45
|
+
}
|
|
46
|
+
close() { }
|
|
47
|
+
deliver(msg) {
|
|
48
|
+
this.emit('message', Buffer.from(JSON.stringify(msg)));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
vi.mock('ws', () => ({ WebSocket: FakeWs }));
|
|
52
|
+
let tempDir;
|
|
53
|
+
let killSpy;
|
|
54
|
+
beforeEach(async () => {
|
|
55
|
+
vi.useFakeTimers();
|
|
56
|
+
lastSocket = null;
|
|
57
|
+
tempDir = await mkdtemp(join(tmpdir(), 'monobrowse-close-test-'));
|
|
58
|
+
vi.spyOn(process, 'cwd').mockReturnValue(tempDir);
|
|
59
|
+
killSpy = vi.spyOn(process, 'kill').mockImplementation(() => true);
|
|
60
|
+
});
|
|
61
|
+
afterEach(async () => {
|
|
62
|
+
vi.useRealTimers();
|
|
63
|
+
vi.restoreAllMocks();
|
|
64
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
65
|
+
});
|
|
66
|
+
async function writePersistedPort(port, pid, savedAt) {
|
|
67
|
+
const dir = join(tempDir, '.monomind', 'monobrowse');
|
|
68
|
+
await mkdir(dir, { recursive: true });
|
|
69
|
+
await writeFile(join(dir, 'active-port.json'), JSON.stringify({ port, pid, launched: true, savedAt }), 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
async function connectedClient(autoAck = false) {
|
|
72
|
+
vi.resetModules();
|
|
73
|
+
const { CdpClient } = await import('../browser/cdp.js');
|
|
74
|
+
const client = new CdpClient();
|
|
75
|
+
const p = client.connect('ws://127.0.0.1:9333/devtools/page/ABC');
|
|
76
|
+
lastSocket.autoAck = autoAck;
|
|
77
|
+
lastSocket.emit('open');
|
|
78
|
+
await p;
|
|
79
|
+
return client;
|
|
80
|
+
}
|
|
81
|
+
describe('#115 review follow-up: closeBrowser() cross-process PID-kill fallback', () => {
|
|
82
|
+
it('uses a fresh persisted PID (in-process map empty) and SIGKILLs it on an ungraceful close', async () => {
|
|
83
|
+
vi.resetModules();
|
|
84
|
+
const { closeBrowser, getLaunchedPid } = await import('../browser/browser.js');
|
|
85
|
+
const port = 9333;
|
|
86
|
+
await writePersistedPort(port, 54321, Date.now());
|
|
87
|
+
// Confirm the in-process map really is empty for this port (fresh module state).
|
|
88
|
+
expect(getLaunchedPid(port)).toBeUndefined();
|
|
89
|
+
const client = await connectedClient();
|
|
90
|
+
const closePromise = closeBrowser(client, port);
|
|
91
|
+
await vi.advanceTimersByTimeAsync(3000); // BROWSER_CLOSE_TIMEOUT_MS
|
|
92
|
+
await closePromise;
|
|
93
|
+
expect(killSpy).toHaveBeenCalledWith(54321, 0);
|
|
94
|
+
expect(killSpy).toHaveBeenCalledWith(54321, 'SIGKILL');
|
|
95
|
+
});
|
|
96
|
+
it('#124-review: does not trust a persisted PID older than the staleness bound', async () => {
|
|
97
|
+
vi.resetModules();
|
|
98
|
+
const { closeBrowser } = await import('../browser/browser.js');
|
|
99
|
+
const port = 9334;
|
|
100
|
+
const twoDaysAgo = Date.now() - 2 * 24 * 60 * 60 * 1000;
|
|
101
|
+
await writePersistedPort(port, 99999, twoDaysAgo);
|
|
102
|
+
const client = await connectedClient();
|
|
103
|
+
const closePromise = closeBrowser(client, port);
|
|
104
|
+
await vi.advanceTimersByTimeAsync(3000);
|
|
105
|
+
await closePromise;
|
|
106
|
+
expect(killSpy).not.toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
it('#124-review: a persisted PID that is no longer alive is not force-killed (liveness check via kill(pid,0))', async () => {
|
|
109
|
+
vi.resetModules();
|
|
110
|
+
const { closeBrowser } = await import('../browser/browser.js');
|
|
111
|
+
const port = 9335;
|
|
112
|
+
await writePersistedPort(port, 11111, Date.now());
|
|
113
|
+
killSpy.mockImplementation((_pid, signal) => {
|
|
114
|
+
if (signal === 0)
|
|
115
|
+
throw Object.assign(new Error('ESRCH'), { code: 'ESRCH' });
|
|
116
|
+
return true;
|
|
117
|
+
});
|
|
118
|
+
const client = await connectedClient();
|
|
119
|
+
const closePromise = closeBrowser(client, port);
|
|
120
|
+
await vi.advanceTimersByTimeAsync(3000);
|
|
121
|
+
await closePromise;
|
|
122
|
+
expect(killSpy).toHaveBeenCalledWith(11111, 0);
|
|
123
|
+
expect(killSpy).not.toHaveBeenCalledWith(11111, 'SIGKILL');
|
|
124
|
+
});
|
|
125
|
+
// The graceful path is what the monodesign detection driver actually takes,
|
|
126
|
+
// and it had no coverage: closeBrowser used to return on the Browser.close
|
|
127
|
+
// ack while Chrome was still exiting, holding its CDP port and its profile's
|
|
128
|
+
// singleton lock, with an unref'd 1s timer as the only force-kill (which
|
|
129
|
+
// never fired at all if the caller's process exited first).
|
|
130
|
+
it('graceful close waits for the process to actually exit, without killing it', async () => {
|
|
131
|
+
vi.resetModules();
|
|
132
|
+
const { closeBrowser } = await import('../browser/browser.js');
|
|
133
|
+
const port = 9337;
|
|
134
|
+
await writePersistedPort(port, 22222, Date.now());
|
|
135
|
+
let alive = true;
|
|
136
|
+
killSpy.mockImplementation((_pid, signal) => {
|
|
137
|
+
if (signal === 0 && !alive)
|
|
138
|
+
throw Object.assign(new Error('ESRCH'), { code: 'ESRCH' });
|
|
139
|
+
return true;
|
|
140
|
+
});
|
|
141
|
+
const client = await connectedClient(true);
|
|
142
|
+
const closePromise = closeBrowser(client, port);
|
|
143
|
+
// Still running a moment after the ack — close() must NOT have resolved.
|
|
144
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
145
|
+
let settled = false;
|
|
146
|
+
void closePromise.then(() => {
|
|
147
|
+
settled = true;
|
|
148
|
+
});
|
|
149
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
150
|
+
expect(settled).toBe(false);
|
|
151
|
+
alive = false; // Chrome finishes exiting
|
|
152
|
+
await vi.advanceTimersByTimeAsync(200);
|
|
153
|
+
await closePromise;
|
|
154
|
+
expect(killSpy).not.toHaveBeenCalledWith(22222, 'SIGKILL');
|
|
155
|
+
});
|
|
156
|
+
it('graceful close force-kills a process that never exits', async () => {
|
|
157
|
+
vi.resetModules();
|
|
158
|
+
const { closeBrowser } = await import('../browser/browser.js');
|
|
159
|
+
const port = 9338;
|
|
160
|
+
await writePersistedPort(port, 33333, Date.now());
|
|
161
|
+
const client = await connectedClient(true);
|
|
162
|
+
const closePromise = closeBrowser(client, port);
|
|
163
|
+
// The exit poll schedules one timer per tick, each from the previous
|
|
164
|
+
// tick's callback. How far a single advance carries through a chain like
|
|
165
|
+
// that is a fake-timer implementation detail that differs by Node version
|
|
166
|
+
// (runAllTimersAsync hung this test on Node 22 while passing on 26), so
|
|
167
|
+
// step the clock until the promise settles instead of assuming.
|
|
168
|
+
let settled = false;
|
|
169
|
+
void closePromise.then(() => {
|
|
170
|
+
settled = true;
|
|
171
|
+
});
|
|
172
|
+
for (let i = 0; i < 200 && !settled; i++)
|
|
173
|
+
await vi.advanceTimersByTimeAsync(100);
|
|
174
|
+
await closePromise;
|
|
175
|
+
expect(settled).toBe(true);
|
|
176
|
+
expect(killSpy).toHaveBeenCalledWith(33333, 'SIGKILL');
|
|
177
|
+
});
|
|
178
|
+
it('no persisted port file at all — closeBrowser is a no-op, no kill attempted', async () => {
|
|
179
|
+
vi.resetModules();
|
|
180
|
+
const { closeBrowser } = await import('../browser/browser.js');
|
|
181
|
+
const client = await connectedClient();
|
|
182
|
+
const closePromise = closeBrowser(client, 9336);
|
|
183
|
+
await vi.advanceTimersByTimeAsync(3000);
|
|
184
|
+
await closePromise;
|
|
185
|
+
expect(killSpy).not.toHaveBeenCalled();
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
//# sourceMappingURL=close-browser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-browser.test.js","sourceRoot":"","sources":["../../../src/__tests__/close-browser.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-log.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/console-log.test.ts"],"names":[],"mappings":""}
|