@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.
Files changed (162) hide show
  1. package/README.md +116 -0
  2. package/dist/args.d.ts +16 -0
  3. package/dist/args.d.ts.map +1 -0
  4. package/dist/args.js +48 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/bridge-utils.cjs +197 -0
  7. package/dist/bridge-utils.cjs.map +1 -0
  8. package/dist/bridge-utils.d.cts +30 -0
  9. package/dist/bridge-utils.d.cts.map +1 -0
  10. package/dist/browser.d.ts +12 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +40 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/bundler.d.ts +6 -0
  15. package/dist/bundler.d.ts.map +1 -0
  16. package/dist/bundler.js +32 -0
  17. package/dist/bundler.js.map +1 -0
  18. package/dist/cdpPreload.cjs +44 -0
  19. package/dist/cdpPreload.cjs.map +1 -0
  20. package/dist/cdpPreload.d.cts +11 -0
  21. package/dist/cdpPreload.d.cts.map +1 -0
  22. package/dist/chrome-extension/background.js +233485 -0
  23. package/dist/chrome-extension/background.js.map +1 -0
  24. package/dist/chrome-extension/content/picker.js +279 -0
  25. package/dist/chrome-extension/content/recorder.js +475 -0
  26. package/dist/chrome-extension/devtools/console.html +17 -0
  27. package/dist/chrome-extension/devtools/console.js +28 -0
  28. package/dist/chrome-extension/devtools/console.js.map +1 -0
  29. package/dist/chrome-extension/devtools/devtools.html +8 -0
  30. package/dist/chrome-extension/devtools/devtools.js +7 -0
  31. package/dist/chrome-extension/devtools/devtools.js.map +1 -0
  32. package/dist/chrome-extension/icons/dramaturg_icon_128.png +0 -0
  33. package/dist/chrome-extension/icons/dramaturg_icon_16.png +0 -0
  34. package/dist/chrome-extension/icons/dramaturg_icon_32.png +0 -0
  35. package/dist/chrome-extension/icons/dramaturg_icon_48.png +0 -0
  36. package/dist/chrome-extension/index.css +1333 -0
  37. package/dist/chrome-extension/index.js +12462 -0
  38. package/dist/chrome-extension/index.js.map +1 -0
  39. package/dist/chrome-extension/index2.js +27327 -0
  40. package/dist/chrome-extension/index2.js.map +1 -0
  41. package/dist/chrome-extension/manifest.json +46 -0
  42. package/dist/chrome-extension/modulepreload-polyfill.js +30 -0
  43. package/dist/chrome-extension/modulepreload-polyfill.js.map +1 -0
  44. package/dist/chrome-extension/newtab/newtab.html +202 -0
  45. package/dist/chrome-extension/offscreen/offscreen.html +6 -0
  46. package/dist/chrome-extension/offscreen/offscreen.js +54 -0
  47. package/dist/chrome-extension/offscreen/offscreen.js.map +1 -0
  48. package/dist/chrome-extension/panel/panel.html +16 -0
  49. package/dist/chrome-extension/panel/panel.js +2210 -0
  50. package/dist/chrome-extension/panel/panel.js.map +1 -0
  51. package/dist/chrome-extension/preferences/preferences.html +14 -0
  52. package/dist/chrome-extension/preferences/preferences.js +102 -0
  53. package/dist/chrome-extension/preferences/preferences.js.map +1 -0
  54. package/dist/chrome-extension/settings.js +13 -0
  55. package/dist/chrome-extension/settings.js.map +1 -0
  56. package/dist/chrome-extension/sw-debugger-core.js +1127 -0
  57. package/dist/chrome-extension/sw-debugger-core.js.map +1 -0
  58. package/dist/cli.d.ts +14 -0
  59. package/dist/cli.d.ts.map +1 -0
  60. package/dist/cli.js +43 -0
  61. package/dist/cli.js.map +1 -0
  62. package/dist/compiler/classify.d.ts +13 -0
  63. package/dist/compiler/classify.d.ts.map +1 -0
  64. package/dist/compiler/classify.js +143 -0
  65. package/dist/compiler/classify.js.map +1 -0
  66. package/dist/compiler/index.d.ts +24 -0
  67. package/dist/compiler/index.d.ts.map +1 -0
  68. package/dist/compiler/index.js +41 -0
  69. package/dist/compiler/index.js.map +1 -0
  70. package/dist/compiler/parser.d.ts +24 -0
  71. package/dist/compiler/parser.d.ts.map +1 -0
  72. package/dist/compiler/parser.js +77 -0
  73. package/dist/compiler/parser.js.map +1 -0
  74. package/dist/compiler/transform.d.ts +20 -0
  75. package/dist/compiler/transform.d.ts.map +1 -0
  76. package/dist/compiler/transform.js +36 -0
  77. package/dist/compiler/transform.js.map +1 -0
  78. package/dist/compiler.d.ts +24 -0
  79. package/dist/compiler.d.ts.map +1 -0
  80. package/dist/compiler.js +129 -0
  81. package/dist/compiler.js.map +1 -0
  82. package/dist/config.d.ts +6 -0
  83. package/dist/config.d.ts.map +1 -0
  84. package/dist/config.js +16 -0
  85. package/dist/config.js.map +1 -0
  86. package/dist/discover.d.ts +5 -0
  87. package/dist/discover.d.ts.map +1 -0
  88. package/dist/discover.js +46 -0
  89. package/dist/discover.js.map +1 -0
  90. package/dist/execute.d.ts +13 -0
  91. package/dist/execute.d.ts.map +1 -0
  92. package/dist/execute.js +281 -0
  93. package/dist/execute.js.map +1 -0
  94. package/dist/index.d.ts +3 -0
  95. package/dist/index.d.ts.map +1 -0
  96. package/dist/index.js +2 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/mode-detect.d.ts +21 -0
  99. package/dist/mode-detect.d.ts.map +1 -0
  100. package/dist/mode-detect.js +67 -0
  101. package/dist/mode-detect.js.map +1 -0
  102. package/dist/proxy-page.d.ts +32 -0
  103. package/dist/proxy-page.d.ts.map +1 -0
  104. package/dist/proxy-page.js +192 -0
  105. package/dist/proxy-page.js.map +1 -0
  106. package/dist/pw-cli.d.ts +12 -0
  107. package/dist/pw-cli.d.ts.map +1 -0
  108. package/dist/pw-cli.js +73 -0
  109. package/dist/pw-cli.js.map +1 -0
  110. package/dist/pw-launch.d.ts +15 -0
  111. package/dist/pw-launch.d.ts.map +1 -0
  112. package/dist/pw-launch.js +97 -0
  113. package/dist/pw-launch.js.map +1 -0
  114. package/dist/pw-preload.cjs +164 -0
  115. package/dist/pw-preload.cjs.map +1 -0
  116. package/dist/pw-preload.d.cts +15 -0
  117. package/dist/pw-preload.d.cts.map +1 -0
  118. package/dist/pw-repl-extension.d.ts +12 -0
  119. package/dist/pw-repl-extension.d.ts.map +1 -0
  120. package/dist/pw-repl-extension.js +100 -0
  121. package/dist/pw-repl-extension.js.map +1 -0
  122. package/dist/pw-repl.d.ts +12 -0
  123. package/dist/pw-repl.d.ts.map +1 -0
  124. package/dist/pw-repl.js +111 -0
  125. package/dist/pw-repl.js.map +1 -0
  126. package/dist/pw-worker.cjs +216 -0
  127. package/dist/pw-worker.cjs.map +1 -0
  128. package/dist/pw-worker.d.cts +13 -0
  129. package/dist/pw-worker.d.cts.map +1 -0
  130. package/dist/pw-worker.d.ts +11 -0
  131. package/dist/pw-worker.d.ts.map +1 -0
  132. package/dist/pw-worker.js +51 -0
  133. package/dist/pw-worker.js.map +1 -0
  134. package/dist/run-test.d.ts +22 -0
  135. package/dist/run-test.d.ts.map +1 -0
  136. package/dist/run-test.js +358 -0
  137. package/dist/run-test.js.map +1 -0
  138. package/dist/runner.d.ts +10 -0
  139. package/dist/runner.d.ts.map +1 -0
  140. package/dist/runner.js +82 -0
  141. package/dist/runner.js.map +1 -0
  142. package/dist/shim/alias.d.ts +11 -0
  143. package/dist/shim/alias.d.ts.map +1 -0
  144. package/dist/shim/alias.js +24 -0
  145. package/dist/shim/alias.js.map +1 -0
  146. package/dist/shim/framework.d.ts +11 -0
  147. package/dist/shim/framework.d.ts.map +1 -0
  148. package/dist/shim/framework.js +11 -0
  149. package/dist/shim/framework.js.map +1 -0
  150. package/dist/shim/test-runner-node.d.ts +49 -0
  151. package/dist/shim/test-runner-node.d.ts.map +1 -0
  152. package/dist/shim/test-runner-node.js +191 -0
  153. package/dist/shim/test-runner-node.js.map +1 -0
  154. package/dist/shim/test-runner.d.ts +44 -0
  155. package/dist/shim/test-runner.d.ts.map +1 -0
  156. package/dist/shim/test-runner.js +181 -0
  157. package/dist/shim/test-runner.js.map +1 -0
  158. package/dist/types.d.ts +41 -0
  159. package/dist/types.d.ts.map +1 -0
  160. package/dist/types.js +2 -0
  161. package/dist/types.js.map +1 -0
  162. 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
@@ -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"}
@@ -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,6 @@
1
+ /**
2
+ * Bundle a test file for browser mode execution.
3
+ * Same approach as packages/vscode/src/bundler.ts — IIFE + shim.
4
+ */
5
+ export declare function bundleTestFile(testFilePath: string): Promise<string>;
6
+ //# sourceMappingURL=bundler.d.ts.map
@@ -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"}
@@ -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"}