@playwright-repl/runner 0.21.2
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/README.md +116 -0
- package/dist/args.d.ts +16 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +48 -0
- package/dist/args.js.map +1 -0
- package/dist/bridge-utils.cjs +197 -0
- package/dist/bridge-utils.cjs.map +1 -0
- package/dist/bridge-utils.d.cts +30 -0
- package/dist/bridge-utils.d.cts.map +1 -0
- package/dist/browser.d.ts +12 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +40 -0
- package/dist/browser.js.map +1 -0
- package/dist/bundler.d.ts +6 -0
- package/dist/bundler.d.ts.map +1 -0
- package/dist/bundler.js +32 -0
- package/dist/bundler.js.map +1 -0
- package/dist/cdpPreload.cjs +44 -0
- package/dist/cdpPreload.cjs.map +1 -0
- package/dist/cdpPreload.d.cts +11 -0
- package/dist/cdpPreload.d.cts.map +1 -0
- package/dist/chrome-extension/background.js +233485 -0
- package/dist/chrome-extension/background.js.map +1 -0
- package/dist/chrome-extension/content/picker.js +279 -0
- package/dist/chrome-extension/content/recorder.js +475 -0
- package/dist/chrome-extension/devtools/console.html +17 -0
- package/dist/chrome-extension/devtools/console.js +28 -0
- package/dist/chrome-extension/devtools/console.js.map +1 -0
- package/dist/chrome-extension/devtools/devtools.html +8 -0
- package/dist/chrome-extension/devtools/devtools.js +7 -0
- package/dist/chrome-extension/devtools/devtools.js.map +1 -0
- package/dist/chrome-extension/icons/dramaturg_icon_128.png +0 -0
- package/dist/chrome-extension/icons/dramaturg_icon_16.png +0 -0
- package/dist/chrome-extension/icons/dramaturg_icon_32.png +0 -0
- package/dist/chrome-extension/icons/dramaturg_icon_48.png +0 -0
- package/dist/chrome-extension/index.css +1333 -0
- package/dist/chrome-extension/index.js +12462 -0
- package/dist/chrome-extension/index.js.map +1 -0
- package/dist/chrome-extension/index2.js +27327 -0
- package/dist/chrome-extension/index2.js.map +1 -0
- package/dist/chrome-extension/manifest.json +46 -0
- package/dist/chrome-extension/modulepreload-polyfill.js +30 -0
- package/dist/chrome-extension/modulepreload-polyfill.js.map +1 -0
- package/dist/chrome-extension/newtab/newtab.html +202 -0
- package/dist/chrome-extension/offscreen/offscreen.html +6 -0
- package/dist/chrome-extension/offscreen/offscreen.js +54 -0
- package/dist/chrome-extension/offscreen/offscreen.js.map +1 -0
- package/dist/chrome-extension/panel/panel.html +16 -0
- package/dist/chrome-extension/panel/panel.js +2210 -0
- package/dist/chrome-extension/panel/panel.js.map +1 -0
- package/dist/chrome-extension/preferences/preferences.html +14 -0
- package/dist/chrome-extension/preferences/preferences.js +102 -0
- package/dist/chrome-extension/preferences/preferences.js.map +1 -0
- package/dist/chrome-extension/settings.js +13 -0
- package/dist/chrome-extension/settings.js.map +1 -0
- package/dist/chrome-extension/sw-debugger-core.js +1127 -0
- package/dist/chrome-extension/sw-debugger-core.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +43 -0
- package/dist/cli.js.map +1 -0
- package/dist/compiler/classify.d.ts +13 -0
- package/dist/compiler/classify.d.ts.map +1 -0
- package/dist/compiler/classify.js +143 -0
- package/dist/compiler/classify.js.map +1 -0
- package/dist/compiler/index.d.ts +24 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +41 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/compiler/parser.d.ts +24 -0
- package/dist/compiler/parser.d.ts.map +1 -0
- package/dist/compiler/parser.js +77 -0
- package/dist/compiler/parser.js.map +1 -0
- package/dist/compiler/transform.d.ts +20 -0
- package/dist/compiler/transform.d.ts.map +1 -0
- package/dist/compiler/transform.js +36 -0
- package/dist/compiler/transform.js.map +1 -0
- package/dist/compiler.d.ts +24 -0
- package/dist/compiler.d.ts.map +1 -0
- package/dist/compiler.js +129 -0
- package/dist/compiler.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -0
- package/dist/discover.d.ts +5 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +46 -0
- package/dist/discover.js.map +1 -0
- package/dist/execute.d.ts +13 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +281 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/mode-detect.d.ts +21 -0
- package/dist/mode-detect.d.ts.map +1 -0
- package/dist/mode-detect.js +67 -0
- package/dist/mode-detect.js.map +1 -0
- package/dist/proxy-page.d.ts +32 -0
- package/dist/proxy-page.d.ts.map +1 -0
- package/dist/proxy-page.js +192 -0
- package/dist/proxy-page.js.map +1 -0
- package/dist/pw-cli.d.ts +12 -0
- package/dist/pw-cli.d.ts.map +1 -0
- package/dist/pw-cli.js +73 -0
- package/dist/pw-cli.js.map +1 -0
- package/dist/pw-launch.d.ts +15 -0
- package/dist/pw-launch.d.ts.map +1 -0
- package/dist/pw-launch.js +97 -0
- package/dist/pw-launch.js.map +1 -0
- package/dist/pw-preload.cjs +164 -0
- package/dist/pw-preload.cjs.map +1 -0
- package/dist/pw-preload.d.cts +15 -0
- package/dist/pw-preload.d.cts.map +1 -0
- package/dist/pw-repl-extension.d.ts +12 -0
- package/dist/pw-repl-extension.d.ts.map +1 -0
- package/dist/pw-repl-extension.js +100 -0
- package/dist/pw-repl-extension.js.map +1 -0
- package/dist/pw-repl.d.ts +12 -0
- package/dist/pw-repl.d.ts.map +1 -0
- package/dist/pw-repl.js +111 -0
- package/dist/pw-repl.js.map +1 -0
- package/dist/pw-worker.cjs +216 -0
- package/dist/pw-worker.cjs.map +1 -0
- package/dist/pw-worker.d.cts +13 -0
- package/dist/pw-worker.d.cts.map +1 -0
- package/dist/pw-worker.d.ts +11 -0
- package/dist/pw-worker.d.ts.map +1 -0
- package/dist/pw-worker.js +51 -0
- package/dist/pw-worker.js.map +1 -0
- package/dist/run-test.d.ts +22 -0
- package/dist/run-test.d.ts.map +1 -0
- package/dist/run-test.js +358 -0
- package/dist/run-test.js.map +1 -0
- package/dist/runner.d.ts +10 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +82 -0
- package/dist/runner.js.map +1 -0
- package/dist/shim/alias.d.ts +11 -0
- package/dist/shim/alias.d.ts.map +1 -0
- package/dist/shim/alias.js +24 -0
- package/dist/shim/alias.js.map +1 -0
- package/dist/shim/framework.d.ts +11 -0
- package/dist/shim/framework.d.ts.map +1 -0
- package/dist/shim/framework.js +11 -0
- package/dist/shim/framework.js.map +1 -0
- package/dist/shim/test-runner-node.d.ts +49 -0
- package/dist/shim/test-runner-node.d.ts.map +1 -0
- package/dist/shim/test-runner-node.js +191 -0
- package/dist/shim/test-runner-node.js.map +1 -0
- package/dist/shim/test-runner.d.ts +44 -0
- package/dist/shim/test-runner.d.ts.map +1 -0
- package/dist/shim/test-runner.js +181 -0
- package/dist/shim/test-runner.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# @playwright-repl/runner
|
|
2
|
+
|
|
3
|
+
Drop-in replacement for `npx playwright test` with context reuse. Keeps the browser open between tests — no teardown/recreate per test.
|
|
4
|
+
|
|
5
|
+
## Performance
|
|
6
|
+
|
|
7
|
+
Bridge mode sends test scripts directly to the browser, bypassing the Playwright test runner entirely. This eliminates the per-run overhead (worker startup, TypeScript compilation, fixture setup) that dominates single-test execution time in the IDE.
|
|
8
|
+
|
|
9
|
+
Node-mode tests that need server-side APIs fall back to the standard Playwright test runner, but reuse the existing browser via CDP instead of launching a new one.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -D @playwright-repl/runner
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Replace `npx playwright test` with `pw test`:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pw test # run all tests
|
|
21
|
+
pw test todomvc/ # run tests in a folder
|
|
22
|
+
pw test --workers 1 # single worker
|
|
23
|
+
pw test --reporter list # custom reporter
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
All Playwright CLI flags work — `pw` passes them through.
|
|
27
|
+
|
|
28
|
+
## How It Works
|
|
29
|
+
|
|
30
|
+
Standard Playwright creates a new browser context for every test. `pw test` reuses the same persistent browser context across tests in the same worker.
|
|
31
|
+
|
|
32
|
+
- **Bridge mode** — compiles the test with esbuild, sends it to the Chrome extension for in-browser execution. Bypasses the Playwright test runner for near-instant feedback in the IDE
|
|
33
|
+
- **Node mode** — falls back to standard Playwright for tests that use Node-only APIs (fs, net, etc.). Reuses the existing browser via CDP when available
|
|
34
|
+
- **Automatic routing** — static analysis detects which mode each test needs
|
|
35
|
+
|
|
36
|
+
## pw Commands
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pw test [files...] # run Playwright tests with context reuse
|
|
40
|
+
pw launch --port 9222 # launch Chrome with extension + CDP port
|
|
41
|
+
pw launch --port 9222 --bridge-port 9877 # custom bridge port
|
|
42
|
+
pw launch --port 9222 --headless # headless mode
|
|
43
|
+
pw repl --port 9222 # Node REPL with Playwright globals
|
|
44
|
+
pw repl --port 9222 script.js # run script, exit (browser stays alive)
|
|
45
|
+
pw repl-extension --bridge-port 9877 # REPL via extension bridge
|
|
46
|
+
pw close --port 9222 # close browser
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### pw repl
|
|
50
|
+
|
|
51
|
+
Lightweight Node REPL with `page`, `context`, `browser`, and `expect` as globals. Powered by `node:repl` — full JavaScript with tab completion and history.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pw launch --port 9222
|
|
55
|
+
pw repl --port 9222
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
pw> await page.goto('https://example.com')
|
|
60
|
+
pw> await page.title()
|
|
61
|
+
Example Domain
|
|
62
|
+
(3.2ms)
|
|
63
|
+
pw> await page.locator('a').count()
|
|
64
|
+
1
|
|
65
|
+
(12.4ms)
|
|
66
|
+
pw> 1 + 1
|
|
67
|
+
2
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### pw repl-extension
|
|
71
|
+
|
|
72
|
+
REPL that routes commands through the Chrome extension bridge. Useful for testing the extension path.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pw launch --port 9222 --bridge-port 9877
|
|
76
|
+
pw repl-extension --bridge-port 9877
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Options
|
|
80
|
+
|
|
81
|
+
| Option | Description |
|
|
82
|
+
|--------|-------------|
|
|
83
|
+
| `--port <n>` | Chrome CDP port (default: 9222) |
|
|
84
|
+
| `--bridge-port <n>` | BridgeServer WebSocket port (default: 9877) |
|
|
85
|
+
| `--headless` | Launch browser in headless mode |
|
|
86
|
+
|
|
87
|
+
All `pw test` options are passed through to Playwright.
|
|
88
|
+
|
|
89
|
+
## CI Setup
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
- name: Install
|
|
93
|
+
run: npm ci
|
|
94
|
+
|
|
95
|
+
- name: Install browsers
|
|
96
|
+
run: npx playwright install --with-deps chromium
|
|
97
|
+
|
|
98
|
+
- name: Run tests
|
|
99
|
+
run: npx pw test
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Compatibility
|
|
103
|
+
|
|
104
|
+
Works with standard `@playwright/test` tests. No changes needed to your test files.
|
|
105
|
+
|
|
106
|
+
**Supported:** All Playwright test features — fixtures, assertions, test.describe, test.beforeEach, etc.
|
|
107
|
+
|
|
108
|
+
**Bridge mode limitations:** Tests that use Node-only APIs (`fs`, `net`, `child_process`) automatically fall back to Node mode.
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
cd packages/runner
|
|
114
|
+
pnpm run build
|
|
115
|
+
pnpm run test
|
|
116
|
+
```
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parser.
|
|
3
|
+
* Matches Playwright Test's argument format.
|
|
4
|
+
*/
|
|
5
|
+
export interface CliOptions {
|
|
6
|
+
config: string;
|
|
7
|
+
grep?: string;
|
|
8
|
+
headed: boolean;
|
|
9
|
+
forceNode?: boolean;
|
|
10
|
+
workers?: number;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
retries?: number;
|
|
13
|
+
filter?: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function parseArgs(args: string[]): CliOptions;
|
|
16
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA2CpD"}
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parser.
|
|
3
|
+
* Matches Playwright Test's argument format.
|
|
4
|
+
*/
|
|
5
|
+
export function parseArgs(args) {
|
|
6
|
+
const opts = {
|
|
7
|
+
config: 'playwright.config.ts',
|
|
8
|
+
headed: false,
|
|
9
|
+
};
|
|
10
|
+
const filter = [];
|
|
11
|
+
for (let i = 0; i < args.length; i++) {
|
|
12
|
+
const arg = args[i];
|
|
13
|
+
switch (arg) {
|
|
14
|
+
case '-c':
|
|
15
|
+
case '--config':
|
|
16
|
+
opts.config = args[++i];
|
|
17
|
+
break;
|
|
18
|
+
case '-g':
|
|
19
|
+
case '--grep':
|
|
20
|
+
opts.grep = args[++i];
|
|
21
|
+
break;
|
|
22
|
+
case '--headed':
|
|
23
|
+
opts.headed = true;
|
|
24
|
+
break;
|
|
25
|
+
case '--node':
|
|
26
|
+
opts.forceNode = true;
|
|
27
|
+
break;
|
|
28
|
+
case '-j':
|
|
29
|
+
case '--workers':
|
|
30
|
+
opts.workers = parseInt(args[++i], 10);
|
|
31
|
+
break;
|
|
32
|
+
case '--timeout':
|
|
33
|
+
opts.timeout = parseInt(args[++i], 10);
|
|
34
|
+
break;
|
|
35
|
+
case '--retries':
|
|
36
|
+
opts.retries = parseInt(args[++i], 10);
|
|
37
|
+
break;
|
|
38
|
+
default:
|
|
39
|
+
if (!arg.startsWith('-')) {
|
|
40
|
+
filter.push(arg);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (filter.length > 0)
|
|
45
|
+
opts.filter = filter;
|
|
46
|
+
return opts;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,IAAI,GAAe;QACvB,MAAM,EAAE,sBAAsB;QAC9B,MAAM,EAAE,KAAK;KACd,CAAC;IACF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,IAAI,CAAC;YACV,KAAK,UAAU;gBACb,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBACxB,MAAM;YACR,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ;gBACX,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtB,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;gBACtB,MAAM;YACR,KAAK,IAAI,CAAC;YACV,KAAK,WAAW;gBACd,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvC,MAAM;YACR,KAAK,WAAW;gBACd,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvC,MAAM;YACR,KAAK,WAAW;gBACd,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvC,MAAM;YACR;gBACE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACzB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnB,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IAC5C,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* bridge-utils — shared utilities for bridge-mode test execution.
|
|
4
|
+
*
|
|
5
|
+
* Used by the VS Code extension for direct bridge execution.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.needsNode = needsNode;
|
|
9
|
+
exports.compile = compile;
|
|
10
|
+
exports.parseAllResults = parseAllResults;
|
|
11
|
+
exports.findResultByName = findResultByName;
|
|
12
|
+
exports.findResultByIndex = findResultByIndex;
|
|
13
|
+
const fs = require("fs");
|
|
14
|
+
const path = require("path");
|
|
15
|
+
// ─── Node API detection ───
|
|
16
|
+
const NODE_API_PATTERNS = [
|
|
17
|
+
// Node built-in modules
|
|
18
|
+
/\brequire\s*\(\s*['"]fs['"]\)/,
|
|
19
|
+
/\brequire\s*\(\s*['"]path['"]\)/,
|
|
20
|
+
/\brequire\s*\(\s*['"]child_process['"]\)/,
|
|
21
|
+
/\brequire\s*\(\s*['"]os['"]\)/,
|
|
22
|
+
/\brequire\s*\(\s*['"]net['"]\)/,
|
|
23
|
+
/\brequire\s*\(\s*['"]http['"]\)/,
|
|
24
|
+
/\brequire\s*\(\s*['"]https['"]\)/,
|
|
25
|
+
/\brequire\s*\(\s*['"]crypto['"]\)/,
|
|
26
|
+
/\bfrom\s+['"]fs['"]/,
|
|
27
|
+
/\bfrom\s+['"]path['"]/,
|
|
28
|
+
/\bfrom\s+['"]child_process['"]/,
|
|
29
|
+
/\bfrom\s+['"]node:/,
|
|
30
|
+
// Node globals
|
|
31
|
+
/\bprocess\.env\b/,
|
|
32
|
+
/\bprocess\.cwd\b/,
|
|
33
|
+
/\b__dirname\b/,
|
|
34
|
+
/\b__filename\b/,
|
|
35
|
+
/\bBuffer\.\b/,
|
|
36
|
+
// Playwright APIs that need Node (callbacks, non-serializable)
|
|
37
|
+
/\.route\s*\(/,
|
|
38
|
+
/\.unroute\s*\(/,
|
|
39
|
+
/\.routeFromHAR\s*\(/,
|
|
40
|
+
/\.waitForEvent\s*\(/,
|
|
41
|
+
/\.waitForResponse\s*\(/,
|
|
42
|
+
/\.waitForRequest\s*\(/,
|
|
43
|
+
/\.\$eval\s*\(/,
|
|
44
|
+
/\.\$\$eval\s*\(/,
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* Check if a test file (and its local imports) uses Node APIs
|
|
48
|
+
* that can't be executed in the bridge (Chrome extension).
|
|
49
|
+
*/
|
|
50
|
+
function needsNode(filePath) {
|
|
51
|
+
const checked = new Set();
|
|
52
|
+
function check(file) {
|
|
53
|
+
if (checked.has(file))
|
|
54
|
+
return false;
|
|
55
|
+
checked.add(file);
|
|
56
|
+
let source;
|
|
57
|
+
try {
|
|
58
|
+
source = fs.readFileSync(file, 'utf-8');
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
for (const pattern of NODE_API_PATTERNS) {
|
|
64
|
+
if (pattern.test(source))
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
const importRe = /(?:import|from)\s+['"](\.[^'"]+)['"]/g;
|
|
68
|
+
let m;
|
|
69
|
+
while ((m = importRe.exec(source)) !== null) {
|
|
70
|
+
const dir = path.dirname(file);
|
|
71
|
+
const candidates = [
|
|
72
|
+
path.resolve(dir, m[1]),
|
|
73
|
+
path.resolve(dir, m[1] + '.ts'),
|
|
74
|
+
path.resolve(dir, m[1] + '.js'),
|
|
75
|
+
];
|
|
76
|
+
for (const c of candidates) {
|
|
77
|
+
if (fs.existsSync(c) && check(c))
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return check(filePath);
|
|
84
|
+
}
|
|
85
|
+
// ─── Compile ───
|
|
86
|
+
/**
|
|
87
|
+
* Bundle a test file into an IIFE string that can be sent to the bridge.
|
|
88
|
+
* Uses esbuild with an alias plugin to replace @playwright/test with the bridge shim.
|
|
89
|
+
*/
|
|
90
|
+
async function compile(testFilePath) {
|
|
91
|
+
const esbuild = require('esbuild');
|
|
92
|
+
const testDir = path.dirname(testFilePath);
|
|
93
|
+
const testFileName = path.basename(testFilePath);
|
|
94
|
+
const shimPath = path.resolve(__dirname, 'shim', 'alias.ts');
|
|
95
|
+
const shimPathJs = shimPath.replace('.ts', '.js');
|
|
96
|
+
const aliasPath = fs.existsSync(shimPath) ? shimPath : shimPathJs;
|
|
97
|
+
const plugin = {
|
|
98
|
+
name: 'pw-bridge',
|
|
99
|
+
setup(build) {
|
|
100
|
+
build.onResolve({ filter: /^__entry__$/ }, () => ({ path: '__entry__', namespace: 'entry' }));
|
|
101
|
+
build.onLoad({ filter: /.*/, namespace: 'entry' }, () => ({
|
|
102
|
+
contents: 'import "./' + testFileName + '";',
|
|
103
|
+
resolveDir: testDir,
|
|
104
|
+
loader: 'ts',
|
|
105
|
+
}));
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
const result = await esbuild.build({
|
|
109
|
+
entryPoints: ['__entry__'],
|
|
110
|
+
bundle: true,
|
|
111
|
+
write: false,
|
|
112
|
+
format: 'iife',
|
|
113
|
+
platform: 'neutral',
|
|
114
|
+
plugins: [plugin],
|
|
115
|
+
alias: { '@playwright/test': aliasPath },
|
|
116
|
+
});
|
|
117
|
+
return result.outputFiles[0].text;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Parse all test results from bridge output text.
|
|
121
|
+
* Returns an array of results in order of appearance.
|
|
122
|
+
*/
|
|
123
|
+
function parseAllResults(text) {
|
|
124
|
+
const lines = text.split('\n');
|
|
125
|
+
const results = [];
|
|
126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
127
|
+
const line = lines[i];
|
|
128
|
+
const passMatch = line.match(/^\s*[✓✔]\s+(.+?)\s+\((\d+)ms\)$/);
|
|
129
|
+
if (passMatch) {
|
|
130
|
+
results.push({ status: 'passed', duration: parseInt(passMatch[2]), errors: [] });
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const failMatch = line.match(/^\s*[✗✘]\s+(.+?)(?:\s+\((\d+)ms\))?$/);
|
|
134
|
+
if (failMatch) {
|
|
135
|
+
const dur = failMatch[2] ? parseInt(failMatch[2]) : 0;
|
|
136
|
+
const errLine = lines[i + 1] || '';
|
|
137
|
+
results.push({ status: 'failed', duration: dur, errors: [{ message: errLine.trim() }] });
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const skipMatch = line.match(/^\s*-\s+(.+?)\s+\(skipped\)$/);
|
|
141
|
+
if (skipMatch) {
|
|
142
|
+
results.push({ status: 'skipped', duration: 0, errors: [] });
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return results;
|
|
147
|
+
}
|
|
148
|
+
function findResultByName(lines, testName) {
|
|
149
|
+
for (let i = 0; i < lines.length; i++) {
|
|
150
|
+
const line = lines[i];
|
|
151
|
+
const passMatch = line.match(/^\s*[✓✔]\s+(.+?)\s+\(\d+ms\)$/);
|
|
152
|
+
if (passMatch && passMatch[1] === testName) {
|
|
153
|
+
const dur = line.match(/\((\d+)ms\)/);
|
|
154
|
+
return { status: 'passed', duration: dur ? parseInt(dur[1]) : 0, errors: [] };
|
|
155
|
+
}
|
|
156
|
+
const failMatch = line.match(/^\s*[✗✘]\s+(.+?)\s+\(\d+ms\)$/);
|
|
157
|
+
if (failMatch && failMatch[1] === testName) {
|
|
158
|
+
const dur = line.match(/\((\d+)ms\)/);
|
|
159
|
+
const errLine = lines[i + 1] || '';
|
|
160
|
+
return { status: 'failed', duration: dur ? parseInt(dur[1]) : 0, errors: [{ message: errLine.trim() }] };
|
|
161
|
+
}
|
|
162
|
+
const skipMatch = line.match(/^\s*-\s+(.+?)\s+\(skipped\)$/);
|
|
163
|
+
if (skipMatch && skipMatch[1] === testName) {
|
|
164
|
+
return { status: 'skipped', duration: 0, errors: [] };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return { status: 'failed', duration: 0, errors: [{ message: 'Test result not found' }] };
|
|
168
|
+
}
|
|
169
|
+
function findResultByIndex(lines, idx) {
|
|
170
|
+
let currentIdx = -1;
|
|
171
|
+
for (let i = 0; i < lines.length; i++) {
|
|
172
|
+
const line = lines[i];
|
|
173
|
+
if (line.match(/^\s*[✓✔]/)) {
|
|
174
|
+
currentIdx++;
|
|
175
|
+
if (currentIdx === idx) {
|
|
176
|
+
const dur = line.match(/\((\d+)ms\)/);
|
|
177
|
+
return { status: 'passed', duration: dur ? parseInt(dur[1]) : 0, errors: [] };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else if (line.match(/^\s*[✗✘]/)) {
|
|
181
|
+
currentIdx++;
|
|
182
|
+
if (currentIdx === idx) {
|
|
183
|
+
const dur = line.match(/\((\d+)ms\)/);
|
|
184
|
+
const errLine = lines[i + 1] || '';
|
|
185
|
+
return { status: 'failed', duration: dur ? parseInt(dur[1]) : 0, errors: [{ message: errLine.trim() }] };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (line.match(/^\s*-.*\(skipped\)/)) {
|
|
189
|
+
currentIdx++;
|
|
190
|
+
if (currentIdx === idx) {
|
|
191
|
+
return { status: 'skipped', duration: 0, errors: [] };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { status: 'failed', duration: 0, errors: [{ message: 'Test result not found' }] };
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=bridge-utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-utils.cjs","sourceRoot":"","sources":["../src/bridge-utils.cts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bridge-utils — shared utilities for bridge-mode test execution.
|
|
3
|
+
*
|
|
4
|
+
* Used by the VS Code extension for direct bridge execution.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check if a test file (and its local imports) uses Node APIs
|
|
8
|
+
* that can't be executed in the bridge (Chrome extension).
|
|
9
|
+
*/
|
|
10
|
+
export declare function needsNode(filePath: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Bundle a test file into an IIFE string that can be sent to the bridge.
|
|
13
|
+
* Uses esbuild with an alias plugin to replace @playwright/test with the bridge shim.
|
|
14
|
+
*/
|
|
15
|
+
export declare function compile(testFilePath: string): Promise<string>;
|
|
16
|
+
export interface TestResultEntry {
|
|
17
|
+
status: string;
|
|
18
|
+
duration: number;
|
|
19
|
+
errors: {
|
|
20
|
+
message: string;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse all test results from bridge output text.
|
|
25
|
+
* Returns an array of results in order of appearance.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseAllResults(text: string): TestResultEntry[];
|
|
28
|
+
export declare function findResultByName(lines: string[], testName: string): TestResultEntry;
|
|
29
|
+
export declare function findResultByIndex(lines: string[], idx: number): TestResultEntry;
|
|
30
|
+
//# sourceMappingURL=bridge-utils.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-utils.d.cts","sourceRoot":"","sources":["../src/bridge-utils.cts"],"names":[],"mappings":"AAAA;;;;GAIG;AAsCH;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgCnD;AAID;;;GAGG;AACH,wBAAsB,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiCnE;AAID,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CA0B/D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAoBnF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAyB/E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launch Chromium with playwright-crx extension.
|
|
3
|
+
* Sets the bridge port in chrome.storage so the offscreen doc connects to it.
|
|
4
|
+
*/
|
|
5
|
+
export declare function launchBrowser(opts: {
|
|
6
|
+
headed: boolean;
|
|
7
|
+
bridgePort: number;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
context: any;
|
|
10
|
+
page: any;
|
|
11
|
+
}>;
|
|
12
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;;;GAkChF"}
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launch Chromium with playwright-crx extension.
|
|
3
|
+
* Sets the bridge port in chrome.storage so the offscreen doc connects to it.
|
|
4
|
+
*/
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
export async function launchBrowser(opts) {
|
|
10
|
+
const require = createRequire(__filename);
|
|
11
|
+
// Find extension dist path
|
|
12
|
+
const extPkgPath = require.resolve('@playwright-repl/extension/package.json');
|
|
13
|
+
const extPath = path.resolve(path.dirname(extPkgPath), 'dist');
|
|
14
|
+
// Launch Chromium with extension
|
|
15
|
+
const pw = require('@playwright/test');
|
|
16
|
+
const context = await pw.chromium.launchPersistentContext('', {
|
|
17
|
+
channel: 'chromium',
|
|
18
|
+
headless: !opts.headed,
|
|
19
|
+
args: [
|
|
20
|
+
`--disable-extensions-except=${extPath}`,
|
|
21
|
+
`--load-extension=${extPath}`,
|
|
22
|
+
'--no-first-run',
|
|
23
|
+
'--no-default-browser-check',
|
|
24
|
+
'--disable-background-timer-throttling',
|
|
25
|
+
'--disable-infobars',
|
|
26
|
+
],
|
|
27
|
+
});
|
|
28
|
+
// Set bridge port in chrome.storage so offscreen doc connects to it
|
|
29
|
+
// (same approach as E2E bridge tests)
|
|
30
|
+
let sw = context.serviceWorkers()[0];
|
|
31
|
+
if (!sw)
|
|
32
|
+
sw = await context.waitForEvent('serviceworker', { timeout: 10000 });
|
|
33
|
+
const extensionId = sw.url().split('/')[2];
|
|
34
|
+
const page = context.pages()[0] || await context.newPage();
|
|
35
|
+
await page.goto(`chrome-extension://${extensionId}/panel/panel.html`);
|
|
36
|
+
await page.evaluate((port) => globalThis.chrome.storage.local.set({ bridgePort: port }), opts.bridgePort);
|
|
37
|
+
await page.goto('about:blank');
|
|
38
|
+
return { context, page };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAA6C;IAC/E,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAE1C,2BAA2B;IAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IAE/D,iCAAiC;IACjC,MAAM,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,EAAE;QAC5D,OAAO,EAAE,UAAU;QACnB,QAAQ,EAAE,CAAC,IAAI,CAAC,MAAM;QACtB,IAAI,EAAE;YACJ,+BAA+B,OAAO,EAAE;YACxC,oBAAoB,OAAO,EAAE;YAC7B,gBAAgB;YAChB,4BAA4B;YAC5B,uCAAuC;YACvC,oBAAoB;SACrB;KACF,CAAC,CAAC;IAEH,oEAAoE;IACpE,sCAAsC;IACtC,IAAI,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE;QAAE,EAAE,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3D,MAAM,IAAI,CAAC,IAAI,CAAC,sBAAsB,WAAW,mBAAmB,CAAC,CAAC;IACtE,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAY,EAAE,EAAE,CAAE,UAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3H,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE/B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB1E"}
|
package/dist/bundler.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundle a test file for browser mode execution.
|
|
3
|
+
* Same approach as packages/vscode/src/bundler.ts — IIFE + shim.
|
|
4
|
+
*/
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
export async function bundleTestFile(testFilePath) {
|
|
10
|
+
const esbuild = await import('esbuild');
|
|
11
|
+
// In dev: resolve from src/. In dist: resolve from dist/.
|
|
12
|
+
// esbuild can compile .ts directly, so point to source.
|
|
13
|
+
let shimPath = path.resolve(path.dirname(__filename), 'shim/test-runner.ts');
|
|
14
|
+
if (!fs.existsSync(shimPath)) {
|
|
15
|
+
shimPath = path.resolve(path.dirname(__filename), 'shim/test-runner.js');
|
|
16
|
+
}
|
|
17
|
+
const result = await esbuild.build({
|
|
18
|
+
entryPoints: [testFilePath],
|
|
19
|
+
bundle: true,
|
|
20
|
+
write: false,
|
|
21
|
+
format: 'iife',
|
|
22
|
+
globalName: '__tests',
|
|
23
|
+
platform: 'browser',
|
|
24
|
+
alias: {
|
|
25
|
+
'@playwright/test': shimPath,
|
|
26
|
+
},
|
|
27
|
+
external: ['fs', 'path', 'child_process', 'os', 'crypto', 'util', 'stream', 'events', 'net', 'http', 'https'],
|
|
28
|
+
});
|
|
29
|
+
const bundledCode = result.outputFiles[0].text;
|
|
30
|
+
return `${bundledCode}\nawait globalThis.__runTests();\n`;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=bundler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundler.js","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,YAAoB;IACvD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,0DAA0D;IAC1D,wDAAwD;IACxD,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAC7E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAC3E,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;QACjC,WAAW,EAAE,CAAC,YAAY,CAAC;QAC3B,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;QACd,UAAU,EAAE,SAAS;QACrB,QAAQ,EAAE,SAAS;QACnB,KAAK,EAAE;YACL,kBAAkB,EAAE,QAAQ;SAC7B;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC;KAC9G,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,OAAO,GAAG,WAAW,oCAAoC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Preload script injected via NODE_OPTIONS --require.
|
|
4
|
+
*
|
|
5
|
+
* Patches chromium.connect() to use connectOverCDP() when the wsEndpoint
|
|
6
|
+
* is a CDP URL (contains /devtools/browser/). This allows the test runner
|
|
7
|
+
* to reuse the existing browser process without version mismatch errors.
|
|
8
|
+
*
|
|
9
|
+
* Safe no-op when connect() is called with a normal Playwright wsEndpoint.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const Module = require("module");
|
|
13
|
+
const origLoad = Module._load;
|
|
14
|
+
let patched = false;
|
|
15
|
+
Module._load = function (request, parent) {
|
|
16
|
+
const mod = origLoad.apply(this, arguments);
|
|
17
|
+
// Intercept playwright-core or @playwright/test to patch chromium.connect
|
|
18
|
+
if (!patched && (request === 'playwright-core' || request === '@playwright/test') && mod?.chromium?.connect && !mod.chromium.__pwReplPatched) {
|
|
19
|
+
patched = true;
|
|
20
|
+
Module._load = origLoad; // remove hook immediately
|
|
21
|
+
const origConnect = mod.chromium.connect.bind(mod.chromium);
|
|
22
|
+
mod.chromium.connect = async function (optionsOrWsEndpoint) {
|
|
23
|
+
const wsEndpoint = typeof optionsOrWsEndpoint === 'string'
|
|
24
|
+
? optionsOrWsEndpoint
|
|
25
|
+
: optionsOrWsEndpoint?.wsEndpoint;
|
|
26
|
+
// Only intercept CDP URLs (from --remote-debugging-port)
|
|
27
|
+
if (!wsEndpoint || !wsEndpoint.includes('/devtools/browser/'))
|
|
28
|
+
return origConnect(optionsOrWsEndpoint);
|
|
29
|
+
const browser = await mod.chromium.connectOverCDP(wsEndpoint);
|
|
30
|
+
// Reuse the persistent context so tests run in the same window
|
|
31
|
+
browser._newContextForReuse = async function () {
|
|
32
|
+
const contexts = browser.contexts();
|
|
33
|
+
return contexts[0] || await browser.newContext();
|
|
34
|
+
};
|
|
35
|
+
browser._disconnectFromReusedContext = async function () { };
|
|
36
|
+
// Don't let the test runner kill our shared browser
|
|
37
|
+
browser.close = async () => { };
|
|
38
|
+
return browser;
|
|
39
|
+
};
|
|
40
|
+
mod.chromium.__pwReplPatched = true;
|
|
41
|
+
}
|
|
42
|
+
return mod;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=cdpPreload.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdpPreload.cjs","sourceRoot":"","sources":["../src/cdpPreload.cts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAEH,iCAAkC;AAElC,MAAM,QAAQ,GAAI,MAAc,CAAC,KAAK,CAAC;AACvC,IAAI,OAAO,GAAG,KAAK,CAAC;AAEnB,MAAc,CAAC,KAAK,GAAG,UAAU,OAAe,EAAE,MAAe;IAChE,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAE5C,0EAA0E;IAC1E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,iBAAiB,IAAI,OAAO,KAAK,kBAAkB,CAAC,IAAI,GAAG,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC7I,OAAO,GAAG,IAAI,CAAC;QACd,MAAc,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,0BAA0B;QAE5D,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE5D,GAAG,CAAC,QAAQ,CAAC,OAAO,GAAG,KAAK,WAAU,mBAAwB;YAC5D,MAAM,UAAU,GAAG,OAAO,mBAAmB,KAAK,QAAQ;gBACxD,CAAC,CAAC,mBAAmB;gBACrB,CAAC,CAAC,mBAAmB,EAAE,UAAU,CAAC;YAEpC,yDAAyD;YACzD,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,oBAAoB,CAAC;gBAC3D,OAAO,WAAW,CAAC,mBAAmB,CAAC,CAAC;YAE1C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAE9D,+DAA+D;YAC/D,OAAO,CAAC,mBAAmB,GAAG,KAAK;gBACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACpC,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;YACnD,CAAC,CAAC;YACF,OAAO,CAAC,4BAA4B,GAAG,KAAK,eAAa,CAAC,CAAC;YAE3D,oDAAoD;YACpD,OAAO,CAAC,KAAK,GAAG,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;YAC/B,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QAEF,GAAG,CAAC,QAAQ,CAAC,eAAe,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preload script injected via NODE_OPTIONS --require.
|
|
3
|
+
*
|
|
4
|
+
* Patches chromium.connect() to use connectOverCDP() when the wsEndpoint
|
|
5
|
+
* is a CDP URL (contains /devtools/browser/). This allows the test runner
|
|
6
|
+
* to reuse the existing browser process without version mismatch errors.
|
|
7
|
+
*
|
|
8
|
+
* Safe no-op when connect() is called with a normal Playwright wsEndpoint.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cdpPreload.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdpPreload.d.cts","sourceRoot":"","sources":["../src/cdpPreload.cts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|