rebrowser-playwright-core 1.47.100 → 1.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/ThirdPartyNotices.txt +70 -384
- package/bin/reinstall_chrome_beta_linux.sh +10 -8
- package/bin/reinstall_chrome_stable_linux.sh +10 -8
- package/bin/reinstall_msedge_beta_linux.sh +11 -9
- package/bin/reinstall_msedge_dev_linux.sh +11 -9
- package/bin/reinstall_msedge_stable_linux.sh +11 -9
- package/browsers.json +24 -12
- package/lib/cli/program.js +49 -19
- package/lib/client/api.js +6 -0
- package/lib/client/browserContext.js +20 -2
- package/lib/client/channelOwner.js +6 -2
- package/lib/client/connection.js +3 -0
- package/lib/client/fetch.js +16 -21
- package/lib/client/jsHandle.js +0 -8
- package/lib/client/localUtils.js +1 -0
- package/lib/client/locator.js +7 -0
- package/lib/client/network.js +180 -17
- package/lib/client/page.js +25 -2
- package/lib/client/playwright.js +6 -3
- package/lib/client/tracing.js +29 -20
- package/lib/client/waiter.js +15 -11
- package/lib/generated/consoleApiSource.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +7 -0
- package/lib/generated/webSocketMockSource.js +7 -0
- package/lib/protocol/validator.js +103 -17
- package/lib/server/ariaSnapshot.js +33 -0
- package/lib/server/bidi/bidiBrowser.js +23 -8
- package/lib/server/bidi/bidiChromium.js +124 -0
- package/lib/server/bidi/bidiConnection.js +1 -3
- package/lib/server/bidi/bidiExecutionContext.js +0 -6
- package/lib/server/bidi/bidiFirefox.js +15 -21
- package/lib/server/bidi/bidiInput.js +16 -32
- package/lib/server/bidi/bidiNetworkManager.js +39 -5
- package/lib/server/bidi/bidiOverCdp.js +103 -0
- package/lib/server/bidi/bidiPage.js +98 -25
- package/lib/server/bidi/bidiPdf.js +140 -0
- package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
- package/lib/server/browser.js +13 -2
- package/lib/server/browserContext.js +6 -23
- package/lib/server/browserType.js +43 -12
- package/lib/server/chromium/chromium.js +9 -17
- package/lib/server/chromium/chromiumSwitches.js +3 -1
- package/lib/server/chromium/crBrowser.js +4 -3
- package/lib/server/chromium/crConnection.js +153 -0
- package/lib/server/chromium/crExecutionContext.js +0 -20
- package/lib/server/chromium/crPage.js +13 -7
- package/lib/server/chromium/videoRecorder.js +1 -1
- package/lib/server/codegen/csharp.js +12 -17
- package/lib/server/codegen/java.js +5 -8
- package/lib/server/codegen/javascript.js +29 -7
- package/lib/server/codegen/language.js +14 -2
- package/lib/server/codegen/python.js +13 -17
- package/lib/server/cookieStore.js +73 -0
- package/lib/server/debugController.js +10 -7
- package/lib/server/deviceDescriptorsSource.json +127 -127
- package/lib/server/dialog.js +1 -0
- package/lib/server/dispatchers/androidDispatcher.js +13 -2
- package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
- package/lib/server/dispatchers/debugControllerDispatcher.js +1 -1
- package/lib/server/dispatchers/dispatcher.js +1 -1
- package/lib/server/dispatchers/frameDispatcher.js +8 -1
- package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
- package/lib/server/dispatchers/pageDispatcher.js +9 -0
- package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
- package/lib/server/dispatchers/tracingDispatcher.js +10 -0
- package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
- package/lib/server/dom.js +79 -36
- package/lib/server/download.js +9 -2
- package/lib/server/fetch.js +105 -96
- package/lib/server/firefox/ffBrowser.js +6 -4
- package/lib/server/firefox/ffExecutionContext.js +0 -15
- package/lib/server/firefox/ffNetworkManager.js +1 -1
- package/lib/server/firefox/ffPage.js +6 -3
- package/lib/server/firefox/firefox.js +2 -13
- package/lib/server/frameSelectors.js +1 -1
- package/lib/server/frames.js +68 -67
- package/lib/server/har/harTracer.js +11 -0
- package/lib/server/index.js +0 -6
- package/lib/server/input.js +0 -1
- package/lib/server/javascript.js +0 -13
- package/lib/server/page.js +53 -9
- package/lib/server/playwright.js +5 -2
- package/lib/server/progress.js +0 -3
- package/lib/server/recorder/contextRecorder.js +33 -50
- package/lib/server/recorder/recorderApp.js +22 -25
- package/lib/server/recorder/recorderCollection.js +68 -79
- package/lib/server/recorder/recorderInTraceViewer.js +144 -0
- package/lib/server/recorder/recorderRunner.js +75 -97
- package/lib/server/recorder/recorderUtils.js +48 -6
- package/lib/server/recorder.js +87 -47
- package/lib/server/registry/index.js +154 -26
- package/lib/server/registry/nativeDeps.js +6 -3
- package/lib/server/socksClientCertificatesInterceptor.js +15 -3
- package/lib/server/trace/recorder/snapshotter.js +2 -12
- package/lib/server/trace/recorder/snapshotterInjected.js +21 -3
- package/lib/server/trace/recorder/tracing.js +127 -17
- package/lib/server/trace/test/inMemorySnapshotter.js +4 -4
- package/lib/server/trace/viewer/traceViewer.js +4 -6
- package/lib/server/webkit/webkit.js +1 -1
- package/lib/server/webkit/wkBrowser.js +8 -7
- package/lib/server/webkit/wkExecutionContext.js +0 -16
- package/lib/server/webkit/wkPage.js +11 -4
- package/lib/utils/comparators.js +12 -30
- package/lib/utils/crypto.js +1 -4
- package/lib/utils/happy-eyeballs.js +13 -0
- package/lib/utils/hostPlatform.js +8 -2
- package/lib/utils/httpServer.js +1 -0
- package/lib/utils/isomorphic/ariaSnapshot.js +267 -0
- package/lib/utils/isomorphic/locatorGenerators.js +30 -21
- package/lib/utils/isomorphic/locatorParser.js +2 -2
- package/lib/utils/isomorphic/recorderUtils.js +227 -0
- package/lib/utils/isomorphic/stringUtils.js +30 -0
- package/lib/utils/isomorphic/urlMatch.js +5 -1
- package/lib/utils/network.js +1 -1
- package/lib/utils/sequence.js +64 -0
- package/lib/utils/stackTrace.js +16 -3
- package/lib/utils/zones.js +32 -23
- package/lib/utilsBundle.js +4 -5
- package/lib/utilsBundleImpl/index.js +190 -33
- package/lib/vite/htmlReport/index.html +19 -16
- package/lib/vite/recorder/assets/codeMirrorModule-AFvV6hAs.js +24 -0
- package/lib/vite/recorder/assets/index-_cTWgVuJ.js +184 -0
- package/lib/vite/recorder/assets/{index-B-MT5gKo.css → index-iA1aAGZg.css} +1 -1
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-KatbITLF.js +24 -0
- package/lib/vite/traceViewer/assets/inspectorTab-DdpLd2bb.js +68 -0
- package/lib/vite/traceViewer/assets/workbench-CdYbzWFD.js +9 -0
- package/lib/vite/traceViewer/embedded.6m3UZh7r.js +2 -0
- package/lib/vite/traceViewer/embedded.html +5 -3
- package/lib/vite/traceViewer/index.WUV-8boJ.js +2 -0
- package/lib/vite/traceViewer/index.html +24 -5
- package/lib/vite/traceViewer/inspectorTab.DEOUW62d.css +1 -0
- package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
- package/lib/vite/traceViewer/recorder.OT2tVHgn.js +2 -0
- package/lib/vite/traceViewer/recorder.html +17 -0
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/uiMode.BZBTyvGn.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +6 -4
- package/lib/vite/traceViewer/{uiMode.D3cNFP6u.css → uiMode.voC1ZiOQ.css} +1 -1
- package/lib/vite/traceViewer/workbench.C-zR9ysA.css +1 -0
- package/package.json +1 -1
- package/types/protocol.d.ts +135 -16
- package/types/types.d.ts +2149 -965
- package/lib/generated/recorderSource.js +0 -7
- package/lib/third_party/diff_match_patch.js +0 -2222
- package/lib/vite/recorder/assets/codeMirrorModule-aW6Vz3gf.js +0 -24
- package/lib/vite/recorder/assets/index-DCpXOVIh.js +0 -47
- package/lib/vite/traceViewer/assets/codeMirrorModule-eFKCUIu2.js +0 -24
- package/lib/vite/traceViewer/assets/workbench-D0cirtfA.js +0 -72
- package/lib/vite/traceViewer/embedded.BkuvsLJp.js +0 -2
- package/lib/vite/traceViewer/index.C968kAiC.js +0 -2
- package/lib/vite/traceViewer/uiMode.BkFnr4V0.js +0 -10
- package/lib/vite/traceViewer/workbench.DjbIuxix.css +0 -1
- /package/lib/server/recorder/{recorderActions.js → recorderFrontend.js} +0 -0
|
@@ -8,15 +8,17 @@ if [[ $(arch) == "aarch64" ]]; then
|
|
|
8
8
|
exit 1
|
|
9
9
|
fi
|
|
10
10
|
|
|
11
|
-
if [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then
|
|
12
|
+
if [[ ! -f "/etc/os-release" ]]; then
|
|
13
|
+
echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
ID=$(bash -c 'source /etc/os-release && echo $ID')
|
|
18
|
+
if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then
|
|
19
|
+
echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
20
22
|
fi
|
|
21
23
|
|
|
22
24
|
# 1. make sure to remove old dev if any.
|
|
@@ -8,15 +8,17 @@ if [[ $(arch) == "aarch64" ]]; then
|
|
|
8
8
|
exit 1
|
|
9
9
|
fi
|
|
10
10
|
|
|
11
|
-
if [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
if [ -z "$PLAYWRIGHT_HOST_PLATFORM_OVERRIDE" ]; then
|
|
12
|
+
if [[ ! -f "/etc/os-release" ]]; then
|
|
13
|
+
echo "ERROR: cannot install on unknown linux distribution (/etc/os-release is missing)"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
ID=$(bash -c 'source /etc/os-release && echo $ID')
|
|
18
|
+
if [[ "${ID}" != "ubuntu" && "${ID}" != "debian" ]]; then
|
|
19
|
+
echo "ERROR: cannot install on $ID distribution - only Ubuntu and Debian are supported"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
20
22
|
fi
|
|
21
23
|
|
|
22
24
|
# 1. make sure to remove old stable if any.
|
package/browsers.json
CHANGED
|
@@ -3,31 +3,37 @@
|
|
|
3
3
|
"browsers": [
|
|
4
4
|
{
|
|
5
5
|
"name": "chromium",
|
|
6
|
-
"revision": "
|
|
6
|
+
"revision": "1148",
|
|
7
7
|
"installByDefault": true,
|
|
8
|
-
"browserVersion": "
|
|
8
|
+
"browserVersion": "131.0.6778.33"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "chromium-headless-shell",
|
|
12
|
+
"revision": "1148",
|
|
13
|
+
"installByDefault": true,
|
|
14
|
+
"browserVersion": "131.0.6778.33"
|
|
9
15
|
},
|
|
10
16
|
{
|
|
11
17
|
"name": "chromium-tip-of-tree",
|
|
12
|
-
"revision": "
|
|
18
|
+
"revision": "1277",
|
|
13
19
|
"installByDefault": false,
|
|
14
|
-
"browserVersion": "
|
|
20
|
+
"browserVersion": "132.0.6834.0"
|
|
15
21
|
},
|
|
16
22
|
{
|
|
17
23
|
"name": "firefox",
|
|
18
|
-
"revision": "
|
|
24
|
+
"revision": "1466",
|
|
19
25
|
"installByDefault": true,
|
|
20
|
-
"browserVersion": "
|
|
26
|
+
"browserVersion": "132.0"
|
|
21
27
|
},
|
|
22
28
|
{
|
|
23
29
|
"name": "firefox-beta",
|
|
24
|
-
"revision": "
|
|
30
|
+
"revision": "1465",
|
|
25
31
|
"installByDefault": false,
|
|
26
|
-
"browserVersion": "
|
|
32
|
+
"browserVersion": "132.0b8"
|
|
27
33
|
},
|
|
28
34
|
{
|
|
29
35
|
"name": "webkit",
|
|
30
|
-
"revision": "
|
|
36
|
+
"revision": "2104",
|
|
31
37
|
"installByDefault": true,
|
|
32
38
|
"revisionOverrides": {
|
|
33
39
|
"mac10.14": "1446",
|
|
@@ -35,14 +41,20 @@
|
|
|
35
41
|
"mac11": "1816",
|
|
36
42
|
"mac11-arm64": "1816",
|
|
37
43
|
"mac12": "2009",
|
|
38
|
-
"mac12-arm64": "2009"
|
|
44
|
+
"mac12-arm64": "2009",
|
|
45
|
+
"ubuntu20.04-x64": "2092",
|
|
46
|
+
"ubuntu20.04-arm64": "2092"
|
|
39
47
|
},
|
|
40
|
-
"browserVersion": "18.
|
|
48
|
+
"browserVersion": "18.2"
|
|
41
49
|
},
|
|
42
50
|
{
|
|
43
51
|
"name": "ffmpeg",
|
|
44
52
|
"revision": "1010",
|
|
45
|
-
"installByDefault": true
|
|
53
|
+
"installByDefault": true,
|
|
54
|
+
"revisionOverrides": {
|
|
55
|
+
"mac12": "1010",
|
|
56
|
+
"mac12-arm64": "1010"
|
|
57
|
+
}
|
|
46
58
|
},
|
|
47
59
|
{
|
|
48
60
|
"name": "android",
|
package/lib/cli/program.js
CHANGED
|
@@ -82,23 +82,41 @@ Examples:
|
|
|
82
82
|
function suggestedBrowsersToInstall() {
|
|
83
83
|
return _server.registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');
|
|
84
84
|
}
|
|
85
|
-
function
|
|
85
|
+
function defaultBrowsersToInstall(options) {
|
|
86
|
+
let executables = _server.registry.defaultExecutables();
|
|
87
|
+
if (options.noShell) executables = executables.filter(e => e.name !== 'chromium-headless-shell');
|
|
88
|
+
if (options.onlyShell) executables = executables.filter(e => e.name !== 'chromium');
|
|
89
|
+
return executables;
|
|
90
|
+
}
|
|
91
|
+
function checkBrowsersToInstall(args, options) {
|
|
92
|
+
if (options.noShell && options.onlyShell) throw new Error(`Only one of --no-shell and --only-shell can be specified`);
|
|
86
93
|
const faultyArguments = [];
|
|
87
94
|
const executables = [];
|
|
88
|
-
|
|
95
|
+
const handleArgument = arg => {
|
|
89
96
|
const executable = _server.registry.findExecutable(arg);
|
|
90
97
|
if (!executable || executable.installType === 'none') faultyArguments.push(arg);else executables.push(executable);
|
|
98
|
+
if ((executable === null || executable === void 0 ? void 0 : executable.browserName) === 'chromium') executables.push(_server.registry.findExecutable('ffmpeg'));
|
|
99
|
+
};
|
|
100
|
+
for (const arg of args) {
|
|
101
|
+
if (arg === 'chromium') {
|
|
102
|
+
if (!options.onlyShell) handleArgument('chromium');
|
|
103
|
+
if (!options.noShell) handleArgument('chromium-headless-shell');
|
|
104
|
+
} else {
|
|
105
|
+
handleArgument(arg);
|
|
106
|
+
}
|
|
91
107
|
}
|
|
92
108
|
if (faultyArguments.length) throw new Error(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);
|
|
93
109
|
return executables;
|
|
94
110
|
}
|
|
95
|
-
_utilsBundle.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').option('--dry-run', 'do not execute installation, only print information').option('--force', 'force reinstall of stable browser channels').action(async function (args, options) {
|
|
111
|
+
_utilsBundle.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').option('--dry-run', 'do not execute installation, only print information').option('--force', 'force reinstall of stable browser channels').option('--only-shell', 'only install headless shell when installing chromium').option('--no-shell', 'do not install chromium headless shell').action(async function (args, options) {
|
|
112
|
+
// For '--no-shell' option, commander sets `shell: false` instead.
|
|
113
|
+
if (options.shell === false) options.noShell = true;
|
|
96
114
|
if ((0, _utils.isLikelyNpxGlobal)()) {
|
|
97
115
|
console.error((0, _utils.wrapInASCIIBox)([`WARNING: It looks like you are running 'npx playwright install' without first`, `installing your project's dependencies.`, ``, `To avoid unexpected behavior, please install your dependencies first, and`, `then run Playwright's install command:`, ``, ` npm install`, ` npx playwright install`, ``, `If your project does not yet depend on Playwright, first install the`, `applicable npm package (most commonly @playwright/test), and`, `then run Playwright's install command to download the browsers:`, ``, ` npm install @playwright/test`, ` npx playwright install`, ``].join('\n'), 1));
|
|
98
116
|
}
|
|
99
117
|
try {
|
|
100
118
|
const hasNoArguments = !args.length;
|
|
101
|
-
const executables = hasNoArguments ?
|
|
119
|
+
const executables = hasNoArguments ? defaultBrowsersToInstall(options) : checkBrowsersToInstall(args, options);
|
|
102
120
|
if (options.withDeps) await _server.registry.installDeps(executables, !!options.dryRun);
|
|
103
121
|
if (options.dryRun) {
|
|
104
122
|
for (const executable of executables) {
|
|
@@ -146,7 +164,7 @@ _utilsBundle.program.command('uninstall').description('Removes browsers used by
|
|
|
146
164
|
});
|
|
147
165
|
_utilsBundle.program.command('install-deps [browser...]').description('install dependencies necessary to run browsers (will ask for sudo permissions)').option('--dry-run', 'Do not execute installation commands, only print them').action(async function (args, options) {
|
|
148
166
|
try {
|
|
149
|
-
if (!args.length) await _server.registry.installDeps(
|
|
167
|
+
if (!args.length) await _server.registry.installDeps(defaultBrowsersToInstall({}), !!options.dryRun);else await _server.registry.installDeps(checkBrowsersToInstall(args, {}), !!options.dryRun);
|
|
150
168
|
} catch (e) {
|
|
151
169
|
console.log(`Failed to install browser dependencies\n${e}`);
|
|
152
170
|
(0, _utils.gracefullyProcessExitDoNotHang)(1);
|
|
@@ -238,13 +256,10 @@ _utilsBundle.program.command('show-trace [trace...]').option('-b, --browser <bro
|
|
|
238
256
|
Examples:
|
|
239
257
|
|
|
240
258
|
$ show-trace https://example.com/trace.zip`);
|
|
241
|
-
async function launchContext(options,
|
|
259
|
+
async function launchContext(options, extraOptions) {
|
|
242
260
|
validateOptions(options);
|
|
243
261
|
const browserType = lookupBrowserType(options);
|
|
244
|
-
const launchOptions =
|
|
245
|
-
headless,
|
|
246
|
-
executablePath
|
|
247
|
-
};
|
|
262
|
+
const launchOptions = extraOptions;
|
|
248
263
|
if (options.channel) launchOptions.channel = options.channel;
|
|
249
264
|
launchOptions.handleSIGINT = false;
|
|
250
265
|
const contextOptions =
|
|
@@ -256,7 +271,7 @@ async function launchContext(options, headless, executablePath) {
|
|
|
256
271
|
// In headful mode, use host device scale factor for things to look nice.
|
|
257
272
|
// In headless, keep things the way it works in Playwright by default.
|
|
258
273
|
// Assume high-dpi on MacOS. TODO: this is not perfect.
|
|
259
|
-
if (!headless) contextOptions.deviceScaleFactor = _os.default.platform() === 'darwin' ? 2 : 1;
|
|
274
|
+
if (!extraOptions.headless) contextOptions.deviceScaleFactor = _os.default.platform() === 'darwin' ? 2 : 1;
|
|
260
275
|
|
|
261
276
|
// Work around the WebKit GTK scrolling issue.
|
|
262
277
|
if (browserType.name() === 'webkit' && process.platform === 'linux') {
|
|
@@ -281,7 +296,7 @@ async function launchContext(options, headless, executablePath) {
|
|
|
281
296
|
process.stdout.write(text);
|
|
282
297
|
process.stdout.write('\n-------------8<-------------\n');
|
|
283
298
|
const autoExitCondition = process.env.PWTEST_CLI_AUTO_EXIT_WHEN;
|
|
284
|
-
if (autoExitCondition && text.includes(autoExitCondition))
|
|
299
|
+
if (autoExitCondition && text.includes(autoExitCondition)) closeBrowser();
|
|
285
300
|
};
|
|
286
301
|
// Make sure we exit abnormally when browser crashes.
|
|
287
302
|
const logs = [];
|
|
@@ -383,7 +398,7 @@ async function launchContext(options, headless, executablePath) {
|
|
|
383
398
|
const hasPage = browser.contexts().some(context => context.pages().length > 0);
|
|
384
399
|
if (hasPage) return;
|
|
385
400
|
// Avoid the error when the last page is closed because the browser has been closed.
|
|
386
|
-
closeBrowser().catch(
|
|
401
|
+
closeBrowser().catch(() => {});
|
|
387
402
|
});
|
|
388
403
|
});
|
|
389
404
|
process.on('SIGINT', async () => {
|
|
@@ -431,13 +446,17 @@ async function open(options, url, language) {
|
|
|
431
446
|
context,
|
|
432
447
|
launchOptions,
|
|
433
448
|
contextOptions
|
|
434
|
-
} = await launchContext(options,
|
|
449
|
+
} = await launchContext(options, {
|
|
450
|
+
headless: !!process.env.PWTEST_CLI_HEADLESS,
|
|
451
|
+
executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH
|
|
452
|
+
});
|
|
435
453
|
await context._enableRecorder({
|
|
436
454
|
language,
|
|
437
455
|
launchOptions,
|
|
438
456
|
contextOptions,
|
|
439
457
|
device: options.device,
|
|
440
|
-
saveStorage: options.saveStorage
|
|
458
|
+
saveStorage: options.saveStorage,
|
|
459
|
+
handleSIGINT: false
|
|
441
460
|
});
|
|
442
461
|
await openPage(context, url);
|
|
443
462
|
}
|
|
@@ -447,11 +466,16 @@ async function codegen(options, url) {
|
|
|
447
466
|
output: outputFile,
|
|
448
467
|
testIdAttribute: testIdAttributeName
|
|
449
468
|
} = options;
|
|
469
|
+
const tracesDir = _path.default.join(_os.default.tmpdir(), `playwright-recorder-trace-${Date.now()}`);
|
|
450
470
|
const {
|
|
451
471
|
context,
|
|
452
472
|
launchOptions,
|
|
453
473
|
contextOptions
|
|
454
|
-
} = await launchContext(options,
|
|
474
|
+
} = await launchContext(options, {
|
|
475
|
+
headless: !!process.env.PWTEST_CLI_HEADLESS,
|
|
476
|
+
executablePath: process.env.PWTEST_CLI_EXECUTABLE_PATH,
|
|
477
|
+
tracesDir
|
|
478
|
+
});
|
|
455
479
|
_utilsBundle.dotenv.config({
|
|
456
480
|
path: 'playwright.env'
|
|
457
481
|
});
|
|
@@ -462,8 +486,10 @@ async function codegen(options, url) {
|
|
|
462
486
|
device: options.device,
|
|
463
487
|
saveStorage: options.saveStorage,
|
|
464
488
|
mode: 'recording',
|
|
489
|
+
codegenMode: process.env.PW_RECORDER_IS_TRACE_VIEWER ? 'trace-events' : 'actions',
|
|
465
490
|
testIdAttributeName,
|
|
466
|
-
outputFile: outputFile ? _path.default.resolve(outputFile) : undefined
|
|
491
|
+
outputFile: outputFile ? _path.default.resolve(outputFile) : undefined,
|
|
492
|
+
handleSIGINT: false
|
|
467
493
|
});
|
|
468
494
|
await openPage(context, url);
|
|
469
495
|
}
|
|
@@ -480,7 +506,9 @@ async function waitForPage(page, captureOptions) {
|
|
|
480
506
|
async function screenshot(options, captureOptions, url, path) {
|
|
481
507
|
const {
|
|
482
508
|
context
|
|
483
|
-
} = await launchContext(options,
|
|
509
|
+
} = await launchContext(options, {
|
|
510
|
+
headless: true
|
|
511
|
+
});
|
|
484
512
|
console.log('Navigating to ' + url);
|
|
485
513
|
const page = await openPage(context, url);
|
|
486
514
|
await waitForPage(page, captureOptions);
|
|
@@ -499,7 +527,9 @@ async function pdf(options, captureOptions, url, path) {
|
|
|
499
527
|
} = await launchContext({
|
|
500
528
|
...options,
|
|
501
529
|
browser: 'chromium'
|
|
502
|
-
},
|
|
530
|
+
}, {
|
|
531
|
+
headless: true
|
|
532
|
+
});
|
|
503
533
|
console.log('Navigating to ' + url);
|
|
504
534
|
const page = await openPage(context, url);
|
|
505
535
|
await waitForPage(page, captureOptions);
|
package/lib/client/api.js
CHANGED
|
@@ -243,6 +243,12 @@ Object.defineProperty(exports, "WebSocket", {
|
|
|
243
243
|
return _network.WebSocket;
|
|
244
244
|
}
|
|
245
245
|
});
|
|
246
|
+
Object.defineProperty(exports, "WebSocketRoute", {
|
|
247
|
+
enumerable: true,
|
|
248
|
+
get: function () {
|
|
249
|
+
return _network.WebSocketRoute;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
246
252
|
Object.defineProperty(exports, "Worker", {
|
|
247
253
|
enumerable: true,
|
|
248
254
|
get: function () {
|
|
@@ -63,6 +63,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|
|
63
63
|
super(parent, type, guid, initializer);
|
|
64
64
|
this._pages = new Set();
|
|
65
65
|
this._routes = [];
|
|
66
|
+
this._webSocketRoutes = [];
|
|
66
67
|
this._browser = null;
|
|
67
68
|
this._browserType = void 0;
|
|
68
69
|
this._bindings = new Map();
|
|
@@ -96,6 +97,9 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|
|
96
97
|
this._channel.on('route', ({
|
|
97
98
|
route
|
|
98
99
|
}) => this._onRoute(network.Route.from(route)));
|
|
100
|
+
this._channel.on('webSocketRoute', ({
|
|
101
|
+
webSocketRoute
|
|
102
|
+
}) => this._onWebSocketRoute(network.WebSocketRoute.from(webSocketRoute)));
|
|
99
103
|
this._channel.on('backgroundPage', ({
|
|
100
104
|
page
|
|
101
105
|
}) => {
|
|
@@ -215,7 +219,11 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|
|
215
219
|
}
|
|
216
220
|
// If the page is closed or unrouteAll() was called without waiting and interception disabled,
|
|
217
221
|
// the method will throw an error - silence it.
|
|
218
|
-
await route._innerContinue(true).catch(() => {});
|
|
222
|
+
await route._innerContinue(true /* isFallback */).catch(() => {});
|
|
223
|
+
}
|
|
224
|
+
async _onWebSocketRoute(webSocketRoute) {
|
|
225
|
+
const routeHandler = this._webSocketRoutes.find(route => route.matches(webSocketRoute.url()));
|
|
226
|
+
if (routeHandler) await routeHandler.handle(webSocketRoute);else webSocketRoute.connectToServer();
|
|
219
227
|
}
|
|
220
228
|
async _onBinding(bindingCall) {
|
|
221
229
|
const func = this._bindings.get(bindingCall._initializer.name);
|
|
@@ -327,6 +335,10 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|
|
327
335
|
this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times));
|
|
328
336
|
await this._updateInterceptionPatterns();
|
|
329
337
|
}
|
|
338
|
+
async routeWebSocket(url, handler) {
|
|
339
|
+
this._webSocketRoutes.unshift(new network.WebSocketRouteHandler(this._options.baseURL, url, handler));
|
|
340
|
+
await this._updateWebSocketInterceptionPatterns();
|
|
341
|
+
}
|
|
330
342
|
async _recordIntoHAR(har, page, options = {}) {
|
|
331
343
|
var _options$updateConten, _options$updateMode, _options$updateConten2;
|
|
332
344
|
const {
|
|
@@ -385,6 +397,12 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|
|
385
397
|
patterns
|
|
386
398
|
});
|
|
387
399
|
}
|
|
400
|
+
async _updateWebSocketInterceptionPatterns() {
|
|
401
|
+
const patterns = network.WebSocketRouteHandler.prepareInterceptionPatterns(this._webSocketRoutes);
|
|
402
|
+
await this._channel.setWebSocketInterceptionPatterns({
|
|
403
|
+
patterns
|
|
404
|
+
});
|
|
405
|
+
}
|
|
388
406
|
_effectiveCloseReason() {
|
|
389
407
|
var _this$_browser3;
|
|
390
408
|
return this._closeReason || ((_this$_browser3 = this._browser) === null || _this$_browser3 === void 0 ? void 0 : _this$_browser3._closeReason);
|
|
@@ -470,7 +488,7 @@ class BrowserContext extends _channelOwner.ChannelOwner {
|
|
|
470
488
|
await this._closedPromise;
|
|
471
489
|
}
|
|
472
490
|
async _enableRecorder(params) {
|
|
473
|
-
await this._channel.
|
|
491
|
+
await this._channel.enableRecorder(params);
|
|
474
492
|
}
|
|
475
493
|
}
|
|
476
494
|
exports.BrowserContext = BrowserContext;
|
|
@@ -39,6 +39,7 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|
|
39
39
|
this._logger = void 0;
|
|
40
40
|
this._instrumentation = void 0;
|
|
41
41
|
this._eventToSubscriptionMapping = new Map();
|
|
42
|
+
this._isInternalType = false;
|
|
42
43
|
this._wasCollected = false;
|
|
43
44
|
this.setMaxListeners(0);
|
|
44
45
|
this._connection = parent instanceof ChannelOwner ? parent._connection : parent;
|
|
@@ -54,6 +55,9 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|
|
54
55
|
this._channel = this._createChannel(new _eventEmitter.EventEmitter());
|
|
55
56
|
this._initializer = initializer;
|
|
56
57
|
}
|
|
58
|
+
markAsInternalType() {
|
|
59
|
+
this._isInternalType = true;
|
|
60
|
+
}
|
|
57
61
|
_setEventToSubscriptionMapping(mapping) {
|
|
58
62
|
this._eventToSubscriptionMapping = mapping;
|
|
59
63
|
}
|
|
@@ -156,14 +160,14 @@ class ChannelOwner extends _eventEmitter.EventEmitter {
|
|
|
156
160
|
channel._object = this;
|
|
157
161
|
return channel;
|
|
158
162
|
}
|
|
159
|
-
async _wrapApiCall(func, isInternal
|
|
163
|
+
async _wrapApiCall(func, isInternal) {
|
|
160
164
|
const logger = this._logger;
|
|
161
165
|
const apiZone = _zones.zones.zoneData('apiZone');
|
|
162
166
|
if (apiZone) return await func(apiZone);
|
|
163
167
|
const stackTrace = (0, _stackTrace.captureLibraryStackTrace)();
|
|
164
168
|
let apiName = stackTrace.apiName;
|
|
165
169
|
const frames = stackTrace.frames;
|
|
166
|
-
isInternal
|
|
170
|
+
if (isInternal === undefined) isInternal = this._isInternalType;
|
|
167
171
|
if (isInternal) apiName = undefined;
|
|
168
172
|
|
|
169
173
|
// Enclosing zone could have provided the apiName and wallTime.
|
package/lib/client/connection.js
CHANGED
|
@@ -315,6 +315,9 @@ class Connection extends _events.EventEmitter {
|
|
|
315
315
|
case 'WebSocket':
|
|
316
316
|
result = new _network.WebSocket(parent, type, guid, initializer);
|
|
317
317
|
break;
|
|
318
|
+
case 'WebSocketRoute':
|
|
319
|
+
result = new _network.WebSocketRoute(parent, type, guid, initializer);
|
|
320
|
+
break;
|
|
318
321
|
case 'Worker':
|
|
319
322
|
result = new _worker.Worker(parent, type, guid, initializer);
|
|
320
323
|
break;
|
package/lib/client/fetch.js
CHANGED
|
@@ -147,8 +147,9 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|
|
147
147
|
(0, _utils.assert)(options.maxRedirects === undefined || options.maxRedirects >= 0, `'maxRedirects' must be greater than or equal to '0'`);
|
|
148
148
|
(0, _utils.assert)(options.maxRetries === undefined || options.maxRetries >= 0, `'maxRetries' must be greater than or equal to '0'`);
|
|
149
149
|
const url = options.url !== undefined ? options.url : options.request.url();
|
|
150
|
-
const params = mapParamsToArray(options.params);
|
|
151
150
|
const method = options.method || ((_options$request = options.request) === null || _options$request === void 0 ? void 0 : _options$request.method());
|
|
151
|
+
let encodedParams = undefined;
|
|
152
|
+
if (typeof options.params === 'string') encodedParams = options.params;else if (options.params instanceof URLSearchParams) encodedParams = options.params.toString();
|
|
152
153
|
// Cannot call allHeaders() here as the request may be paused inside route handler.
|
|
153
154
|
const headersObj = options.headers || ((_options$request2 = options.request) === null || _options$request2 === void 0 ? void 0 : _options$request2.headers());
|
|
154
155
|
const headers = headersObj ? (0, _utils.headersObjectToArray)(headersObj) : undefined;
|
|
@@ -167,7 +168,18 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|
|
167
168
|
throw new Error(`Unexpected 'data' type`);
|
|
168
169
|
}
|
|
169
170
|
} else if (options.form) {
|
|
170
|
-
|
|
171
|
+
if (globalThis.FormData && options.form instanceof FormData) {
|
|
172
|
+
formData = [];
|
|
173
|
+
for (const [name, value] of options.form.entries()) {
|
|
174
|
+
if (typeof value !== 'string') throw new Error(`Expected string for options.form["${name}"], found File. Please use options.multipart instead.`);
|
|
175
|
+
formData.push({
|
|
176
|
+
name,
|
|
177
|
+
value
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
formData = objectToArray(options.form);
|
|
182
|
+
}
|
|
171
183
|
} else if (options.multipart) {
|
|
172
184
|
multipartData = [];
|
|
173
185
|
if (globalThis.FormData && options.multipart instanceof FormData) {
|
|
@@ -201,7 +213,8 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
|
|
|
201
213
|
};
|
|
202
214
|
const result = await this._channel.fetch({
|
|
203
215
|
url,
|
|
204
|
-
params,
|
|
216
|
+
params: typeof options.params === 'object' ? objectToArray(options.params) : undefined,
|
|
217
|
+
encodedParams,
|
|
205
218
|
method,
|
|
206
219
|
headers,
|
|
207
220
|
postData: postDataBuffer,
|
|
@@ -373,24 +386,6 @@ function objectToArray(map) {
|
|
|
373
386
|
});
|
|
374
387
|
return result;
|
|
375
388
|
}
|
|
376
|
-
function queryStringToArray(queryString) {
|
|
377
|
-
const searchParams = new URLSearchParams(queryString);
|
|
378
|
-
return searchParamsToArray(searchParams);
|
|
379
|
-
}
|
|
380
|
-
function searchParamsToArray(searchParams) {
|
|
381
|
-
if (searchParams.size === 0) return undefined;
|
|
382
|
-
const result = [];
|
|
383
|
-
for (const [name, value] of searchParams.entries()) result.push({
|
|
384
|
-
name,
|
|
385
|
-
value
|
|
386
|
-
});
|
|
387
|
-
return result;
|
|
388
|
-
}
|
|
389
|
-
function mapParamsToArray(params) {
|
|
390
|
-
if (params instanceof URLSearchParams) return searchParamsToArray(params);
|
|
391
|
-
if (typeof params === 'string') return queryStringToArray(params);
|
|
392
|
-
return objectToArray(params);
|
|
393
|
-
}
|
|
394
389
|
function isFilePayload(value) {
|
|
395
390
|
return typeof value === 'object' && value['name'] && value['mimeType'] && value['buffer'];
|
|
396
391
|
}
|
package/lib/client/jsHandle.js
CHANGED
|
@@ -86,14 +86,6 @@ class JSHandle extends _channelOwner.ChannelOwner {
|
|
|
86
86
|
throw e;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
-
async _objectCount() {
|
|
90
|
-
return await this._wrapApiCall(async () => {
|
|
91
|
-
const {
|
|
92
|
-
count
|
|
93
|
-
} = await this._channel.objectCount();
|
|
94
|
-
return count;
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
89
|
toString() {
|
|
98
90
|
return this._preview;
|
|
99
91
|
}
|
package/lib/client/localUtils.js
CHANGED
package/lib/client/locator.js
CHANGED
|
@@ -291,6 +291,13 @@ class Locator {
|
|
|
291
291
|
timeout
|
|
292
292
|
}), options.timeout);
|
|
293
293
|
}
|
|
294
|
+
async ariaSnapshot(options) {
|
|
295
|
+
const result = await this._frame._channel.ariaSnapshot({
|
|
296
|
+
...options,
|
|
297
|
+
selector: this._selector
|
|
298
|
+
});
|
|
299
|
+
return result.snapshot;
|
|
300
|
+
}
|
|
294
301
|
async scrollIntoViewIfNeeded(options = {}) {
|
|
295
302
|
return await this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({
|
|
296
303
|
...options,
|