From 0f636116e25c251710c7e9a618d90f0628493736 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 5 Sep 2024 12:57:16 +0200 Subject: [PATCH 001/805] chore: mark 1.48.0-next (#32466) --- package-lock.json | 68 +++++++++---------- package.json | 2 +- .../playwright-browser-chromium/package.json | 4 +- .../playwright-browser-firefox/package.json | 4 +- .../playwright-browser-webkit/package.json | 4 +- packages/playwright-chromium/package.json | 4 +- packages/playwright-core/package.json | 2 +- packages/playwright-ct-core/package.json | 6 +- packages/playwright-ct-react/package.json | 4 +- packages/playwright-ct-react17/package.json | 4 +- packages/playwright-ct-solid/package.json | 4 +- packages/playwright-ct-svelte/package.json | 4 +- packages/playwright-ct-vue/package.json | 4 +- packages/playwright-ct-vue2/package.json | 4 +- packages/playwright-firefox/package.json | 4 +- packages/playwright-test/package.json | 4 +- packages/playwright-webkit/package.json | 4 +- packages/playwright/package.json | 4 +- 18 files changed, 67 insertions(+), 67 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8edb318925d17..6c65c8e2470f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "playwright-internal", - "version": "1.47.0-next", + "version": "1.48.0-next", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "playwright-internal", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "workspaces": [ "packages/*" @@ -7912,10 +7912,10 @@ } }, "packages/playwright": { - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "bin": { "playwright": "cli.js" @@ -7929,11 +7929,11 @@ }, "packages/playwright-browser-chromium": { "name": "@playwright/browser-chromium", - "version": "1.47.0-next", + "version": "1.48.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "engines": { "node": ">=18" @@ -7941,11 +7941,11 @@ }, "packages/playwright-browser-firefox": { "name": "@playwright/browser-firefox", - "version": "1.47.0-next", + "version": "1.48.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "engines": { "node": ">=18" @@ -7953,22 +7953,22 @@ }, "packages/playwright-browser-webkit": { "name": "@playwright/browser-webkit", - "version": "1.47.0-next", + "version": "1.48.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "engines": { "node": ">=18" } }, "packages/playwright-chromium": { - "version": "1.47.0-next", + "version": "1.48.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "bin": { "playwright": "cli.js" @@ -7978,7 +7978,7 @@ } }, "packages/playwright-core": { - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -7989,11 +7989,11 @@ }, "packages/playwright-ct-core": { "name": "@playwright/experimental-ct-core", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "playwright": "1.47.0-next", - "playwright-core": "1.47.0-next", + "playwright": "1.48.0-next", + "playwright-core": "1.48.0-next", "vite": "^5.2.8" }, "engines": { @@ -8002,10 +8002,10 @@ }, "packages/playwright-ct-react": { "name": "@playwright/experimental-ct-react", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -8017,10 +8017,10 @@ }, "packages/playwright-ct-react17": { "name": "@playwright/experimental-ct-react17", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { @@ -8032,10 +8032,10 @@ }, "packages/playwright-ct-solid": { "name": "@playwright/experimental-ct-solid", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "vite-plugin-solid": "^2.7.0" }, "bin": { @@ -8050,10 +8050,10 @@ }, "packages/playwright-ct-svelte": { "name": "@playwright/experimental-ct-svelte", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@sveltejs/vite-plugin-svelte": "^3.0.1" }, "bin": { @@ -8068,10 +8068,10 @@ }, "packages/playwright-ct-vue": { "name": "@playwright/experimental-ct-vue", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-vue": "^4.2.1" }, "bin": { @@ -8083,10 +8083,10 @@ }, "packages/playwright-ct-vue2": { "name": "@playwright/experimental-ct-vue2", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-vue2": "^2.2.0" }, "bin": { @@ -8135,11 +8135,11 @@ } }, "packages/playwright-firefox": { - "version": "1.47.0-next", + "version": "1.48.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "bin": { "playwright": "cli.js" @@ -8150,10 +8150,10 @@ }, "packages/playwright-test": { "name": "@playwright/test", - "version": "1.47.0-next", + "version": "1.48.0-next", "license": "Apache-2.0", "dependencies": { - "playwright": "1.47.0-next" + "playwright": "1.48.0-next" }, "bin": { "playwright": "cli.js" @@ -8163,11 +8163,11 @@ } }, "packages/playwright-webkit": { - "version": "1.47.0-next", + "version": "1.48.0-next", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "bin": { "playwright": "cli.js" diff --git a/package.json b/package.json index e01aae1896bac..84634dcb64cb6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "playwright-internal", "private": true, - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", diff --git a/packages/playwright-browser-chromium/package.json b/packages/playwright-browser-chromium/package.json index 5a3d0761ccbfe..ac4869cb7ac20 100644 --- a/packages/playwright-browser-chromium/package.json +++ b/packages/playwright-browser-chromium/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-chromium", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright package that automatically installs Chromium", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" } } diff --git a/packages/playwright-browser-firefox/package.json b/packages/playwright-browser-firefox/package.json index 86778490f259c..974c76ac0cfb5 100644 --- a/packages/playwright-browser-firefox/package.json +++ b/packages/playwright-browser-firefox/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-firefox", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright package that automatically installs Firefox", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" } } diff --git a/packages/playwright-browser-webkit/package.json b/packages/playwright-browser-webkit/package.json index 1e108574c569b..58e819b0d3ad3 100644 --- a/packages/playwright-browser-webkit/package.json +++ b/packages/playwright-browser-webkit/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/browser-webkit", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright package that automatically installs WebKit", "repository": { "type": "git", @@ -27,6 +27,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" } } diff --git a/packages/playwright-chromium/package.json b/packages/playwright-chromium/package.json index 55897f465e31d..00f5299d3e98e 100644 --- a/packages/playwright-chromium/package.json +++ b/packages/playwright-chromium/package.json @@ -1,6 +1,6 @@ { "name": "playwright-chromium", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate Chromium", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" } } diff --git a/packages/playwright-core/package.json b/packages/playwright-core/package.json index 155f526eaef06..3a931d4b9aea6 100644 --- a/packages/playwright-core/package.json +++ b/packages/playwright-core/package.json @@ -1,6 +1,6 @@ { "name": "playwright-core", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", diff --git a/packages/playwright-ct-core/package.json b/packages/playwright-ct-core/package.json index 870554680674b..ef959ebeb58b6 100644 --- a/packages/playwright-ct-core/package.json +++ b/packages/playwright-ct-core/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-core", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing Helpers", "repository": { "type": "git", @@ -26,8 +26,8 @@ } }, "dependencies": { - "playwright-core": "1.47.0-next", + "playwright-core": "1.48.0-next", "vite": "^5.2.8", - "playwright": "1.47.0-next" + "playwright": "1.48.0-next" } } diff --git a/packages/playwright-ct-react/package.json b/packages/playwright-ct-react/package.json index d788859d3e5cc..b024d75855d92 100644 --- a/packages/playwright-ct-react/package.json +++ b/packages/playwright-ct-react/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-react", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing for React", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-react17/package.json b/packages/playwright-ct-react17/package.json index d60e249184ef7..46e1c80fff187 100644 --- a/packages/playwright-ct-react17/package.json +++ b/packages/playwright-ct-react17/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-react17", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing for React", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-react": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-solid/package.json b/packages/playwright-ct-solid/package.json index b99cd395b6fa0..5fa614a43b7c3 100644 --- a/packages/playwright-ct-solid/package.json +++ b/packages/playwright-ct-solid/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-solid", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing for Solid", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "vite-plugin-solid": "^2.7.0" }, "devDependencies": { diff --git a/packages/playwright-ct-svelte/package.json b/packages/playwright-ct-svelte/package.json index 88cf44d6eebbf..1b3cb47789e4b 100644 --- a/packages/playwright-ct-svelte/package.json +++ b/packages/playwright-ct-svelte/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-svelte", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing for Svelte", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@sveltejs/vite-plugin-svelte": "^3.0.1" }, "devDependencies": { diff --git a/packages/playwright-ct-vue/package.json b/packages/playwright-ct-vue/package.json index 35b340902b3c7..f648cf2acace7 100644 --- a/packages/playwright-ct-vue/package.json +++ b/packages/playwright-ct-vue/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-vue", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing for Vue", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-vue": "^4.2.1" }, "bin": { diff --git a/packages/playwright-ct-vue2/package.json b/packages/playwright-ct-vue2/package.json index 10be77c26bba7..c104e44ca6eeb 100644 --- a/packages/playwright-ct-vue2/package.json +++ b/packages/playwright-ct-vue2/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/experimental-ct-vue2", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "Playwright Component Testing for Vue2", "repository": { "type": "git", @@ -30,7 +30,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@playwright/experimental-ct-core": "1.47.0-next", + "@playwright/experimental-ct-core": "1.48.0-next", "@vitejs/plugin-vue2": "^2.2.0" }, "devDependencies": { diff --git a/packages/playwright-firefox/package.json b/packages/playwright-firefox/package.json index dd528d0ef85e2..7fe7b929f1788 100644 --- a/packages/playwright-firefox/package.json +++ b/packages/playwright-firefox/package.json @@ -1,6 +1,6 @@ { "name": "playwright-firefox", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate Firefox", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" } } diff --git a/packages/playwright-test/package.json b/packages/playwright-test/package.json index fed09fd22fac6..d70f9f0a185de 100644 --- a/packages/playwright-test/package.json +++ b/packages/playwright-test/package.json @@ -1,6 +1,6 @@ { "name": "@playwright/test", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -30,6 +30,6 @@ }, "scripts": {}, "dependencies": { - "playwright": "1.47.0-next" + "playwright": "1.48.0-next" } } diff --git a/packages/playwright-webkit/package.json b/packages/playwright-webkit/package.json index f65486ed3acb2..ff6c8e97b0c79 100644 --- a/packages/playwright-webkit/package.json +++ b/packages/playwright-webkit/package.json @@ -1,6 +1,6 @@ { "name": "playwright-webkit", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate WebKit", "repository": { "type": "git", @@ -30,6 +30,6 @@ "install": "node install.js" }, "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" } } diff --git a/packages/playwright/package.json b/packages/playwright/package.json index d6a2aa23b236e..519c33171cbd8 100644 --- a/packages/playwright/package.json +++ b/packages/playwright/package.json @@ -1,6 +1,6 @@ { "name": "playwright", - "version": "1.47.0-next", + "version": "1.48.0-next", "description": "A high-level API to automate web browsers", "repository": { "type": "git", @@ -58,7 +58,7 @@ }, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-next" + "playwright-core": "1.48.0-next" }, "optionalDependencies": { "fsevents": "2.3.2" From 29f1541b14ff66158bfbbbb821976119f196d499 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 5 Sep 2024 13:44:22 +0200 Subject: [PATCH 002/805] chore: roll stable test runner to 1.47 beta (#32469) --- .../stable-test-runner/package-lock.json | 50 ++++++++++--------- .../stable-test-runner/package.json | 2 +- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/tests/playwright-test/stable-test-runner/package-lock.json b/tests/playwright-test/stable-test-runner/package-lock.json index e6bf87ad763a0..ffa522a45588f 100644 --- a/tests/playwright-test/stable-test-runner/package-lock.json +++ b/tests/playwright-test/stable-test-runner/package-lock.json @@ -5,15 +5,16 @@ "packages": { "": { "dependencies": { - "@playwright/test": "1.45.0-beta-1718411373000" + "@playwright/test": "1.47.0-beta-1725531189000" } }, "node_modules/@playwright/test": { - "version": "1.45.0-beta-1718411373000", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.0-beta-1718411373000.tgz", - "integrity": "sha512-MUSJtFJLYqVgiR6HEHBc9BNlwVoA8hDbb0MaSJLPCEt4Q5jYsD5orNxDXJC5jgWqOEDUzSaCAU+iHs5UbIG9IQ==", + "version": "1.47.0-beta-1725531189000", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0-beta-1725531189000.tgz", + "integrity": "sha512-vIXLYI725qen6gbrkiD+KphLnjHEHumK7lv6BYP4ZTzbI48Cc7eKkysrLIP1EajghejmPa0DCwsrQmMEElM1mQ==", + "license": "Apache-2.0", "dependencies": { - "playwright": "1.45.0-beta-1718411373000" + "playwright": "1.47.0-beta-1725531189000" }, "bin": { "playwright": "cli.js" @@ -27,6 +28,7 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -36,11 +38,12 @@ } }, "node_modules/playwright": { - "version": "1.45.0-beta-1718411373000", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0-beta-1718411373000.tgz", - "integrity": "sha512-ytXqNRkVkZVAm8VH1zGlUqJltWbElVkAnqw2fUeXelku2we+ZFL7gnMiSxiKIlfTfrKQgvdlMgWiZ1s4r5cW2Q==", + "version": "1.47.0-beta-1725531189000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0-beta-1725531189000.tgz", + "integrity": "sha512-OkqvMHZOGrXL0xR8qUb0sY4/VK0CElbgJjC2pMVo77zxfOaBjzWVT3Zq5+zeoAOc+LUTWrG8YJNpRIlLoiDZlg==", + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.0-beta-1718411373000" + "playwright-core": "1.47.0-beta-1725531189000" }, "bin": { "playwright": "cli.js" @@ -53,9 +56,10 @@ } }, "node_modules/playwright-core": { - "version": "1.45.0-beta-1718411373000", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0-beta-1718411373000.tgz", - "integrity": "sha512-s9FTt2EMcnY8/BhJEMJN7tW3KogupYIv8DRBMb1fMtJQyFgH+iQwcvmj/an4MiXCtGXgQ0NNhVAbJtVwgjvHNA==", + "version": "1.47.0-beta-1725531189000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0-beta-1725531189000.tgz", + "integrity": "sha512-a3jiPt5nHo14i/4is7diMKiq+e0Tc/UNjiVy7fHH1gfPw9kHQMAgWuoOYwMAawFNFOyYuZSk4KNBTRfVgtMkVw==", + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -66,11 +70,11 @@ }, "dependencies": { "@playwright/test": { - "version": "1.45.0-beta-1718411373000", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.0-beta-1718411373000.tgz", - "integrity": "sha512-MUSJtFJLYqVgiR6HEHBc9BNlwVoA8hDbb0MaSJLPCEt4Q5jYsD5orNxDXJC5jgWqOEDUzSaCAU+iHs5UbIG9IQ==", + "version": "1.47.0-beta-1725531189000", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0-beta-1725531189000.tgz", + "integrity": "sha512-vIXLYI725qen6gbrkiD+KphLnjHEHumK7lv6BYP4ZTzbI48Cc7eKkysrLIP1EajghejmPa0DCwsrQmMEElM1mQ==", "requires": { - "playwright": "1.45.0-beta-1718411373000" + "playwright": "1.47.0-beta-1725531189000" } }, "fsevents": { @@ -80,18 +84,18 @@ "optional": true }, "playwright": { - "version": "1.45.0-beta-1718411373000", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0-beta-1718411373000.tgz", - "integrity": "sha512-ytXqNRkVkZVAm8VH1zGlUqJltWbElVkAnqw2fUeXelku2we+ZFL7gnMiSxiKIlfTfrKQgvdlMgWiZ1s4r5cW2Q==", + "version": "1.47.0-beta-1725531189000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0-beta-1725531189000.tgz", + "integrity": "sha512-OkqvMHZOGrXL0xR8qUb0sY4/VK0CElbgJjC2pMVo77zxfOaBjzWVT3Zq5+zeoAOc+LUTWrG8YJNpRIlLoiDZlg==", "requires": { "fsevents": "2.3.2", - "playwright-core": "1.45.0-beta-1718411373000" + "playwright-core": "1.47.0-beta-1725531189000" } }, "playwright-core": { - "version": "1.45.0-beta-1718411373000", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0-beta-1718411373000.tgz", - "integrity": "sha512-s9FTt2EMcnY8/BhJEMJN7tW3KogupYIv8DRBMb1fMtJQyFgH+iQwcvmj/an4MiXCtGXgQ0NNhVAbJtVwgjvHNA==" + "version": "1.47.0-beta-1725531189000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0-beta-1725531189000.tgz", + "integrity": "sha512-a3jiPt5nHo14i/4is7diMKiq+e0Tc/UNjiVy7fHH1gfPw9kHQMAgWuoOYwMAawFNFOyYuZSk4KNBTRfVgtMkVw==" } } } diff --git a/tests/playwright-test/stable-test-runner/package.json b/tests/playwright-test/stable-test-runner/package.json index 97adee767d2ca..c30cd47132047 100644 --- a/tests/playwright-test/stable-test-runner/package.json +++ b/tests/playwright-test/stable-test-runner/package.json @@ -1,6 +1,6 @@ { "private": true, "dependencies": { - "@playwright/test": "1.45.0-beta-1718411373000" + "@playwright/test": "1.47.0-beta-1725531189000" } } From 895d017fb86c0be0959f501dd77e20c127456afd Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 5 Sep 2024 13:44:58 +0200 Subject: [PATCH 003/805] chore: update browser patches as of July, 25th, 2024 (#32468) --- browser_patches/firefox/UPSTREAM_CONFIG.sh | 2 +- .../firefox/juggler/NetworkObserver.js | 2 + .../firefox/juggler/TargetRegistry.js | 41 + .../juggler/content/JugglerFrameChild.jsm | 2 +- .../screencast/nsScreencastService.cpp | 4 +- .../firefox/patches/bootstrap.diff | 342 +-- browser_patches/webkit/UPSTREAM_CONFIG.sh | 2 +- browser_patches/webkit/patches/bootstrap.diff | 1995 ++++++++++------- 8 files changed, 1452 insertions(+), 938 deletions(-) diff --git a/browser_patches/firefox/UPSTREAM_CONFIG.sh b/browser_patches/firefox/UPSTREAM_CONFIG.sh index aee7dca3d9277..ff333634246d9 100644 --- a/browser_patches/firefox/UPSTREAM_CONFIG.sh +++ b/browser_patches/firefox/UPSTREAM_CONFIG.sh @@ -1,3 +1,3 @@ REMOTE_URL="https://github.com/mozilla/gecko-dev" BASE_BRANCH="release" -BASE_REVISION="4c9a3f8e2db68ae0a8fcf6bbf0574e3c0549ff49" +BASE_REVISION="cf0397e3ba298868fdca53f894da5b0d239dc09e" diff --git a/browser_patches/firefox/juggler/NetworkObserver.js b/browser_patches/firefox/juggler/NetworkObserver.js index 8eb69d813360e..aa6f8662773de 100644 --- a/browser_patches/firefox/juggler/NetworkObserver.js +++ b/browser_patches/firefox/juggler/NetworkObserver.js @@ -602,6 +602,8 @@ class NetworkObserver { proxyFilter.onProxyFilterResult(defaultProxyInfo); return; } + if (this._targetRegistry.shouldBustHTTPAuthCacheForProxy(proxy)) + Services.obs.notifyObservers(null, "net:clear-active-logins"); proxyFilter.onProxyFilterResult(protocolProxyService.newProxyInfo( proxy.type, proxy.host, diff --git a/browser_patches/firefox/juggler/TargetRegistry.js b/browser_patches/firefox/juggler/TargetRegistry.js index 8c23ff8c9371b..c40c831d01257 100644 --- a/browser_patches/firefox/juggler/TargetRegistry.js +++ b/browser_patches/firefox/juggler/TargetRegistry.js @@ -116,6 +116,7 @@ class TargetRegistry { this._browserToTarget = new Map(); this._browserIdToTarget = new Map(); + this._proxiesWithClashingAuthCacheKeys = new Set(); this._browserProxy = null; // Cleanup containers from previous runs (if any) @@ -234,12 +235,50 @@ class TargetRegistry { onOpenWindow(win); } + // Firefox uses nsHttpAuthCache to cache authentication to the proxy. + // If we're provided with a single proxy with a multiple different authentications, then + // we should clear the nsHttpAuthCache on every request. + shouldBustHTTPAuthCacheForProxy(proxy) { + return this._proxiesWithClashingAuthCacheKeys.has(proxy); + } + + _updateProxiesWithSameAuthCacheAndDifferentCredentials() { + const proxyIdToCredentials = new Map(); + const allProxies = [...this._browserContextIdToBrowserContext.values()].map(bc => bc._proxy).filter(Boolean); + if (this._browserProxy) + allProxies.push(this._browserProxy); + const proxyAuthCacheKeyAndProxy = allProxies.map(proxy => [ + JSON.stringify({ + type: proxy.type, + host: proxy.host, + port: proxy.port, + }), + proxy, + ]); + this._proxiesWithClashingAuthCacheKeys.clear(); + + proxyAuthCacheKeyAndProxy.sort(([cacheKey1], [cacheKey2]) => cacheKey1 < cacheKey2 ? -1 : 1); + for (let i = 0; i < proxyAuthCacheKeyAndProxy.length - 1; ++i) { + const [cacheKey1, proxy1] = proxyAuthCacheKeyAndProxy[i]; + const [cacheKey2, proxy2] = proxyAuthCacheKeyAndProxy[i + 1]; + if (cacheKey1 !== cacheKey2) + continue; + if (proxy1.username === proxy2.username && proxy1.password === proxy2.password) + continue; + // `proxy1` and `proxy2` have the same caching key, but serve different credentials. + // We have to bust HTTP Auth Cache everytime there's a request that will use either of the proxies. + this._proxiesWithClashingAuthCacheKeys.add(proxy1); + this._proxiesWithClashingAuthCacheKeys.add(proxy2); + } + } + async cancelDownload(options) { this._downloadInterceptor.cancelDownload(options.uuid); } setBrowserProxy(proxy) { this._browserProxy = proxy; + this._updateProxiesWithSameAuthCacheAndDifferentCredentials(); } getProxyInfo(channel) { @@ -906,12 +945,14 @@ class BrowserContext { } this._registry._browserContextIdToBrowserContext.delete(this.browserContextId); this._registry._userContextIdToBrowserContext.delete(this.userContextId); + this._registry._updateProxiesWithSameAuthCacheAndDifferentCredentials(); } setProxy(proxy) { // Clear AuthCache. Services.obs.notifyObservers(null, "net:clear-active-logins"); this._proxy = proxy; + this._registry._updateProxiesWithSameAuthCacheAndDifferentCredentials(); } setIgnoreHTTPSErrors(ignoreHTTPSErrors) { diff --git a/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm b/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm index 47fcabbd814c0..05d91473d3a8d 100644 --- a/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm +++ b/browser_patches/firefox/juggler/content/JugglerFrameChild.jsm @@ -70,7 +70,7 @@ class JugglerFrameChild extends JSWindowActorChild { const agents = topBrowingContextToAgents.get(this.browsingContext); // The agents are already re-bound to a new actor. - if (agents.actor !== this) + if (agents?.actor !== this) return; topBrowingContextToAgents.delete(this.browsingContext); diff --git a/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp b/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp index 25f6171801414..062a8514296fa 100644 --- a/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp +++ b/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp @@ -129,7 +129,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterfaceStartCapture(capability); + int error = mCaptureModule->StartCaptureCounted(capability); if (error) { fprintf(stderr, "StartCapture error %d\n", error); return false; @@ -152,7 +152,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterfaceDeRegisterCaptureDataCallback(this); else mCaptureModule->DeRegisterRawFrameCallback(this); - mCaptureModule->StopCapture(); + mCaptureModule->StopCaptureCounted(); if (mEncoder) { mEncoder->finish([this, protect = RefPtr{this}] { NS_DispatchToMainThread(NS_NewRunnableFunction( diff --git a/browser_patches/firefox/patches/bootstrap.diff b/browser_patches/firefox/patches/bootstrap.diff index be98b14c2f874..4344455a667ab 100644 --- a/browser_patches/firefox/patches/bootstrap.diff +++ b/browser_patches/firefox/patches/bootstrap.diff @@ -106,7 +106,7 @@ index f6d425f36a965f03ac82dbe3ab6cde06f12751ac..d60999ab2658b1e1e5f07a8aee530451 browser/chrome/browser/search-extensions/amazon/favicon.ico browser/chrome/browser/search-extensions/amazondotcn/favicon.ico diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in -index 725a63981ccb58c5e47c096f39fa686a5ba5a9e8..5fe548a9b6652c4407dad6364bf20833b7fa7f3e 100644 +index 3bf9d511555510414f39db7f99a6b5a2a743f178..bb0f71dd602193536c23f7b865ec5dce3ee02242 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -189,6 +189,9 @@ @@ -167,7 +167,7 @@ index d49c6fbf1bf83b832795fa674f6b41f223eef812..7ea3540947ff5f61b15f27fbf4b95564 const transportProvider = { setListener(upgradeListener) { diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp -index 6e1a1b689398fa6c3c73f2f243ae02c67a4476c8..9dcf71ce753cf11f295d83eb7653e940065c8e2c 100644 +index db5b5b990727aefcbaa47f89e0f53f4048e60038..bcd2321f46d9bca719fc530054984a2163c21f86 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp @@ -106,8 +106,15 @@ struct ParamTraits @@ -188,7 +188,7 @@ index 6e1a1b689398fa6c3c73f2f243ae02c67a4476c8..9dcf71ce753cf11f295d83eb7653e940 template <> struct ParamTraits -@@ -2804,6 +2811,40 @@ void BrowsingContext::DidSet(FieldIndex, +@@ -2807,6 +2814,40 @@ void BrowsingContext::DidSet(FieldIndex, PresContextAffectingFieldChanged(); } @@ -230,10 +230,10 @@ index 6e1a1b689398fa6c3c73f2f243ae02c67a4476c8..9dcf71ce753cf11f295d83eb7653e940 nsString&& aOldValue) { MOZ_ASSERT(IsTop()); diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h -index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad546dfbfddd 100644 +index 61135ab0d7894c500c3c5d80d107e283c01b6830..cc8eb043f1f78214843ec7b335dd9932587d9bbd 100644 --- a/docshell/base/BrowsingContext.h +++ b/docshell/base/BrowsingContext.h -@@ -199,10 +199,10 @@ struct EmbedderColorSchemes { +@@ -203,10 +203,10 @@ struct EmbedderColorSchemes { FIELD(GVInaudibleAutoplayRequestStatus, GVAutoplayRequestStatus) \ /* ScreenOrientation-related APIs */ \ FIELD(CurrentOrientationAngle, float) \ @@ -246,7 +246,7 @@ index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad54 FIELD(EmbedderElementType, Maybe) \ FIELD(MessageManagerGroup, nsString) \ FIELD(MaxTouchPointsOverride, uint8_t) \ -@@ -240,6 +240,10 @@ struct EmbedderColorSchemes { +@@ -244,6 +244,10 @@ struct EmbedderColorSchemes { * embedder element. */ \ FIELD(EmbedderColorSchemes, EmbedderColorSchemes) \ FIELD(DisplayMode, dom::DisplayMode) \ @@ -257,7 +257,7 @@ index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad54 /* The number of entries added to the session history because of this \ * browsing context. */ \ FIELD(HistoryEntryCount, uint32_t) \ -@@ -926,6 +930,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { +@@ -937,6 +941,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { return GetPrefersColorSchemeOverride(); } @@ -272,7 +272,7 @@ index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad54 bool IsInBFCache() const; bool AllowJavascript() const { return GetAllowJavascript(); } -@@ -1090,6 +1102,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { +@@ -1101,6 +1113,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { void WalkPresContexts(Callback&&); void PresContextAffectingFieldChanged(); @@ -297,10 +297,19 @@ index 5ec95a61e4d3af265cbe7dd9d83f6535da1d103e..f8acafe6d58c429af27a38363e06ad54 bool CanSet(FieldIndex, bool, ContentParent*) { diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp -index 4c92988c9b90503c95cbec63e4dc85b5f789c488..cd6eb741a432ef761bb07d8d8e97441ed111cb6e 100644 +index b59a70321b6c5801e4a4f916ee303c999747570b..1eded29480eb4b401327da9ed33a63a18e3297b9 100644 --- a/docshell/base/CanonicalBrowsingContext.cpp +++ b/docshell/base/CanonicalBrowsingContext.cpp -@@ -1593,6 +1593,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI, +@@ -324,6 +324,8 @@ void CanonicalBrowsingContext::ReplacedBy( + txn.SetHasRestoreData(GetHasRestoreData()); + txn.SetShouldDelayMediaFromStart(GetShouldDelayMediaFromStart()); + txn.SetForceOffline(GetForceOffline()); ++ txn.SetPrefersReducedMotionOverride(GetPrefersReducedMotionOverride()); ++ txn.SetForcedColorsOverride(GetForcedColorsOverride()); + + // Propagate some settings on BrowsingContext replacement so they're not lost + // on bfcached navigations. These are important for GeckoView (see bug +@@ -1594,6 +1596,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI, return; } @@ -314,7 +323,7 @@ index 4c92988c9b90503c95cbec63e4dc85b5f789c488..cd6eb741a432ef761bb07d8d8e97441e } diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp -index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161be28fee3c 100644 +index 354b2c0d66976fd7fd431902bfc7816131602496..7948aa03c8fd865bf7953faaeea2bda84ade04c8 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -15,6 +15,12 @@ @@ -330,15 +339,15 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" #include "mozilla/AutoRestore.h" -@@ -64,6 +70,7 @@ - #include "mozilla/dom/ContentFrameMessageManager.h" +@@ -66,6 +72,7 @@ #include "mozilla/dom/DocGroup.h" #include "mozilla/dom/Element.h" + #include "mozilla/dom/FragmentDirective.h" +#include "mozilla/dom/Geolocation.h" #include "mozilla/dom/HTMLAnchorElement.h" #include "mozilla/dom/HTMLIFrameElement.h" #include "mozilla/dom/PerformanceNavigation.h" -@@ -88,6 +95,7 @@ +@@ -90,6 +97,7 @@ #include "mozilla/dom/JSWindowActorChild.h" #include "mozilla/dom/DocumentBinding.h" #include "mozilla/ipc/ProtocolUtils.h" @@ -346,7 +355,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b #include "mozilla/net/DocumentChannel.h" #include "mozilla/net/DocumentChannelChild.h" #include "mozilla/net/ParentChannelWrapper.h" -@@ -111,6 +119,7 @@ +@@ -113,6 +121,7 @@ #include "nsIDocumentViewer.h" #include "mozilla/dom/Document.h" #include "nsHTMLDocument.h" @@ -362,7 +371,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b #include "nsNetCID.h" #include "nsNetUtil.h" #include "nsObjectLoadingContent.h" -@@ -346,6 +356,13 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, +@@ -347,6 +357,13 @@ nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext, mAllowDNSPrefetch(true), mAllowWindowControl(true), mCSSErrorReportingEnabled(false), @@ -376,7 +385,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b mAllowAuth(mItemType == typeContent), mAllowKeywordFixup(false), mDisableMetaRefreshWhenInactive(false), -@@ -3066,6 +3083,214 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { +@@ -3046,6 +3063,214 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) { return NS_OK; } @@ -591,7 +600,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b NS_IMETHODIMP nsDocShell::GetIsNavigating(bool* aOut) { *aOut = mIsNavigating; -@@ -4754,7 +4979,7 @@ nsDocShell::GetVisibility(bool* aVisibility) { +@@ -4734,7 +4959,7 @@ nsDocShell::GetVisibility(bool* aVisibility) { } void nsDocShell::ActivenessMaybeChanged() { @@ -600,7 +609,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b if (RefPtr presShell = GetPresShell()) { presShell->ActivenessMaybeChanged(); } -@@ -6676,6 +6901,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType, +@@ -6672,6 +6897,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType, return false; // no entry to save into } @@ -611,7 +620,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b MOZ_ASSERT(!mozilla::SessionHistoryInParent(), "mOSHE cannot be non-null with SHIP"); nsCOMPtr viewer = mOSHE->GetDocumentViewer(); -@@ -8408,6 +8637,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { +@@ -8401,6 +8630,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) { true, // aForceNoOpener getter_AddRefs(newBC)); MOZ_ASSERT(!newBC); @@ -624,7 +633,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b return rv; } -@@ -9528,6 +9763,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, +@@ -9533,6 +9768,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr); nsCOMPtr req; @@ -641,7 +650,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { -@@ -12691,6 +12936,9 @@ class OnLinkClickEvent : public Runnable { +@@ -12710,6 +12955,9 @@ class OnLinkClickEvent : public Runnable { mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied, mTriggeringPrincipal); } @@ -651,7 +660,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b return NS_OK; } -@@ -12775,6 +13023,8 @@ nsresult nsDocShell::OnLinkClick( +@@ -12792,6 +13040,8 @@ nsresult nsDocShell::OnLinkClick( nsCOMPtr ev = new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied, aIsTrusted, aTriggeringPrincipal); @@ -661,7 +670,7 @@ index 87a34cf5b2f29bb3a7287327cc329974201856b6..014152f79069ee4196e2cda9374d161b } diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h -index f01e3426c4bc3a2145629be1bc7cf1d9cfd4c8bf..d4d76e391034203a67d4f2def714ba6efb1bea7b 100644 +index 0ea84df4dde885fd8e7f7e6045db56a0fa6b2691..b00bc444a5a25e63f98e583959d5f6812caf1815 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -15,6 +15,7 @@ @@ -723,7 +732,7 @@ index f01e3426c4bc3a2145629be1bc7cf1d9cfd4c8bf..d4d76e391034203a67d4f2def714ba6e bool mAllowKeywordFixup : 1; bool mDisableMetaRefreshWhenInactive : 1; diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl -index 024c0f544c54b7cfb0eeb64e5dc39a0b5d2a5950..63adaf24fd6dfd75f559323ae3c07e265f9f8241 100644 +index fdc04f16c6f547077ad8c872f9357d85d4513c50..199f8fdb0670265c715f99f5cac1a2b2f22c963d 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -44,6 +44,7 @@ interface nsIURI; @@ -734,7 +743,7 @@ index 024c0f544c54b7cfb0eeb64e5dc39a0b5d2a5950..63adaf24fd6dfd75f559323ae3c07e26 interface nsIEditor; interface nsIEditingSession; interface nsIInputStream; -@@ -729,6 +730,36 @@ interface nsIDocShell : nsIDocShellTreeItem +@@ -719,6 +720,36 @@ interface nsIDocShell : nsIDocShellTreeItem */ void synchronizeLayoutHistoryState(); @@ -772,10 +781,10 @@ index 024c0f544c54b7cfb0eeb64e5dc39a0b5d2a5950..63adaf24fd6dfd75f559323ae3c07e26 * This attempts to save any applicable layout history state (like * scroll position) in the nsISHEntry. This is normally done diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp -index 8cbf8b8075488fe1edc33b558f90224bd992117c..72198d51ca3c74eb855c928319551505422d6ebd 100644 +index c6cb09e1955d371cd19f563b30b486bcc2318304..d836946872b8e32360a925be5084472191e04f05 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp -@@ -3680,6 +3680,9 @@ void Document::SendToConsole(nsCOMArray& aMessages) { +@@ -3674,6 +3674,9 @@ void Document::SendToConsole(nsCOMArray& aMessages) { } void Document::ApplySettingsFromCSP(bool aSpeculative) { @@ -785,7 +794,7 @@ index 8cbf8b8075488fe1edc33b558f90224bd992117c..72198d51ca3c74eb855c928319551505 nsresult rv = NS_OK; if (!aSpeculative) { // 1) apply settings from regular CSP -@@ -3737,6 +3740,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { +@@ -3731,6 +3734,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) { MOZ_ASSERT(!mScriptGlobalObject, "CSP must be initialized before mScriptGlobalObject is set!"); @@ -797,7 +806,7 @@ index 8cbf8b8075488fe1edc33b558f90224bd992117c..72198d51ca3c74eb855c928319551505 // If this is a data document - no need to set CSP. if (mLoadedAsData) { return NS_OK; -@@ -4522,6 +4530,10 @@ bool Document::HasFocus(ErrorResult& rv) const { +@@ -4501,6 +4509,10 @@ bool Document::HasFocus(ErrorResult& rv) const { return false; } @@ -808,7 +817,7 @@ index 8cbf8b8075488fe1edc33b558f90224bd992117c..72198d51ca3c74eb855c928319551505 if (!fm->IsInActiveWindow(bc)) { return false; } -@@ -18892,6 +18904,66 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const { +@@ -18878,6 +18890,66 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const { return PreferenceSheet::PrefsFor(*this).mColorScheme; } @@ -876,7 +885,7 @@ index 8cbf8b8075488fe1edc33b558f90224bd992117c..72198d51ca3c74eb855c928319551505 if (!sLoadingForegroundTopLevelContentDocument) { return false; diff --git a/dom/base/Document.h b/dom/base/Document.h -index 0b0d0ca3d0fdb1d5c2b88b77e78cd164230e040a..82d340aba7e4f37fde2dae09bd831ccb24302a12 100644 +index 7eea29947d91f6b99363d7bf4c69f4e7b3276636..227314db13631b825b9b0701e8f9e5e630f78a72 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -4035,6 +4035,9 @@ class Document : public nsINode, @@ -890,10 +899,10 @@ index 0b0d0ca3d0fdb1d5c2b88b77e78cd164230e040a..82d340aba7e4f37fde2dae09bd831ccb static bool AutomaticStorageAccessPermissionCanBeGranted( diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp -index 14a00b8ed85f69312a89990acbb5e0f9755bd832..c97bb6cdd125e755333254a954777b06815352c7 100644 +index a7229fe412644212747646bee5e111cb427bab52..4fdefb186804ed39d4670cca32e495d95f3546d6 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp -@@ -338,14 +338,18 @@ void Navigator::GetAppName(nsAString& aAppName) const { +@@ -344,14 +344,18 @@ void Navigator::GetAppName(nsAString& aAppName) const { * for more detail. */ /* static */ @@ -914,7 +923,7 @@ index 14a00b8ed85f69312a89990acbb5e0f9755bd832..c97bb6cdd125e755333254a954777b06 // Split values on commas. for (nsDependentSubstring lang : -@@ -397,7 +401,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) { +@@ -403,7 +407,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) { } void Navigator::GetLanguages(nsTArray& aLanguages) { @@ -929,7 +938,7 @@ index 14a00b8ed85f69312a89990acbb5e0f9755bd832..c97bb6cdd125e755333254a954777b06 // The returned value is cached by the binding code. The window listens to the // accept languages change and will clear the cache when needed. It has to -@@ -2281,7 +2291,8 @@ bool Navigator::Webdriver() { +@@ -2308,7 +2318,8 @@ bool Navigator::Webdriver() { } #endif @@ -940,10 +949,10 @@ index 14a00b8ed85f69312a89990acbb5e0f9755bd832..c97bb6cdd125e755333254a954777b06 AutoplayPolicy Navigator::GetAutoplayPolicy(AutoplayPolicyMediaType aType) { diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h -index e559dc4d6aef61b7012a27f3d6c3186a12a15319..9798a50789ce972c4d9e94419e20a5cde4cd552a 100644 +index 4c400554f9b129f4482b513b46b90b780f2b8796..6efdca2363d83327562751757753abd602c80ddd 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h -@@ -215,7 +215,7 @@ class Navigator final : public nsISupports, public nsWrapperCache { +@@ -218,7 +218,7 @@ class Navigator final : public nsISupports, public nsWrapperCache { StorageManager* Storage(); @@ -953,10 +962,10 @@ index e559dc4d6aef61b7012a27f3d6c3186a12a15319..9798a50789ce972c4d9e94419e20a5cd dom::MediaCapabilities* MediaCapabilities(); dom::MediaSession* MediaSession(); diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp -index d2c863bd6549a7e2fbbc09deb99c93cdde6a7199..2639a0e3160250d3cd3c8a8074147039405931a8 100644 +index 1edbffd5353a77fd84bc9abecb0628557512fa67..33376c1d44dbc0561c210e48401d6b173924067d 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp -@@ -8731,7 +8731,8 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8796,7 +8796,8 @@ nsresult nsContentUtils::SendMouseEvent( bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized, @@ -966,7 +975,7 @@ index d2c863bd6549a7e2fbbc09deb99c93cdde6a7199..2639a0e3160250d3cd3c8a8074147039 nsPoint offset; nsCOMPtr widget = GetWidget(aPresShell, &offset); if (!widget) return NS_ERROR_FAILURE; -@@ -8739,6 +8740,7 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8804,6 +8805,7 @@ nsresult nsContentUtils::SendMouseEvent( EventMessage msg; Maybe exitFrom; bool contextMenuKey = false; @@ -974,7 +983,7 @@ index d2c863bd6549a7e2fbbc09deb99c93cdde6a7199..2639a0e3160250d3cd3c8a8074147039 if (aType.EqualsLiteral("mousedown")) { msg = eMouseDown; } else if (aType.EqualsLiteral("mouseup")) { -@@ -8763,6 +8765,12 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8828,6 +8830,12 @@ nsresult nsContentUtils::SendMouseEvent( msg = eMouseHitTest; } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) { msg = eMouseExploreByTouch; @@ -987,7 +996,7 @@ index d2c863bd6549a7e2fbbc09deb99c93cdde6a7199..2639a0e3160250d3cd3c8a8074147039 } else { return NS_ERROR_FAILURE; } -@@ -8771,12 +8779,21 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8836,12 +8844,21 @@ nsresult nsContentUtils::SendMouseEvent( aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE; } @@ -1011,7 +1020,7 @@ index d2c863bd6549a7e2fbbc09deb99c93cdde6a7199..2639a0e3160250d3cd3c8a8074147039 event.pointerId = aIdentifier; event.mModifiers = GetWidgetModifiers(aModifiers); event.mButton = aButton; -@@ -8787,8 +8804,10 @@ nsresult nsContentUtils::SendMouseEvent( +@@ -8852,8 +8869,10 @@ nsresult nsContentUtils::SendMouseEvent( event.mPressure = aPressure; event.mInputSource = aInputSourceArg; event.mClickCount = aClickCount; @@ -1023,10 +1032,10 @@ index d2c863bd6549a7e2fbbc09deb99c93cdde6a7199..2639a0e3160250d3cd3c8a8074147039 nsPresContext* presContext = aPresShell->GetPresContext(); if (!presContext) return NS_ERROR_FAILURE; diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h -index 4291d2c5d1e17b75b2a0f3f26c84b0fbea03b027..18b311c64f825977e2c01ccc9dbfd6cd97ed8778 100644 +index ef3c1fd7cbb3a6c457ec7d70a50fd412077f4279..bd4e6e5db6273f024684169439fd31e0095b45f4 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h -@@ -3065,7 +3065,8 @@ class nsContentUtils { +@@ -3078,7 +3078,8 @@ class nsContentUtils { int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow, mozilla::PreventDefaultResult* aPreventDefault, @@ -1037,10 +1046,10 @@ index 4291d2c5d1e17b75b2a0f3f26c84b0fbea03b027..18b311c64f825977e2c01ccc9dbfd6cd static void FirePageShowEventForFrameLoaderSwap( nsIDocShellTreeItem* aItem, diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp -index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fac10ef5fd 100644 +index 6d611b4a8485325435267c89c88b5511bb37d2f2..13640d6bd8fc34797f5f0088bf12ff016b4b3ae7 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp -@@ -685,6 +685,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) { +@@ -684,6 +684,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) { return NS_ERROR_FAILURE; } @@ -1067,7 +1076,7 @@ index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fa NS_IMETHODIMP nsDOMWindowUtils::SendMouseEvent( const nsAString& aType, float aX, float aY, int32_t aButton, -@@ -699,7 +719,7 @@ nsDOMWindowUtils::SendMouseEvent( +@@ -698,7 +718,7 @@ nsDOMWindowUtils::SendMouseEvent( aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false, aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true, aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false, @@ -1076,7 +1085,7 @@ index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fa } NS_IMETHODIMP -@@ -717,7 +737,7 @@ nsDOMWindowUtils::SendMouseEventToWindow( +@@ -716,7 +736,7 @@ nsDOMWindowUtils::SendMouseEventToWindow( aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true, nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true, aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false, @@ -1085,7 +1094,7 @@ index 9bc8340b9009717e0feecd5c14ff02be07a03daf..70ea04c7f11e6ccfadf72a82ec1741fa } NS_IMETHODIMP -@@ -726,13 +746,13 @@ nsDOMWindowUtils::SendMouseEventCommon( +@@ -725,13 +745,13 @@ nsDOMWindowUtils::SendMouseEventCommon( int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId, bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized, @@ -1115,10 +1124,10 @@ index 63968c9b7a4e418e4c0de6e7a75fa215a36a9105..decf3ea3833ccdffd49a7aded2d600f9 MOZ_CAN_RUN_SCRIPT nsresult SendTouchEventCommon( diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp -index 4e2d60469346772d6dad49b38b06a37c9f819a79..5123a1b40a951f2aa10b1b018c4e72abf18d0d27 100644 +index 587f03849d72d72020e89f4456dec481c9ede9f6..d0a910d3ae25fd4f6545f6d9130c8be04a06ed0e 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp -@@ -1678,6 +1678,10 @@ Maybe nsFocusManager::SetFocusInner(Element* aNewContent, +@@ -1684,6 +1684,10 @@ Maybe nsFocusManager::SetFocusInner(Element* aNewContent, (GetActiveBrowsingContext() == newRootBrowsingContext); } @@ -1129,7 +1138,7 @@ index 4e2d60469346772d6dad49b38b06a37c9f819a79..5123a1b40a951f2aa10b1b018c4e72ab // Exit fullscreen if a website focuses another window if (StaticPrefs::full_screen_api_exit_on_windowRaise() && !isElementInActiveWindow && (aFlags & FLAG_RAISE)) { -@@ -2263,6 +2267,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, +@@ -2269,6 +2273,7 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, bool aIsLeavingDocument, bool aAdjustWidget, bool aRemainActive, Element* aElementToFocus, uint64_t aActionId) { @@ -1137,7 +1146,7 @@ index 4e2d60469346772d6dad49b38b06a37c9f819a79..5123a1b40a951f2aa10b1b018c4e72ab LOGFOCUS(("<>", aActionId)); // hold a reference to the focused content, which may be null -@@ -2309,6 +2314,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, +@@ -2315,6 +2320,11 @@ bool nsFocusManager::BlurImpl(BrowsingContext* aBrowsingContextToClear, return true; } @@ -1149,7 +1158,7 @@ index 4e2d60469346772d6dad49b38b06a37c9f819a79..5123a1b40a951f2aa10b1b018c4e72ab // Keep a ref to presShell since dispatching the DOM event may cause // the document to be destroyed. RefPtr presShell = docShell->GetPresShell(); -@@ -2986,7 +2996,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow, +@@ -2992,7 +3002,9 @@ void nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow, } } @@ -1161,7 +1170,7 @@ index 4e2d60469346772d6dad49b38b06a37c9f819a79..5123a1b40a951f2aa10b1b018c4e72ab // care of lowering the present active window. This happens in // a separate runnable to avoid touching multiple windows in diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp -index c678a0a94150e73c6f5cd086c91a9848d4d0cfb8..0b362540bab495bffcf8a336351650f5897e0af5 100644 +index 460ccc17f2cd34f172215aaf5616badaa44f8ca5..d294373ca9b8987dd8bf056f4dae72c27903dcd7 100644 --- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -2514,10 +2514,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument, @@ -1206,7 +1215,7 @@ index c678a0a94150e73c6f5cd086c91a9848d4d0cfb8..0b362540bab495bffcf8a336351650f5 void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) { diff --git a/dom/base/nsGlobalWindowOuter.h b/dom/base/nsGlobalWindowOuter.h -index 3c26344c3d45c57606d498008946fc480cd2eb96..b02909587341860ad805072755761474029f6eec 100644 +index 0039d6d91b23953afbd6aec2b4d1f064db3c3b1c..7a6c5da16651d34ea60c69331365d94886da1993 100644 --- a/dom/base/nsGlobalWindowOuter.h +++ b/dom/base/nsGlobalWindowOuter.h @@ -314,6 +314,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget, @@ -1218,10 +1227,10 @@ index 3c26344c3d45c57606d498008946fc480cd2eb96..b02909587341860ad805072755761474 // Outer windows only. virtual void EnsureSizeAndPositionUpToDate() override; diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp -index 6c77574df7973f12a5afd28bd9eb2bf5c4ae91ff..76feda136c7e39b0ebe3333714b41347ecc6aef2 100644 +index 600fce143a0e1e35a18b980211686436be08533f..ec6f7c60d0a3756dcf8892e4690281e1a65f9b6a 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp -@@ -1388,6 +1388,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions, +@@ -1387,6 +1387,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions, mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv); } @@ -1284,10 +1293,10 @@ index 6c77574df7973f12a5afd28bd9eb2bf5c4ae91ff..76feda136c7e39b0ebe3333714b41347 DOMQuad& aQuad, const GeometryNode& aFrom, const ConvertCoordinateOptions& aOptions, CallerType aCallerType, diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h -index d2a2fd008d15b5aa4534df1d7298108980bff41d..df86f5d534b4718bf1912da305fa2548a04637dc 100644 +index 2906bbb56c86cd287620b4bd067366f6703299d7..06697f07c7544c816181fa9849ce178bf38303aa 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h -@@ -2265,6 +2265,10 @@ class nsINode : public mozilla::dom::EventTarget { +@@ -2282,6 +2282,10 @@ class nsINode : public mozilla::dom::EventTarget { nsTArray>& aResult, ErrorResult& aRv); @@ -1468,7 +1477,7 @@ index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1 ~Geolocation(); diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp -index 958601616b8f5749ae704b0cdd8a0c5a397dc021..87fa7c434f852b4203beec320d7b27bbcfc108ef 100644 +index 30093e5d408caa054a04adddf63ce2bec384eed6..2852746b6f5b50981dba29a65ce25c1fd55390e3 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -57,6 +57,7 @@ @@ -1494,7 +1503,7 @@ index 958601616b8f5749ae704b0cdd8a0c5a397dc021..87fa7c434f852b4203beec320d7b27bb return NS_OK; } diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl -index 27b9ff5acf8b1100a3b55d55cc390a15b2a3e3a4..7e8e2264dd4bb814cca5b00de80fcd5ce5c4be4d 100644 +index 9d185e8e7edcde63f0d2e0c05a32dfddaf71609c..9d48d2e33575c7f214152c6f8140f9a3a3313b44 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -373,6 +373,26 @@ interface nsIDOMWindowUtils : nsISupports { @@ -1525,10 +1534,10 @@ index 27b9ff5acf8b1100a3b55d55cc390a15b2a3e3a4..7e8e2264dd4bb814cca5b00de80fcd5c * touchstart, touchend, touchmove, and touchcancel * diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp -index 3d1f399edb4feb0793c214917464be2599739e6e..1d4a176b1a111a9415710f1bf1db1323620e4ee0 100644 +index 27fb1239dbd2a635688d022602d4a49dfff0560a..39f9dd48eef038503a50632c5e1395fecea6cae3 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp -@@ -1652,6 +1652,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent, +@@ -1639,6 +1639,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent, if (postLayerization) { postLayerization->Register(); } @@ -1565,15 +1574,12 @@ index 5aa445d2e0a6169e57c44569974d557b3baf7064..671f71979b407f0ca17c66f13805e851 } diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.cc b/dom/media/systemservices/video_engine/desktop_capture_impl.cc -index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d15e8431f 100644 +index d4b40fda96ea759eb92e1351e1046a9e0b85689b..b2123a3be05b2622a5e07d5ee32752d0feaaa57f 100644 --- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc +++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc -@@ -135,11 +135,12 @@ int32_t ScreenDeviceInfoImpl::GetOrientation(const char* aDeviceUniqueIdUTF8, - return 0; - } +@@ -137,9 +137,10 @@ int32_t ScreenDeviceInfoImpl::GetOrientation(const char* aDeviceUniqueIdUTF8, --VideoCaptureModule* DesktopCaptureImpl::Create(const int32_t aModuleId, -+VideoCaptureModuleEx* DesktopCaptureImpl::Create(const int32_t aModuleId, + DesktopCaptureImpl* DesktopCaptureImpl::Create(const int32_t aModuleId, const char* aUniqueId, - const CaptureDeviceType aType) { + const CaptureDeviceType aType, @@ -1653,7 +1659,7 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d MOZ_ASSERT(!capturer == !mCaptureThread); if (!capturer) { -@@ -654,6 +672,15 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result aResult, +@@ -663,6 +681,15 @@ void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result aResult, frameInfo.height = aFrame->size().height(); frameInfo.videoType = VideoType::kARGB; @@ -1670,18 +1676,18 @@ index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel; diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.h b/dom/media/systemservices/video_engine/desktop_capture_impl.h -index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a6e3c4e75 100644 +index 9aebaa39321839eb3beb503fc4ed33e303bb0deb..1dd75f3cdb8078b01c4d43a0ac3d8a6ea3ec47ab 100644 --- a/dom/media/systemservices/video_engine/desktop_capture_impl.h +++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h -@@ -24,6 +24,7 @@ - #include "api/video/video_sink_interface.h" +@@ -25,6 +25,7 @@ #include "modules/desktop_capture/desktop_capturer.h" #include "modules/video_capture/video_capture.h" + #include "rtc_base/synchronization/mutex.h" +#include "rtc_base/deprecated/recursive_critical_section.h" #include "desktop_device_info.h" - #include "mozilla/DataMutex.h" -@@ -43,6 +44,21 @@ namespace webrtc { + #include "MediaEngineSource.h" +@@ -45,6 +46,33 @@ namespace webrtc { class VideoCaptureEncodeInterface; @@ -1698,12 +1704,24 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a + + virtual void RegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) = 0; + virtual void DeRegisterRawFrameCallback(RawFrameCallback* rawFrameCallback) = 0; ++ int32_t StartCaptureCounted(const VideoCaptureCapability& aCapability) { ++ ++capture_counter_; ++ return capture_counter_ == 1 ? StartCapture(aCapability) : 0; ++ } ++ ++ int32_t StopCaptureCounted() { ++ --capture_counter_; ++ return capture_counter_ == 0 ? StopCapture() : 0; ++ } ++ ++ private: ++ int32_t capture_counter_ = 0; +}; + // simulate deviceInfo interface for video engine, bridge screen/application and // real screen/application device info -@@ -158,13 +174,13 @@ class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo { +@@ -160,13 +188,13 @@ class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo { // As with video, DesktopCaptureImpl is a proxy for screen sharing // and follows the video pipeline design class DesktopCaptureImpl : public DesktopCapturer::Callback, @@ -1712,15 +1730,14 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a public: /* Create a screen capture modules object */ -- static VideoCaptureModule* Create( -+ static VideoCaptureModuleEx* Create( + static DesktopCaptureImpl* Create( const int32_t aModuleId, const char* aUniqueId, - const mozilla::camera::CaptureDeviceType aType); + const mozilla::camera::CaptureDeviceType aType, bool aCaptureCursor = true); [[nodiscard]] static std::shared_ptr CreateDeviceInfo(const int32_t aId, -@@ -178,6 +194,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -180,6 +208,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, void DeRegisterCaptureDataCallback( rtc::VideoSinkInterface* aCallback) override; int32_t StopCaptureIfAllClientsClose() override; @@ -1729,7 +1746,7 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a int32_t SetCaptureRotation(VideoRotation aRotation) override; bool SetApplyRotation(bool aEnable) override; -@@ -200,7 +218,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -203,7 +233,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, protected: DesktopCaptureImpl(const int32_t aId, const char* aUniqueId, @@ -1739,7 +1756,7 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a virtual ~DesktopCaptureImpl(); private: -@@ -208,6 +227,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -211,6 +242,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, static constexpr uint32_t kMaxDesktopCaptureCpuUsage = 50; void InitOnThread(std::unique_ptr aCapturer, int aFramerate); void ShutdownOnThread(); @@ -1749,7 +1766,7 @@ index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a // DesktopCapturer::Callback interface. void OnCaptureResult(DesktopCapturer::Result aResult, std::unique_ptr aFrame) override; -@@ -215,6 +237,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, +@@ -218,6 +252,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback, // Notifies all mCallbacks of OnFrame(). mCaptureThread only. void NotifyOnFrame(const VideoFrame& aFrame); @@ -1803,7 +1820,7 @@ index 3b39538e51840cd9b1685b2efd2ff2e9ec83608a..c7bf4f2d53b58bbacb22b3ebebf6f3fc return aGlobalOrNull; diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp -index 11d09909f73fee425fd0f50b384c396a52e02a36..b0e668881bcd3b850de709ebf2557ae8391b8fe8 100644 +index f4aecfaf44d40d651f816c56db4b46c605754132..ef017504972454c12de7d6a7ff38a76a8253a62d 100644 --- a/dom/security/nsCSPUtils.cpp +++ b/dom/security/nsCSPUtils.cpp @@ -22,6 +22,7 @@ @@ -1812,9 +1829,9 @@ index 11d09909f73fee425fd0f50b384c396a52e02a36..b0e668881bcd3b850de709ebf2557ae8 #include "nsWhitespaceTokenizer.h" +#include "nsDocShell.h" + #include "mozilla/Assertions.h" #include "mozilla/Components.h" - #include "mozilla/dom/CSPDictionariesBinding.h" -@@ -132,6 +133,11 @@ void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc, +@@ -133,6 +134,11 @@ void CSP_ApplyMetaCSPToDoc(mozilla::dom::Document& aDoc, return; } @@ -1850,10 +1867,10 @@ index 2f71b284ee5f7e11f117c447834b48355784448c..2640bd57123c2b03bf4b06a2419cd020 * returned quads are further translated relative to the window * origin -- which is not the layout origin. Further translation diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp -index 321895e700a3129febba908fd7f35664c56ff637..375596973393158c7ff4586105451c336f63b5a0 100644 +index 4a7ebb25233ce685e73d53085e22337e9ad8bc59..0b7b24a4da5511ff2fa6695eb55f5533b2e574ab 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp -@@ -1001,7 +1001,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) { +@@ -998,7 +998,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) { AssertIsOnMainThread(); nsTArray languages; @@ -1862,7 +1879,7 @@ index 321895e700a3129febba908fd7f35664c56ff637..375596973393158c7ff4586105451c33 RuntimeService* runtime = RuntimeService::GetService(); if (runtime) { -@@ -1188,8 +1188,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) { +@@ -1185,8 +1185,7 @@ bool RuntimeService::RegisterWorker(WorkerPrivate& aWorkerPrivate) { } // The navigator overridden properties should have already been read. @@ -1886,7 +1903,7 @@ index 321895e700a3129febba908fd7f35664c56ff637..375596973393158c7ff4586105451c33 template void RuntimeService::BroadcastAllWorkers(const Func& aFunc) { AssertIsOnMainThread(); -@@ -2310,6 +2316,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers( +@@ -2314,6 +2320,14 @@ void PropagateStorageAccessPermissionGrantedToWorkers( } } @@ -1928,7 +1945,7 @@ index d10dabb5c5ff8e17851edf2bd2efc08e74584d8e..53c4070c5fde43b27fb8fbfdcf4c23d8 bool IsWorkerGlobal(JSObject* global); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp -index df248acda417ae2f304a7f5fa5d067912e402431..5a5b07409c6bca2c8cd80f4595c4e524b56566ef 100644 +index 7fbfdb0eeed2fc9d9a6ba12192150d5bdeed40b3..c31ae2724d09036ec2ba0b71cd94f648e9b90868 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -682,6 +682,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable { @@ -1938,7 +1955,7 @@ index df248acda417ae2f304a7f5fa5d067912e402431..5a5b07409c6bca2c8cd80f4595c4e524 +class ResetDefaultLocaleRunnable final : public WorkerControlRunnable { + public: + explicit ResetDefaultLocaleRunnable(WorkerPrivate* aWorkerPrivate) -+ : WorkerControlRunnable(aWorkerPrivate, "ResetDefaultLocaleRunnable", WorkerThread) {} ++ : WorkerControlRunnable("ResetDefaultLocaleRunnable") {} + + virtual bool WorkerRun(JSContext* aCx, + WorkerPrivate* aWorkerPrivate) override { @@ -1947,10 +1964,10 @@ index df248acda417ae2f304a7f5fa5d067912e402431..5a5b07409c6bca2c8cd80f4595c4e524 + } +}; + - class UpdateLanguagesRunnable final : public WorkerRunnable { + class UpdateLanguagesRunnable final : public WorkerThreadRunnable { nsTArray mLanguages; -@@ -1992,6 +2004,16 @@ void WorkerPrivate::UpdateContextOptions( +@@ -2091,6 +2103,16 @@ void WorkerPrivate::UpdateContextOptions( } } @@ -1959,7 +1976,7 @@ index df248acda417ae2f304a7f5fa5d067912e402431..5a5b07409c6bca2c8cd80f4595c4e524 + + RefPtr runnable = + new ResetDefaultLocaleRunnable(this); -+ if (!runnable->Dispatch()) { ++ if (!runnable->Dispatch(this)) { + NS_WARNING("Failed to reset default locale in worker!"); + } +} @@ -1967,7 +1984,7 @@ index df248acda417ae2f304a7f5fa5d067912e402431..5a5b07409c6bca2c8cd80f4595c4e524 void WorkerPrivate::UpdateLanguages(const nsTArray& aLanguages) { AssertIsOnParentThread(); -@@ -5509,6 +5531,15 @@ void WorkerPrivate::UpdateContextOptionsInternal( +@@ -5667,6 +5689,15 @@ void WorkerPrivate::UpdateContextOptionsInternal( } } @@ -1984,10 +2001,10 @@ index df248acda417ae2f304a7f5fa5d067912e402431..5a5b07409c6bca2c8cd80f4595c4e524 const nsTArray& aLanguages) { WorkerGlobalScope* globalScope = GlobalScope(); diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h -index ce754ba9f6c23544f9c4b0393e3a3d1f9dcd24c1..caa917248fdd6594792d17c23e75329f35ae1e75 100644 +index 57212e01fb75da52187195acfbe052b19464286a..bc75882ee661d5c987187cd11b388443227d59bc 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h -@@ -417,6 +417,8 @@ class WorkerPrivate final +@@ -418,6 +418,8 @@ class WorkerPrivate final void UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions); @@ -1996,7 +2013,7 @@ index ce754ba9f6c23544f9c4b0393e3a3d1f9dcd24c1..caa917248fdd6594792d17c23e75329f void UpdateLanguagesInternal(const nsTArray& aLanguages); void UpdateJSWorkerMemoryParameterInternal(JSContext* aCx, JSGCParamKey key, -@@ -1034,6 +1036,8 @@ class WorkerPrivate final +@@ -1045,6 +1047,8 @@ class WorkerPrivate final void UpdateContextOptions(const JS::ContextOptions& aContextOptions); @@ -2058,7 +2075,7 @@ index 523e84c8c93f4221701f90f2e8ee146ec8e1adbd..98d5b1176e5378431b859a2dbd4d4e77 inline ClippedTime TimeClip(double time); diff --git a/js/src/debugger/Object.cpp b/js/src/debugger/Object.cpp -index 17528b0fd99ce8274e702746ff5674de4c3d4f2d..37fa52ae07381bec3504136b9bec0aa1ca110d6b 100644 +index 6ca6c31830066f9677988daca8566e93a8335c26..3f963dbf6127c997810e380802e56b023b5db4c8 100644 --- a/js/src/debugger/Object.cpp +++ b/js/src/debugger/Object.cpp @@ -2468,7 +2468,11 @@ Maybe DebuggerObject::call(JSContext* cx, @@ -2074,7 +2091,7 @@ index 17528b0fd99ce8274e702746ff5674de4c3d4f2d..37fa52ae07381bec3504136b9bec0aa1 } diff --git a/js/src/vm/DateTime.cpp b/js/src/vm/DateTime.cpp -index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd67623e7d2 100644 +index 623a6863a54fb0d653ebe55fd83356f1a8c8be15..1c0ef7b0d3ee2f61de728a68dd704a5d09757b38 100644 --- a/js/src/vm/DateTime.cpp +++ b/js/src/vm/DateTime.cpp @@ -186,6 +186,11 @@ void js::DateTimeInfo::internalResetTimeZone(ResetTimeZoneMode mode) { @@ -2089,7 +2106,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 void js::DateTimeInfo::updateTimeZone() { MOZ_ASSERT(timeZoneStatus_ != TimeZoneStatus::Valid); -@@ -527,10 +532,24 @@ void js::ResetTimeZoneInternal(ResetTimeZoneMode mode) { +@@ -529,10 +534,24 @@ void js::ResetTimeZoneInternal(ResetTimeZoneMode mode) { js::DateTimeInfo::resetTimeZone(mode); } @@ -2114,7 +2131,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 #if JS_HAS_INTL_API # if defined(XP_WIN) static bool IsOlsonCompatibleWindowsTimeZoneId(std::string_view tz) { -@@ -748,6 +767,15 @@ static bool ReadTimeZoneLink(std::string_view tz, +@@ -750,6 +769,15 @@ static bool ReadTimeZoneLink(std::string_view tz, void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { #if JS_HAS_INTL_API @@ -2130,7 +2147,7 @@ index 21ecc2e9f50a16357ace3320335d31a4929fc146..c4b1444ce53b20a700d2ff9f18521bd6 // In the future we should not be setting a default ICU time zone at all, // instead all accesses should go through the appropriate DateTimeInfo // instance depending on the resist fingerprinting status. For now we return -@@ -759,7 +787,6 @@ void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { +@@ -761,7 +789,6 @@ void js::DateTimeInfo::internalResyncICUDefaultTimeZone() { if (const char* tzenv = std::getenv("TZ")) { std::string_view tz(tzenv); @@ -2178,7 +2195,7 @@ index fd6d7ae078b8f6b3cc46a4a993a1e044a7128c90..4743094e489122dd9ee8ab9a7a175dd7 void internalResyncICUDefaultTimeZone(); diff --git a/layout/base/GeometryUtils.cpp b/layout/base/GeometryUtils.cpp -index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2d9b789cf 100644 +index 0ec6ee3eb37c6493d8a25352fd0e54e1927bceab..885dba71bc5815e5f6f3ec2700c376aa119b30d0 100644 --- a/layout/base/GeometryUtils.cpp +++ b/layout/base/GeometryUtils.cpp @@ -23,6 +23,7 @@ @@ -2228,10 +2245,10 @@ index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2 // No boxes to return return; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp -index 7674abb3d07fb1958eed38e730be83a2b56f75f2..f88a1a3bd6f1df7ebbdd836d82c677de043c5f41 100644 +index 6e588cff05c8d6fdaec53a980fce1bc8d2141953..a173b1154e171d7fa5454b27baf85f72a09501a6 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp -@@ -11205,7 +11205,9 @@ bool PresShell::ComputeActiveness() const { +@@ -11063,7 +11063,9 @@ bool PresShell::ComputeActiveness() const { if (!browserChild->IsVisible()) { MOZ_LOG(gLog, LogLevel::Debug, (" > BrowserChild %p is not visible", browserChild)); @@ -2243,10 +2260,10 @@ index 7674abb3d07fb1958eed38e730be83a2b56f75f2..f88a1a3bd6f1df7ebbdd836d82c677de // If the browser is visible but just due to be preserving layers diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp -index 429ad335cc148353b4a094f8fb6eff0dfe48012a..8b45056e6f055aa00bb4e43f0f24e6cbf00d1335 100644 +index 2ed62888d70663f3560fcaa9bc29ff98cb44c323..f5540c38df6a064094e013c841d943c63049dd75 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp -@@ -713,6 +713,10 @@ bool nsLayoutUtils::AllowZoomingForDocument( +@@ -698,6 +698,10 @@ bool nsLayoutUtils::AllowZoomingForDocument( !aDocument->GetPresShell()->AsyncPanZoomEnabled()) { return false; } @@ -2257,7 +2274,7 @@ index 429ad335cc148353b4a094f8fb6eff0dfe48012a..8b45056e6f055aa00bb4e43f0f24e6cb // True if we allow zooming for all documents on this platform, or if we are // in RDM. BrowsingContext* bc = aDocument->GetBrowsingContext(); -@@ -9764,6 +9768,9 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont, +@@ -9794,6 +9798,9 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont, /* static */ bool nsLayoutUtils::ShouldHandleMetaViewport(const Document* aDocument) { @@ -2268,10 +2285,10 @@ index 429ad335cc148353b4a094f8fb6eff0dfe48012a..8b45056e6f055aa00bb4e43f0f24e6cb return StaticPrefs::dom_meta_viewport_enabled() || (bc && bc->InRDMPane()); } diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h -index 7bb839ae18835d128dc9285b7f9dc5b5e06335af..09e3979d07447522ace740daf2b818a6c551ceba 100644 +index d273793fc8d92b5c19ec0562730eab249cc41eb8..46b4078c6031318265a8338e01f52ab60bd9c0e8 100644 --- a/layout/style/GeckoBindings.h +++ b/layout/style/GeckoBindings.h -@@ -625,6 +625,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*); +@@ -596,6 +596,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*); bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*); bool Gecko_MediaFeatures_PrefersReducedTransparency( const mozilla::dom::Document*); @@ -2280,7 +2297,7 @@ index 7bb839ae18835d128dc9285b7f9dc5b5e06335af..09e3979d07447522ace740daf2b818a6 const mozilla::dom::Document*); mozilla::StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme( diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp -index fbdde4102dd7872d460760580e93657a6aeb07bd..d51a927f8d5c4788f10ae94543b1630e9dd4420a 100644 +index cc86d1abf6ccfe48530607c41cd675612cbe5582..8cce20c719fee8a0480ae6ea1fd53c6639d0bd7b 100644 --- a/layout/style/nsMediaFeatures.cpp +++ b/layout/style/nsMediaFeatures.cpp @@ -260,11 +260,11 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) { @@ -2301,10 +2318,10 @@ index fbdde4102dd7872d460760580e93657a6aeb07bd..d51a927f8d5c4788f10ae94543b1630e bool Gecko_MediaFeatures_PrefersReducedTransparency(const Document* aDocument) { diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp -index 6be031113fb1197aa6eecbf6fc109147ca6ee5b1..f836dde97895d4b1177bfcebcaab6420abd855b8 100644 +index 5ff1c5ad8b265f25ab5a18a639e4e5b420d93443..a788218d4f281daee274d14b7dd15f4c19eeddce 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp -@@ -657,7 +657,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) +@@ -691,7 +691,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) mInterceptionInfo(rhs.mInterceptionInfo), mHasInjectedCookieForCookieBannerHandling( rhs.mHasInjectedCookieForCookieBannerHandling), @@ -2314,7 +2331,7 @@ index 6be031113fb1197aa6eecbf6fc109147ca6ee5b1..f836dde97895d4b1177bfcebcaab6420 } LoadInfo::LoadInfo( -@@ -2373,4 +2374,16 @@ LoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) { +@@ -2416,4 +2417,16 @@ LoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) { return NS_OK; } @@ -2332,10 +2349,10 @@ index 6be031113fb1197aa6eecbf6fc109147ca6ee5b1..f836dde97895d4b1177bfcebcaab6420 + } // namespace mozilla::net diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h -index a8631b09b26708ca10f683f1a9dd6b8467d3fe8e..a0bd72113e3539d815d32382946581ee62f39b6c 100644 +index e6badeeee816bc74af22fb9ef5f88b58f13ac5b7..994216ee9b26e7cbc85b948165051d5d2bc7efb1 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h -@@ -401,6 +401,8 @@ class LoadInfo final : public nsILoadInfo { +@@ -408,6 +408,8 @@ class LoadInfo final : public nsILoadInfo { bool mHasInjectedCookieForCookieBannerHandling = false; bool mWasSchemelessInput = false; @@ -2345,10 +2362,10 @@ index a8631b09b26708ca10f683f1a9dd6b8467d3fe8e..a0bd72113e3539d815d32382946581ee // This is exposed solely for testing purposes and should not be used outside of diff --git a/netwerk/base/TRRLoadInfo.cpp b/netwerk/base/TRRLoadInfo.cpp -index 920e7623a7f912296fc23361f66ab35a30c35f1e..dfea0d0f7a72da9699615d7ff778e429e7ae40fb 100644 +index 48560a8b3be4ace3aab241373ff1eab0e5bb2187..b2114472b04b4e837b1c7b080ce8718f5f67f43b 100644 --- a/netwerk/base/TRRLoadInfo.cpp +++ b/netwerk/base/TRRLoadInfo.cpp -@@ -861,5 +861,15 @@ TRRLoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) { +@@ -870,5 +870,15 @@ TRRLoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) { return NS_ERROR_NOT_IMPLEMENTED; } @@ -2365,10 +2382,10 @@ index 920e7623a7f912296fc23361f66ab35a30c35f1e..dfea0d0f7a72da9699615d7ff778e429 } // namespace net } // namespace mozilla diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl -index ddfcb223e6126c943b58e9d198f0e2fa767c3de1..4280b836c55e5778ad4c94226ea537facb19c436 100644 +index 8ff5e556c98689542297517a7bdf57e0a2ccf400..b1429dbe180cbc84cf467991bb24124f5857d62b 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl -@@ -1532,4 +1532,6 @@ interface nsILoadInfo : nsISupports +@@ -1544,4 +1544,6 @@ interface nsILoadInfo : nsISupports * Whether the load has gone through the URL bar, where the fixup had to add * the protocol scheme. */ [infallible] attribute boolean wasSchemelessInput; @@ -2376,7 +2393,7 @@ index ddfcb223e6126c943b58e9d198f0e2fa767c3de1..4280b836c55e5778ad4c94226ea537fa + [infallible] attribute unsigned long long jugglerLoadIdentifier; }; diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl -index 946cc95a8806644f88d38a7b1c7b9c0614e3cbff..a7b92019c5bbf356d1bbacfbff8fca9a041cf62a 100644 +index 7f91d2df6f8bb4020c75c132dc8f6bf26625fa1e..ba6569f4be8fc54ec96ee44d5de45a0904c077ba 100644 --- a/netwerk/base/nsINetworkInterceptController.idl +++ b/netwerk/base/nsINetworkInterceptController.idl @@ -59,6 +59,7 @@ interface nsIInterceptedChannel : nsISupports @@ -2388,10 +2405,10 @@ index 946cc95a8806644f88d38a7b1c7b9c0614e3cbff..a7b92019c5bbf356d1bbacfbff8fca9a /** * Set the status and reason for the forthcoming synthesized response. diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp -index 32d7036ff18828ec8938a8dc0a98ad3297132706..65585e719dda8f62319a5fc34baf69c59e51162c 100644 +index dfd80e8867ec46464ddcfc30316236c824950cb1..a702bbe63cf56984519000854e9f487dcac3cee4 100644 --- a/netwerk/ipc/DocumentLoadListener.cpp +++ b/netwerk/ipc/DocumentLoadListener.cpp -@@ -167,6 +167,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext, +@@ -168,6 +168,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext, loadInfo->SetHasValidUserGestureActivation( aLoadState->HasValidUserGestureActivation()); loadInfo->SetIsMetaRefresh(aLoadState->IsMetaRefresh()); @@ -2400,7 +2417,7 @@ index 32d7036ff18828ec8938a8dc0a98ad3297132706..65585e719dda8f62319a5fc34baf69c5 return loadInfo.forget(); } diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp -index c58fbc96391f8dcb585bd00b5ae8cba9088abd82..c121c891b61c9d60df770020c4ad09521d2bbfe6 100644 +index 5695d46f924abe6b765f3645d746cc4248051c1c..d28ead55f6a8458f70ca43c693e7396c5dc53858 100644 --- a/netwerk/protocol/http/InterceptedHttpChannel.cpp +++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp @@ -727,6 +727,14 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor) @@ -2438,10 +2455,10 @@ index c58fbc96391f8dcb585bd00b5ae8cba9088abd82..c121c891b61c9d60df770020c4ad0952 if (mPump && mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) { mPump->PeekStream(CallTypeSniffers, static_cast(this)); diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp -index f2c47c42a6b6448ede3a6fef1510a3982336d5af..9e35df57102c93238de2e4d548bbe1205d227f3b 100644 +index f25949e6cc907ff18a76d68fc2e8005bd40146ea..9be4cb34517b06b94c6e145aef8a8ea5d2687d97 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp -@@ -1382,6 +1382,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( +@@ -1389,6 +1389,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta( void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -2453,10 +2470,10 @@ index f2c47c42a6b6448ede3a6fef1510a3982336d5af..9e35df57102c93238de2e4d548bbe120 nsCOMPtr preloadCsp = mDocument->GetPreloadCsp(); if (!preloadCsp) { diff --git a/security/manager/ssl/nsCertOverrideService.cpp b/security/manager/ssl/nsCertOverrideService.cpp -index b8d0bbc3a12f74c19284b26eadada361abeb7946..a50379c57158748684e2ea5065550af81c1e9b86 100644 +index fcc2a45e6de8eaeb1af2404a69bd3df58cf2aec8..d4c1df007bf5993cf9e0dadbe91aa2c38afc42ec 100644 --- a/security/manager/ssl/nsCertOverrideService.cpp +++ b/security/manager/ssl/nsCertOverrideService.cpp -@@ -438,7 +438,12 @@ nsCertOverrideService::HasMatchingOverride( +@@ -437,7 +437,12 @@ nsCertOverrideService::HasMatchingOverride( bool disableAllSecurityCheck = false; { MutexAutoLock lock(mMutex); @@ -2470,7 +2487,7 @@ index b8d0bbc3a12f74c19284b26eadada361abeb7946..a50379c57158748684e2ea5065550af8 } if (disableAllSecurityCheck) { *aIsTemporary = false; -@@ -650,14 +655,24 @@ static bool IsDebugger() { +@@ -649,14 +654,24 @@ static bool IsDebugger() { NS_IMETHODIMP nsCertOverrideService:: @@ -2573,7 +2590,7 @@ index df1c5e464b845b6a8bfedadb86d0e7aab7fd3ffc..34451e791bb59f635134de702d9e5f64 } diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl -index 517c87a285dd93220cb2654d6ba7bb05c66cdeb7..e3010421d8dbe5ed5ed72feedb9f15805b32503e 100644 +index 217beda78edf31bab4c37209964d7a5bf5425195..7ba723410eb93328a8f078c58a96eefc2599feea 100644 --- a/toolkit/components/browser/nsIWebBrowserChrome.idl +++ b/toolkit/components/browser/nsIWebBrowserChrome.idl @@ -74,6 +74,9 @@ interface nsIWebBrowserChrome : nsISupports @@ -2603,6 +2620,19 @@ index 00a5381133f8cec0de452c31c7151801a1acc0b9..5d3e3d6f566dc724f257beaeb994ceda let provider = this._chooseProvider(); if (provider.failed) { +diff --git a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp +index 32b1ac481382dd6aa3dda5572f013c2447a1a004..808031fbeb9b99b67c13c99c66b1aa1aff41f48a 100644 +--- a/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp ++++ b/toolkit/components/resistfingerprinting/nsUserCharacteristics.cpp +@@ -525,7 +525,7 @@ void PopulateLanguages() { + // sufficient to only collect this information as the other properties are + // just reformats of Navigator::GetAcceptLanguages. + nsTArray languages; +- dom::Navigator::GetAcceptLanguages(languages); ++ dom::Navigator::GetAcceptLanguages(nullptr, languages); + nsCString output = "["_ns; + + for (const auto& language : languages) { diff --git a/toolkit/components/startup/nsAppStartup.cpp b/toolkit/components/startup/nsAppStartup.cpp index 3314cb813f6ceb67096eeda0864ad3b16c0616cb..5aac63649e186d624a9905a5d16513f8353f5515 100644 --- a/toolkit/components/startup/nsAppStartup.cpp @@ -2632,10 +2662,10 @@ index 654903fadb709be976b72f36f155e23bc0622152..815b3dc24c9fda6b1db6c4666ac68904 int32_t aMaxSelfProgress, int32_t aCurTotalProgress, diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp -index b482214d31fe2a50ad075b424bc3f97edbc5148b..bd93fd73f165ef1da6422c6b8f141f0a82d77f0f 100644 +index 0767cb1539f940e5f634b58de44d876606903a09..dc0d72b4ff36d5ba7808528aefecb33f05b6672c 100644 --- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp +++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp -@@ -1853,7 +1853,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( +@@ -1861,7 +1861,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent( // Open a minimal popup. *aIsPopupRequested = true; @@ -2649,20 +2679,20 @@ index b482214d31fe2a50ad075b424bc3f97edbc5148b..bd93fd73f165ef1da6422c6b8f141f0a /** diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs -index 34bf1b9e19ae54f78d134b023af96820bc13a905..b85793edcd1996833420a026cb08706d648ece14 100644 +index deaed885c759d8e53ebf0beb53c5b7c4d4bd82f0..8e01e16490ab063361220d363494dfdf00442342 100644 --- a/toolkit/mozapps/update/UpdateService.sys.mjs +++ b/toolkit/mozapps/update/UpdateService.sys.mjs -@@ -3852,6 +3852,8 @@ UpdateService.prototype = { - }, +@@ -3875,6 +3875,8 @@ export class UpdateService { + } get disabledForTesting() { + /* playwright */ + return true; - return ( - (Cu.isInAutomation || - lazy.Marionette.running || + return lazy.UpdateServiceStub.updateDisabledForTesting; + } + diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild -index b697eb1e3b02b0ffcc95a6e492dc23eb888488cc..0f4059341dbb3c2ecb2c46be0850e0d56e2a7453 100644 +index 8c2b2bf996bd889651dc7fac1dc351b4c47b567e..07d237eb17a657ce051fd0aa5e53449c0c3159f6 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -155,6 +155,7 @@ if CONFIG["ENABLE_WEBDRIVER"]: @@ -2726,7 +2756,7 @@ index fe72a2715da8846146377e719559c16e6ef1f7ff..a5959143bac8f62ee359fa3883a844f3 // nsDocumentViewer::LoadComplete that doesn't do various things // that are not relevant here because this wasn't an actual diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp -index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295ea050b878 100644 +index b9120ededd25707c90f33f65d3cead26433efdac..4d5728a73786d804d6b32da4d42934da2864eda1 100644 --- a/uriloader/exthandler/nsExternalHelperAppService.cpp +++ b/uriloader/exthandler/nsExternalHelperAppService.cpp @@ -112,6 +112,7 @@ @@ -2750,7 +2780,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e nsresult nsExternalHelperAppService::GetFileTokenForPath( const char16_t* aPlatformAppPath, nsIFile** aFile) { nsDependentString platformAppPath(aPlatformAppPath); -@@ -1442,7 +1449,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) { +@@ -1441,7 +1448,12 @@ nsresult nsExternalAppHandler::SetUpTempFile(nsIChannel* aChannel) { // Strip off the ".part" from mTempLeafName mTempLeafName.Truncate(mTempLeafName.Length() - ArrayLength(".part") + 1); @@ -2763,7 +2793,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e mSaver = do_CreateInstance(NS_BACKGROUNDFILESAVERSTREAMLISTENER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); -@@ -1631,7 +1643,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { +@@ -1630,7 +1642,36 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { return NS_OK; } @@ -2801,7 +2831,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e if (NS_FAILED(rv)) { nsresult transferError = rv; -@@ -1683,6 +1724,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { +@@ -1682,6 +1723,9 @@ NS_IMETHODIMP nsExternalAppHandler::OnStartRequest(nsIRequest* request) { bool alwaysAsk = true; mMimeInfo->GetAlwaysAskBeforeHandling(&alwaysAsk); @@ -2811,7 +2841,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e if (alwaysAsk) { // But we *don't* ask if this mimeInfo didn't come from // our user configuration datastore and the user has said -@@ -2199,6 +2243,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver, +@@ -2198,6 +2242,16 @@ nsExternalAppHandler::OnSaveComplete(nsIBackgroundFileSaver* aSaver, NotifyTransfer(aStatus); } @@ -2828,7 +2858,7 @@ index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295e return NS_OK; } -@@ -2680,6 +2734,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { +@@ -2679,6 +2733,15 @@ NS_IMETHODIMP nsExternalAppHandler::Cancel(nsresult aReason) { } } @@ -2987,7 +3017,7 @@ diff --git a/widget/cocoa/NativeKeyBindings.mm b/widget/cocoa/NativeKeyBindings. index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce8050630a1aa 100644 --- a/widget/cocoa/NativeKeyBindings.mm +++ b/widget/cocoa/NativeKeyBindings.mm -@@ -528,6 +528,13 @@ void NativeKeyBindings::GetEditCommandsForTests( +@@ -528,6 +528,13 @@ break; case KEY_NAME_INDEX_ArrowLeft: if (aEvent.IsAlt()) { @@ -3001,7 +3031,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) { -@@ -550,6 +557,13 @@ void NativeKeyBindings::GetEditCommandsForTests( +@@ -550,6 +557,13 @@ break; case KEY_NAME_INDEX_ArrowRight: if (aEvent.IsAlt()) { @@ -3015,7 +3045,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) { -@@ -572,6 +586,10 @@ void NativeKeyBindings::GetEditCommandsForTests( +@@ -572,6 +586,10 @@ break; case KEY_NAME_INDEX_ArrowUp: if (aEvent.IsControl()) { @@ -3026,7 +3056,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 break; } if (aEvent.IsMeta()) { -@@ -582,7 +600,7 @@ void NativeKeyBindings::GetEditCommandsForTests( +@@ -582,7 +600,7 @@ !aEvent.IsShift() ? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:)) : ToObjcSelectorPtr( @@ -3035,7 +3065,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805 aCommands); break; } -@@ -609,6 +627,10 @@ void NativeKeyBindings::GetEditCommandsForTests( +@@ -609,6 +627,10 @@ break; case KEY_NAME_INDEX_ArrowDown: if (aEvent.IsControl()) { @@ -3258,10 +3288,10 @@ index 8ba46829357fc4acc47bf20842fd869902efa000..a1b5b2c5230d90981bd563d4df2d2bf1 } }; diff --git a/xpcom/reflect/xptinfo/xptinfo.h b/xpcom/reflect/xptinfo/xptinfo.h -index 2456c2c2b58b27cd595880b547ed20fb687a1835..e967c089b2331c7cd36d34e511543fbc84320b7d 100644 +index 787d30d881adedd57d2025ca57bff4bc6c57e803..ae1a0172c960ab16919133485722d2ae0cdbcbd4 100644 --- a/xpcom/reflect/xptinfo/xptinfo.h +++ b/xpcom/reflect/xptinfo/xptinfo.h -@@ -514,7 +514,7 @@ static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size"); +@@ -505,7 +505,7 @@ static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size"); #if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE) # define PARAM_BUFFER_COUNT 18 #else diff --git a/browser_patches/webkit/UPSTREAM_CONFIG.sh b/browser_patches/webkit/UPSTREAM_CONFIG.sh index 8127a24878a05..c90cb3071225a 100644 --- a/browser_patches/webkit/UPSTREAM_CONFIG.sh +++ b/browser_patches/webkit/UPSTREAM_CONFIG.sh @@ -1,3 +1,3 @@ REMOTE_URL="https://github.com/WebKit/WebKit.git" BASE_BRANCH="main" -BASE_REVISION="a47deb713746fa2f228e8450a52ed0ecafc5309d" +BASE_REVISION="f371dbc2bb4292037ed394e2162150a16ef977fc" diff --git a/browser_patches/webkit/patches/bootstrap.diff b/browser_patches/webkit/patches/bootstrap.diff index 84061248f1683..9b8aa596c4c1d 100644 --- a/browser_patches/webkit/patches/bootstrap.diff +++ b/browser_patches/webkit/patches/bootstrap.diff @@ -1,8 +1,8 @@ diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt -index 3c0295bc0b5f5d417beee189e208f3582b54fdb9..65176f0a49628933887a06690217bfcc5d34f395 100644 +index 3a1013bab702f71303ee800f6b3e9a65a08f4de6..9448f06498ea591e51516d5ef7b543f63655b6ae 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt -@@ -1389,22 +1389,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS +@@ -1392,22 +1392,27 @@ set(JavaScriptCore_INSPECTOR_DOMAINS ${JAVASCRIPTCORE_DIR}/inspector/protocol/CSS.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Canvas.json ${JAVASCRIPTCORE_DIR}/inspector/protocol/Console.json @@ -62,7 +62,7 @@ index b26ef7b2b8f732160ddee36697a61ca7776fc2c3..9a442a4cda7efd7f2bd4e225d8bcbfed $(PROJECT_DIR)/inspector/protocol/Security.json $(PROJECT_DIR)/inspector/protocol/ServiceWorker.json diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make -index 15d6e32cd525905b116f25a5bdd50bd1ef390cee..74b1415d21dcddc49e842e077e87e06724af8365 100644 +index 3033ef7fc7e1db0e4b6fb85236997ce92b1946a5..87fc65714ad2caa21ac19aabf0a7d93badb4c848 100644 --- a/Source/JavaScriptCore/DerivedSources.make +++ b/Source/JavaScriptCore/DerivedSources.make @@ -298,22 +298,27 @@ INSPECTOR_DOMAINS := \ @@ -94,7 +94,7 @@ index 15d6e32cd525905b116f25a5bdd50bd1ef390cee..74b1415d21dcddc49e842e077e87e067 $(JavaScriptCore)/inspector/protocol/ServiceWorker.json \ $(JavaScriptCore)/inspector/protocol/Target.json \ diff --git a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp -index 528cceee66a1b1c91a0d0e59d5f1a1770a050c17..1e12d22fd2ce5363068ce7f5725f6e76ef7e8ad8 100644 +index 9bc5d1fd8e2a7e576be046b3c6ae1266696cf552..610f810db1dd6865c500c0796386a8284f4178e9 100644 --- a/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp +++ b/Source/JavaScriptCore/inspector/IdentifiersFactory.cpp @@ -32,14 +32,21 @@ @@ -133,10 +133,10 @@ index eb25aedee4cd9ebe007e06c2515b37ee095b06f4..badf6559595c8377db1089ca3c25008e static String requestId(unsigned long identifier); }; diff --git a/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp b/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp -index b9296c03d37fa75ec9b6349dca0dd1862df5d348..96e14d95cd24c80a40e9ce4a528db6fe1cfcc534 100644 +index 143135027999755614d5fae2b897d8dd5e62d611..a357963f3350d29ea0fd90a20ac2393ff6a0efa9 100644 --- a/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp +++ b/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp -@@ -84,7 +84,10 @@ static RefPtr jsToInspectorValue(JSC::JSGlobalObject* globalObject, +@@ -85,7 +85,10 @@ static RefPtr jsToInspectorValue(JSC::JSGlobalObject* globalObject, JSC::PropertyNameArray propertyNames(vm, JSC::PropertyNameMode::Strings, JSC::PrivateSymbolMode::Exclude); object.methodTable()->getOwnPropertyNames(&object, globalObject, propertyNames, JSC::DontEnumPropertiesMode::Exclude); for (auto& name : propertyNames) { @@ -149,10 +149,10 @@ index b9296c03d37fa75ec9b6349dca0dd1862df5d348..96e14d95cd24c80a40e9ce4a528db6fe return nullptr; inspectorObject->setValue(name.string(), inspectorValue.releaseNonNull()); diff --git a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp -index 80f5a61e477022fae12df0ba4f727e7076012fe3..7e513ea23a9a9ca0800ea21a11e51fad3417f1d2 100644 +index 3b2056bf5a71301383e0895d77cc6f16842235a9..eaf73171ce70ac43abbe404122a263ce708bb41f 100644 --- a/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp +++ b/Source/JavaScriptCore/inspector/InspectorBackendDispatcher.cpp -@@ -99,7 +99,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple +@@ -100,7 +100,7 @@ void BackendDispatcher::registerDispatcherForDomain(const String& domain, Supple m_dispatchers.set(domain, dispatcher); } @@ -161,7 +161,7 @@ index 80f5a61e477022fae12df0ba4f727e7076012fe3..7e513ea23a9a9ca0800ea21a11e51fad { Ref protect(*this); -@@ -144,6 +144,9 @@ void BackendDispatcher::dispatch(const String& message) +@@ -145,6 +145,9 @@ void BackendDispatcher::dispatch(const String& message) requestId = *requestIdInt; } @@ -239,10 +239,10 @@ index 082dd93cb0505c5bc7a2d5a7cf78fa0306809082..3f50f49ef9e691b3dc57dafd66c1e7d3 bool m_isPaused { false }; }; diff --git a/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp b/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp -index 15d2592d36b402bf2210dc4970ff40957022e84a..99ac14dc75ff5296e1f6c42bdbf8c128f2d82254 100644 +index c33e236f5228e21c6d5e0ea9bd97d07cdcb70640..7f160aec0f13e8c936aa7dea769d4e160d716452 100644 --- a/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp +++ b/Source/JavaScriptCore/inspector/JSGlobalObjectConsoleClient.cpp -@@ -221,6 +221,14 @@ void JSGlobalObjectConsoleClient::screenshot(JSGlobalObject*, Ref&&); diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp -index 594584db96a3de67b92910f472f1403bc9b26ce2..8ba453f9ae8726ccfb26c55180371c20bed6962e 100644 +index 0cb6efeef2430faa5dbd812f71d4abfd5f6eb9df..787ec6a5f8413c0a9dc133cb0e51ccdab58d40d0 100644 --- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp +++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp @@ -194,9 +194,8 @@ void InspectorRuntimeAgent::callFunctionOn(const Protocol::Runtime::RemoteObject @@ -598,10 +598,10 @@ index 0000000000000000000000000000000000000000..8377901cb3ad75c29532a1f0f547efb5 +} diff --git a/Source/JavaScriptCore/inspector/protocol/Input.json b/Source/JavaScriptCore/inspector/protocol/Input.json new file mode 100644 -index 0000000000000000000000000000000000000000..b9ab57a2b5739ed997231399b4bd4042a0cb0935 +index 0000000000000000000000000000000000000000..1c43b476603325fa412bcfded9163e7a00aebbfa --- /dev/null +++ b/Source/JavaScriptCore/inspector/protocol/Input.json -@@ -0,0 +1,223 @@ +@@ -0,0 +1,264 @@ +{ + "domain": "Input", + "availability": ["web"], @@ -610,6 +610,16 @@ index 0000000000000000000000000000000000000000..b9ab57a2b5739ed997231399b4bd4042 + "id": "TimeSinceEpoch", + "description": "UTC time in seconds, counted from January 1, 1970.", + "type": "number" ++ }, ++ { ++ "id": "TouchPoint", ++ "type": "object", ++ "description": "Touch point.", ++ "properties": [ ++ { "name": "x", "type": "integer", "description": "X coordinate of the event relative to the main frame's viewport in CSS pixels." }, ++ { "name": "y", "type": "integer", "description": "Y coordinate of the event relative to the main frame's viewport in CSS pixels." }, ++ { "name": "id", "type": "integer", "description": "Identifier used to track touch sources between events, must be unique within an event." } ++ ] + } + ], + "commands": [ @@ -822,6 +832,37 @@ index 0000000000000000000000000000000000000000..b9ab57a2b5739ed997231399b4bd4042 + "type": "integer" + } + ] ++ }, ++ { ++ "name": "dispatchTouchEvent", ++ "description": "Dispatches a touch event to the page.", ++ "async": true, ++ "parameters": [ ++ { ++ "name": "type", ++ "description": "Type of the touch event.", ++ "type": "string", ++ "enum": [ ++ "touchStart", ++ "touchMove", ++ "touchEnd", ++ "touchCancel" ++ ] ++ }, ++ { ++ "name": "modifiers", ++ "description": "Bit field representing pressed modifier keys. Alt=1, Ctrl=2, Meta/Command=4, Shift=8\n(default: 0).", ++ "optional": true, ++ "type": "integer" ++ }, ++ { ++ "name": "touchPoints", ++ "description": "List of touch points", ++ "type": "array", ++ "optional": true, ++ "items": { "$ref": "TouchPoint" } ++ } ++ ] + } + ] +} @@ -1660,18 +1701,10 @@ index 24891ad836086fd23024fcb4d08ca63f6974c812..29f4b6b1923383fec7a99d28a4e815dc private: enum ArgumentRequirement { ArgumentRequired, ArgumentNotRequired }; diff --git a/Source/ThirdParty/libwebrtc/CMakeLists.txt b/Source/ThirdParty/libwebrtc/CMakeLists.txt -index edfc7022920e6fd9300b5b1a58a1c161096c0aa5..7f68528deb95c970c030c9effd0bdea843c67624 100644 +index a17275db76e30bf2f42bc8faa6dea14383b2ab27..f630ddaddfa5a5b048e028c233e84e8bec1e0370 100644 --- a/Source/ThirdParty/libwebrtc/CMakeLists.txt +++ b/Source/ThirdParty/libwebrtc/CMakeLists.txt -@@ -60,7 +60,6 @@ set(webrtc_SOURCES - Source/third_party/abseil-cpp/absl/debugging/stacktrace.cc - Source/third_party/abseil-cpp/absl/debugging/symbolize.cc - Source/third_party/abseil-cpp/absl/flags/commandlineflag.cc -- Source/third_party/abseil-cpp/absl/flags/flag.cc - Source/third_party/abseil-cpp/absl/flags/flag_test_defs.cc - Source/third_party/abseil-cpp/absl/flags/internal/commandlineflag.cc - Source/third_party/abseil-cpp/absl/flags/internal/flag.cc -@@ -455,6 +454,7 @@ set(webrtc_SOURCES +@@ -453,6 +453,7 @@ set(webrtc_SOURCES Source/third_party/boringssl/src/crypto/x509/x_val.c Source/third_party/boringssl/src/crypto/x509/x_x509a.c Source/third_party/boringssl/src/crypto/x509/x_x509.c @@ -1679,7 +1712,7 @@ index edfc7022920e6fd9300b5b1a58a1c161096c0aa5..7f68528deb95c970c030c9effd0bdea8 Source/third_party/boringssl/src/decrepit/bio/base64_bio.c Source/third_party/boringssl/src/decrepit/blowfish/blowfish.c Source/third_party/boringssl/src/decrepit/cast/cast.c -@@ -533,6 +533,11 @@ set(webrtc_SOURCES +@@ -532,6 +533,11 @@ set(webrtc_SOURCES Source/third_party/crc32c/src/src/crc32c.cc Source/third_party/crc32c/src/src/crc32c_portable.cc Source/third_party/crc32c/src/src/crc32c_sse42.cc @@ -1691,7 +1724,7 @@ index edfc7022920e6fd9300b5b1a58a1c161096c0aa5..7f68528deb95c970c030c9effd0bdea8 Source/third_party/libyuv/source/compare.cc Source/third_party/libyuv/source/compare_common.cc Source/third_party/libyuv/source/compare_gcc.cc -@@ -2404,6 +2409,10 @@ set(webrtc_INCLUDE_DIRECTORIES PRIVATE +@@ -2402,6 +2408,10 @@ set(webrtc_INCLUDE_DIRECTORIES PRIVATE Source/third_party/libsrtp/config Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include @@ -1703,26 +1736,25 @@ index edfc7022920e6fd9300b5b1a58a1c161096c0aa5..7f68528deb95c970c030c9effd0bdea8 Source/third_party/opus/src/celt Source/third_party/opus/src/include diff --git a/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig b/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig -index 5155536dddb0d3627a021a28e6d733fde5ffbf1b..02c8aad77cd735d7e3cc5f072d62cc50c5b9aace 100644 +index 6b20d97d3d46359b2b2f9b4e8454a65c2ddbe9e3..80883fe3659389a3c385fd46ecd905bc0923d3ef 100644 --- a/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig +++ b/Source/ThirdParty/libwebrtc/Configurations/Base-libwebrtc.xcconfig -@@ -21,7 +21,7 @@ - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +@@ -22,6 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --HEADER_SEARCH_PATHS = Source Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/crc32c/config Source/third_party/crc32c/include Source/third_party/crc32c/src/include Source/third_party/libaom/source/libaom; -+HEADER_SEARCH_PATHS = Source Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/crc32c/config Source/third_party/crc32c/include Source/third_party/crc32c/src/include Source/third_party/libaom/source/libaom Source/third_party/libwebm/mkvmuxer Source/third_party/libvpx/source/libvpx/third_party/libwebm; + HEADER_SEARCH_PATHS = Source Source/third_party/libsrtp/crypto/include Source/third_party/libsrtp/include Source/third_party/boringssl/src/include Source/third_party/libyuv/include Source/webrtc/sdk/objc/Framework/Headers Source/webrtc/common_audio/signal_processing/include Source/webrtc/modules/audio_coding/codecs/isac/main/include Source/third_party/opus/src/celt Source/third_party/opus/src/include Source/third_party/opus/src/src Source/webrtc/modules/audio_device/mac Source/webrtc/modules/audio_device/ios Source/webrtc Source/webrtc/sdk/objc Source/webrtc/sdk/objc/base Source/webrtc/sdk/objc/Framework/Classes Source/third_party/libsrtp/config Source/webrtc/sdk/objc/Framework/Classes/Common Source/webrtc/sdk/objc/Framework/Classes/Video Source/webrtc/sdk/objc/Framework/Classes/PeerConnection Source/third_party/abseil-cpp Source/third_party/libvpx/source/libvpx Source/third_party/libwebm/webm_parser/include Source/third_party/crc32c/config Source/third_party/crc32c/include Source/third_party/crc32c/src/include Source/third_party/libaom/source/libaom Source/third_party/protobuf/src; ++HEADER_SEARCH_PATHS = ${HEADER_SEARCH_PATHS} Source/third_party/libwebm/mkvmuxer Source/third_party/libvpx/source/libvpx/third_party/libwebm; USE_HEADERMAP = NO; WARNING_CFLAGS = -Wno-deprecated-declarations $(inherited); diff --git a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp -index a01284369bedab3d44e7a3c2671590b3ca2b18fc..6a75fd2d366386e12dc612bdcfb914613c636478 100644 +index fca61ffe9f0563d87b364e0fa681ceab1d7bb26f..5c0d72f6c0bab0bc0011a123302c5654ec5664ba 100644 --- a/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp +++ b/Source/ThirdParty/libwebrtc/Configurations/libwebrtc.exp -@@ -402,3 +402,24 @@ __ZN3rtc7LogSink12OnLogMessageENSt3__117basic_string_viewIcNS1_11char_traitsIcEE - __ZN3rtc7LogSink12OnLogMessageERKNS_10LogLineRefE - __ZN3rtc7LogSink12OnLogMessageERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEENS_15LoggingSeverityEPKc - __ZTVN3rtc7LogSinkE +@@ -403,3 +403,24 @@ __ZN3rtc17AsyncPacketSocket20NotifyPacketReceivedERKNS_14ReceivedPacketE + __ZN3rtc17AsyncPacketSocket30RegisterReceivedPacketCallbackEN4absl12AnyInvocableIFvPS0_RKNS_14ReceivedPacketEEEE + __ZN3rtc17AsyncPacketSocket32DeregisterReceivedPacketCallbackEv + __ZN3rtc18NetworkManagerBaseC2Ev +__ZN8mkvmuxer11SegmentInfo15set_writing_appEPKc +__ZN8mkvmuxer11SegmentInfo4InitEv +__ZN8mkvmuxer7Segment10OutputCuesEb @@ -1769,7 +1801,7 @@ index f95c3b6c6b73a01974f26d88bcc533e5032ddb66..6a9368c60824cd32649c93286522d779 #include "api/array_view.h" diff --git a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj -index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6a981a2a0 100644 +index 5e185d2c3aae7eb99b72dbbb1a04af638a6dfc63..d2fbb40ee5d8349d617b287368ae1a47a131e4ee 100644 --- a/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj +++ b/Source/ThirdParty/libwebrtc/libwebrtc.xcodeproj/project.pbxproj @@ -35,6 +35,20 @@ @@ -1793,7 +1825,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 /* Begin PBXBuildFile section */ 2D6BFF60280A93DF00A1A74F /* video_coding.h in Headers */ = {isa = PBXBuildFile; fileRef = 4131C45B234C81710028A615 /* video_coding.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2D6BFF61280A93EC00A1A74F /* video_codec_initializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4131C45E234C81720028A615 /* video_codec_initializer.h */; settings = {ATTRIBUTES = (Public, ); }; }; -@@ -5135,6 +5149,9 @@ +@@ -5193,6 +5207,9 @@ DDF30D9127C5C725006A526F /* receive_side_congestion_controller.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF30D9027C5C725006A526F /* receive_side_congestion_controller.h */; }; DDF30D9527C5C756006A526F /* bwe_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF30D9327C5C756006A526F /* bwe_defines.h */; }; DDF30D9627C5C756006A526F /* remote_bitrate_estimator.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF30D9427C5C756006A526F /* remote_bitrate_estimator.h */; }; @@ -1803,7 +1835,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ -@@ -5623,6 +5640,13 @@ +@@ -5681,6 +5698,13 @@ remoteGlobalIDString = DDF30D0527C5C003006A526F; remoteInfo = absl; }; @@ -1817,7 +1849,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ -@@ -11200,6 +11224,9 @@ +@@ -11465,6 +11489,9 @@ DDF30D9027C5C725006A526F /* receive_side_congestion_controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = receive_side_congestion_controller.h; sourceTree = ""; }; DDF30D9327C5C756006A526F /* bwe_defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bwe_defines.h; sourceTree = ""; }; DDF30D9427C5C756006A526F /* remote_bitrate_estimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = remote_bitrate_estimator.h; sourceTree = ""; }; @@ -1827,7 +1859,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 FB39D0D11200F0E300088E69 /* libwebrtc.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libwebrtc.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ -@@ -20044,6 +20071,7 @@ +@@ -20596,6 +20623,7 @@ isa = PBXGroup; children = ( CDFD2F9224C4B2F90048DAC3 /* common */, @@ -1835,7 +1867,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 CDEBB19224C0191800ADBD44 /* webm_parser */, ); path = libwebm; -@@ -20471,6 +20499,16 @@ +@@ -21007,6 +21035,16 @@ path = include; sourceTree = ""; }; @@ -1852,7 +1884,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 FB39D06E1200ED9200088E69 = { isa = PBXGroup; children = ( -@@ -23761,6 +23799,7 @@ +@@ -24293,6 +24331,7 @@ ); dependencies = ( 410B3827292B73E90003E515 /* PBXTargetDependency */, @@ -1860,7 +1892,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 DD2E76E827C6B69A00F2A74C /* PBXTargetDependency */, CDEBB4CC24C01AB400ADBD44 /* PBXTargetDependency */, 411ED040212E0811004320BA /* PBXTargetDependency */, -@@ -23843,6 +23882,7 @@ +@@ -24375,6 +24414,7 @@ 4460B8B92B155B6A00392062 /* vp9_qp_parser_fuzzer */, 444A6EF02AEADFC9005FE121 /* vp9_replay_fuzzer */, 44945C512B9BA1C300447FFD /* webm_fuzzer */, @@ -1868,7 +1900,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 ); }; /* End PBXProject section */ -@@ -23926,6 +23966,23 @@ +@@ -24458,6 +24498,23 @@ shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Scripts/create-symlink-to-altroot.sh\"\n"; }; @@ -1892,7 +1924,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ -@@ -25901,6 +25958,9 @@ +@@ -26471,6 +26528,9 @@ 5CDD865E1E43B8B500621E92 /* min_max_operations.c in Sources */, 4189395B242A71F5007FDC41 /* min_video_bitrate_experiment.cc in Sources */, 41B8D8FB28CB85CB00E5FA37 /* missing_mandatory_parameter_cause.cc in Sources */, @@ -1902,7 +1934,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 4131C387234B957D0028A615 /* moving_average.cc in Sources */, 41FCBB1521B1F7AA00A5DF27 /* moving_average.cc in Sources */, 5CD286101E6A64C90094FDC8 /* moving_max.cc in Sources */, -@@ -26778,6 +26838,11 @@ +@@ -27372,6 +27432,11 @@ target = DDF30D0527C5C003006A526F /* absl */; targetProxy = DD2E76E727C6B69A00F2A74C /* PBXContainerItemProxy */; }; @@ -1914,7 +1946,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ -@@ -27353,6 +27418,27 @@ +@@ -27947,6 +28012,27 @@ }; name = Production; }; @@ -1942,7 +1974,7 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 FB39D0711200ED9200088E69 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5D7C59C71208C68B001C873E /* DebugRelease.xcconfig */; -@@ -27655,6 +27741,16 @@ +@@ -28249,6 +28335,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Production; }; @@ -1960,10 +1992,10 @@ index c25fd16f75eacc283d613509f3232b8de6ddde40..01ec8f8556149cf22a5304771a0b61b6 isa = XCConfigurationList; buildConfigurations = ( diff --git a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml -index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfba0791949 100644 +index 4d6f1829d52f1a0ea19c1a0de58e86304360c177..59a7410430ecc8db82f5b0bfcc11ba045b1f4aec 100644 --- a/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml +++ b/Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml -@@ -562,6 +562,7 @@ ApplePayEnabled: +@@ -563,6 +563,7 @@ ApplePayEnabled: default: false # FIXME: This is on by default in WebKit2 PLATFORM(COCOA). Perhaps we should consider turning it on for WebKitLegacy as well. @@ -1971,7 +2003,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb AsyncClipboardAPIEnabled: type: bool status: mature -@@ -572,7 +573,7 @@ AsyncClipboardAPIEnabled: +@@ -573,7 +574,7 @@ AsyncClipboardAPIEnabled: default: false WebKit: "PLATFORM(COCOA) || PLATFORM(GTK)" : true @@ -1980,28 +2012,15 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb WebCore: default: false -@@ -1781,9 +1782,10 @@ CrossOriginEmbedderPolicyEnabled: +@@ -1810,6 +1811,7 @@ CrossOriginEmbedderPolicyEnabled: WebCore: default: false +# Playwright: disable setting. CrossOriginOpenerPolicyEnabled: type: bool -- status: stable -+ status: preview - category: security - humanReadableName: "Cross-Origin-Opener-Policy (COOP) header" - humanReadableDescription: "Support for Cross-Origin-Opener-Policy (COOP) header" -@@ -1791,7 +1793,7 @@ CrossOriginOpenerPolicyEnabled: - WebKitLegacy: - default: false - WebKit: -- default: true -+ default: false - WebCore: - default: false - -@@ -1835,7 +1837,7 @@ CustomPasteboardDataEnabled: + status: stable +@@ -1864,7 +1866,7 @@ CustomPasteboardDataEnabled: WebKitLegacy: default: false WebKit: @@ -2010,7 +2029,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb default: false CustomStateSetEnabled: -@@ -1894,6 +1896,7 @@ DOMAudioSessionFullEnabled: +@@ -1923,6 +1925,7 @@ DOMAudioSessionFullEnabled: WebCore: default: false @@ -2018,7 +2037,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb DOMPasteAccessRequestsEnabled: type: bool status: internal -@@ -1905,7 +1908,7 @@ DOMPasteAccessRequestsEnabled: +@@ -1934,7 +1937,7 @@ DOMPasteAccessRequestsEnabled: default: false WebKit: "PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(VISION)": true @@ -2027,7 +2046,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb WebCore: default: false -@@ -2249,7 +2252,7 @@ DirectoryUploadEnabled: +@@ -2278,7 +2281,7 @@ DirectoryUploadEnabled: WebKitLegacy: default: false WebKit: @@ -2036,7 +2055,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb default: false WebCore: default: false -@@ -3261,6 +3264,7 @@ InspectorAttachmentSide: +@@ -3304,6 +3307,7 @@ InspectorAttachmentSide: WebKit: default: 0 @@ -2044,7 +2063,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb InspectorStartsAttached: type: bool status: embedder -@@ -3268,7 +3272,7 @@ InspectorStartsAttached: +@@ -3311,7 +3315,7 @@ InspectorStartsAttached: exposed: [ WebKit ] defaultValue: WebKit: @@ -2053,7 +2072,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb InspectorWindowFrame: type: String -@@ -3622,9 +3626,10 @@ LayoutViewportHeightExpansionFactor: +@@ -3650,9 +3654,10 @@ LayoutViewportHeightExpansionFactor: WebCore: default: 0 @@ -2065,7 +2084,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb category: html humanReadableName: "Lazy iframe loading" humanReadableDescription: "Enable lazy iframe loading support" -@@ -3632,9 +3637,9 @@ LazyIframeLoadingEnabled: +@@ -3660,9 +3665,9 @@ LazyIframeLoadingEnabled: WebKitLegacy: default: true WebKit: @@ -2077,7 +2096,16 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb LazyImageLoadingEnabled: type: bool -@@ -5084,6 +5089,19 @@ PitchCorrectionAlgorithm: +@@ -5084,7 +5089,7 @@ PermissionsAPIEnabled: + WebKitLegacy: + default: false + WebKit: +- "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE)" : true ++ "PLATFORM(COCOA) || PLATFORM(GTK) || PLATFORM(WPE) || PLATFORM(WIN)" : true + default: false + WebCore: + default: false +@@ -5143,6 +5148,19 @@ PitchCorrectionAlgorithm: WebCore: default: MediaPlayerEnums::PitchCorrectionAlgorithm::BestAllAround @@ -2097,7 +2125,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb PointerLockOptionsEnabled: type: bool status: testable -@@ -5622,7 +5640,7 @@ ScreenOrientationAPIEnabled: +@@ -5697,7 +5715,7 @@ ScreenOrientationAPIEnabled: WebKitLegacy: default: false WebKit: @@ -2106,7 +2134,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb WebCore: default: false -@@ -6854,6 +6872,7 @@ UseCGDisplayListsForDOMRendering: +@@ -6946,6 +6964,7 @@ UseCGDisplayListsForDOMRendering: WebKit: default: true @@ -2114,7 +2142,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb UseGPUProcessForCanvasRenderingEnabled: type: bool status: stable -@@ -6866,7 +6885,7 @@ UseGPUProcessForCanvasRenderingEnabled: +@@ -6958,7 +6977,7 @@ UseGPUProcessForCanvasRenderingEnabled: defaultValue: WebKit: "ENABLE(GPU_PROCESS_BY_DEFAULT)": true @@ -2123,7 +2151,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb default: false UseGPUProcessForDOMRenderingEnabled: -@@ -6876,7 +6895,7 @@ UseGPUProcessForDOMRenderingEnabled: +@@ -6968,7 +6987,7 @@ UseGPUProcessForDOMRenderingEnabled: humanReadableName: "GPU Process: DOM Rendering" humanReadableDescription: "Enable DOM rendering in GPU Process" webcoreBinding: none @@ -2132,7 +2160,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb exposed: [ WebKit ] defaultValue: WebKit: -@@ -6908,6 +6927,7 @@ UseGPUProcessForMediaEnabled: +@@ -7000,6 +7019,7 @@ UseGPUProcessForMediaEnabled: "ENABLE(GPU_PROCESS_BY_DEFAULT)": true default: false @@ -2140,7 +2168,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb UseGPUProcessForWebGLEnabled: type: bool status: internal -@@ -6919,7 +6939,7 @@ UseGPUProcessForWebGLEnabled: +@@ -7011,7 +7031,7 @@ UseGPUProcessForWebGLEnabled: default: false WebKit: "ENABLE(GPU_PROCESS_BY_DEFAULT) && ENABLE(GPU_PROCESS_WEBGL_BY_DEFAULT)": true @@ -2150,7 +2178,7 @@ index 7dc92bd115c44d969d31491db7ce123587f4a7fe..c0628987487ee41f927fc1bb4aa73dfb WebCore: "ENABLE(GPU_PROCESS_BY_DEFAULT) && ENABLE(GPU_PROCESS_WEBGL_BY_DEFAULT)": true diff --git a/Source/WTF/wtf/PlatformEnable.h b/Source/WTF/wtf/PlatformEnable.h -index ad8e407924f61aec230fea626efc6fb01f21f9f7..65b4a862906752f53e9d95d3238271846290329f 100644 +index 48c40a6bfa8ae0a275bbd8f3ae62f4701916fa48..a32e26e01d83999c575649a9fc0d96c71b655259 100644 --- a/Source/WTF/wtf/PlatformEnable.h +++ b/Source/WTF/wtf/PlatformEnable.h @@ -401,7 +401,7 @@ @@ -2172,10 +2200,10 @@ index ad8e407924f61aec230fea626efc6fb01f21f9f7..65b4a862906752f53e9d95d323827184 #if !defined(ENABLE_TOUCH_ACTION_REGIONS) diff --git a/Source/WTF/wtf/PlatformEnableCocoa.h b/Source/WTF/wtf/PlatformEnableCocoa.h -index 119cfbc1e518ca18fd7fe925e433054fc071f4d6..e4111b7f6ed0c0245e8ca1f7d1a4b3f674312615 100644 +index 5fef3978fdfb0dc92609688fdf282ea26a0859ef..70190e180003951e48c4084a1788f504730171ca 100644 --- a/Source/WTF/wtf/PlatformEnableCocoa.h +++ b/Source/WTF/wtf/PlatformEnableCocoa.h -@@ -780,7 +780,7 @@ +@@ -781,7 +781,7 @@ #endif #if !defined(ENABLE_SEC_ITEM_SHIM) @@ -2185,10 +2213,10 @@ index 119cfbc1e518ca18fd7fe925e433054fc071f4d6..e4111b7f6ed0c0245e8ca1f7d1a4b3f6 #if !defined(ENABLE_SERVER_PRECONNECT) diff --git a/Source/WTF/wtf/PlatformHave.h b/Source/WTF/wtf/PlatformHave.h -index 770c60d0bfdb4219917347d24e06f6076f447ebd..153e93b0ad35f4f3182c619fc25ecc1bd236a3e6 100644 +index 33d00e530b23f32e279214a88379041ec2a7c3b7..0d7b3f08bef8f010d96d85df5d1672dac87054ec 100644 --- a/Source/WTF/wtf/PlatformHave.h +++ b/Source/WTF/wtf/PlatformHave.h -@@ -418,7 +418,7 @@ +@@ -425,7 +425,7 @@ #define HAVE_FOUNDATION_WITH_SAME_SITE_COOKIE_SUPPORT 1 #endif @@ -2197,7 +2225,7 @@ index 770c60d0bfdb4219917347d24e06f6076f447ebd..153e93b0ad35f4f3182c619fc25ecc1b #define HAVE_OS_DARK_MODE_SUPPORT 1 #endif -@@ -1262,7 +1262,8 @@ +@@ -1248,7 +1248,8 @@ #endif #if PLATFORM(MAC) @@ -2223,13 +2251,13 @@ index 007b8fe3292f326504013be8198ae020f7aacf35..4439f901b4a9a92d881c7cee24ad9cd2 namespace Unicode { diff --git a/Source/WebCore/DerivedSources.make b/Source/WebCore/DerivedSources.make -index bad5e65c0f8eb201e0865430156c19501a6f357d..daa60c7b289870a77f3af4bbb24fa8c2632ccaa1 100644 +index 3c93bf646040ac804afc9c98b855829e98b87269..366b9c6714aa4f378a156577bd932a31ee5737a6 100644 --- a/Source/WebCore/DerivedSources.make +++ b/Source/WebCore/DerivedSources.make -@@ -1150,6 +1150,10 @@ JS_BINDING_IDLS := \ - $(WebCore)/dom/Slotable.idl \ - $(WebCore)/dom/StaticRange.idl \ - $(WebCore)/dom/StringCallback.idl \ +@@ -1156,6 +1156,10 @@ JS_BINDING_IDLS := \ + $(WebCore)/dom/SubscriberCallback.idl \ + $(WebCore)/dom/SubscriptionObserver.idl \ + $(WebCore)/dom/SubscriptionObserverCallback.idl \ + $(WebCore)/dom/Document+Touch.idl \ + $(WebCore)/dom/Touch.idl \ + $(WebCore)/dom/TouchEvent.idl \ @@ -2237,7 +2265,7 @@ index bad5e65c0f8eb201e0865430156c19501a6f357d..daa60c7b289870a77f3af4bbb24fa8c2 $(WebCore)/dom/Text.idl \ $(WebCore)/dom/TextDecoder.idl \ $(WebCore)/dom/TextDecoderStream.idl \ -@@ -1737,9 +1741,6 @@ JS_BINDING_IDLS := \ +@@ -1745,9 +1749,6 @@ JS_BINDING_IDLS := \ ADDITIONAL_BINDING_IDLS = \ DocumentTouch.idl \ GestureEvent.idl \ @@ -2248,10 +2276,10 @@ index bad5e65c0f8eb201e0865430156c19501a6f357d..daa60c7b289870a77f3af4bbb24fa8c2 vpath %.in $(WEBKITADDITIONS_HEADER_SEARCH_PATHS) diff --git a/Source/WebCore/Modules/geolocation/Geolocation.cpp b/Source/WebCore/Modules/geolocation/Geolocation.cpp -index 6cfaedf99ffdc456d0d0cc631636d1719981c598..682b822d464f084be76a5272f44b23adcd20ed21 100644 +index be20114bdebd713c5224893ac73078b03b22e392..4174bdf02631d421a0f1fdadfde21c308e4c7735 100644 --- a/Source/WebCore/Modules/geolocation/Geolocation.cpp +++ b/Source/WebCore/Modules/geolocation/Geolocation.cpp -@@ -359,8 +359,9 @@ bool Geolocation::shouldBlockGeolocationRequests() +@@ -360,8 +360,9 @@ bool Geolocation::shouldBlockGeolocationRequests() bool isSecure = SecurityOrigin::isSecure(document->url()) || document->isSecureContext(); bool hasMixedContent = !document->foundMixedContent().isEmpty(); bool isLocalOrigin = securityOrigin()->isLocal(); @@ -2311,10 +2339,10 @@ index c6a03b56d8358316c9ce422c1a11438bd216f80f..69fbd319b7cd084ca125a8db1b5d92ef set(CSS_VALUE_PLATFORM_DEFINES "HAVE_OS_DARK_MODE_SUPPORT=1") diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt -index 9b508a64017aaba7038419d75b2026326c6b3408..79060874c56510b59c874b8969c816bfb0214b3a 100644 +index 8ca60190e2f9110b74e37350ae12de7ff324de0e..0ad2e7621561b0a0eb67dc39555a2b99169df9c2 100644 --- a/Source/WebCore/SourcesCocoa.txt +++ b/Source/WebCore/SourcesCocoa.txt -@@ -715,3 +715,9 @@ testing/cocoa/WebViewVisualIdentificationOverlay.mm +@@ -716,3 +716,9 @@ testing/cocoa/WebViewVisualIdentificationOverlay.mm platform/graphics/angle/GraphicsContextGLANGLE.cpp @no-unify platform/graphics/cocoa/GraphicsContextGLCocoa.mm @no-unify platform/graphics/cv/GraphicsContextGLCVCocoa.cpp @no-unify @@ -2371,10 +2399,10 @@ index 92f1879df295fc63a9194dc54d3f7499c5fe3041..67c40d056aee6a8149ed1ff16ce4c835 +JSSpeechSynthesisEventInit.cpp +// Playwright: end. diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj -index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb552e10cb91 100644 +index 2dd82a349b4c111364b9032a5e5a3d81e238798e..f18701e5aa5a6dd0bd2619a0cfb92316aee41ffd 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj -@@ -6220,6 +6220,13 @@ +@@ -6198,6 +6198,13 @@ EDE3A5000C7A430600956A37 /* ColorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE3A4FF0C7A430600956A37 /* ColorMac.h */; settings = {ATTRIBUTES = (Private, ); }; }; EDEC98030AED7E170059137F /* WebCorePrefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EDEC98020AED7E170059137F /* WebCorePrefix.h */; }; EFCC6C8F20FE914400A2321B /* CanvasActivityRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -2388,7 +2416,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 F12171F616A8CF0B000053CA /* WebVTTElement.h in Headers */ = {isa = PBXBuildFile; fileRef = F12171F416A8BC63000053CA /* WebVTTElement.h */; }; F32BDCD92363AACA0073B6AE /* UserGestureEmulationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = F32BDCD72363AACA0073B6AE /* UserGestureEmulationScope.h */; }; F344C7141125B82C00F26EEE /* InspectorFrontendClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F344C7121125B82C00F26EEE /* InspectorFrontendClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; -@@ -20217,6 +20224,14 @@ +@@ -20153,6 +20160,14 @@ EDEC98020AED7E170059137F /* WebCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCorePrefix.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; EFB7287B2124C73D005C2558 /* CanvasActivityRecord.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasActivityRecord.cpp; sourceTree = ""; }; EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasActivityRecord.h; sourceTree = ""; }; @@ -2403,7 +2431,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 F12171F316A8BC63000053CA /* WebVTTElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebVTTElement.cpp; sourceTree = ""; }; F12171F416A8BC63000053CA /* WebVTTElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebVTTElement.h; sourceTree = ""; }; F32BDCD52363AAC90073B6AE /* UserGestureEmulationScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserGestureEmulationScope.cpp; sourceTree = ""; }; -@@ -27846,6 +27861,11 @@ +@@ -27805,6 +27820,11 @@ BC4A5324256055590028C592 /* TextDirectionSubmenuInclusionBehavior.h */, 2D4F96F11A1ECC240098BF88 /* TextIndicator.cpp */, 2D4F96F21A1ECC240098BF88 /* TextIndicator.h */, @@ -2415,7 +2443,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 F48570A42644C76D00C05F71 /* TranslationContextMenuInfo.h */, F4E1965F21F26E4E00285078 /* UndoItem.cpp */, 2ECDBAD521D8906300F00ECD /* UndoItem.h */, -@@ -34246,6 +34266,8 @@ +@@ -34147,6 +34167,8 @@ 29E4D8DF16B0940F00C84704 /* PlatformSpeechSynthesizer.h */, 1AD8F81A11CAB9E900E93E54 /* PlatformStrategies.cpp */, 1AD8F81911CAB9E900E93E54 /* PlatformStrategies.h */, @@ -2424,7 +2452,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 0FD7C21D23CE41E30096D102 /* PlatformWheelEvent.cpp */, 935C476A09AC4D4F00A6AAB4 /* PlatformWheelEvent.h */, F491A66A2A9FEFA300F96146 /* PlatformWheelEvent.serialization.in */, -@@ -36916,6 +36938,7 @@ +@@ -36817,6 +36839,7 @@ AD6E71AB1668899D00320C13 /* DocumentSharedObjectPool.h */, 6BDB5DC1227BD3B800919770 /* DocumentStorageAccess.cpp */, 6BDB5DC0227BD3B800919770 /* DocumentStorageAccess.h */, @@ -2432,7 +2460,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 7CE7FA5B1EF882300060C9D6 /* DocumentTouch.cpp */, 7CE7FA591EF882300060C9D6 /* DocumentTouch.h */, A8185F3209765765005826D9 /* DocumentType.cpp */, -@@ -41657,6 +41680,8 @@ +@@ -41547,6 +41570,8 @@ F4E90A3C2B52038E002DA469 /* PlatformTextAlternatives.h in Headers */, 0F7D07331884C56C00B4AF86 /* PlatformTextTrack.h in Headers */, 074E82BB18A69F0E007EF54C /* PlatformTimeRanges.h in Headers */, @@ -2441,7 +2469,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 CDD08ABD277E542600EA3755 /* PlatformTrackConfiguration.h in Headers */, CD1F9B022700323D00617EB6 /* PlatformVideoColorPrimaries.h in Headers */, CD1F9B01270020B700617EB6 /* PlatformVideoColorSpace.h in Headers */, -@@ -42939,6 +42964,7 @@ +@@ -42826,6 +42851,7 @@ 0F54DD081881D5F5003EEDBB /* Touch.h in Headers */, 71B7EE0D21B5C6870031C1EF /* TouchAction.h in Headers */, 0F54DD091881D5F5003EEDBB /* TouchEvent.h in Headers */, @@ -2449,7 +2477,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 0F54DD0A1881D5F5003EEDBB /* TouchList.h in Headers */, 070334D71459FFD5008D8D45 /* TrackBase.h in Headers */, BE88E0C21715CE2600658D98 /* TrackListBase.h in Headers */, -@@ -44089,6 +44115,8 @@ +@@ -43980,6 +44006,8 @@ 2D22830323A8470700364B7E /* CursorMac.mm in Sources */, 5CBD59592280E926002B22AA /* CustomHeaderFields.cpp in Sources */, 07E4BDBF2A3A5FAB000D5509 /* DictationCaretAnimator.cpp in Sources */, @@ -2458,7 +2486,7 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 7CE6CBFD187F394900D46BF5 /* FormatConverter.cpp in Sources */, 4667EA3E2968D9DA00BAB1E2 /* GameControllerHapticEffect.mm in Sources */, 46FE73D32968E52000B8064C /* GameControllerHapticEngines.mm in Sources */, -@@ -44176,6 +44204,9 @@ +@@ -44068,6 +44096,9 @@ CE88EE262414467B007F29C2 /* TextAlternativeWithRange.mm in Sources */, BE39137129B267F500FA5D4F /* TextTransformCocoa.cpp in Sources */, 51DF6D800B92A18E00C2DC85 /* ThreadCheck.mm in Sources */, @@ -2469,10 +2497,10 @@ index d6bd3e93dbaf2ccf6171d38aadc56fd9bc0841d1..38a9c62b6b1106e6ccb705012d93eb55 538EC8021F96AF81004D22A8 /* UnifiedSource1.cpp in Sources */, 538EC8051F96AF81004D22A8 /* UnifiedSource2-mm.mm in Sources */, diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp -index a54b85c9d3a0fbd0e24c2b0398eafe44830d2cbc..e23ae4813a861b7c6fdfad06951f02bee76201db 100644 +index a934d32a2b01e6273e1d97a7b8fd7e0999495dc5..379eee720dda27b29b32f26ab5a10d83ce78f4b9 100644 --- a/Source/WebCore/accessibility/AccessibilityObject.cpp +++ b/Source/WebCore/accessibility/AccessibilityObject.cpp -@@ -66,6 +66,7 @@ +@@ -67,6 +67,7 @@ #include "HTMLSlotElement.h" #include "HTMLTextAreaElement.h" #include "HitTestResult.h" @@ -2480,7 +2508,7 @@ index a54b85c9d3a0fbd0e24c2b0398eafe44830d2cbc..e23ae4813a861b7c6fdfad06951f02be #include "LocalFrame.h" #include "LocalizedStrings.h" #include "MathMLNames.h" -@@ -3992,9 +3993,14 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const +@@ -3968,9 +3969,14 @@ AccessibilityObjectInclusion AccessibilityObject::defaultObjectInclusion() const if (roleValue() == AccessibilityRole::ApplicationDialog) return AccessibilityObjectInclusion::IncludeObject; @@ -2497,8 +2525,30 @@ index a54b85c9d3a0fbd0e24c2b0398eafe44830d2cbc..e23ae4813a861b7c6fdfad06951f02be bool AccessibilityObject::accessibilityIsIgnored() const { AXComputedObjectAttributeCache* attributeCache = nullptr; +diff --git a/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp b/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp +index 7641906564fb1e480f56923343a8ee6149f60820..ed530124becb719e66b211f468c24376887c4cc4 100644 +--- a/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp ++++ b/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp +@@ -289,7 +289,7 @@ String AccessibilityObjectAtspi::text() const + if (!value.isNull()) + return value; + +- auto text = m_coreObject->textUnderElement(TextUnderElementMode(TextUnderElementMode::Children::IncludeAllChildren)); ++ auto text = m_coreObject->textUnderElement({ TextUnderElementMode::Children::IncludeAllChildren }); + if (auto* renderer = m_coreObject->renderer()) { + if (is(*renderer) && downcast(*renderer).markerRenderer()) { + if (renderer->style().direction() == TextDirection::LTR) { +@@ -315,7 +315,7 @@ unsigned AccessibilityObject::getLengthForTextRange() const + textLength = downcast(*renderer).text().length(); + + if (!textLength && allowsTextRanges()) +- textLength = textUnderElement(TextUnderElementMode(TextUnderElementMode::Children::IncludeAllChildren)).length(); ++ textLength = textUnderElement({ TextUnderElementMode::Children::IncludeAllChildren }).length(); + + return textLength; + } diff --git a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h -index a5a6d8a0c426db0b465d3c932de52f0678d5f5e8..75bb28488a3790ff0bfda8af3f3b641d9b519bd5 100644 +index bec74918c24d17a88bb1583504d00e2a11a5e6c6..8c86fc1552c091e6751e87c60af728b4ce37f2a1 100644 --- a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h +++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h @@ -183,6 +183,8 @@ namespace WebCore { @@ -2511,10 +2561,10 @@ index a5a6d8a0c426db0b465d3c932de52f0678d5f5e8..75bb28488a3790ff0bfda8af3f3b641d macro(DynamicsCompressorNode) \ macro(ElementInternals) \ diff --git a/Source/WebCore/css/query/MediaQueryFeatures.cpp b/Source/WebCore/css/query/MediaQueryFeatures.cpp -index 9892fda4291cae0e0d338fac8b0f98cd0126807d..7ecfd659809ab30e82a9c00ec7710292a1bd5611 100644 +index 450c429a76a97ba079087eaecc0deca236f3a419..726765635432192654ee218874813a1d09a83af4 100644 --- a/Source/WebCore/css/query/MediaQueryFeatures.cpp +++ b/Source/WebCore/css/query/MediaQueryFeatures.cpp -@@ -368,7 +368,11 @@ const FeatureSchema& forcedColors() +@@ -364,7 +364,11 @@ const FeatureSchema& forcedColors() static MainThreadNeverDestroyed schema { "forced-colors"_s, FixedVector { CSSValueNone, CSSValueActive }, @@ -2527,7 +2577,7 @@ index 9892fda4291cae0e0d338fac8b0f98cd0126807d..7ecfd659809ab30e82a9c00ec7710292 return MatchingIdentifiers { CSSValueNone }; } }; -@@ -547,6 +551,9 @@ const FeatureSchema& prefersReducedMotion() +@@ -546,6 +550,9 @@ const FeatureSchema& prefersReducedMotion() [](auto& context) { bool userPrefersReducedMotion = [&] { Ref frame = *context.document->frame(); @@ -2631,7 +2681,7 @@ index 9b344003de17b96d8b9ca8c7f32143a27543b1ea..2208a3f2b7d930bcd291e65b474d4c30 ] partial interface Element { // Returns Promise if PointerLockOptionsEnabled Runtime Flag is set, otherwise returns undefined. diff --git a/Source/WebCore/dom/PointerEvent.cpp b/Source/WebCore/dom/PointerEvent.cpp -index c35c7851f168954a0c5265ea218a2173b7b079a8..500b267351d2e4ac9864129650b6c00627a8ea6f 100644 +index 204b5f08ba950ead5f7d853d3c7fc9274ce46a26..e2f117a2a3e221fc4ca14b02c82cda952f0cd63b 100644 --- a/Source/WebCore/dom/PointerEvent.cpp +++ b/Source/WebCore/dom/PointerEvent.cpp @@ -27,9 +27,11 @@ @@ -2646,9 +2696,9 @@ index c35c7851f168954a0c5265ea218a2173b7b079a8..500b267351d2e4ac9864129650b6c006 #include namespace WebCore { -@@ -122,4 +124,51 @@ PointerEvent::PointerEvent(const AtomString& type, PointerID pointerId, const St - - PointerEvent::~PointerEvent() = default; +@@ -133,4 +135,51 @@ Vector> PointerEvent::getCoalescedEvents() + return m_coalescedEvents; + } +#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS_FAMILY) && !PLATFORM(WPE) + @@ -2699,7 +2749,7 @@ index c35c7851f168954a0c5265ea218a2173b7b079a8..500b267351d2e4ac9864129650b6c006 + } // namespace WebCore diff --git a/Source/WebCore/dom/PointerEvent.h b/Source/WebCore/dom/PointerEvent.h -index 261a8c7e8946cac87b9ebc5fc5e3b697f326b7f4..02645d3bdce44f40a648e720e99a6b296f371fb2 100644 +index c54bbf8060253b9000f3da9be8ff327a2625ff86..6b05fc5f61444ea9dc7775491801c585ae44045e 100644 --- a/Source/WebCore/dom/PointerEvent.h +++ b/Source/WebCore/dom/PointerEvent.h @@ -34,6 +34,8 @@ @@ -2711,8 +2761,8 @@ index 261a8c7e8946cac87b9ebc5fc5e3b697f326b7f4..02645d3bdce44f40a648e720e99a6b29 #endif #if ENABLE(TOUCH_EVENTS) && PLATFORM(WPE) -@@ -86,7 +88,7 @@ public: - static Ref create(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType); +@@ -88,7 +90,7 @@ public: + static Ref create(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType, CanBubble, IsCancelable); static Ref create(const AtomString& type, PointerID, const String& pointerType, IsPrimary = IsPrimary::No); -#if ENABLE(TOUCH_EVENTS) && (PLATFORM(IOS_FAMILY) || PLATFORM(WPE)) @@ -2720,9 +2770,9 @@ index 261a8c7e8946cac87b9ebc5fc5e3b697f326b7f4..02645d3bdce44f40a648e720e99a6b29 static Ref create(const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); static Ref create(const AtomString& type, const PlatformTouchEvent&, unsigned touchIndex, bool isPrimary, Ref&&, const IntPoint& touchDelta = { }); #endif -@@ -140,7 +142,7 @@ private: +@@ -144,7 +146,7 @@ private: PointerEvent(const AtomString&, Init&&); - PointerEvent(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType); + PointerEvent(const AtomString& type, MouseButton, const MouseEvent&, PointerID, const String& pointerType, CanBubble, IsCancelable); PointerEvent(const AtomString& type, PointerID, const String& pointerType, IsPrimary); -#if ENABLE(TOUCH_EVENTS) && (PLATFORM(IOS_FAMILY) || PLATFORM(WPE)) +#if ENABLE(TOUCH_EVENTS) @@ -2757,7 +2807,7 @@ index 7813532cc52d582c42aebc979a1ecd1137765f08..c01cbd53ad2430a6ffab9a80fc73e74a #endif // USE(LIBWPE) diff --git a/Source/WebCore/html/FileInputType.cpp b/Source/WebCore/html/FileInputType.cpp -index 67feb6c9b89bbbbffd343d535d990c682be6e737..c60ffff41ace3b711920d867ab4f8dde9446b487 100644 +index 7a26cfbbaf3d9583064a5eb30a049b5ac04847f0..1377da39ae4cc134b87358871fdb39431161244b 100644 --- a/Source/WebCore/html/FileInputType.cpp +++ b/Source/WebCore/html/FileInputType.cpp @@ -37,6 +37,7 @@ @@ -2768,7 +2818,7 @@ index 67feb6c9b89bbbbffd343d535d990c682be6e737..c60ffff41ace3b711920d867ab4f8dde #include "LocalFrame.h" #include "LocalizedStrings.h" #include "MIMETypeRegistry.h" -@@ -157,6 +158,11 @@ void FileInputType::handleDOMActivateEvent(Event& event) +@@ -158,6 +159,11 @@ void FileInputType::handleDOMActivateEvent(Event& event) if (input.isDisabledFormControl()) return; @@ -2780,7 +2830,7 @@ index 67feb6c9b89bbbbffd343d535d990c682be6e737..c60ffff41ace3b711920d867ab4f8dde if (!UserGestureIndicator::processingUserGesture()) return; -@@ -345,7 +351,9 @@ void FileInputType::setFiles(RefPtr&& files, RequestIcon shouldRequest +@@ -346,7 +352,9 @@ void FileInputType::setFiles(RefPtr&& files, RequestIcon shouldRequest pathsChanged = true; else { for (unsigned i = 0; i < length; ++i) { @@ -2873,7 +2923,7 @@ index 3a981b5bf5ca0bbf4d1c9f0b125564742cd8cad9..f8fc2ca6700461627933f149c5837075 } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp -index 79e5f20d096d724bcee0866175c0ceee1fb2ea12..94fbc44587f6a1c58cf81cf4a75cb42ca1e87161 100644 +index da310c6df500f80d2ae762c890ce9733d892ebd1..50db06b983b2eb4ac89942df94838e009bc82175 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.cpp +++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp @@ -598,6 +598,12 @@ void InspectorInstrumentation::applyUserAgentOverrideImpl(InstrumentingAgents& i @@ -2965,7 +3015,20 @@ index 79e5f20d096d724bcee0866175c0ceee1fb2ea12..94fbc44587f6a1c58cf81cf4a75cb42c #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) void InspectorInstrumentation::defaultAppearanceDidChangeImpl(InstrumentingAgents& instrumentingAgents) { -@@ -1051,6 +1060,12 @@ void InspectorInstrumentation::consoleStopRecordingCanvasImpl(InstrumentingAgent +@@ -915,6 +924,12 @@ void InspectorInstrumentation::interceptResponseImpl(InstrumentingAgents& instru + networkAgent->interceptResponse(response, identifier, WTFMove(handler)); + } + ++void InspectorInstrumentation::setStoppingLoadingDueToProcessSwapImpl(InstrumentingAgents& instrumentingAgents, bool value) ++{ ++ if (auto* networkAgent = instrumentingAgents.enabledNetworkAgent()) ++ networkAgent->setStoppingLoadingDueToProcessSwap(value); ++} ++ + // JavaScriptCore InspectorDebuggerAgent should know Console MessageTypes. + static bool isConsoleAssertMessage(MessageSource source, MessageType type) + { +@@ -1051,6 +1066,12 @@ void InspectorInstrumentation::consoleStopRecordingCanvasImpl(InstrumentingAgent canvasAgent->consoleStopRecordingCanvas(context); } @@ -2978,7 +3041,7 @@ index 79e5f20d096d724bcee0866175c0ceee1fb2ea12..94fbc44587f6a1c58cf81cf4a75cb42c void InspectorInstrumentation::didOpenDatabaseImpl(InstrumentingAgents& instrumentingAgents, Database& database) { if (auto* databaseAgent = instrumentingAgents.enabledDatabaseAgent()) -@@ -1357,6 +1372,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins +@@ -1357,6 +1378,36 @@ void InspectorInstrumentation::renderLayerDestroyedImpl(InstrumentingAgents& ins layerTreeAgent->renderLayerDestroyed(renderLayer); } @@ -3015,7 +3078,7 @@ index 79e5f20d096d724bcee0866175c0ceee1fb2ea12..94fbc44587f6a1c58cf81cf4a75cb42c InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(WorkerOrWorkletGlobalScope& globalScope) { return globalScope.inspectorController().m_instrumentingAgents; -@@ -1373,6 +1418,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(Page& page) +@@ -1373,6 +1424,13 @@ InstrumentingAgents& InspectorInstrumentation::instrumentingAgents(Page& page) return page.inspectorController().m_instrumentingAgents.get(); } @@ -3030,7 +3093,7 @@ index 79e5f20d096d724bcee0866175c0ceee1fb2ea12..94fbc44587f6a1c58cf81cf4a75cb42c { // Using RefPtr makes us hit the m_inRemovedLastRefFunction assert. diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h -index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f6873a81c 100644 +index 156e222e4383bee7448347d84cb052b0d9b9ae70..9bce3a168c314fc34043578c248d69cb89b48426 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.h +++ b/Source/WebCore/inspector/InspectorInstrumentation.h @@ -31,6 +31,7 @@ @@ -3080,7 +3143,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f - static void loaderDetachedFromFrame(LocalFrame&, DocumentLoader&); static void frameStartedLoading(LocalFrame&); static void frameStoppedLoading(LocalFrame&); - static void didCompleteRenderingFrame(LocalFrame&); + static void didCompleteRenderingFrame(Frame&); - static void frameScheduledNavigation(Frame&, Seconds delay); + static void frameScheduledNavigation(Frame&, Seconds delay, bool targetIsCurrentFrame); static void frameClearedScheduledNavigation(Frame&); @@ -3089,7 +3152,15 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) static void defaultAppearanceDidChange(Page&); #endif -@@ -269,6 +274,7 @@ public: +@@ -248,6 +253,7 @@ public: + static bool shouldInterceptResponse(const LocalFrame&, const ResourceResponse&); + static void interceptRequest(ResourceLoader&, Function&&); + static void interceptResponse(const LocalFrame&, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwap(Page*, bool); + + static void addMessageToConsole(Page&, std::unique_ptr); + static void addMessageToConsole(WorkerOrWorkletGlobalScope&, std::unique_ptr); +@@ -269,6 +275,7 @@ public: static void stopProfiling(Page&, JSC::JSGlobalObject*, const String& title); static void consoleStartRecordingCanvas(CanvasRenderingContext&, JSC::JSGlobalObject&, JSC::JSObject* options); static void consoleStopRecordingCanvas(CanvasRenderingContext&); @@ -3097,7 +3168,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f static void performanceMark(ScriptExecutionContext&, const String&, std::optional, LocalFrame*); -@@ -327,6 +333,12 @@ public: +@@ -327,6 +334,12 @@ public: static void layerTreeDidChange(Page*); static void renderLayerDestroyed(Page*, const RenderLayer&); @@ -3110,7 +3181,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f static void frontendCreated(); static void frontendDeleted(); static bool hasFrontends() { return InspectorInstrumentationPublic::hasFrontends(); } -@@ -343,6 +355,8 @@ public: +@@ -343,6 +356,8 @@ public: static void registerInstrumentingAgents(InstrumentingAgents&); static void unregisterInstrumentingAgents(InstrumentingAgents&); @@ -3119,7 +3190,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f private: static void didClearWindowObjectInWorldImpl(InstrumentingAgents&, LocalFrame&, DOMWrapperWorld&); static bool isDebuggerPausedImpl(InstrumentingAgents&); -@@ -422,6 +436,7 @@ private: +@@ -422,6 +437,7 @@ private: static void didRecalculateStyleImpl(InstrumentingAgents&); static void didScheduleStyleRecalculationImpl(InstrumentingAgents&, Document&); static void applyUserAgentOverrideImpl(InstrumentingAgents&, String&); @@ -3127,7 +3198,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f static void applyEmulatedMediaImpl(InstrumentingAgents&, AtomString&); static void flexibleBoxRendererBeganLayoutImpl(InstrumentingAgents&, const RenderObject&); -@@ -436,6 +451,7 @@ private: +@@ -436,6 +452,7 @@ private: static void didReceiveDataImpl(InstrumentingAgents&, ResourceLoaderIdentifier, const SharedBuffer*, int encodedDataLength); static void didFinishLoadingImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, const NetworkLoadMetrics&, ResourceLoader*); static void didFailLoadingImpl(InstrumentingAgents&, ResourceLoaderIdentifier, DocumentLoader*, const ResourceError&); @@ -3135,7 +3206,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f static void willLoadXHRSynchronouslyImpl(InstrumentingAgents&); static void didLoadXHRSynchronouslyImpl(InstrumentingAgents&); static void scriptImportedImpl(InstrumentingAgents&, ResourceLoaderIdentifier, const String& sourceString); -@@ -446,13 +462,13 @@ private: +@@ -446,13 +463,13 @@ private: static void frameDetachedFromParentImpl(InstrumentingAgents&, LocalFrame&); static void didCommitLoadImpl(InstrumentingAgents&, LocalFrame&, DocumentLoader*); static void frameDocumentUpdatedImpl(InstrumentingAgents&, LocalFrame&); @@ -3151,7 +3222,15 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) static void defaultAppearanceDidChangeImpl(InstrumentingAgents&); #endif -@@ -479,6 +495,7 @@ private: +@@ -463,6 +480,7 @@ private: + static bool shouldInterceptResponseImpl(InstrumentingAgents&, const ResourceResponse&); + static void interceptRequestImpl(InstrumentingAgents&, ResourceLoader&, Function&&); + static void interceptResponseImpl(InstrumentingAgents&, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwapImpl(InstrumentingAgents&, bool); + + static void addMessageToConsoleImpl(InstrumentingAgents&, std::unique_ptr); + +@@ -479,6 +497,7 @@ private: static void stopProfilingImpl(InstrumentingAgents&, JSC::JSGlobalObject*, const String& title); static void consoleStartRecordingCanvasImpl(InstrumentingAgents&, CanvasRenderingContext&, JSC::JSGlobalObject&, JSC::JSObject* options); static void consoleStopRecordingCanvasImpl(InstrumentingAgents&, CanvasRenderingContext&); @@ -3159,7 +3238,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f static void performanceMarkImpl(InstrumentingAgents&, const String& label, std::optional, LocalFrame*); -@@ -537,6 +554,12 @@ private: +@@ -537,6 +556,12 @@ private: static void layerTreeDidChangeImpl(InstrumentingAgents&); static void renderLayerDestroyedImpl(InstrumentingAgents&, const RenderLayer&); @@ -3172,7 +3251,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f static InstrumentingAgents& instrumentingAgents(Page&); static InstrumentingAgents& instrumentingAgents(WorkerOrWorkletGlobalScope&); static InstrumentingAgents& instrumentingAgents(ServiceWorkerGlobalScope&); -@@ -1070,6 +1093,13 @@ inline void InspectorInstrumentation::applyUserAgentOverride(LocalFrame& frame, +@@ -1070,6 +1095,13 @@ inline void InspectorInstrumentation::applyUserAgentOverride(LocalFrame& frame, applyUserAgentOverrideImpl(*agents, userAgent); } @@ -3186,7 +3265,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f inline void InspectorInstrumentation::applyEmulatedMedia(LocalFrame& frame, AtomString& media) { FAST_RETURN_IF_NO_FRONTENDS(void()); -@@ -1172,6 +1202,13 @@ inline void InspectorInstrumentation::didFailLoading(ServiceWorkerGlobalScope& g +@@ -1172,6 +1204,13 @@ inline void InspectorInstrumentation::didFailLoading(ServiceWorkerGlobalScope& g didFailLoadingImpl(instrumentingAgents(globalScope), identifier, nullptr, error); } @@ -3200,7 +3279,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f inline void InspectorInstrumentation::continueAfterXFrameOptionsDenied(LocalFrame& frame, ResourceLoaderIdentifier identifier, DocumentLoader& loader, const ResourceResponse& response) { // Treat the same as didReceiveResponse. -@@ -1262,13 +1299,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(LocalFrame& frame) +@@ -1262,13 +1301,6 @@ inline void InspectorInstrumentation::frameDocumentUpdated(LocalFrame& frame) frameDocumentUpdatedImpl(*agents, frame); } @@ -3214,7 +3293,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f inline void InspectorInstrumentation::frameStartedLoading(LocalFrame& frame) { FAST_RETURN_IF_NO_FRONTENDS(void()); -@@ -1290,11 +1320,11 @@ inline void InspectorInstrumentation::frameStoppedLoading(LocalFrame& frame) +@@ -1290,11 +1322,11 @@ inline void InspectorInstrumentation::frameStoppedLoading(LocalFrame& frame) frameStoppedLoadingImpl(*agents, frame); } @@ -3228,7 +3307,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f } inline void InspectorInstrumentation::frameClearedScheduledNavigation(Frame& frame) -@@ -1310,6 +1340,13 @@ inline void InspectorInstrumentation::accessibilitySettingsDidChange(Page& page) +@@ -1310,6 +1342,13 @@ inline void InspectorInstrumentation::accessibilitySettingsDidChange(Page& page) accessibilitySettingsDidChangeImpl(instrumentingAgents(page)); } @@ -3242,7 +3321,21 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f #if ENABLE(DARK_MODE_CSS) || HAVE(OS_DARK_MODE_SUPPORT) inline void InspectorInstrumentation::defaultAppearanceDidChange(Page& page) { -@@ -1698,6 +1735,11 @@ inline void InspectorInstrumentation::performanceMark(ScriptExecutionContext& co +@@ -1362,6 +1401,13 @@ inline void InspectorInstrumentation::interceptResponse(const LocalFrame& frame, + interceptResponseImpl(*agents, response, identifier, WTFMove(handler)); + } + ++inline void InspectorInstrumentation::setStoppingLoadingDueToProcessSwap(Page* page, bool value) ++{ ++ ASSERT(InspectorInstrumentationPublic::hasFrontends()); ++ if (auto* agents = instrumentingAgents(page)) ++ setStoppingLoadingDueToProcessSwapImpl(*agents, value); ++} ++ + inline void InspectorInstrumentation::didOpenDatabase(Database& database) + { + FAST_RETURN_IF_NO_FRONTENDS(void()); +@@ -1698,6 +1744,11 @@ inline void InspectorInstrumentation::performanceMark(ScriptExecutionContext& co performanceMarkImpl(*agents, label, WTFMove(startTime), frame); } @@ -3254,7 +3347,7 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f inline void InspectorInstrumentation::didRequestAnimationFrame(Document& document, int callbackId) { FAST_RETURN_IF_NO_FRONTENDS(void()); -@@ -1754,6 +1796,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren +@@ -1754,6 +1805,42 @@ inline void InspectorInstrumentation::renderLayerDestroyed(Page* page, const Ren renderLayerDestroyedImpl(*agents, renderLayer); } @@ -3297,8 +3390,60 @@ index bc7a4a0839df63c54a2651feb02baa8aa554e886..3d137bfd99bdbbebbbf1cf983be6356f inline InstrumentingAgents* InspectorInstrumentation::instrumentingAgents(ScriptExecutionContext* context) { return context ? instrumentingAgents(*context) : nullptr; +diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp +index a67a1244fa526ad5759068e97e0d220f59565d6e..0048589109fccb9472fe35a410337771b1063d72 100644 +--- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp ++++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.cpp +@@ -50,4 +50,9 @@ void InspectorInstrumentationWebKit::interceptResponseInternal(const LocalFrame& + InspectorInstrumentation::interceptResponse(frame, response, identifier, WTFMove(handler)); + } + ++void InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwapInternal(Page* page, bool value) ++{ ++ InspectorInstrumentation::setStoppingLoadingDueToProcessSwap(page, value); ++} ++ + } // namespace WebCore +diff --git a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h +index c028341e84e59a6b1b16107fd74feb21f70b12ab..d385418ac34e8f315f201801a2c65226c8f6fee2 100644 +--- a/Source/WebCore/inspector/InspectorInstrumentationWebKit.h ++++ b/Source/WebCore/inspector/InspectorInstrumentationWebKit.h +@@ -33,6 +33,7 @@ + namespace WebCore { + + class LocalFrame; ++class Page; + class ResourceLoader; + class ResourceRequest; + class ResourceResponse; +@@ -44,12 +45,14 @@ public: + static bool shouldInterceptResponse(const LocalFrame*, const ResourceResponse&); + static void interceptRequest(ResourceLoader&, Function&&); + static void interceptResponse(const LocalFrame*, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwap(Page*, bool); + + private: + static bool shouldInterceptRequestInternal(const ResourceLoader&); + static bool shouldInterceptResponseInternal(const LocalFrame&, const ResourceResponse&); + static void interceptRequestInternal(ResourceLoader&, Function&&); + static void interceptResponseInternal(const LocalFrame&, const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); ++ static void setStoppingLoadingDueToProcessSwapInternal(Page*, bool); + }; + + inline bool InspectorInstrumentationWebKit::shouldInterceptRequest(const ResourceLoader& loader) +@@ -79,4 +82,10 @@ inline void InspectorInstrumentationWebKit::interceptResponse(const LocalFrame* + interceptResponseInternal(*frame, response, identifier, WTFMove(handler)); + } + ++inline void InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwap(Page* page, bool value) ++{ ++ FAST_RETURN_IF_NO_FRONTENDS(void()); ++ setStoppingLoadingDueToProcessSwapInternal(page, value); ++} ++ + } diff --git a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp -index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69db64f9720 100644 +index ec5000cb553f244224ac2dc5be229c11c42e5d7f..cf6bc9545f04ad7fdba7c2dfaf46ac45e158f15e 100644 --- a/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp @@ -55,6 +55,7 @@ @@ -3340,7 +3485,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d #include "StaticNodeList.h" #include "StyleProperties.h" #include "StyleResolver.h" -@@ -145,7 +153,8 @@ using namespace HTMLNames; +@@ -146,7 +154,8 @@ using namespace HTMLNames; static const size_t maxTextSize = 10000; static const UChar horizontalEllipsisUChar[] = { horizontalEllipsis, 0 }; @@ -3350,7 +3495,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d { if (!colorObject) return std::nullopt; -@@ -164,7 +173,7 @@ static std::optional parseColor(RefPtr&& colorObject) +@@ -165,7 +174,7 @@ static std::optional parseColor(RefPtr&& colorObject) static std::optional parseRequiredConfigColor(const String& fieldName, JSON::Object& configObject) { @@ -3359,7 +3504,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d } static Color parseOptionalConfigColor(const String& fieldName, JSON::Object& configObject) -@@ -192,6 +201,20 @@ static bool parseQuad(Ref&& quadArray, FloatQuad* quad) +@@ -193,6 +202,20 @@ static bool parseQuad(Ref&& quadArray, FloatQuad* quad) return true; } @@ -3380,7 +3525,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d class RevalidateStyleAttributeTask { WTF_MAKE_FAST_ALLOCATED; public: -@@ -466,6 +489,20 @@ Node* InspectorDOMAgent::assertNode(Inspector::Protocol::ErrorString& errorStrin +@@ -467,6 +490,20 @@ Node* InspectorDOMAgent::assertNode(Inspector::Protocol::ErrorString& errorStrin return node.get(); } @@ -3401,7 +3546,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d Document* InspectorDOMAgent::assertDocument(Inspector::Protocol::ErrorString& errorString, Inspector::Protocol::DOM::NodeId nodeId) { RefPtr node = assertNode(errorString, nodeId); -@@ -1540,16 +1577,7 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::o +@@ -1541,16 +1578,7 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::o Inspector::Protocol::ErrorStringOr InspectorDOMAgent::highlightNode(std::optional&& nodeId, const Inspector::Protocol::Runtime::RemoteObjectId& objectId, Ref&& highlightInspectorObject, RefPtr&& gridOverlayInspectorObject, RefPtr&& flexOverlayInspectorObject, std::optional&& showRulers) { Inspector::Protocol::ErrorString errorString; @@ -3419,7 +3564,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d if (!node) return makeUnexpected(errorString); -@@ -1804,15 +1832,155 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Ins +@@ -1805,15 +1833,155 @@ Inspector::Protocol::ErrorStringOr InspectorDOMAgent::setInspectedNode(Ins return { }; } @@ -3578,7 +3723,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d if (!object) return makeUnexpected("Missing injected script for given nodeId"_s); -@@ -3078,7 +3246,7 @@ Inspector::Protocol::ErrorStringOr InspectorDO +@@ -3079,7 +3247,7 @@ Inspector::Protocol::ErrorStringOr InspectorDO return makeUnexpected("Missing node for given path"_s); } @@ -3587,7 +3732,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d { Document* document = &node->document(); if (auto* templateHost = document->templateDocumentHost()) -@@ -3087,12 +3255,18 @@ RefPtr InspectorDOMAgent::resolveNod +@@ -3088,12 +3256,18 @@ RefPtr InspectorDOMAgent::resolveNod if (!frame) return nullptr; @@ -3609,7 +3754,7 @@ index 129c6f01b48eaf4fb39914721a0909e25d6d9a97..d8636860918f3f8c24ae91897840f69d } Node* InspectorDOMAgent::scriptValueAsNode(JSC::JSValue value) -@@ -3200,4 +3374,89 @@ Inspector::Protocol::ErrorStringOr> In +@@ -3201,4 +3375,89 @@ Inspector::Protocol::ErrorStringOr> In #endif } @@ -3773,7 +3918,7 @@ index 5f1dba2bc4d5c2f113a88dcc9ba479679cb79233..73e49d699919b68cffff41f612e461e2 void discardBindings(); diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp -index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf72cdbbf8 100644 +index f8a58175bdaa13ae7d2bb722df119e140ec7618f..b601fdd3d16a3fc016ce3af50d416a0880990d7b 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.cpp @@ -59,6 +59,7 @@ @@ -3784,7 +3929,7 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf #include "Page.h" #include "PlatformStrategies.h" #include "ProgressTracker.h" -@@ -339,8 +340,8 @@ static Ref buildObjectForResourceRequest( +@@ -340,8 +341,8 @@ static Ref buildObjectForResourceRequest( .release(); if (request.httpBody() && !request.httpBody()->isEmpty()) { @@ -3795,7 +3940,7 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf } if (resourceLoader) { -@@ -393,6 +394,8 @@ RefPtr InspectorNetworkAgent::buildObjec +@@ -394,6 +395,8 @@ RefPtr InspectorNetworkAgent::buildObjec .setSource(responseSource(response.source())) .release(); @@ -3804,7 +3949,25 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf if (resourceLoader) { auto* metrics = response.deprecatedNetworkLoadMetricsOrNull(); responseObject->setTiming(buildObjectForTiming(metrics ? *metrics : NetworkLoadMetrics::emptyMetrics(), *resourceLoader)); -@@ -960,6 +963,7 @@ void InspectorNetworkAgent::continuePendingResponses() +@@ -680,6 +683,9 @@ void InspectorNetworkAgent::didFailLoading(ResourceLoaderIdentifier identifier, + String requestId = IdentifiersFactory::requestId(identifier.toUInt64()); + + if (loader && m_resourcesData->resourceType(requestId) == InspectorPageAgent::DocumentResource) { ++ if (m_stoppingLoadingDueToProcessSwap) ++ return; ++ + auto* frame = loader->frame(); + if (frame && frame->loader().documentLoader() && frame->document()) { + m_resourcesData->addResourceSharedBuffer(requestId, +@@ -909,6 +915,7 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::disable() + m_instrumentingAgents.setEnabledNetworkAgent(nullptr); + m_resourcesData->clear(); + m_extraRequestHeaders.clear(); ++ m_stoppingLoadingDueToProcessSwap = false; + + continuePendingRequests(); + continuePendingResponses(); +@@ -961,6 +968,7 @@ void InspectorNetworkAgent::continuePendingResponses() Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setExtraHTTPHeaders(Ref&& headers) { @@ -3812,7 +3975,19 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf for (auto& entry : headers.get()) { auto stringValue = entry.value->asString(); if (!!stringValue) -@@ -1238,6 +1242,9 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithReq +@@ -1210,6 +1218,11 @@ void InspectorNetworkAgent::interceptResponse(const ResourceResponse& response, + m_frontendDispatcher->responseIntercepted(requestId, resourceResponse.releaseNonNull()); + } + ++void InspectorNetworkAgent::setStoppingLoadingDueToProcessSwap(bool stopping) ++{ ++ m_stoppingLoadingDueToProcessSwap = stopping; ++} ++ + Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptContinue(const Inspector::Protocol::Network::RequestId& requestId, Inspector::Protocol::Network::NetworkStage networkStage) + { + switch (networkStage) { +@@ -1239,6 +1252,9 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptWithReq return makeUnexpected("Missing pending intercept request for given requestId"_s); auto& loader = *pendingRequest->m_loader; @@ -3822,7 +3997,7 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf ResourceRequest request = loader.request(); if (!!url) request.setURL(URL({ }, url)); -@@ -1333,14 +1340,23 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequest +@@ -1334,14 +1350,23 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::interceptRequest response.setHTTPStatusCode(status); response.setHTTPStatusText(String { statusText }); HTTPHeaderMap explicitHeaders; @@ -3848,7 +4023,7 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf if (loader->reachedTerminalState()) return; -@@ -1403,6 +1419,12 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulatedCondi +@@ -1404,6 +1429,12 @@ Inspector::Protocol::ErrorStringOr InspectorNetworkAgent::setEmulatedCondi #endif // ENABLE(INSPECTOR_NETWORK_THROTTLING) @@ -3862,7 +4037,7 @@ index f481bcb61f039dc5608e0c03ee6eb14e8cb19762..92cf076baeff2db243cf035cad036ccf { return startsWithLettersIgnoringASCIICase(mimeType, "text/"_s) diff --git a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h -index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..5dd4464256e0f5d652fa51fd611286ddc1da6f5c 100644 +index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..03a28b599df29e82392b70cf6b83a700134c53a3 100644 --- a/Source/WebCore/inspector/agents/InspectorNetworkAgent.h +++ b/Source/WebCore/inspector/agents/InspectorNetworkAgent.h @@ -34,6 +34,8 @@ @@ -3882,8 +4057,24 @@ index dc7e574ee6e9256a1f75ea838d20ca7f5e9190de..5dd4464256e0f5d652fa51fd611286dd // InspectorInstrumentation void willRecalculateStyle(); +@@ -132,6 +135,7 @@ public: + bool shouldInterceptResponse(const ResourceResponse&); + void interceptResponse(const ResourceResponse&, ResourceLoaderIdentifier, CompletionHandler)>&&); + void interceptRequest(ResourceLoader&, Function&&); ++ void setStoppingLoadingDueToProcessSwap(bool); + + void searchOtherRequests(const JSC::Yarr::RegularExpression&, Ref>&); + void searchInRequest(Inspector::Protocol::ErrorString&, const Inspector::Protocol::Network::RequestId&, const String& query, bool caseSensitive, bool isRegex, RefPtr>&); +@@ -258,6 +262,7 @@ private: + bool m_enabled { false }; + bool m_loadingXHRSynchronously { false }; + bool m_interceptionEnabled { false }; ++ bool m_stoppingLoadingDueToProcessSwap { false }; + }; + + } // namespace WebCore diff --git a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp -index 84eb4dc2127420db005063e0f60d5ad950081719..5f85bc7ba23b9488d03bf7dfa5da645fb2717734 100644 +index 97fa6f1ae18db5b4a1fc8f8f99ce0605fb76a793..fd761459048e7e976b7351eb8714acc63f42bf2d 100644 --- a/Source/WebCore/inspector/agents/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/agents/InspectorPageAgent.cpp @@ -32,19 +32,26 @@ @@ -3928,7 +4119,7 @@ index 84eb4dc2127420db005063e0f60d5ad950081719..5f85bc7ba23b9488d03bf7dfa5da645f #include "ScriptController.h" #include "ScriptSourceCode.h" #include "SecurityOrigin.h" -@@ -66,11 +76,18 @@ +@@ -66,14 +76,21 @@ #include "StyleScope.h" #include "Theme.h" #include @@ -3946,7 +4137,11 @@ index 84eb4dc2127420db005063e0f60d5ad950081719..5f85bc7ba23b9488d03bf7dfa5da645f +#include #include #include - #include +-#include ++#include + + #if ENABLE(APPLICATION_MANIFEST) + #include "CachedApplicationManifest.h" @@ -92,6 +109,11 @@ namespace WebCore { using namespace Inspector; @@ -4286,7 +4481,7 @@ index 84eb4dc2127420db005063e0f60d5ad950081719..5f85bc7ba23b9488d03bf7dfa5da645f -Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem coordinateSystem) +Inspector::Protocol::ErrorStringOr InspectorPageAgent::snapshotRect(int x, int y, int width, int height, Inspector::Protocol::Page::CoordinateSystem coordinateSystem, std::optional&& omitDeviceScaleFactor) { - SnapshotOptions options { { }, PixelFormat::BGRA8, DestinationColorSpace::SRGB() }; + SnapshotOptions options { { }, ImageBufferPixelFormat::BGRA8, DestinationColorSpace::SRGB() }; if (coordinateSystem == Inspector::Protocol::Page::CoordinateSystem::Viewport) options.flags.add(SnapshotFlags::InViewCoordinates); + if (omitDeviceScaleFactor.has_value() && *omitDeviceScaleFactor) @@ -4322,7 +4517,7 @@ index 84eb4dc2127420db005063e0f60d5ad950081719..5f85bc7ba23b9488d03bf7dfa5da645f +{ + bool success = WTF::setTimeZoneOverride(timeZone); + if (!success) -+ return makeUnexpected("Invalid time zone "_s + timeZone); ++ return makeUnexpected(makeString("Invalid time zone "_s, timeZone)); + + return { }; +} @@ -5193,10 +5388,10 @@ index 2ca6ee01a341eefead66a92e2af77875263a9df3..131bbd8c268a748b43cac105370d7b73 protected: static SameSiteInfo sameSiteInfo(const Document&, IsForDOMCookieAccess = IsForDOMCookieAccess::No); diff --git a/Source/WebCore/loader/DocumentLoader.cpp b/Source/WebCore/loader/DocumentLoader.cpp -index fa516b91382c4c784d30f38a6782e7a29007e7d4..89c56c793e97771f75b109a2fd04a0e671425aa1 100644 +index 22b83991d32085991eb502728333dc7648ab883f..6bd27284c1799448f387338738c7a7fbc8cc3690 100644 --- a/Source/WebCore/loader/DocumentLoader.cpp +++ b/Source/WebCore/loader/DocumentLoader.cpp -@@ -765,8 +765,10 @@ void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc +@@ -766,8 +766,10 @@ void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const Resourc if (!didReceiveRedirectResponse) return completionHandler(WTFMove(newRequest)); @@ -5228,7 +5423,7 @@ index fa516b91382c4c784d30f38a6782e7a29007e7d4..89c56c793e97771f75b109a2fd04a0e6 { ASSERT(navigationID); diff --git a/Source/WebCore/loader/DocumentLoader.h b/Source/WebCore/loader/DocumentLoader.h -index 05c8c4a42b9273c15889c0ab11199b67954dfe15..6947545eef196ef105c6292c8734b5b86d7dc8f2 100644 +index 3f7d86c6ba98d5d5a6ad716bd3d78885bb9411e0..94dbc77f454b70733d7f15db8fac00ac72fb8657 100644 --- a/Source/WebCore/loader/DocumentLoader.h +++ b/Source/WebCore/loader/DocumentLoader.h @@ -207,6 +207,8 @@ public: @@ -5241,10 +5436,10 @@ index 05c8c4a42b9273c15889c0ab11199b67954dfe15..6947545eef196ef105c6292c8734b5b8 CheckedPtr checkedFrameLoader() const; WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const; diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp -index 213b18eed87af84e1f36ccda4008e3d2ea24721f..b8d3567ef231c363a5b40caef6427657d4cdb73f 100644 +index 231a764c5b88f9986e324587e62f94abd119fff8..260b5368d67f75616e7aeba7c3170fb52af5f054 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp -@@ -1290,6 +1290,7 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr stat +@@ -1322,6 +1322,7 @@ void FrameLoader::loadInSameDocument(URL url, RefPtr stat } m_client->dispatchDidNavigateWithinPage(); @@ -5252,16 +5447,15 @@ index 213b18eed87af84e1f36ccda4008e3d2ea24721f..b8d3567ef231c363a5b40caef6427657 document->statePopped(stateObject ? stateObject.releaseNonNull() : SerializedScriptValue::nullValue()); m_client->dispatchDidPopStateWithinPage(); -@@ -1781,6 +1782,8 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t - if (!dispatchNavigateEvent(newURL, type, loader->triggeringAction(), NavigationHistoryBehavior::Auto, true)) - return; +@@ -1821,6 +1822,7 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t + const String& httpMethod = loader->request().httpMethod(); + if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) { + loader->replacedByFragmentNavigation(m_frame); -+ + RefPtr oldDocumentLoader = m_documentLoader; NavigationAction action { frame->protectedDocument().releaseNonNull(), loader->request(), InitiatedByMainFrame::Unknown, loader->isRequestFromClientOrUserInput(), policyChecker().loadType(), isFormSubmission }; - oldDocumentLoader->setTriggeringAction(WTFMove(action)); -@@ -1814,7 +1817,9 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t +@@ -1857,7 +1859,9 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t } RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || frame->history().provisionalItem()); @@ -5271,21 +5465,17 @@ index 213b18eed87af84e1f36ccda4008e3d2ea24721f..b8d3567ef231c363a5b40caef6427657 continueLoadAfterNavigationPolicy(request, RefPtr { weakFormState.get() }.get(), navigationPolicyDecision, allowNavigationToInvalidURL); completionHandler(); }, PolicyDecisionMode::Asynchronous); -@@ -3079,14 +3084,19 @@ String FrameLoader::userAgent(const URL& url) const +@@ -3126,10 +3130,15 @@ String FrameLoader::userAgent(const URL& url) const String FrameLoader::navigatorPlatform() const { + String platform; + - if (RefPtr localFrame = dynamicDowncast(m_frame->mainFrame())) { - if (RefPtr documentLoader = localFrame->loader().activeDocumentLoader()) { - auto& customNavigatorPlatform = documentLoader->customNavigatorPlatform(); - if (!customNavigatorPlatform.isEmpty()) -- return customNavigatorPlatform; -+ platform = customNavigatorPlatform; - } - } + auto customNavigatorPlatform = m_frame->mainFrame().customNavigatorPlatform(); + if (!customNavigatorPlatform.isEmpty()) +- return customNavigatorPlatform; - return String(); ++ platform = customNavigatorPlatform; + + InspectorInstrumentation::applyPlatformOverride(m_frame, platform); + @@ -5293,7 +5483,7 @@ index 213b18eed87af84e1f36ccda4008e3d2ea24721f..b8d3567ef231c363a5b40caef6427657 } void FrameLoader::dispatchOnloadEvents() -@@ -3544,6 +3554,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, LoadWill +@@ -3594,6 +3603,8 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, LoadWill checkCompleted(); if (frame->page()) checkLoadComplete(loadWillContinueInAnotherProcess); @@ -5302,7 +5492,7 @@ index 213b18eed87af84e1f36ccda4008e3d2ea24721f..b8d3567ef231c363a5b40caef6427657 } void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, const SecurityOrigin* requesterOrigin, bool shouldContinue, NavigationHistoryBehavior historyHandling) -@@ -4422,9 +4434,6 @@ String FrameLoader::referrer() const +@@ -4476,9 +4487,6 @@ String FrameLoader::referrer() const void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() { @@ -5312,7 +5502,7 @@ index 213b18eed87af84e1f36ccda4008e3d2ea24721f..b8d3567ef231c363a5b40caef6427657 Vector> worlds; ScriptController::getAllWorlds(worlds); for (auto& world : worlds) -@@ -4434,13 +4443,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() +@@ -4488,13 +4496,12 @@ void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds() void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world) { Ref frame = m_frame.get(); @@ -5345,10 +5535,10 @@ index 91340dc21042f545592b442bc42dbceed06219b2..f3591fe333761b10a25ddaf4a4f8d721 virtual bool shouldPerformSecurityChecks() const { return false; } virtual bool havePerformedSecurityChecks(const ResourceResponse&) const { return false; } diff --git a/Source/WebCore/loader/NavigationScheduler.cpp b/Source/WebCore/loader/NavigationScheduler.cpp -index 16e15b0565a75933a4f10828cca190f4b055a05b..0189a5b49bc593b63413abb16524027f24daacc6 100644 +index 9af8f29088f6ac3841fe68cd8629ef18a6ca5675..f28e41daee51b3d4fd6c185532c6acf941dd30ad 100644 --- a/Source/WebCore/loader/NavigationScheduler.cpp +++ b/Source/WebCore/loader/NavigationScheduler.cpp -@@ -695,7 +695,7 @@ void NavigationScheduler::startTimer() +@@ -703,7 +703,7 @@ void NavigationScheduler::startTimer() Seconds delay = 1_s * m_redirect->delay(); m_timer.startOneShot(delay); @@ -5392,10 +5582,10 @@ index b74c5258454b0df9f74aa8a5297674b733925685..b6c3999745368c7f7e2e6176bfca6dc0 void ProgressTracker::incrementProgress(ResourceLoaderIdentifier identifier, const ResourceResponse& response) diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp -index bf685913e33c7d5959c158b7735321682d5e7208..8c184ff01799f5172c9a774a115014c5f6f18270 100644 +index 0838ffc91ef3b9b3990bb05bb0c52dec1128f92e..6f536869db9c2aa0264d2e800bc9f3e7adb9a379 100644 --- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp +++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp -@@ -1068,8 +1068,11 @@ ResourceErrorOr> CachedResourceLoader::requ +@@ -1089,8 +1089,11 @@ ResourceErrorOr> CachedResourceLoader::requ request.updateReferrerPolicy(document() ? document()->referrerPolicy() : ReferrerPolicy::Default); @@ -5409,7 +5599,7 @@ index bf685913e33c7d5959c158b7735321682d5e7208..8c184ff01799f5172c9a774a115014c5 Ref page = *frame->page(); -@@ -1682,8 +1685,9 @@ Vector> CachedResourceLoader::allCachedSVGImages() const +@@ -1703,8 +1706,9 @@ Vector> CachedResourceLoader::allCachedSVGImages() const ResourceErrorOr> CachedResourceLoader::preload(CachedResource::Type type, CachedResourceRequest&& request) { @@ -5422,10 +5612,10 @@ index bf685913e33c7d5959c158b7735321682d5e7208..8c184ff01799f5172c9a774a115014c5 ASSERT(m_document); if (request.charset().isEmpty() && m_document && (type == CachedResource::Type::Script || type == CachedResource::Type::CSSStyleSheet)) diff --git a/Source/WebCore/page/ChromeClient.h b/Source/WebCore/page/ChromeClient.h -index 9225486c5aaf841df1d5de85c40928307b4d72dc..93bc7be141be1043a057b6ad6c297397a5c6cfa8 100644 +index 1712a19473ab6db4db50a1d746846a091dce7417..ed27724b92ba34e0f2a543f398701f31a6764bc3 100644 --- a/Source/WebCore/page/ChromeClient.h +++ b/Source/WebCore/page/ChromeClient.h -@@ -335,7 +335,7 @@ public: +@@ -339,7 +339,7 @@ public: #endif #if ENABLE(ORIENTATION_EVENTS) @@ -5435,10 +5625,10 @@ index 9225486c5aaf841df1d5de85c40928307b4d72dc..93bc7be141be1043a057b6ad6c297397 #if ENABLE(INPUT_TYPE_COLOR) diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp -index ff5f86a7c24bdb06a7ae0d6015de450a323cdae0..1760ac36123b4543279d7278fd9d328637da9ca3 100644 +index 82f9dab5460c78f49a48adfb8c1fcaf19b0a0b9e..b3c8a054f7c6e0b9db2cdc50fd077c687ccdd62b 100644 --- a/Source/WebCore/page/EventHandler.cpp +++ b/Source/WebCore/page/EventHandler.cpp -@@ -4326,6 +4326,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr +@@ -4346,6 +4346,12 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event, CheckDr if (!document) return false; @@ -5451,7 +5641,7 @@ index ff5f86a7c24bdb06a7ae0d6015de450a323cdae0..1760ac36123b4543279d7278fd9d3286 dragState().dataTransfer = DataTransfer::createForDrag(*document); auto hasNonDefaultPasteboardData = HasNonDefaultPasteboardData::No; -@@ -4952,7 +4958,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -4972,7 +4978,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve // Increment the platform touch id by 1 to avoid storing a key of 0 in the hashmap. unsigned touchPointTargetKey = point.id() + 1; @@ -5460,7 +5650,7 @@ index ff5f86a7c24bdb06a7ae0d6015de450a323cdae0..1760ac36123b4543279d7278fd9d3286 bool pointerCancelled = false; #endif RefPtr touchTarget; -@@ -4999,7 +5005,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5019,7 +5025,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve // we also remove it from the map. touchTarget = m_originatingTouchPointTargets.take(touchPointTargetKey); @@ -5469,7 +5659,7 @@ index ff5f86a7c24bdb06a7ae0d6015de450a323cdae0..1760ac36123b4543279d7278fd9d3286 HitTestResult result = hitTestResultAtPoint(pagePoint, hitType | HitTestRequest::Type::AllowChildFrameContent); pointerTarget = result.targetElement(); pointerCancelled = (pointerTarget != touchTarget); -@@ -5022,7 +5028,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve +@@ -5042,7 +5048,7 @@ HandleUserInputEventResult EventHandler::handleTouchEvent(const PlatformTouchEve if (!targetFrame) continue; @@ -5518,7 +5708,7 @@ index 084db825e36bd46126fea95fc7183bf2e931be7e..dac3caef67600f8c7c945fd857a91140 } diff --git a/Source/WebCore/page/FrameSnapshotting.h b/Source/WebCore/page/FrameSnapshotting.h -index 055e3d8b2821c366b403fcc6ea0f2c9b1bd8029b..0e1bb019ba0ad1f76ef62abb164b80ccf26755be 100644 +index 5b365008debe6b8d5a95a572a4c2725b0a7a519d..2c6ad49a45a1759f446aced179c0c5a7bfb4b07a 100644 --- a/Source/WebCore/page/FrameSnapshotting.h +++ b/Source/WebCore/page/FrameSnapshotting.h @@ -55,6 +55,7 @@ enum class SnapshotFlags : uint16_t { @@ -5530,7 +5720,7 @@ index 055e3d8b2821c366b403fcc6ea0f2c9b1bd8029b..0e1bb019ba0ad1f76ef62abb164b80cc struct SnapshotOptions { diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp -index 2b5e1e58bad69cba3d4c6de1e0d35f01ad9bb5f2..098355b3f71ebc2ec51862671a860d2964850c88 100644 +index 097302d7502b8a28db7c7ab8d778d17365b03533..4ab5ee0e71b2010ea5297e8d1d4ec03b9fd27097 100644 --- a/Source/WebCore/page/History.cpp +++ b/Source/WebCore/page/History.cpp @@ -32,6 +32,7 @@ @@ -5541,16 +5731,17 @@ index 2b5e1e58bad69cba3d4c6de1e0d35f01ad9bb5f2..098355b3f71ebc2ec51862671a860d29 #include "LocalFrame.h" #include "LocalFrameLoaderClient.h" #include "Logging.h" -@@ -304,6 +305,7 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data +@@ -304,6 +305,8 @@ ExceptionOr History::stateObjectAdded(RefPtr&& data - if (!urlString.isEmpty()) - frame->protectedDocument()->updateURLForPushOrReplaceState(fullURL); + auto historyBehavior = stateObjectType == StateObjectType::Replace ? NavigationHistoryBehavior::Replace : NavigationHistoryBehavior::Push; + frame->loader().updateURLAndHistory(fullURL, WTFMove(data), historyBehavior); + InspectorInstrumentation::didNavigateWithinPage(*frame); ++ + return { }; + } - if (stateObjectType == StateObjectType::Push) { - frame->checkedHistory()->pushState(WTFMove(data), fullURL.string()); diff --git a/Source/WebCore/page/LocalFrame.cpp b/Source/WebCore/page/LocalFrame.cpp -index 114dbb1c6838198c7240af78726dd58073051704..26a2eebe64e0d34710ddd02b3dbb350ddef53f3a 100644 +index 119ae91c675f4bf1d03b9fc4878c9449416583b8..f0a10738508ca82499b474b8f221fdaf18ec3efc 100644 --- a/Source/WebCore/page/LocalFrame.cpp +++ b/Source/WebCore/page/LocalFrame.cpp @@ -40,6 +40,7 @@ @@ -5594,7 +5785,7 @@ index 114dbb1c6838198c7240af78726dd58073051704..26a2eebe64e0d34710ddd02b3dbb350d return 0; } #endif // ENABLE(ORIENTATION_EVENTS) -@@ -1340,6 +1344,362 @@ String LocalFrame::customUserAgentAsSiteSpecificQuirks() const +@@ -1350,6 +1354,362 @@ OptionSet LocalFrame::advancedPrivacyProtections() c return { }; } @@ -5958,7 +6149,7 @@ index 114dbb1c6838198c7240af78726dd58073051704..26a2eebe64e0d34710ddd02b3dbb350d #undef FRAME_RELEASE_LOG_ERROR diff --git a/Source/WebCore/page/LocalFrame.h b/Source/WebCore/page/LocalFrame.h -index aef60e6fe0be63ec1aca391fde6a1bc961a9e768..fd43db619f60121d4a2dbadb08c4c8e1d4092226 100644 +index c2fc366ed759fb9e1d83821c4fff4b05a6b8fe35..d3eec8aa3129ae6567b1402968374015f11efaa2 100644 --- a/Source/WebCore/page/LocalFrame.h +++ b/Source/WebCore/page/LocalFrame.h @@ -28,8 +28,10 @@ @@ -6020,7 +6211,7 @@ index aef60e6fe0be63ec1aca391fde6a1bc961a9e768..fd43db619f60121d4a2dbadb08c4c8e1 void selfOnlyRef(); void selfOnlyDeref(); -@@ -353,7 +355,6 @@ private: +@@ -355,7 +357,6 @@ private: #if ENABLE(DATA_DETECTION) std::unique_ptr m_dataDetectionResults; #endif @@ -6028,7 +6219,7 @@ index aef60e6fe0be63ec1aca391fde6a1bc961a9e768..fd43db619f60121d4a2dbadb08c4c8e1 void betterApproximateNode(const IntPoint& testPoint, const NodeQualifier&, Node*& best, Node* failedNode, IntPoint& bestPoint, IntRect& bestRect, const IntRect& testRect); bool hitTestResultAtViewportLocation(const FloatPoint& viewportLocation, HitTestResult&, IntPoint& center); -@@ -361,6 +362,7 @@ private: +@@ -363,6 +364,7 @@ private: enum class ShouldFindRootEditableElement : bool { No, Yes }; Node* qualifyingNodeAtViewportLocation(const FloatPoint& viewportLocation, FloatPoint& adjustedViewportLocation, const NodeQualifier&, ShouldApproximate, ShouldFindRootEditableElement = ShouldFindRootEditableElement::Yes); @@ -6037,10 +6228,10 @@ index aef60e6fe0be63ec1aca391fde6a1bc961a9e768..fd43db619f60121d4a2dbadb08c4c8e1 ViewportArguments m_viewportArguments; diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp -index 34c1e3039b5db70d15493524c96e507c2ce95199..2eb25218240da0a7878d9db2be1e9d3301e5d990 100644 +index 72ffbbfd28edb23a93c8c8fba76ab25a7f7b0f72..8d787339e6b570e210765bb1cddec6c4705c2a25 100644 --- a/Source/WebCore/page/Page.cpp +++ b/Source/WebCore/page/Page.cpp -@@ -579,6 +579,45 @@ void Page::setOverrideViewportArguments(const std::optional& +@@ -592,6 +592,45 @@ void Page::setOverrideViewportArguments(const std::optional& document->updateViewportArguments(); } @@ -6086,7 +6277,7 @@ index 34c1e3039b5db70d15493524c96e507c2ce95199..2eb25218240da0a7878d9db2be1e9d33 ScrollingCoordinator* Page::scrollingCoordinator() { if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) { -@@ -3868,6 +3907,26 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) +@@ -3873,6 +3912,26 @@ void Page::setUseDarkAppearanceOverride(std::optional valueOverride) #endif } @@ -6114,10 +6305,10 @@ index 34c1e3039b5db70d15493524c96e507c2ce95199..2eb25218240da0a7878d9db2be1e9d33 { if (insets == m_fullscreenInsets) diff --git a/Source/WebCore/page/Page.h b/Source/WebCore/page/Page.h -index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd8a083b9d 100644 +index 67a128b27cdd46115158ec20e7ce38dd56fde3d6..8ec6a45348412257db2b027f6f15027a21725466 100644 --- a/Source/WebCore/page/Page.h +++ b/Source/WebCore/page/Page.h -@@ -321,6 +321,9 @@ public: +@@ -341,6 +341,9 @@ public: const std::optional& overrideViewportArguments() const { return m_overrideViewportArguments; } WEBCORE_EXPORT void setOverrideViewportArguments(const std::optional&); @@ -6127,7 +6318,7 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd static void refreshPlugins(bool reload); WEBCORE_EXPORT PluginData& pluginData(); void clearPluginData(); -@@ -385,6 +388,10 @@ public: +@@ -405,6 +408,10 @@ public: #if ENABLE(DRAG_SUPPORT) DragController& dragController() { return m_dragController.get(); } const DragController& dragController() const { return m_dragController.get(); } @@ -6138,7 +6329,7 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd #endif FocusController& focusController() const { return *m_focusController; } WEBCORE_EXPORT CheckedRef checkedFocusController() const; -@@ -568,6 +575,10 @@ public: +@@ -588,6 +595,10 @@ public: WEBCORE_EXPORT void effectiveAppearanceDidChange(bool useDarkAppearance, bool useElevatedUserInterfaceLevel); bool defaultUseDarkAppearance() const { return m_useDarkAppearance; } void setUseDarkAppearanceOverride(std::optional); @@ -6149,7 +6340,7 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd #if ENABLE(TEXT_AUTOSIZING) float textAutosizingWidth() const { return m_textAutosizingWidth; } -@@ -1015,6 +1026,11 @@ public: +@@ -1035,6 +1046,11 @@ public: WEBCORE_EXPORT void setInteractionRegionsEnabled(bool); #endif @@ -6161,7 +6352,7 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) DeviceOrientationUpdateProvider* deviceOrientationUpdateProvider() const { return m_deviceOrientationUpdateProvider.get(); } #endif -@@ -1197,6 +1213,9 @@ private: +@@ -1248,6 +1264,9 @@ private: #if ENABLE(DRAG_SUPPORT) UniqueRef m_dragController; @@ -6171,7 +6362,7 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd #endif std::unique_ptr m_focusController; #if ENABLE(CONTEXT_MENUS) -@@ -1275,6 +1294,8 @@ private: +@@ -1327,6 +1346,8 @@ private: bool m_useElevatedUserInterfaceLevel { false }; bool m_useDarkAppearance { false }; std::optional m_useDarkAppearanceOverride; @@ -6180,7 +6371,7 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd #if ENABLE(TEXT_AUTOSIZING) float m_textAutosizingWidth { 0 }; -@@ -1454,6 +1475,11 @@ private: +@@ -1506,6 +1527,11 @@ private: #endif std::optional m_overrideViewportArguments; @@ -6193,10 +6384,10 @@ index 39c4f65e563afee7e7bb770a7b174eb64432f04c..2aae08e7fd481aeae907d0acaae595fd #if ENABLE(DEVICE_ORIENTATION) && PLATFORM(IOS_FAMILY) RefPtr m_deviceOrientationUpdateProvider; diff --git a/Source/WebCore/page/PageConsoleClient.cpp b/Source/WebCore/page/PageConsoleClient.cpp -index 18e3cde7b9ae368de4b87c88c2f8324b77cbd7c8..1ebc51b6d81fc6ae17124e7be7da039609df03d0 100644 +index 8fcc6f546882998be87d52c296c4637c6fd5af0f..73e3adc185923ba249f39f070a0b9fbb20418b0b 100644 --- a/Source/WebCore/page/PageConsoleClient.cpp +++ b/Source/WebCore/page/PageConsoleClient.cpp -@@ -439,4 +439,9 @@ Ref PageConsoleClient::protectedPage() const +@@ -434,4 +434,9 @@ Ref PageConsoleClient::protectedPage() const return m_page.get(); } @@ -6269,10 +6460,10 @@ index 91a9847a4083393e225f42e71c2dd590a88c0289..b0838c84e4ba24378db42f40a68856af #endif ; diff --git a/Source/WebCore/page/Screen.cpp b/Source/WebCore/page/Screen.cpp -index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6f9c5f754 100644 +index 706f67ca9d5b98f519080fad94d424a130b18a0e..c98147603680bd21c83a0b2b1593fa84a733f22f 100644 --- a/Source/WebCore/page/Screen.cpp +++ b/Source/WebCore/page/Screen.cpp -@@ -111,6 +111,9 @@ int Screen::availLeft() const +@@ -102,6 +102,9 @@ int Screen::availLeft() const if (fingerprintingProtectionsEnabled(*frame)) return 0; @@ -6282,7 +6473,7 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 return static_cast(screenAvailableRect(frame->protectedView().get()).x()); } -@@ -126,6 +129,9 @@ int Screen::availTop() const +@@ -117,6 +120,9 @@ int Screen::availTop() const if (fingerprintingProtectionsEnabled(*frame)) return 0; @@ -6292,7 +6483,7 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 return static_cast(screenAvailableRect(frame->protectedView().get()).y()); } -@@ -141,6 +147,9 @@ int Screen::availHeight() const +@@ -132,6 +138,9 @@ int Screen::availHeight() const if (fingerprintingProtectionsEnabled(*frame)) return static_cast(frame->screenSize().height()); @@ -6302,7 +6493,7 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 return static_cast(screenAvailableRect(frame->protectedView().get()).height()); } -@@ -156,6 +165,9 @@ int Screen::availWidth() const +@@ -147,6 +156,9 @@ int Screen::availWidth() const if (fingerprintingProtectionsEnabled(*frame)) return static_cast(frame->screenSize().width()); @@ -6313,10 +6504,10 @@ index 4e4dfdebe954bf3f047d3a86a758dfd0913f732e..da2bcd0256cdfc2ba28fb07094abd0b6 } diff --git a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp -index 2b3cffe02206bf456a7c39ef66b3176f89a33b86..64bffe692552e7fbbbabd71e11de9c40c6ec3951 100644 +index 50cf04e63a7de97d508448f181429f5b7fa438a3..6c2a5c085436eac669bce5f1d9094764ba0c6250 100644 --- a/Source/WebCore/page/csp/ContentSecurityPolicy.cpp +++ b/Source/WebCore/page/csp/ContentSecurityPolicy.cpp -@@ -343,6 +343,8 @@ bool ContentSecurityPolicy::allowContentSecurityPolicySourceStarToMatchAnyProtoc +@@ -344,6 +344,8 @@ bool ContentSecurityPolicy::allowContentSecurityPolicySourceStarToMatchAnyProtoc template typename std::enable_if::value, bool>::type ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, Predicate&& predicate, Args&&... args) const { @@ -6325,7 +6516,7 @@ index 2b3cffe02206bf456a7c39ef66b3176f89a33b86..64bffe692552e7fbbbabd71e11de9c40 bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; for (auto& policy : m_policies) { if (policy->isReportOnly() != isReportOnly) -@@ -356,6 +358,8 @@ typename std::enable_if bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposition, ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { @@ -6334,7 +6525,7 @@ index 2b3cffe02206bf456a7c39ef66b3176f89a33b86..64bffe692552e7fbbbabd71e11de9c40 bool isReportOnly = disposition == ContentSecurityPolicy::Disposition::ReportOnly; bool isAllowed = true; for (auto& policy : m_policies) { -@@ -372,6 +376,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit +@@ -373,6 +377,8 @@ bool ContentSecurityPolicy::allPoliciesWithDispositionAllow(Disposition disposit template bool ContentSecurityPolicy::allPoliciesAllow(ViolatedDirectiveCallback&& callback, Predicate&& predicate, Args&&... args) const { @@ -6475,7 +6666,7 @@ index 34f49853b1d5ac8d8409bbd36d203bf7dfbb08e8..6d2808d510413e89ae9851733437d15b bool m_disallowFileAccess { false }; }; diff --git a/Source/WebCore/platform/DragImage.cpp b/Source/WebCore/platform/DragImage.cpp -index dc894343a5d9ce0e45a370a83bebf97fdcbeccc5..00003bd9bada8f134b6cc49f47c8c5cb459d1ebd 100644 +index c359242a7967dab94b8dc3c276a6df5473527145..64b0c6a0bfdf27a0305c25e8b8e0cda637450aa4 100644 --- a/Source/WebCore/platform/DragImage.cpp +++ b/Source/WebCore/platform/DragImage.cpp @@ -280,7 +280,7 @@ DragImage::~DragImage() @@ -6488,10 +6679,10 @@ index dc894343a5d9ce0e45a370a83bebf97fdcbeccc5..00003bd9bada8f134b6cc49f47c8c5cb IntSize dragImageSize(DragImageRef) { diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp -index a4e3064903c7bfb3d64244804828fe1c6d76c222..2dfa62b08f83ff5e576fcb29962fe885fdffec86 100644 +index 092649a26549e8fc7c5683ad47585b4d7b1a0eab..7944352d9218b6237cfb4baceb686fcfa056c0ef 100644 --- a/Source/WebCore/platform/MIMETypeRegistry.cpp +++ b/Source/WebCore/platform/MIMETypeRegistry.cpp -@@ -666,6 +666,9 @@ bool MIMETypeRegistry::canShowMIMEType(const String& mimeType) +@@ -663,6 +663,9 @@ bool MIMETypeRegistry::canShowMIMEType(const String& mimeType) if (startsWithLettersIgnoringASCIICase(mimeType, "text/"_s)) return !isUnsupportedTextMIMEType(mimeType); @@ -6634,7 +6825,7 @@ index ae46341ba71c7f6df7c607bd852338cdb7f83fe1..b318c0771192344a6891c1f097cb0b93 +} // namespace WebCore +#endif diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h -index 9db6f2d77f14bd77f075a4c826dea1768452fcb9..7a7d48b016037d3865603619b2c4ca67e737bc42 100644 +index 6c64c7040eb190c3d67380070e884a8230029c26..d0f8341c538cbc2323ac0074a5ef3226d00a5fd6 100644 --- a/Source/WebCore/platform/PlatformScreen.h +++ b/Source/WebCore/platform/PlatformScreen.h @@ -151,13 +151,18 @@ WEBCORE_EXPORT float screenScaleFactor(UIScreen * = nullptr); @@ -6806,10 +6997,10 @@ index d137ffd1a8ed0b788bd28197c6d7e9f7d14e852f..dcf8bf3f7ee6b037a370712e2ac36b6e if (!image || !encodeImage(image, mimeType, &encodedImage)) return { }; diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h -index a82b748682f984fcdd4f5413d0254e0f5573f043..2c3d4bba92c63235c124a400d89455499aa3a189 100644 +index 5b659c763b9754b025a63f89522954cc39915b9a..448b50a2b131361a75d3f816cdcbb6a102551280 100644 --- a/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h +++ b/Source/WebCore/platform/graphics/cg/ImageBufferUtilitiesCG.h -@@ -38,7 +38,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(const void* buffer, size_t b +@@ -38,7 +38,7 @@ WEBCORE_EXPORT uint8_t verifyImageBufferIsBigEnough(std::span buf RetainPtr utiFromImageBufferMIMEType(const String& mimeType); CFStringRef jpegUTI(); @@ -6830,8 +7021,21 @@ index 6f43c048cd8354c97097c8365b772b92a429b670..7bccf4f7921fb3b0848781252cd69b4b namespace WebCore { +diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp +index 6f4b01b50a2278bfd0d0a072f5d1b6b367128706..f258f5f3e769c8c3a78a7801ebde09234c0298f7 100644 +--- a/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp ++++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerRegistryScanner.cpp +@@ -860,7 +860,7 @@ MediaPlayerEnums::SupportsType GStreamerRegistryScanner::isContentTypeSupported( + return SupportsType::IsNotSupported; + } + #else +- if (!factories.hasElementForMediaType(ElementFactories::Type::Decryptor, "application/x-webm-enc")) ++ if (!factories.hasElementForMediaType(ElementFactories::Type::Decryptor, "application/x-webm-enc"_s)) + return SupportsType::IsNotSupported; + #endif // GST_CHECK_VERSION(1, 22, 0) + } diff --git a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp -index f6d2e39b6a9f454067734b3cb5a03ed243450dfa..fd78c6b39e35b57677ff6da0f66e5a76998efa47 100644 +index eb9710f7d61121f2414c8aa6734dc27653e292bb..9c0c7b350a6140681242ce36a180d6866e3e0fc2 100644 --- a/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp +++ b/Source/WebCore/platform/graphics/win/ComplexTextControllerUniscribe.cpp @@ -169,6 +169,33 @@ static Vector stringIndicesFromClusters(const Vector& clusters, @@ -6849,7 +7053,7 @@ index f6d2e39b6a9f454067734b3cb5a03ed243450dfa..fd78c6b39e35b57677ff6da0f66e5a76 + if (!numItems) + return numItems; + -+ if (font->platformData().isSystemFont() || font->platformData().hasVariations()) ++ if (font->platformData().hasVariations()) + return numItems; + + bool allGoodCharacters = true; @@ -6878,20 +7082,21 @@ index f6d2e39b6a9f454067734b3cb5a03ed243450dfa..fd78c6b39e35b57677ff6da0f66e5a76 // Determine the string for this item. const UChar* str = cp.data() + items[i].iCharPos; diff --git a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp -index 8185125ac6aa07d4ee99d676d82c79932c2d84fd..0b2a8da1463c905d1e6f1448cdc0c0f63228b30f 100644 +index 979ec06ecd698b60066dc6775bf1b647624baa56..14d06fdd5b7b7df2a1942ed975cebf117beb4d1f 100644 --- a/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformKeyboardEventGtk.cpp -@@ -37,7 +37,9 @@ +@@ -37,8 +37,10 @@ #include #include #include +#include #include + #include +#include namespace WebCore { -@@ -1301,6 +1303,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode) +@@ -1302,6 +1304,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForGdkKeyCode(unsigned keycode) } @@ -7368,21 +7573,22 @@ index ae439e30f1fb239d18e1164e8896dfb272c75673..4cf29eda13d1f2dc2f03750c0ef8985b #endif // USE(LIBWPE) diff --git a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp -index 76f1c37bb02952511a95331d2cc778eabc2375f5..c36cc0ca55e8797264100da69081dace30654393 100644 +index a8674916429908cabb86bd95dc5b3da217e1556b..75cbb518708ebd459b1ed8e3206cdb02e502067d 100644 --- a/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp +++ b/Source/WebCore/platform/libwpe/PlatformKeyboardEventLibWPE.cpp -@@ -30,8 +30,10 @@ +@@ -30,9 +30,11 @@ #include "WindowsKeyboardCodes.h" #include +#include #include + #include #include +#include namespace WebCore { -@@ -1302,6 +1304,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode) +@@ -1303,6 +1305,246 @@ int PlatformKeyboardEvent::windowsKeyCodeForWPEKeyCode(unsigned keycode) return 0; } @@ -7746,23 +7952,11 @@ index 0552842dbe3f3a2c12a504178f5a8ca977e1c4db..2ef3b1b459d8a9b4e86b4556feeb4f07 namespace WebCore { class WEBCORE_EXPORT LibWebRTCProviderGStreamer : public LibWebRTCProvider { -diff --git a/Source/WebCore/platform/network/DNS.cpp b/Source/WebCore/platform/network/DNS.cpp -index 3d9581954d0d01ccbe66c8c45d1ff36e5a978e04..a4c95274cf97237cc0dbb25d0641c944aa684538 100644 ---- a/Source/WebCore/platform/network/DNS.cpp -+++ b/Source/WebCore/platform/network/DNS.cpp -@@ -30,6 +30,7 @@ - #include "DNSResolveQueue.h" - #include - #include -+#include - - #if OS(UNIX) - #include diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp -index 80b35d678bb9f3cd3f34af6258785b0c8a088347..b72058db305a8e6228893c5a8ce3f578861dae89 100644 +index 65679251a5c66afcf60ed4d4267169eefed745f5..2cb9dc1f0e777fd172e52f5a6c8f4d6910c08c47 100644 --- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp +++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp -@@ -235,8 +235,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) +@@ -236,8 +236,11 @@ void HTTPHeaderMap::add(HTTPHeaderName name, const String& value) auto index = m_commonHeaders.findIf([&](auto& header) { return header.key == name; }); @@ -7789,10 +7983,10 @@ index cf43da22a5f7674a1b24c4d39b492e0b8c318f3a..524e671cf6959fc48aefe4ec5a0611cb WEBCORE_EXPORT void setCookie(const Cookie&); WEBCORE_EXPORT void setCookies(const Vector&, const URL&, const URL& mainDocumentURL); diff --git a/Source/WebCore/platform/network/ResourceResponseBase.cpp b/Source/WebCore/platform/network/ResourceResponseBase.cpp -index e1bf41ea3b643d3841167abca8a6bd55f5f161f1..d7df4847f04fe832196f269d32c1ce1fc54cc650 100644 +index 97e5f6f38b9c036e8fc2fe6f4d4108f458113816..1391de13e58d82fd0ab9bf66bbc922d5bffa0627 100644 --- a/Source/WebCore/platform/network/ResourceResponseBase.cpp +++ b/Source/WebCore/platform/network/ResourceResponseBase.cpp -@@ -74,6 +74,7 @@ ResourceResponseBase::ResourceResponseBase(std::optional d +@@ -75,6 +75,7 @@ ResourceResponseBase::ResourceResponseBase(std::optional d , m_httpStatusText(data ? data->httpStatusText : String { }) , m_httpVersion(data ? data->httpVersion : String { }) , m_httpHeaderFields(data ? data->httpHeaderFields : HTTPHeaderMap { }) @@ -7800,7 +7994,7 @@ index e1bf41ea3b643d3841167abca8a6bd55f5f161f1..d7df4847f04fe832196f269d32c1ce1f , m_networkLoadMetrics(data && data->networkLoadMetrics ? Box::create(*data->networkLoadMetrics) : Box { }) , m_certificateInfo(data ? data->certificateInfo : std::nullopt) , m_httpStatusCode(data ? data->httpStatusCode : 0) -@@ -892,6 +893,7 @@ std::optional ResourceResponseBase::getResponseData() cons +@@ -893,6 +894,7 @@ std::optional ResourceResponseBase::getResponseData() cons String { m_httpStatusText }, String { m_httpVersion }, HTTPHeaderMap { m_httpHeaderFields }, @@ -7808,7 +8002,7 @@ index e1bf41ea3b643d3841167abca8a6bd55f5f161f1..d7df4847f04fe832196f269d32c1ce1f m_networkLoadMetrics ? std::optional(*m_networkLoadMetrics) : std::nullopt, m_source, m_type, -@@ -965,6 +967,11 @@ std::optional Coder Coder httpStatusCode; decoder >> httpStatusCode; if (!httpStatusCode) -@@ -1019,6 +1026,7 @@ std::optional Coder Coder&&, size_t); diff --git a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp -index 798c95d09029dd354980a227bf906c43d9b75ee3..83461976697da56c2c5e51f56fd3e6fe1a9e28c0 100644 +index 7567442a6bdccbe755b2cf5e3fa42265a065a9e1..4886cf0b5a6bc0b8a270d763ad481f5bc6f0d1c2 100644 --- a/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp +++ b/Source/WebCore/platform/network/curl/NetworkStorageSessionCurl.cpp -@@ -134,6 +134,12 @@ void NetworkStorageSession::setCookieAcceptPolicy(CookieAcceptPolicy policy) con +@@ -135,6 +135,12 @@ void NetworkStorageSession::setCookieAcceptPolicy(CookieAcceptPolicy policy) con cookieDatabase().setAcceptPolicy(policy); } @@ -8038,10 +8232,10 @@ index 09ab1320beacc41ae92399f3320aaf805d9d81d1..e1caf6e7ebd61151439a9c86350e5712 { GUniquePtr targetCookie(cookie.toSoupCookie()); diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp -index 602348fdd5c5d7aec9cb00fcc0512be0d791ba68..ded04cb4ac56cf906f4e6e62a2bc50d016363cf5 100644 +index 71c773f4532b6670c4f29496cc8c4bd3093304b1..5876dfa98bb9cdb78d0de807d4408ae661c3f288 100644 --- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp -@@ -39,6 +39,7 @@ +@@ -40,6 +40,7 @@ #include #include #include @@ -8049,7 +8243,7 @@ index 602348fdd5c5d7aec9cb00fcc0512be0d791ba68..ded04cb4ac56cf906f4e6e62a2bc50d0 namespace WebCore { -@@ -689,7 +690,10 @@ template void getStringData(IDataObject* data, FORMATETC* format, Ve +@@ -690,7 +691,10 @@ template void getStringData(IDataObject* data, FORMATETC* format, Ve STGMEDIUM store; if (FAILED(data->GetData(format, &store))) return; @@ -8104,10 +8298,10 @@ index 0379437d84807e4a8d3846afac5ec8a70e743e70..1ae19e2b755e99c9f4c3e6d5dc0e4f8b if (!m_dragDataMap.isEmpty() || !m_platformDragData) return m_dragDataMap; diff --git a/Source/WebCore/platform/win/KeyEventWin.cpp b/Source/WebCore/platform/win/KeyEventWin.cpp -index d948c806e68a05a9899a67c00048435c4dc93134..9a5a045f8642ca403b1da59a0ac7e838c86fc4d7 100644 +index d450bf9d0fd1f0bf8f28db483ac9d3d60fa9d114..72a59403a0b5493aea4a8e28eb15eac24b652b09 100644 --- a/Source/WebCore/platform/win/KeyEventWin.cpp +++ b/Source/WebCore/platform/win/KeyEventWin.cpp -@@ -242,10 +242,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, +@@ -243,10 +243,16 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(HWND, WPARAM code, LPARAM keyData, { } @@ -8128,10 +8322,10 @@ index d948c806e68a05a9899a67c00048435c4dc93134..9a5a045f8642ca403b1da59a0ac7e838 OptionSet PlatformKeyboardEvent::currentStateOfModifierKeys() diff --git a/Source/WebCore/platform/win/PasteboardWin.cpp b/Source/WebCore/platform/win/PasteboardWin.cpp -index 6ead5f4dea594fac7fad10fe97ad5a1ce605804f..a0cd7169ee36a3bec67b6a224444078fab61b699 100644 +index 03e5dc0b6ff099c281c61f05b29cf155b96922af..9b4694bc816e0e62a37c57e64729f183baca9080 100644 --- a/Source/WebCore/platform/win/PasteboardWin.cpp +++ b/Source/WebCore/platform/win/PasteboardWin.cpp -@@ -1136,7 +1136,21 @@ void Pasteboard::writeCustomData(const Vector& data) +@@ -1137,7 +1137,21 @@ void Pasteboard::writeCustomData(const Vector& data) } clear(); @@ -8153,7 +8347,7 @@ index 6ead5f4dea594fac7fad10fe97ad5a1ce605804f..a0cd7169ee36a3bec67b6a224444078f if (::OpenClipboard(m_owner)) { const auto& customData = data.first(); customData.forEachPlatformStringOrBuffer([](auto& type, auto& stringOrBuffer) { -@@ -1175,4 +1189,25 @@ void Pasteboard::write(const Color&) +@@ -1176,4 +1190,25 @@ void Pasteboard::write(const Color&) { } @@ -8623,11 +8817,24 @@ index 0000000000000000000000000000000000000000..a76b583a1e65cd6999fab4784c22dd9c +}; + +} // namespace WebCore +diff --git a/Source/WebCore/rendering/AncestorSubgridIterator.cpp b/Source/WebCore/rendering/AncestorSubgridIterator.cpp +index 9e7a774c2e0e591e491e0cda3657ae02f4543453..3161944e8f455d4dd33f6bbfd81ae2bb54d0787a 100644 +--- a/Source/WebCore/rendering/AncestorSubgridIterator.cpp ++++ b/Source/WebCore/rendering/AncestorSubgridIterator.cpp +@@ -30,7 +30,7 @@ + + namespace WebCore { + +-AncestorSubgridIterator::AncestorSubgridIterator() = default; ++AncestorSubgridIterator::AncestorSubgridIterator() { }; + + AncestorSubgridIterator::AncestorSubgridIterator(SingleThreadWeakPtr firstAncestorSubgrid, GridTrackSizingDirection direction) + : m_firstAncestorSubgrid(firstAncestorSubgrid) diff --git a/Source/WebCore/rendering/RenderTextControl.cpp b/Source/WebCore/rendering/RenderTextControl.cpp -index 58574b4d9fb503918e2cac0993ffe778f256a953..23de6aecb4ea7f7a1a36af6a93611559f19cfc11 100644 +index 5d81c5942027e02222430036013e2a066a6bae06..0246502c570719cc9c9362726b9bc03ded002a0b 100644 --- a/Source/WebCore/rendering/RenderTextControl.cpp +++ b/Source/WebCore/rendering/RenderTextControl.cpp -@@ -222,13 +222,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren) +@@ -225,13 +225,13 @@ void RenderTextControl::layoutExcludedChildren(bool relayoutChildren) } } @@ -8681,7 +8888,7 @@ index 1d8488e0d36288e09cd5662bd7f770ade95dfee3..dee07f87b47d62d4ef8ede45824bdb2f WorkerOrWorkletGlobalScope& m_globalScope; }; diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp -index 53209e9de68b0da9c7251d2575fa17195488ae60..5629471032b6a26186e8abff73c6f80e99e13a65 100644 +index 5f283341f89b3bc3be0c7508a0d995144764bb45..dc618d18fcfe7ef819f3724847f3d4e4c6771fc2 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp @@ -96,6 +96,8 @@ @@ -8693,7 +8900,7 @@ index 53209e9de68b0da9c7251d2575fa17195488ae60..5629471032b6a26186e8abff73c6f80e #endif #if ENABLE(APPLE_PAY_REMOTE_UI) -@@ -1098,6 +1100,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) +@@ -1090,6 +1092,14 @@ void NetworkConnectionToWebProcess::clearPageSpecificData(PageIdentifier pageID) storageSession->clearPageSpecificDataForResourceLoadStatistics(pageID); } @@ -8709,10 +8916,10 @@ index 53209e9de68b0da9c7251d2575fa17195488ae60..5629471032b6a26186e8abff73c6f80e { if (auto* storageSession = networkProcess().storageSession(m_sessionID)) diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h -index 12fe210ef04c92edf4b44b70f9bb35d00cc8a7d1..1196d7e9192dc01cac4914ac10998613f48c231c 100644 +index 0b2641927c4f8b17381b8e8c5bfa5e666506e229..22073e29d1104d928e5ca2fa56ffe830ede1f8a8 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h -@@ -345,6 +345,8 @@ private: +@@ -343,6 +343,8 @@ private: void clearPageSpecificData(WebCore::PageIdentifier); @@ -8722,7 +8929,7 @@ index 12fe210ef04c92edf4b44b70f9bb35d00cc8a7d1..1196d7e9192dc01cac4914ac10998613 void logUserInteraction(RegistrableDomain&&); diff --git a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in -index eb27201d553e64146b8d36d21a49e3981d6f05c1..d49ea6c810dfd4f460b24d94681d6b9ca088b020 100644 +index 1edf0f0137dcf67dd425ce92180cdd5a1811475b..0af045974298fee7227b0cfa8b2b9e6c54779ec0 100644 --- a/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in @@ -74,6 +74,8 @@ messages -> NetworkConnectionToWebProcess LegacyReceiver { @@ -8735,10 +8942,10 @@ index eb27201d553e64146b8d36d21a49e3981d6f05c1..d49ea6c810dfd4f460b24d94681d6b9c LogUserInteraction(WebCore::RegistrableDomain domain) ResourceLoadStatisticsUpdated(Vector statistics) -> () diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.cpp b/Source/WebKit/NetworkProcess/NetworkProcess.cpp -index f9b765f8732de5d51b093fc776920e55b760cba3..621ee3d381f62e2ae6d2c4a71e8a5803a4729d67 100644 +index 5d7274e691dbe4a9c4763b349abca7d94e878554..d58697dd16691e1caa53a5548eb68cff1309f163 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.cpp +++ b/Source/WebKit/NetworkProcess/NetworkProcess.cpp -@@ -658,6 +658,12 @@ void NetworkProcess::registrableDomainsExemptFromWebsiteDataDeletion(PAL::Sessio +@@ -659,6 +659,12 @@ void NetworkProcess::registrableDomainsExemptFromWebsiteDataDeletion(PAL::Sessio completionHandler({ }); } @@ -8752,7 +8959,7 @@ index f9b765f8732de5d51b093fc776920e55b760cba3..621ee3d381f62e2ae6d2c4a71e8a5803 { if (auto* session = networkSession(sessionID)) { diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.h b/Source/WebKit/NetworkProcess/NetworkProcess.h -index 6d41842684f3e0e8b1190359f87105b747cf9da9..279d5c033397afb120a082953c0112f34bf2878a 100644 +index 95572ae0054657f1f8f2840291d49f8d23340990..38f6df007d51c53792d270f3d50fa2f1b77b4ca1 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.h +++ b/Source/WebKit/NetworkProcess/NetworkProcess.h @@ -33,6 +33,7 @@ @@ -8782,10 +8989,10 @@ index 6d41842684f3e0e8b1190359f87105b747cf9da9..279d5c033397afb120a082953c0112f3 void clearUserInteraction(PAL::SessionID, RegistrableDomain&&, CompletionHandler&&); void deleteAndRestrictWebsiteDataForRegistrableDomains(PAL::SessionID, OptionSet, RegistrableDomainsToDeleteOrRestrictWebsiteDataFor&&, bool shouldNotifyPage, CompletionHandler&&)>&&); diff --git a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -index 5e590b5a09f8bd5d040e2e68d54c545c52d4b179..c58bb6270ab75026187fdda6c94822f6aa47a35a 100644 +index 9679dc2ceea7b085638c19c00ba9fd04e71507da..130f12138c427a90dfffb96d7e219a258e819d10 100644 --- a/Source/WebKit/NetworkProcess/NetworkProcess.messages.in +++ b/Source/WebKit/NetworkProcess/NetworkProcess.messages.in -@@ -79,6 +79,8 @@ messages -> NetworkProcess LegacyReceiver { +@@ -82,6 +82,8 @@ messages -> NetworkProcess LegacyReceiver { SetInspectionForServiceWorkersAllowed(PAL::SessionID sessionID, bool inspectable) @@ -8795,7 +9002,7 @@ index 5e590b5a09f8bd5d040e2e68d54c545c52d4b179..c58bb6270ab75026187fdda6c94822f6 ClearUserInteraction(PAL::SessionID sessionID, WebCore::RegistrableDomain resourceDomain) -> () DumpResourceLoadStatistics(PAL::SessionID sessionID) -> (String dumpedStatistics) diff --git a/Source/WebKit/NetworkProcess/NetworkSession.h b/Source/WebKit/NetworkProcess/NetworkSession.h -index e086cbe963b9965c9203c0023a67250302a0d9c4..b9a10a505a48e0708b048a7af71fb69e5df5d6a4 100644 +index f5a62296667657a7f094627e0792cb4284c04ec4..93c34c61f1cb29f3ed4c1c787da6f3efe994cfb2 100644 --- a/Source/WebKit/NetworkProcess/NetworkSession.h +++ b/Source/WebKit/NetworkProcess/NetworkSession.h @@ -200,6 +200,9 @@ public: @@ -8817,10 +9024,10 @@ index e086cbe963b9965c9203c0023a67250302a0d9c4..b9a10a505a48e0708b048a7af71fb69e HashSet> m_keptAliveLoads; diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm -index dc841a54751eb8ffa12f62a0817174aaca29eea7..ab6e9cb48c00e4ede2b53322cca8693c02e69a44 100644 +index 6c4c0e37a75426d90667c9ec595f8fa1b19ca502..45d1e5916c8cc5ec0136cf3b3596e9efb5e4a1ec 100644 --- a/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm +++ b/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm -@@ -767,6 +767,8 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didRece +@@ -769,6 +769,8 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didRece if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { sessionCocoa->setClientAuditToken(challenge); @@ -8829,7 +9036,7 @@ index dc841a54751eb8ffa12f62a0817174aaca29eea7..ab6e9cb48c00e4ede2b53322cca8693c NSURLSessionTaskTransactionMetrics *metrics = task._incompleteTaskMetrics.transactionMetrics.lastObject; auto tlsVersion = (tls_protocol_version_t)metrics.negotiatedTLSProtocolVersion.unsignedShortValue; -@@ -1108,6 +1110,13 @@ ALLOW_DEPRECATED_DECLARATIONS_END +@@ -1113,6 +1115,13 @@ - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)data resourceResponse.setDeprecatedNetworkLoadMetrics(WebCore::copyTimingData(taskMetrics, networkDataTask->networkLoadMetrics())); @@ -8988,10 +9195,10 @@ index 486849ef6f550a0f3caab311abf5743c6d38e5af..afeaac63a18d9e71d3afead23b7da4fe void NetworkSessionCurl::didReceiveChallenge(WebSocketTask& webSocketTask, WebCore::AuthenticationChallenge&& challenge, CompletionHandler&& challengeCompletionHandler) diff --git a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp -index 60106d6125f85d0cf848e828fd4ed7a50005f105..021d7b6d12baf4671a2968753969ca4675044313 100644 +index a5198bfa752746dd83dc2617606a27194afcd86f..3ca6b32e93bdaff2baae22170c84efe9bfe875d3 100644 --- a/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp +++ b/Source/WebKit/NetworkProcess/curl/WebSocketTaskCurl.cpp -@@ -36,11 +36,12 @@ +@@ -37,11 +37,12 @@ namespace WebKit { @@ -9005,7 +9212,7 @@ index 60106d6125f85d0cf848e828fd4ed7a50005f105..021d7b6d12baf4671a2968753969ca46 , m_scheduler(WebCore::CurlContext::singleton().streamScheduler()) { // We use topOrigin in case of service worker websocket connections, for which pageID does not link to a real page. -@@ -52,7 +53,7 @@ WebSocketTask::WebSocketTask(NetworkSocketChannel& channel, WebPageProxyIdentifi +@@ -53,7 +54,7 @@ WebSocketTask::WebSocketTask(NetworkSocketChannel& channel, WebPageProxyIdentifi if (networkSession() && networkSession()->networkProcess().localhostAliasesForTesting().contains(m_request.url().host())) localhostAlias = WebCore::CurlStream::LocalhostAlias::Enable; @@ -9014,7 +9221,7 @@ index 60106d6125f85d0cf848e828fd4ed7a50005f105..021d7b6d12baf4671a2968753969ca46 m_channel.didSendHandshakeRequest(WebCore::ResourceRequest(m_request)); } -@@ -257,7 +258,7 @@ void WebSocketTask::tryServerTrustEvaluation(WebCore::AuthenticationChallenge&& +@@ -258,7 +259,7 @@ void WebSocketTask::tryServerTrustEvaluation(WebCore::AuthenticationChallenge&& if (networkSession() && networkSession()->networkProcess().localhostAliasesForTesting().contains(m_request.url().host())) localhostAlias = WebCore::CurlStream::LocalhostAlias::Enable; @@ -9064,10 +9271,10 @@ index 51f3fb7ae9a4e208bc11ac583b72e772eac5e4dc..386ec972eba86763b83407c322a971a3 ;; Except deny access to new-style iOS Keychain folders which are UUIDs. (deny file-read* file-write* diff --git a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp -index 15fb15b528ae9177e69fd4b6b43b81b7216232ff..075499ebbc20845a80830cdce105fb590f0772f8 100644 +index 61d9c1d41fdc490faf800fb30d66eb4603950cbf..3dffffe74cd04b22e40ce0d94326760404fbbc6c 100644 --- a/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp +++ b/Source/WebKit/NetworkProcess/soup/NetworkDataTaskSoup.cpp -@@ -460,6 +460,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& inputStream) +@@ -461,6 +461,8 @@ void NetworkDataTaskSoup::didSendRequest(GRefPtr&& inputStream) m_networkLoadMetrics.responseStart = MonotonicTime::now(); #endif @@ -9076,7 +9283,7 @@ index 15fb15b528ae9177e69fd4b6b43b81b7216232ff..075499ebbc20845a80830cdce105fb59 dispatchDidReceiveResponse(); } -@@ -562,6 +564,8 @@ bool NetworkDataTaskSoup::acceptCertificate(GTlsCertificate* certificate, GTlsCe +@@ -563,6 +565,8 @@ bool NetworkDataTaskSoup::acceptCertificate(GTlsCertificate* certificate, GTlsCe { ASSERT(m_soupMessage); URL url = soupURIToURL(soup_message_get_uri(m_soupMessage.get())); @@ -9125,10 +9332,10 @@ index 60e79ff683e280591d686468c42decf1ac109ed2..99707bc16644b88ff24a192029f3866e } diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake -index b33c07849a629c7c5d4ea4b5cbb6788af3dd3023..aedd95cea9e6388cab32274967513224890287a5 100644 +index a509f56343f94f1bc30658ec9928ec1796a5a9b8..e2fcf6d35053f6982975d238f17b76f49e1bacdc 100644 --- a/Source/WebKit/PlatformGTK.cmake +++ b/Source/WebKit/PlatformGTK.cmake -@@ -323,6 +323,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES +@@ -324,6 +324,9 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GSTREAMER_PBUTILS_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} @@ -9138,7 +9345,7 @@ index b33c07849a629c7c5d4ea4b5cbb6788af3dd3023..aedd95cea9e6388cab32274967513224 ) list(APPEND WebKit_INTERFACE_INCLUDE_DIRECTORIES -@@ -353,6 +356,9 @@ if (USE_LIBWEBRTC) +@@ -354,6 +357,9 @@ if (USE_LIBWEBRTC) list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES "${THIRDPARTY_DIR}/libwebrtc/Source/" "${THIRDPARTY_DIR}/libwebrtc/Source/webrtc" @@ -9148,7 +9355,7 @@ index b33c07849a629c7c5d4ea4b5cbb6788af3dd3023..aedd95cea9e6388cab32274967513224 ) endif () -@@ -404,6 +410,12 @@ else () +@@ -405,6 +411,12 @@ else () set(WebKitGTK_ENUM_HEADER_TEMPLATE ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitEnumTypesGtk3.h.in) endif () @@ -9162,7 +9369,7 @@ index b33c07849a629c7c5d4ea4b5cbb6788af3dd3023..aedd95cea9e6388cab32274967513224 set(WebKitGTK_ENUM_GENERATION_HEADERS ${WebKitGTK_INSTALLED_HEADERS}) list(REMOVE_ITEM WebKitGTK_ENUM_GENERATION_HEADERS ${WebKitGTK_DERIVED_SOURCES_DIR}/webkit/WebKitEnumTypes.h) diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake -index 43d58da592e9b0f0bd6ca5cef5cbca0c4ba39b31..1fd4a732ca871704bbb915e93cf62d206c9db46e 100644 +index aa5c183a4c0946270713840071cf0167533158f6..637365fbb7d91f99ba1478188291bedff9b1cc2b 100644 --- a/Source/WebKit/PlatformWPE.cmake +++ b/Source/WebKit/PlatformWPE.cmake @@ -111,6 +111,8 @@ list(APPEND WebKit_SERIALIZATION_IN_FILES @@ -9182,7 +9389,7 @@ index 43d58da592e9b0f0bd6ca5cef5cbca0c4ba39b31..1fd4a732ca871704bbb915e93cf62d20 ) if (ENABLE_2022_GLIB_API) -@@ -425,7 +428,16 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES +@@ -426,7 +429,16 @@ list(APPEND WebKit_SYSTEM_INCLUDE_DIRECTORIES ${GIO_UNIX_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} @@ -9200,7 +9407,7 @@ index 43d58da592e9b0f0bd6ca5cef5cbca0c4ba39b31..1fd4a732ca871704bbb915e93cf62d20 list(APPEND WebKit_LIBRARIES WPE::libwpe diff --git a/Source/WebKit/PlatformWin.cmake b/Source/WebKit/PlatformWin.cmake -index 06a86d0cfd1ca90f383af2b079f60ce220f8eb02..9e21935463bf964ecb090be48e68b50ef29c049b 100644 +index 7da9a409b65a577566f143a26a9717d4ba687a3c..711b5e1c4c82dfdf9ac6139a6de0785d29c1cc20 100644 --- a/Source/WebKit/PlatformWin.cmake +++ b/Source/WebKit/PlatformWin.cmake @@ -56,8 +56,13 @@ list(APPEND WebKit_SOURCES @@ -9306,7 +9513,7 @@ index 06a86d0cfd1ca90f383af2b079f60ce220f8eb02..9e21935463bf964ecb090be48e68b50e + list(APPEND WebProcess_SOURCES WebProcess/EntryPoint/win/WebProcessMain.cpp - ) + diff --git a/Source/WebKit/Shared/API/c/wpe/WebKit.h b/Source/WebKit/Shared/API/c/wpe/WebKit.h index a9aa21f5589dec453db1713c8846e0d2e687f552..9b94469d078d92e4b9e0c8149122b19a4d3b5307 100644 --- a/Source/WebKit/Shared/API/c/wpe/WebKit.h @@ -9319,6 +9526,22 @@ index a9aa21f5589dec453db1713c8846e0d2e687f552..9b94469d078d92e4b9e0c8149122b19a #include #include #include +diff --git a/Source/WebKit/Shared/AuxiliaryProcess.h b/Source/WebKit/Shared/AuxiliaryProcess.h +index bc4f258d0970d21655a311ba72932296440111f8..21bf2a8dc680ead511ddb17a9a7ae891c835ee30 100644 +--- a/Source/WebKit/Shared/AuxiliaryProcess.h ++++ b/Source/WebKit/Shared/AuxiliaryProcess.h +@@ -210,6 +210,11 @@ struct AuxiliaryProcessInitializationParameters { + #if PLATFORM(COCOA) + SDKAlignedBehaviors clientSDKAlignedBehaviors; + #endif ++// Playwright begin ++#if !PLATFORM(COCOA) ++ bool shouldEnableSharedArrayBuffer { false }; ++#endif ++// Playwright end + }; + + } // namespace WebKit diff --git a/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h b/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h index b09b17a5bff38e3ba8d6bb53da9ef09d229bdb61..46aa1caa93402711a08f5980387a957f783038e5 100644 --- a/Source/WebKit/Shared/Cocoa/CompletionHandlerCallChecker.h @@ -9407,10 +9630,10 @@ index e33858caab024b20217304209d7bf428e3335653..4026f6244889e5a0ee85edb72696d0be NSEvent* nativeEvent() const { return m_nativeEvent.get(); } #elif PLATFORM(GTK) diff --git a/Source/WebKit/Shared/NativeWebWheelEvent.h b/Source/WebKit/Shared/NativeWebWheelEvent.h -index dfdebf37842c22c2d27f5cb39b22fa8aa09f5511..76b76a53abfe9f43c044fc29d0f16ac9969b7252 100644 +index f8e96218fd2671d1c0aca5e549efe0d8b94ef0f9..6cebd61bceb39c08e916fe991e4c3fc6f34b4704 100644 --- a/Source/WebKit/Shared/NativeWebWheelEvent.h +++ b/Source/WebKit/Shared/NativeWebWheelEvent.h -@@ -73,7 +73,8 @@ public: +@@ -74,7 +74,8 @@ public: #elif PLATFORM(WIN) NativeWebWheelEvent(HWND, UINT message, WPARAM, LPARAM, float deviceScaleFactor); #endif @@ -9434,10 +9657,10 @@ index ea1eb9f00feaaecf73bdddc37c904e88f43bfa85..8a631e5293a11abd650958baad4e9678 #endif }; diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in -index 4be677ef8090d21da5dedbc275ef58f2b7c41654..b538f2e810668aa1039601ccff94960fb2d00525 100644 +index 54bfa4555c6dd11f8ee8e3a75df6ba97c1032e84..c795925b062886a3eee42ef3b37e2f084ae55f7d 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in -@@ -2683,6 +2683,9 @@ class WebCore::AuthenticationChallenge { +@@ -2691,6 +2691,9 @@ class WebCore::AuthenticationChallenge { class WebCore::DragData { #if PLATFORM(COCOA) String pasteboardName(); @@ -9447,7 +9670,7 @@ index 4be677ef8090d21da5dedbc275ef58f2b7c41654..b538f2e810668aa1039601ccff94960f #endif WebCore::IntPoint clientPosition(); WebCore::IntPoint globalPosition(); -@@ -3246,6 +3249,7 @@ enum class WebCore::WasPrivateRelayed : bool; +@@ -3254,6 +3257,7 @@ enum class WebCore::WasPrivateRelayed : bool; String httpStatusText; String httpVersion; WebCore::HTTPHeaderMap httpHeaderFields; @@ -9668,11 +9891,57 @@ index 0000000000000000000000000000000000000000..f4f09d171ebf9774b3f8744751d220d3 + RefPtr customData() + bool canSmartReplace() +} +diff --git a/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp b/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp +index 5bae771f7b19ebeaea42edca80198a598f1b49e4..82fa8826f7bd505f596fd7f0d378d62ba1ac3f2f 100644 +--- a/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp ++++ b/Source/WebKit/Shared/unix/AuxiliaryProcessMain.cpp +@@ -38,6 +38,15 @@ + + namespace WebKit { + ++static bool hasArgument(const char* argument, int argc, char** argv) ++{ ++ for (int i = 0; i < argc; ++i) { ++ if (!strcmp(argument, argv[i])) ++ return true; ++ } ++ return false; ++} ++ + AuxiliaryProcessMainCommon::AuxiliaryProcessMainCommon() + { + #if ENABLE(BREAKPAD) +@@ -57,6 +66,10 @@ bool AuxiliaryProcessMainCommon::parseCommandLine(int argc, char** argv) + if (argc > 3 && argv[3] && !strcmp(argv[3], "--configure-jsc-for-testing")) + JSC::Config::configureForTesting(); + #endif ++// Playwright begin ++ if (hasArgument("--enable-shared-array-buffer", argc, argv)) ++ m_parameters.shouldEnableSharedArrayBuffer = true; ++// Playwright end + return true; + } + +diff --git a/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp b/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp +index 9edb5fbcd103cd8d1b224dfd60ac88aabe9626d2..9ed392ae3809f8bda92a2765ffadc643f23fe856 100644 +--- a/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp ++++ b/Source/WebKit/Shared/win/AuxiliaryProcessMainWin.cpp +@@ -41,6 +41,10 @@ bool AuxiliaryProcessMainCommon::parseCommandLine(int argc, char** argv) + m_parameters.connectionIdentifier = IPC::Connection::Identifier { reinterpret_cast(parseIntegerAllowingTrailingJunk(StringView::fromLatin1(argv[++i])).value_or(0)) }; + else if (!strcmp(argv[i], "-processIdentifier") && i + 1 < argc) + m_parameters.processIdentifier = ObjectIdentifier(parseIntegerAllowingTrailingJunk(StringView::fromLatin1(argv[++i])).value_or(0)); ++// Playwright begin ++ else if (!strcmp(argv[i], "-enable-shared-array-buffer")) ++ m_parameters.shouldEnableSharedArrayBuffer = true; ++// Playwright end + else if (!strcmp(argv[i], "-configure-jsc-for-testing")) + JSC::Config::configureForTesting(); + else if (!strcmp(argv[i], "-disable-jit")) diff --git a/Source/WebKit/Shared/win/WebEventFactory.cpp b/Source/WebKit/Shared/win/WebEventFactory.cpp -index 76e3fa1aa685906adfff43aed55c9902084be0af..0cf48a92e368005e843f08c4f4096fdeaff0b1a8 100644 +index 4d418e2bd7f970bc5bfebceb88adb172e5eb8540..e988f9011fa194224f7376e134d50fc553725289 100644 --- a/Source/WebKit/Shared/win/WebEventFactory.cpp +++ b/Source/WebKit/Shared/win/WebEventFactory.cpp -@@ -483,7 +483,7 @@ WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message +@@ -484,7 +484,7 @@ WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(HWND hwnd, UINT message #if ENABLE(TOUCH_EVENTS) WebTouchEvent WebEventFactory::createWebTouchEvent() { @@ -9682,7 +9951,7 @@ index 76e3fa1aa685906adfff43aed55c9902084be0af..0cf48a92e368005e843f08c4f4096fde #endif // ENABLE(TOUCH_EVENTS) diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt -index 5a8ce0964def0adf03f875b70bfeebd0d7a3df6e..2a6a24d1247d9e18a0b978cbd4a700f2af485d6c 100644 +index 3844b4e93816ad5e4a1ac4156516bc29c0203eb2..922a99ed0e62d66e39eb20b05f757870da8be85e 100644 --- a/Source/WebKit/Sources.txt +++ b/Source/WebKit/Sources.txt @@ -377,6 +377,7 @@ Shared/XR/XRDeviceProxy.cpp @@ -9722,8 +9991,8 @@ index 5a8ce0964def0adf03f875b70bfeebd0d7a3df6e..2a6a24d1247d9e18a0b978cbd4a700f2 +UIProcess/WebPageInspectorInputAgent.cpp UIProcess/WebPageProxy.cpp UIProcess/WebPageProxyMessageReceiverRegistration.cpp - UIProcess/WebPasteboardProxy.cpp -@@ -573,7 +580,11 @@ UIProcess/Inspector/WebInspectorUtilities.cpp + UIProcess/WebPageProxyTesting.cpp +@@ -574,7 +581,11 @@ UIProcess/Inspector/WebInspectorUtilities.cpp UIProcess/Inspector/WebPageDebuggable.cpp UIProcess/Inspector/WebPageInspectorController.cpp @@ -9736,10 +10005,10 @@ index 5a8ce0964def0adf03f875b70bfeebd0d7a3df6e..2a6a24d1247d9e18a0b978cbd4a700f2 UIProcess/Media/AudioSessionRoutingArbitratorProxy.cpp UIProcess/Media/MediaUsageManager.cpp diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt -index ff2daa513c7fd2791b3f28e47b521a8ad4ade968..d75ff772fd46b53c5734203ae4e617ffffde5657 100644 +index fe64c9af8d7f79b86941404d5aed66424a675bf7..0f1e5aa7a24ddc03c7462226312b4ffb354de632 100644 --- a/Source/WebKit/SourcesCocoa.txt +++ b/Source/WebKit/SourcesCocoa.txt -@@ -271,6 +271,7 @@ UIProcess/API/Cocoa/_WKArchiveExclusionRule.mm +@@ -270,6 +270,7 @@ UIProcess/API/Cocoa/_WKArchiveExclusionRule.mm UIProcess/API/Cocoa/_WKAttachment.mm UIProcess/API/Cocoa/_WKAutomationSession.mm UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm @@ -9756,7 +10025,7 @@ index ff2daa513c7fd2791b3f28e47b521a8ad4ade968..d75ff772fd46b53c5734203ae4e617ff UIProcess/Inspector/mac/WKInspectorResourceURLSchemeHandler.mm UIProcess/Inspector/mac/WKInspectorViewController.mm diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt -index 4ccf24056472cbaca8f61ed82ab6447f8bb45db7..4d283f3cb33cee9756252c929a8551b0d8595295 100644 +index 94d0f078de20208836e4a1a63f6dd0ce4e7ab556..fce80ee80cb3f2079b7405d49b5646af060c10be 100644 --- a/Source/WebKit/SourcesGTK.txt +++ b/Source/WebKit/SourcesGTK.txt @@ -130,6 +130,7 @@ UIProcess/API/glib/WebKitAutomationSession.cpp @no-unify @@ -9793,7 +10062,7 @@ index 4ccf24056472cbaca8f61ed82ab6447f8bb45db7..4d283f3cb33cee9756252c929a8551b0 UIProcess/gtk/WebPasteboardProxyGtk.cpp UIProcess/gtk/WebPopupMenuProxyGtk.cpp diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt -index 3dfcab5bbd7918b57c5dcaf8c0548bb0c4da52f2..82d274947520fe70f91da62bf1e39f728a65a003 100644 +index e6c9ee4c1e8ee1ad95ae6595e061378b377a3501..71882922bff1ad74a96b0bca2ea5522f81ef70ed 100644 --- a/Source/WebKit/SourcesWPE.txt +++ b/Source/WebKit/SourcesWPE.txt @@ -132,6 +132,7 @@ UIProcess/API/glib/WebKitAuthenticationRequest.cpp @no-unify @@ -9820,7 +10089,7 @@ index 3dfcab5bbd7918b57c5dcaf8c0548bb0c4da52f2..82d274947520fe70f91da62bf1e39f72 UIProcess/API/wpe/WebKitInputMethodContextWPE.cpp @no-unify UIProcess/API/wpe/WebKitInputMethodContextImplWPE.cpp @no-unify UIProcess/API/wpe/WebKitPopupMenu.cpp @no-unify -@@ -225,6 +228,7 @@ UIProcess/glib/DisplayLinkGLib.cpp +@@ -227,6 +230,7 @@ UIProcess/glib/DisplayLinkGLib.cpp UIProcess/glib/DisplayVBlankMonitor.cpp UIProcess/glib/DisplayVBlankMonitorDRM.cpp UIProcess/glib/DisplayVBlankMonitorTimer.cpp @@ -9828,7 +10097,7 @@ index 3dfcab5bbd7918b57c5dcaf8c0548bb0c4da52f2..82d274947520fe70f91da62bf1e39f72 UIProcess/glib/ScreenManager.cpp UIProcess/glib/WebPageProxyGLib.cpp UIProcess/glib/WebProcessPoolGLib.cpp -@@ -255,7 +259,12 @@ UIProcess/linux/MemoryPressureMonitor.cpp +@@ -259,7 +263,12 @@ UIProcess/linux/MemoryPressureMonitor.cpp UIProcess/soup/WebProcessPoolSoup.cpp UIProcess/wpe/AcceleratedBackingStoreDMABuf.cpp @@ -9841,7 +10110,7 @@ index 3dfcab5bbd7918b57c5dcaf8c0548bb0c4da52f2..82d274947520fe70f91da62bf1e39f72 UIProcess/wpe/WebPageProxyWPE.cpp UIProcess/wpe/WebPreferencesWPE.cpp -@@ -279,6 +288,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp +@@ -286,6 +295,8 @@ WebProcess/WebCoreSupport/glib/WebEditorClientGLib.cpp WebProcess/WebCoreSupport/soup/WebFrameNetworkingContext.cpp @@ -9923,7 +10192,7 @@ index 9ecfb4e61a015c97e3adaeccfcf52ce24735eeed..decae9b739c9692921305b87449f6557 virtual void setStatusText(WebKit::WebPageProxy*, const WTF::String&) { } virtual void mouseDidMoveOverElement(WebKit::WebPageProxy&, const WebKit::WebHitTestResultData&, OptionSet, Object*) { } diff --git a/Source/WebKit/UIProcess/API/C/WKInspector.cpp b/Source/WebKit/UIProcess/API/C/WKInspector.cpp -index 990b0e5ebad19fdaf1b0036585be2ed88bc125d2..9f1931dbdd8c70d3637a2d71406b5968896037f2 100644 +index 16229e649d69b812be84b487ec87941cb0986250..88a5fa4bd77136a2370175696d078c20e1d58edd 100644 --- a/Source/WebKit/UIProcess/API/C/WKInspector.cpp +++ b/Source/WebKit/UIProcess/API/C/WKInspector.cpp @@ -28,6 +28,11 @@ @@ -9966,10 +10235,10 @@ index 026121d114c5fcad84c1396be8d692625beaa3bd..edd6e5cae033124c589959a42522fde0 } #endif diff --git a/Source/WebKit/UIProcess/API/C/WKPage.cpp b/Source/WebKit/UIProcess/API/C/WKPage.cpp -index 47abb7de04be89f82e90f0a2197ef129b2d2f1cd..fb71b452a27d62af68165a778647c4b2e0236443 100644 +index 4abc7ac9b65c92e1f8ac122b97abf32c69631eb7..93e67e9e60ffa2536be7da1b70a7704d6eb3313f 100644 --- a/Source/WebKit/UIProcess/API/C/WKPage.cpp +++ b/Source/WebKit/UIProcess/API/C/WKPage.cpp -@@ -1780,6 +1780,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient +@@ -1781,6 +1781,13 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient completionHandler(String()); } @@ -9983,7 +10252,7 @@ index 47abb7de04be89f82e90f0a2197ef129b2d2f1cd..fb71b452a27d62af68165a778647c4b2 void setStatusText(WebPageProxy* page, const String& text) final { if (!m_client.setStatusText) -@@ -1809,6 +1816,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient +@@ -1810,6 +1817,8 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient { if (!m_client.didNotHandleKeyEvent) return; @@ -10074,7 +10343,7 @@ index 857afb1b892c2ee7327808f3dab0cff441c92c52..332bb2e687d6b97fd11f1366ade5b178 { return _preferences->inactiveMediaCaptureSteamRepromptIntervalInMinutes(); diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h -index 3ff86aaf450aaa15ebd57e6703927f1234c35f3f..e3914dc048bcd7fc595a21ef11d648a70c8c84d4 100644 +index 950a5587c9ed75292e6ad8b4f898b73de3dabc25..f315b1023c6910e23e88d18022a18b6710308a55 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h +++ b/Source/WebKit/UIProcess/API/Cocoa/WKPreferencesPrivate.h @@ -119,6 +119,7 @@ typedef NS_ENUM(NSInteger, _WKPitchCorrectionAlgorithm) { @@ -10124,7 +10393,7 @@ index eff4cf557033561ab20762d93a58c2d71f5505f0..2fd5a2515c54d9edcab48fa3d993298f NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm -index 350914dd5352683024925bb820148ba2582cd0c7..ac9767ff4920e066b11da4556b2df77debd18a1f 100644 +index 2432da7fa381ba09f73f2126b978e4b454e42e4b..d3f1ce3d339b6ebd6d61100eb8d4c71d86258f00 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm @@ -51,6 +51,7 @@ @@ -10135,7 +10404,7 @@ index 350914dd5352683024925bb820148ba2582cd0c7..ac9767ff4920e066b11da4556b2df77d #import #import #import -@@ -446,6 +447,11 @@ - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date comple +@@ -450,6 +451,11 @@ - (void)removeDataOfTypes:(NSSet *)dataTypes modifiedSince:(NSDate *)date comple }); } @@ -10332,7 +10601,7 @@ index 4974e14214e2bb3e982325b885bab33e54f83998..cacdf8c71fab248d38d2faf03f7affdc typedef NS_ENUM(NSInteger, _WKUserStyleLevel) { _WKUserStyleUserLevel, diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm -index 383bd33cc0b53ea049d2e6fb1bf338d584caeb18..e29ba10dceced9d115b09e014cc086c5453e33fe 100644 +index 8f7d300c449fd3323f3a47630a5b87835e7b2350..8b2b098f0bc8d9ad27654c33f616c0b73330573c 100644 --- a/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKUserStyleSheet.mm @@ -35,6 +35,7 @@ @@ -10546,7 +10815,7 @@ index 0000000000000000000000000000000000000000..e0b1da48465c850f541532ed961d1b77 +WebKit::WebPageProxy* webkitBrowserInspectorCreateNewPageInContext(WebKitWebContext*); +void webkitBrowserInspectorQuitApplication(); diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp -index e0a36ef8b438626b97ca791c250868c15fd663ea..1af633927046fd388d7a7a9a4b4e503e31df2e65 100644 +index 13452bf008a5a5b8cce2367296c20df5b05ced59..2055a9f371e8b60d7702988bfd7ffd1ad0bd55c2 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitUIClient.cpp @@ -94,6 +94,10 @@ private: @@ -10561,10 +10830,10 @@ index e0a36ef8b438626b97ca791c250868c15fd663ea..1af633927046fd388d7a7a9a4b4e503e bool canRunBeforeUnloadConfirmPanel() const final { return true; } diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp -index f2df10c56663a21420eafc06ace0d204eaae1747..dc2b805b52c202d4910633bf9c6db6edf07f3b5f 100644 +index 47eca6bcf0048acad8e4d213cae94edc03efbffc..b5b1e526b988be8c6ab5830d933c7becb52344f3 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebContext.cpp -@@ -417,10 +417,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa +@@ -421,10 +421,19 @@ static void webkitWebContextSetProperty(GObject* object, guint propID, const GVa } } @@ -10584,7 +10853,7 @@ index f2df10c56663a21420eafc06ace0d204eaae1747..dc2b805b52c202d4910633bf9c6db6ed GUniquePtr bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr)); WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object); -@@ -477,6 +486,8 @@ static void webkitWebContextConstructed(GObject* object) +@@ -481,6 +490,8 @@ static void webkitWebContextConstructed(GObject* object) static void webkitWebContextDispose(GObject* object) { @@ -10593,7 +10862,7 @@ index f2df10c56663a21420eafc06ace0d204eaae1747..dc2b805b52c202d4910633bf9c6db6ed WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv; if (!priv->clientsDetached) { priv->clientsDetached = true; -@@ -938,6 +949,11 @@ WebKitNetworkSession* webkit_web_context_get_network_session_for_automation(WebK +@@ -942,6 +953,11 @@ WebKitNetworkSession* webkit_web_context_get_network_session_for_automation(WebK return nullptr; #endif } @@ -10630,7 +10899,7 @@ index c1945fbe717a42afc1f51d64a80c7de3fa9009ba..ab63fe19b00ecbd64c9421e6eecad3e2 #endif +int webkitWebContextExistingCount(); diff --git a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp -index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d1abcd895 100644 +index 061a05bdd19eea75552cad40e78794dfd26f6668..d96b4efdb43131cfccff3ace107b3959eb6a4a1c 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitWebView.cpp @@ -34,6 +34,7 @@ @@ -10657,7 +10926,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d #include "WebKitPrintOperationPrivate.h" #include "WebKitWebInspectorPrivate.h" #include "WebKitWebViewBasePrivate.h" -@@ -145,6 +146,7 @@ enum { +@@ -146,6 +147,7 @@ enum { CLOSE, SCRIPT_DIALOG, @@ -10665,7 +10934,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d DECIDE_POLICY, PERMISSION_REQUEST, -@@ -497,6 +499,16 @@ GRefPtr WebKitWebViewClient::showOptionMenu(WebKitPopupMenu& p +@@ -506,6 +508,16 @@ GRefPtr WebKitWebViewClient::showOptionMenu(WebKitPopupMenu& p void WebKitWebViewClient::frameDisplayed(WKWPE::View&) { @@ -10682,7 +10951,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d { SetForScope inFrameDisplayedGuard(m_webView->priv->inFrameDisplayed, true); for (const auto& callback : m_webView->priv->frameDisplayedCallbacks) { -@@ -513,6 +525,18 @@ void WebKitWebViewClient::frameDisplayed(WKWPE::View&) +@@ -522,6 +534,18 @@ void WebKitWebViewClient::frameDisplayed(WKWPE::View&) } } @@ -10701,7 +10970,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d void WebKitWebViewClient::willStartLoad(WKWPE::View&) { webkitWebViewWillStartLoad(m_webView); -@@ -599,7 +623,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* +@@ -608,7 +632,7 @@ static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request) { @@ -10710,7 +10979,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d if (WEBKIT_IS_POINTER_LOCK_PERMISSION_REQUEST(request)) { webkit_permission_request_allow(request); return TRUE; -@@ -913,6 +937,10 @@ static void webkitWebViewConstructed(GObject* object) +@@ -927,6 +951,10 @@ static void webkitWebViewConstructed(GObject* object) priv->websitePolicies = adoptGRef(webkit_website_policies_new()); Ref configuration = priv->relatedView && priv->relatedView->priv->configurationForNextRelatedView ? priv->relatedView->priv->configurationForNextRelatedView.releaseNonNull() : webkitWebViewCreatePageConfiguration(webView); @@ -10721,7 +10990,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d webkitWebViewCreatePage(webView, WTFMove(configuration)); webkitWebContextWebViewCreated(priv->context.get(), webView); -@@ -1942,6 +1970,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) +@@ -1956,6 +1984,15 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass) G_TYPE_BOOLEAN, 1, WEBKIT_TYPE_SCRIPT_DIALOG); @@ -10737,7 +11006,7 @@ index 9c64c74cc0f7fbfbc8c63d7815dece46c2c3c6f4..23d807f87cf8beaf7f4b05d15b12055d /** * WebKitWebView::decide-policy: * @web_view: the #WebKitWebView on which the signal is emitted -@@ -2734,6 +2771,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const +@@ -2748,6 +2785,23 @@ void webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const webkit_script_dialog_unref(webView->priv->currentScriptDialog); } @@ -10786,7 +11055,7 @@ index 805f9f638c1630b5e9310494ae2970262de001cc..add3e80896c2e82bdd12cee15c8014bf #include <@API_INCLUDE_PREFIX@/WebKitClipboardPermissionRequest.h> #include <@API_INCLUDE_PREFIX@/WebKitColorChooserRequest.h> diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp -index cea5882f6c455898e1b5a231e1213e6b71ff21b6..d82b93d3c759b1184869b3504e1c3c07f53cc8ce 100644 +index 36a0e39f8b13dcaa57ac1221d24e06a35eabe9b0..6a51f9653ccfb26c52405e44390f4aa3dd5f23f6 100644 --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp @@ -269,6 +269,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool @@ -10811,7 +11080,7 @@ index cea5882f6c455898e1b5a231e1213e6b71ff21b6..d82b93d3c759b1184869b3504e1c3c07 void PageClientImpl::didChangeContentSize(const IntSize& size) diff --git a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h -index adf00c390a0bc584955be83d15baae5898a928eb..2a70aba8ef2d8d5882f6520425e1b9d06796b477 100644 +index 8b747ca183ddd04160b29cd9b89e5e40ad8161ab..6c99ff9824ea2db3719b84ee3f5766011213d998 100644 --- a/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h +++ b/Source/WebKit/UIProcess/API/gtk/PageClientImpl.h @@ -105,7 +105,7 @@ private: @@ -10924,10 +11193,10 @@ index 496079da90993ac37689b060b69ecd4a67c2b6a8..af30181ca922f16c0f6e245c70e5ce7d G_BEGIN_DECLS diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp -index 44ca7ff8b13bf0b1d4b16d90b8488f596175f2a1..58371f574003fba1d280ad0464b7688cd99b5ebe 100644 +index f6690c7780dff32a043c51f7afaba00119a92c44..f48f5b67505176bac3406212e266a6addd6e226a 100644 --- a/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp +++ b/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp -@@ -2946,6 +2946,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) +@@ -2930,6 +2930,11 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase) #endif } @@ -10939,7 +11208,7 @@ index 44ca7ff8b13bf0b1d4b16d90b8488f596175f2a1..58371f574003fba1d280ad0464b7688c void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext) { ASSERT(webkitWebViewBase->priv->acceleratedBackingStore); -@@ -3002,12 +3007,12 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) +@@ -2986,12 +2991,12 @@ void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase) webkitWebViewBase->priv->acceleratedBackingStore->update({ }); } @@ -11013,13 +11282,13 @@ index 26d1790017e528f26ae04dac635678d5494bfd04..b9832e9221edaa14af485d34ac6216ff virtual void didChangePageID(WKWPE::View&) { } virtual void didReceiveUserMessage(WKWPE::View&, WebKit::UserMessage&&, CompletionHandler&& completionHandler) { completionHandler(WebKit::UserMessage()); } diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp -index f498562d70a4652f6831ac6bc12ef86e537d3930..73b11a5904d32e28c469622f98f0d90659c40a40 100644 +index b9b6b379136653e9dc13313715e0d281a2c8cb01..7cb887f31dc381739b079be0ab2548075fbc0690 100644 --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp -@@ -33,9 +33,13 @@ - #include "NativeWebWheelEvent.h" +@@ -34,9 +34,13 @@ #include "TouchGestureController.h" - #include "WPEWebView.h" + #include "WPEWebViewLegacy.h" + #include "WPEWebViewPlatform.h" +#include "WebColorPickerWPE.h" +#include "WebDateTimePickerWPE.h" #include "WebContextMenuProxy.h" @@ -11030,8 +11299,8 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..73b11a5904d32e28c469622f98f0d906 #include #include #include -@@ -45,6 +49,12 @@ - #include +@@ -50,6 +54,12 @@ + #include #endif +#if USE(SKIA) @@ -11043,7 +11312,7 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..73b11a5904d32e28c469622f98f0d906 namespace WebKit { PageClientImpl::PageClientImpl(WKWPE::View& view) -@@ -203,7 +213,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I +@@ -208,7 +218,7 @@ WebCore::IntPoint PageClientImpl::accessibilityScreenToRootView(const WebCore::I WebCore::IntRect PageClientImpl::rootViewToAccessibilityScreen(const WebCore::IntRect& rect) { @@ -11052,7 +11321,7 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..73b11a5904d32e28c469622f98f0d906 } void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool) -@@ -465,6 +475,64 @@ void PageClientImpl::selectionDidChange() +@@ -487,6 +497,64 @@ void PageClientImpl::selectionDidChange() m_view.selectionDidChange(); } @@ -11117,7 +11386,7 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..73b11a5904d32e28c469622f98f0d906 WebKitWebResourceLoadManager* PageClientImpl::webResourceLoadManager() { return m_view.webResourceLoadManager(); -@@ -475,4 +543,23 @@ void PageClientImpl::callAfterNextPresentationUpdate(CompletionHandler&& +@@ -497,4 +565,23 @@ void PageClientImpl::callAfterNextPresentationUpdate(CompletionHandler&& m_view.callAfterNextPresentationUpdate(WTFMove(callback)); } @@ -11142,10 +11411,10 @@ index f498562d70a4652f6831ac6bc12ef86e537d3930..73b11a5904d32e28c469622f98f0d906 + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h -index 6c113e0349dea1d7457874a948d6e55ba2625730..0fcffc23a58401ac54cd6864011a3dd86fa0683b 100644 +index dc56a4f5af6ddf3ff3d557493482b5b25efcd24d..f1f69fb9341fa8bfff6e1ae045db5465a1b85eed 100644 --- a/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h +++ b/Source/WebKit/UIProcess/API/wpe/PageClientImpl.h -@@ -166,10 +166,25 @@ private: +@@ -166,9 +166,24 @@ private: void didChangeWebPageID() const override; void selectionDidChange() override; @@ -11156,7 +11425,6 @@ index 6c113e0349dea1d7457874a948d6e55ba2625730..0fcffc23a58401ac54cd6864011a3dd8 + RefPtr takeViewSnapshot(std::optional&&, bool nominalResolution) override; +#endif WebKitWebResourceLoadManager* webResourceLoadManager() override; - void didClearEditorStateAfterPageTransition() final { } +#if ENABLE(DATALIST_ELEMENT) + RefPtr createDataListSuggestionsDropdown(WebKit::WebPageProxy& page) override; @@ -11172,21 +11440,6 @@ index 6c113e0349dea1d7457874a948d6e55ba2625730..0fcffc23a58401ac54cd6864011a3dd8 WKWPE::View& m_view; }; -diff --git a/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp b/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp -index 8c1b77dd3c2c5dab2943647a845767e4c6086f9f..c9ae70281bab0404a525d82db9054b0db3d9eb78 100644 ---- a/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp -+++ b/Source/WebKit/UIProcess/API/wpe/WPEWebView.cpp -@@ -98,7 +98,9 @@ View::View(struct wpe_view_backend* backend, WPEDisplay* display, const API::Pag - auto& preferences = configuration->preferences(); - preferences.setAcceleratedCompositingEnabled(true); - preferences.setForceCompositingMode(true); -- preferences.setThreadedScrollingEnabled(true); -+ // Playwright override begin -+ preferences.setThreadedScrollingEnabled(false); -+ // Playwright override end - - auto& pool = configuration->processPool(); - m_pageProxy = pool.createWebPage(*m_pageClient, WTFMove(configuration)); diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h b/Source/WebKit/UIProcess/API/wpe/WebKitBrowserInspector.h new file mode 100644 index 0000000000000000000000000000000000000000..273c5105cdf1638955cea01128c9bbab3e64436c @@ -11514,10 +11767,10 @@ index 65bf3b71e451aad11039130d2d23a68f5fce499f..99a1402270bcd210107bcc4f02983789 // Save base64-encoded file contents to a local file path and return the path. // This reuses the basename of the remote file path so that the filename exposed to DOM API remains the same. diff --git a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp -index 15a56d77cdd54d17a38e71b4adf31c981e6407ee..6bc36ee8b7b762699283ab6cbb12b11cf243836a 100644 +index a889806fbc7d1329a6bd7a6d179d31318cc2f010..197f2fdc887eef0a25f82a5d4702e6d34a3a126e 100644 --- a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp +++ b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.cpp -@@ -168,7 +168,11 @@ void AuxiliaryProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& lau +@@ -165,7 +165,11 @@ void AuxiliaryProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& lau launchOptions.processCmdPrefix = String::fromUTF8(processCmdPrefix); #endif // ENABLE(DEVELOPER_MODE) && (PLATFORM(GTK) || PLATFORM(WPE)) @@ -11530,7 +11783,7 @@ index 15a56d77cdd54d17a38e71b4adf31c981e6407ee..6bc36ee8b7b762699283ab6cbb12b11c platformGetLaunchOptions(launchOptions); } diff --git a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h -index f203c2ea1a77939b1acaf5352e4cf67a58817ab2..08db3dba0ab5c4e22207c1dced9530ddad67e976 100644 +index e792deb624dc217fd9502461c0f7cabf789d812c..43b2912a05eaea0911662934305e94a6cc1477d1 100644 --- a/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h +++ b/Source/WebKit/UIProcess/AuxiliaryProcessProxy.h @@ -277,13 +277,16 @@ protected: @@ -11550,7 +11803,7 @@ index f203c2ea1a77939b1acaf5352e4cf67a58817ab2..08db3dba0ab5c4e22207c1dced9530dd - Vector platformOverrideLanguages() const; void platformStartConnectionTerminationWatchdog(); - ResponsivenessTimer m_responsivenessTimer; + // Connection::Client diff --git a/Source/WebKit/UIProcess/BackingStore.h b/Source/WebKit/UIProcess/BackingStore.h index e1d579d6d428c3575ddf83b9d78dae045beb218d..9a2830e50ec8ab965e4a5a2b5faa9285c99bcc99 100644 --- a/Source/WebKit/UIProcess/BackingStore.h @@ -11744,7 +11997,7 @@ index 3ac9df925437afb3b4d37107fc6c02dc9ee41fa6..eb0dc8703860ef5006d6df26a6ca6115 { if (!m_uiDelegate) diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm -index 58b550ade47802818b3d5ed8027f757ec7b282ec..31cbc0362a1d991de69ebd040ea70700716e097f 100644 +index 4e64905585de45ffa75c2d5b2ff2c3748fa15d15..342549d7c38432d9304ebd0bc1b55e4154f54948 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm @@ -38,6 +38,7 @@ @@ -11755,7 +12008,7 @@ index 58b550ade47802818b3d5ed8027f757ec7b282ec..31cbc0362a1d991de69ebd040ea70700 #import "PlaybackSessionManagerProxy.h" #import "QuickLookThumbnailLoader.h" #import "RemoteLayerTreeTransaction.h" -@@ -293,10 +294,84 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() +@@ -298,10 +299,84 @@ bool WebPageProxy::scrollingUpdatesDisabledForTesting() void WebPageProxy::startDrag(const DragItem& dragItem, ShareableBitmap::Handle&& dragImageHandle) { @@ -11811,9 +12064,9 @@ index 58b550ade47802818b3d5ed8027f757ec7b282ec..31cbc0362a1d991de69ebd040ea70700 + NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName]; + m_overrideDragPasteboardName = String([pasteboard name]); + } -+ send(Messages::WebPage::SetDragPasteboardName(m_overrideDragPasteboardName)); ++ legacyMainFrameProcess().send(Messages::WebPage::SetDragPasteboardName(m_overrideDragPasteboardName), webPageIDInMainFrameProcess()); + } else { -+ send(Messages::WebPage::SetDragPasteboardName(""_s)); ++ legacyMainFrameProcess().send(Messages::WebPage::SetDragPasteboardName(""_s), webPageIDInMainFrameProcess()); + } +} + @@ -11842,7 +12095,7 @@ index 58b550ade47802818b3d5ed8027f757ec7b282ec..31cbc0362a1d991de69ebd040ea70700 #if ENABLE(ATTACHMENT_ELEMENT) diff --git a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm -index ddef8d1c1f33c435baa3c5f3faa80dca2b01401b..9ec578895ed986ae786b45b2fe755a5848703567 100644 +index 36b1489cbe2de1698e6baebef5dc8f8e6d1f3acd..bdffd070443436f026b987aa86d1c22e61463dbf 100644 --- a/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm +++ b/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm @@ -434,7 +434,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END @@ -11854,7 +12107,7 @@ index ddef8d1c1f33c435baa3c5f3faa80dca2b01401b..9ec578895ed986ae786b45b2fe755a58 #endif #if (PLATFORM(IOS) || PLATFORM(VISION)) && HAVE(AGX_COMPILER_SERVICE) -@@ -840,8 +840,8 @@ void WebProcessPool::registerNotificationObservers() +@@ -790,8 +790,8 @@ void WebProcessPool::registerNotificationObservers() }]; m_scrollerStyleNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSPreferredScrollerStyleDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *notification) { @@ -12025,7 +12278,7 @@ index 555814f9771f8f16d3572cd7007817ba4296d6d3..8850e4adb182e7f0b23e5cde45f14ad8 } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp -index f9123661bf8e84307bfe55a78999d4e35c70f165..897c488a2cef712613e53cd0c502f5e48b201341 100644 +index cc5e0d803a2069c6a5539fe1bccb67c5c9b1b3aa..7841be001cb5bc6db99b3d71f881c6e9b298e5fd 100644 --- a/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp +++ b/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp @@ -40,8 +40,10 @@ @@ -12064,7 +12317,7 @@ index f9123661bf8e84307bfe55a78999d4e35c70f165..897c488a2cef712613e53cd0c502f5e4 m_downloadProxyMap.downloadFinished(*this); }); } else -@@ -168,6 +176,21 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour +@@ -153,6 +161,21 @@ void DownloadProxy::decideDestinationWithSuggestedFilename(const WebCore::Resour suggestedFilename = m_suggestedFilename; suggestedFilename = MIMETypeRegistry::appendFileExtensionIfNecessary(suggestedFilename, response.mimeType()); @@ -12086,7 +12339,7 @@ index f9123661bf8e84307bfe55a78999d4e35c70f165..897c488a2cef712613e53cd0c502f5e4 m_client->decideDestinationWithSuggestedFilename(*this, response, ResourceResponseBase::sanitizeSuggestedFilename(suggestedFilename), [this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)] (AllowOverwrite allowOverwrite, String destination) mutable { SandboxExtension::Handle sandboxExtensionHandle; if (!destination.isNull()) { -@@ -216,6 +239,8 @@ void DownloadProxy::didFinish() +@@ -201,6 +224,8 @@ void DownloadProxy::didFinish() updateQuarantinePropertiesIfPossible(); #endif m_client->didFinish(*this); @@ -12095,7 +12348,7 @@ index f9123661bf8e84307bfe55a78999d4e35c70f165..897c488a2cef712613e53cd0c502f5e4 // This can cause the DownloadProxy object to be deleted. m_downloadProxyMap.downloadFinished(*this); -@@ -226,6 +251,8 @@ void DownloadProxy::didFail(const ResourceError& error, std::span +@@ -211,6 +236,8 @@ void DownloadProxy::didFail(const ResourceError& error, std::span m_legacyResumeData = createData(resumeData); m_client->didFail(*this, error, m_legacyResumeData.get()); @@ -12117,7 +12370,7 @@ index 6f0d076b1b1cb0ec3e1c7fdc5f3a6dfffe9ee63d..656d4259dbf9ab97a8b0408c061c0fd2 } // namespace WebKit diff --git a/Source/WebKit/UIProcess/DrawingAreaProxy.h b/Source/WebKit/UIProcess/DrawingAreaProxy.h -index a11762ba4969c3b5a38b01ba3eb831940e48c9ab..e4df189df7b5246dd39a485f735743f81cdc3041 100644 +index 77d47a91327391c2b8bc3a3fc12f512c25160649..3173e2545ae0a79b90342234b008fd26a0ad72a7 100644 --- a/Source/WebKit/UIProcess/DrawingAreaProxy.h +++ b/Source/WebKit/UIProcess/DrawingAreaProxy.h @@ -98,6 +98,7 @@ public: @@ -12128,7 +12381,7 @@ index a11762ba4969c3b5a38b01ba3eb831940e48c9ab..e4df189df7b5246dd39a485f735743f8 virtual void minimumSizeForAutoLayoutDidChange() { } virtual void sizeToContentAutoSizeMaximumSizeDidChange() { } -@@ -181,6 +182,10 @@ private: +@@ -184,6 +185,10 @@ private: virtual void update(uint64_t /* backingStoreStateID */, UpdateInfo&&) { } virtual void exitAcceleratedCompositingMode(uint64_t /* backingStoreStateID */, UpdateInfo&&) { } #endif @@ -12153,7 +12406,7 @@ index fc5c53f18ad2dee2c2f40cdbb86ca7f24b262d8d..d93d804d3a8ebaa30856710df544f3db } diff --git a/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..f9af359a8b81babaf855132ec168feb22ef5799b +index 0000000000000000000000000000000000000000..8d20e2aa36ba0f7996c20a6a02792c7f151bbed5 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/CairoJpegEncoder.cpp @@ -0,0 +1,246 @@ @@ -12200,7 +12453,7 @@ index 0000000000000000000000000000000000000000..f9af359a8b81babaf855132ec168feb2 + +#include "config.h" + -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) + +#include "CairoJpegEncoder.h" + @@ -12441,10 +12694,10 @@ index 0000000000000000000000000000000000000000..4ec8b96bbbddf8a7b042f53a8068754a +cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality); diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab85677745577f9a7 +index 0000000000000000000000000000000000000000..b0527d43bf28c7b6f25a5dc3f2b9ff42e0a96190 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.cpp -@@ -0,0 +1,393 @@ +@@ -0,0 +1,387 @@ +/* + * Copyright (C) 2020 Microsoft Corporation. + * @@ -12497,7 +12750,7 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 +#include +#endif + -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) +#include "CairoJpegEncoder.h" +#include "DrawingAreaProxyCoordinatedGraphics.h" +#include "DrawingAreaProxy.h" @@ -12543,7 +12796,7 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 + m_encoder = nullptr; +} + -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) +void InspectorScreencastAgent::didPaint(sk_sp&& surface) +{ + sk_sp image(surface); @@ -12564,16 +12817,15 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 + m_encoder->encodeFrame(sk_sp(image), displaySize); + if (m_screencast) { + { -+ SkBitmap bitmap; -+ bitmap.setInfo(SkImageInfo::Make(image->width(), image->height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType)); -+ if (!bitmap.tryAllocPixels() || !image->readPixels(bitmap.pixmap(), 0, 0)) { -+ fprintf(stderr, "Failed to read pixels from SkImage\n"); ++ SkPixmap pixmap; ++ if (!image->peekPixels(&pixmap)) { ++ fprintf(stderr, "Failed to peek pixels from SkImage to compute hash\n"); + return; + } + // Do not send the same frame over and over. -+ size_t len = bitmap.computeByteSize(); ++ size_t len = pixmap.computeByteSize(); + auto cryptoDigest = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_1); -+ cryptoDigest->addBytes(std::span(reinterpret_cast(bitmap.getPixels()), len)); ++ cryptoDigest->addBytes(std::span(reinterpret_cast(pixmap.addr()), len)); + auto digest = cryptoDigest->computeHash(); + if (m_lastFrameDigest == digest) + return; @@ -12585,13 +12837,8 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 + // Scale image to fit width / height + double scale = std::min(m_screencastWidth / displaySize.width(), m_screencastHeight / displaySize.height()); + if (scale < 1) { -+ // Create a destination bitmap with the desired size -+ SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(displaySize.width() * scale, displaySize.height() * scale); + SkBitmap dstBitmap; -+ if (!dstBitmap.allocPixels(dstInfo)) { -+ fprintf(stderr, "Failed to allocate dstBitmap\n"); -+ return; -+ } ++ dstBitmap.allocPixels(SkImageInfo::MakeN32Premul(displaySize.width() * scale, displaySize.height() * scale)); + SkCanvas canvas(dstBitmap); + canvas.scale(scale, scale); + canvas.drawImage(image, 0, 0); @@ -12600,7 +12847,7 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 + + SkPixmap pixmap; + if (!image->peekPixels(&pixmap)) { -+ fprintf(stderr, "Failed to peek pixels from SkImage\n"); ++ fprintf(stderr, "Failed to peek pixels from SkImage for JPEG encoding\n"); + return; + } + @@ -12619,7 +12866,7 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 +} +#endif + -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) +void InspectorScreencastAgent::didPaint(cairo_surface_t* surface) +{ +#if PLATFORM(WPE) @@ -12826,7 +13073,7 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 +} +#endif + -+#if USE(CAIRO) && !PLATFORM(WPE) ++#if (USE(CAIRO) && !PLATFORM(WPE)) || PLATFORM(GTK) +void InspectorScreencastAgent::encodeFrame() +{ + if (!m_encoder && !m_screencast) @@ -12840,7 +13087,7 @@ index 0000000000000000000000000000000000000000..41c52ae52e31fb90721be7cab8567774 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..72399da38336232f93776e8c6e8b342ad51711ba +index 0000000000000000000000000000000000000000..f1322caa318ca408731697b2eb6349e0dc9c8537 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/InspectorScreencastAgent.h @@ -0,0 +1,109 @@ @@ -12914,10 +13161,10 @@ index 0000000000000000000000000000000000000000..72399da38336232f93776e8c6e8b342a + void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; + void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; + -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) + void didPaint(sk_sp&& surface); +#endif -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) + void didPaint(cairo_surface_t*); +#endif + @@ -12955,7 +13202,7 @@ index 0000000000000000000000000000000000000000..72399da38336232f93776e8c6e8b342a +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3f2fe93e6 +index 0000000000000000000000000000000000000000..8690b1a245d463cd29c0196ab609ab69c80cc0a9 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.cpp @@ -0,0 +1,437 @@ @@ -13000,14 +13247,14 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 +#include +#include + -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) +#include +#include +#include +#include +#endif + -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) +#include +#endif + @@ -13095,11 +13342,11 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 + WTF_MAKE_NONCOPYABLE(VPXFrame); + WTF_MAKE_FAST_ALLOCATED; +public: -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) + explicit VPXFrame(sk_sp&& surface) + : m_surface(WTFMove(surface)) + { } -+#elif USE(CAIRO) ++#elif USE(CAIRO) || PLATFORM(GTK) + explicit VPXFrame(RefPtr&& surface) + : m_surface(WTFMove(surface)) + { } @@ -13115,7 +13362,7 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 + + void convertToVpxImage(vpx_image_t* image) + { -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) + // Convert the updated region to YUV ready for encoding. + SkImageInfo info = SkImageInfo::Make(m_surface->width(), m_surface->height(), kN32_SkColorType, kPremul_SkAlphaType); + int argb_stride = info.minRowBytes(); @@ -13124,7 +13371,7 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 + uint8_t* argb_data = buffer.get(); + if (!m_surface->readPixels(info, argb_data, argb_stride, 0, 0)) + fprintf(stderr, "Read SkImage to ARGB buffer\n"); -+#elif USE(CAIRO) ++#elif USE(CAIRO) || PLATFORM(GTK) + // Convert the updated region to YUV ready for encoding. + const uint8_t* argb_data = cairo_image_surface_get_data(m_surface.get()); + int argb_stride = cairo_image_surface_get_stride(m_surface.get()); @@ -13150,9 +13397,9 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 + } + +private: -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) + sk_sp m_surface; -+#elif USE(CAIRO) ++#elif USE(CAIRO) || PLATFORM(GTK) + RefPtr m_surface; +#elif PLATFORM(MAC) + RetainPtr m_windowImage; @@ -13315,7 +13562,7 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 + m_lastFrameTimestamp = now; +} + -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) +void ScreencastEncoder::encodeFrame(sk_sp&& image, IntSize size) +{ + flushLastFrame(); @@ -13339,7 +13586,7 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 + canvas.drawImage(image, 0, 0); + m_lastFrame = makeUnique(surface.asImage()); +} -+#elif USE(CAIRO) ++#elif USE(CAIRO) || PLATFORM(GTK) +void ScreencastEncoder::encodeFrame(cairo_surface_t* drawingAreaSurface, IntSize size) +{ + flushLastFrame(); @@ -13398,7 +13645,7 @@ index 0000000000000000000000000000000000000000..026f5f7cbb9a81d83b9d4c307aecffe3 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h new file mode 100644 -index 0000000000000000000000000000000000000000..987577f5d9c2bb21eec25bc0839cc3af7b84ce1e +index 0000000000000000000000000000000000000000..f8701329f574bfad15f0e5456360a3ee3bd21b48 --- /dev/null +++ b/Source/WebKit/UIProcess/Inspector/Agents/ScreencastEncoder.h @@ -0,0 +1,82 @@ @@ -13456,9 +13703,9 @@ index 0000000000000000000000000000000000000000..987577f5d9c2bb21eec25bc0839cc3af + ScreencastEncoder(std::unique_ptr&&, WebCore::IntSize); + ~ScreencastEncoder(); + -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) + void encodeFrame(sk_sp&&, WebCore::IntSize); -+#elif USE(CAIRO) ++#elif USE(CAIRO) || PLATFORM(GTK) + void encodeFrame(cairo_surface_t*, WebCore::IntSize); +#elif PLATFORM(MAC) + void encodeFrame(RetainPtr&&); @@ -13619,10 +13866,10 @@ index 0000000000000000000000000000000000000000..e2ce910f3fd7f587add552275b7e7176 + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp -index fedef553cec70feb6c6475a5f752fbc6833dbb38..16e73d6a724dd80487b7b140aaaccfec253eb7aa 100644 +index 5cd89b25d3d87ec952d9a1a55351c9a7d76b9125..f43f2b64bcb6fffc672406f9eea9f7bda96918d6 100644 --- a/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp +++ b/Source/WebKit/UIProcess/Inspector/InspectorTargetProxy.cpp -@@ -28,11 +28,10 @@ +@@ -28,7 +28,7 @@ #include "MessageSenderInlines.h" #include "ProvisionalPageProxy.h" @@ -13631,11 +13878,7 @@ index fedef553cec70feb6c6475a5f752fbc6833dbb38..16e73d6a724dd80487b7b140aaaccfec #include "WebPageInspectorTarget.h" #include "WebPageMessages.h" #include "WebPageProxy.h" --#include "WebProcessProxy.h" - - namespace WebKit { - -@@ -40,19 +39,17 @@ using namespace Inspector; +@@ -40,19 +40,17 @@ using namespace Inspector; std::unique_ptr InspectorTargetProxy::create(WebPageProxy& page, const String& targetId, Inspector::InspectorTargetType type) { @@ -13660,14 +13903,14 @@ index fedef553cec70feb6c6475a5f752fbc6833dbb38..16e73d6a724dd80487b7b140aaaccfec , m_identifier(targetId) , m_type(type) { -@@ -99,6 +96,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() +@@ -99,6 +97,31 @@ void InspectorTargetProxy::didCommitProvisionalTarget() m_provisionalPage = nullptr; } +void InspectorTargetProxy::willResume() +{ + if (m_page.hasRunningProcess()) -+ m_page.send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow()); ++ m_page.legacyMainFrameProcess().send(Messages::WebPage::ResumeInspectorIfPausedInNewWindow(), m_page.webPageIDInMainFrameProcess()); +} + +void InspectorTargetProxy::activate(String& error) @@ -13733,7 +13976,7 @@ index a2239cec8e18850f35f7f88a9c4ebadc62bf4023..79f3ff84327dc075ec96983e04db4b10 } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp -index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0654b9679 100644 +index 96cfb0cbc8749708d263a79270746a0185bff348..c6a71685084ca322925c848a404e5d80db0b727e 100644 --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.cpp @@ -26,13 +26,21 @@ @@ -13811,13 +14054,13 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 + // window.open will create page with already running process. + if (!m_inspectedPage->hasRunningProcess()) + return; - String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); + String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page); } +void WebPageInspectorController::didFinishAttachingToWebProcess() +{ -+ String pageTargetID = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); ++ String pageTargetID = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); + // Create target only after attaching to a Web Process first time. Before that + // we cannot event establish frontend connection. + if (m_targets.contains(pageTargetID)) @@ -13827,7 +14070,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 + void WebPageInspectorController::pageClosed() { -+ String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); ++ String pageTargetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); + destroyInspectorTarget(pageTargetId); + disconnectAllFrontends(); @@ -13842,7 +14085,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 +{ + if (reason != ProcessTerminationReason::Crash) + return false; -+ String targetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID()); ++ String targetId = WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess()); + auto it = m_targets.find(targetId); + if (it == m_targets.end()) + return false; @@ -13926,7 +14169,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 } #endif -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) +void WebPageInspectorController::didPaint(sk_sp&& surface) +{ + if (!m_frontendRouter->hasFrontends()) @@ -13935,7 +14178,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 + m_screecastAgent->didPaint(WTFMove(surface)); +} +#endif -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) +void WebPageInspectorController::didPaint(cairo_surface_t* surface) +{ + if (!m_frontendRouter->hasFrontends()) @@ -14016,14 +14259,14 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 + if (!m_inspectedPage->isPageOpenedByDOMShowingInitialEmptyDocument()) + return false; + -+ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID())); ++ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess())); + ASSERT(target); + return target->isPaused(); +} + +void WebPageInspectorController::setContinueLoadingCallback(WTF::Function&& callback) +{ -+ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageID())); ++ auto* target = m_targets.get(WebPageInspectorTarget::toTargetID(m_inspectedPage->webPageIDInMainFrameProcess())); + ASSERT(target); + target->setResumeCallback(WTFMove(callback)); +} @@ -14069,7 +14312,7 @@ index 6d229b943fe69cd258b32b1e38c5716715a4cd4b..916464f24c583edeacca19cc1955cea0 + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h -index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..964fd0b69738771ec24e8da54bbe1aea583dfd90 100644 +index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..00b4ae5f9a7ac36f1fceab1c3ab39b20086302ae 100644 --- a/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h +++ b/Source/WebKit/UIProcess/Inspector/WebPageInspectorController.h @@ -26,6 +26,7 @@ @@ -14164,10 +14407,10 @@ index c6aafe0e9339c8ac02dc133754ddc23e1cb522ff..964fd0b69738771ec24e8da54bbe1aea #if ENABLE(REMOTE_INSPECTOR) void setIndicating(bool); #endif -+#if USE(SKIA) ++#if USE(SKIA) && !PLATFORM(GTK) + void didPaint(sk_sp&&); +#endif -+#if USE(CAIRO) ++#if USE(CAIRO) || PLATFORM(GTK) + void didPaint(cairo_surface_t*); +#endif + using NavigationHandler = Function; @@ -14454,10 +14697,10 @@ index 0000000000000000000000000000000000000000..d0e11ed81a6257c011df23d5870da740 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..bb5dcfc6234db1b5100e4aa98d678370a4dad12d +index 0000000000000000000000000000000000000000..f0675fcaf55625bce9b23a378d556030c27997f8 --- /dev/null +++ b/Source/WebKit/UIProcess/InspectorPlaywrightAgent.cpp -@@ -0,0 +1,1025 @@ +@@ -0,0 +1,1026 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -14529,6 +14772,7 @@ index 0000000000000000000000000000000000000000..bb5dcfc6234db1b5100e4aa98d678370 +#include +#include +#include ++#include + +using namespace Inspector; + @@ -14640,13 +14884,13 @@ index 0000000000000000000000000000000000000000..bb5dcfc6234db1b5100e4aa98d678370 +static Ref> getEnabledWindowFeatures(const WebCore::WindowFeatures& features) { + auto result = JSON::ArrayOf::create(); + if (features.x) -+ result->addItem("left="_s + String::number(*features.x)); ++ result->addItem(makeString("left="_s, String::number(*features.x))); + if (features.y) -+ result->addItem("top="_s + String::number(*features.y)); ++ result->addItem(makeString("top="_s, String::number(*features.y))); + if (features.width) -+ result->addItem("width="_s + String::number(*features.width)); ++ result->addItem(makeString("width="_s, String::number(*features.width))); + if (features.height) -+ result->addItem("height="_s + String::number(*features.height)); ++ result->addItem(makeString("height="_s, String::number(*features.height))); + if (features.menuBarVisible) + result->addItem("menubar"_s); + if (features.toolBarVisible) @@ -15191,7 +15435,7 @@ index 0000000000000000000000000000000000000000..bb5dcfc6234db1b5100e4aa98d678370 + } + + auto sandboxExtensionHandles = SandboxExtension::createReadOnlyHandlesForFiles("InspectorPlaywrightAgent::grantFileReadAccess"_s, files); -+ pageProxyChannel->page().send(Messages::WebPage::ExtendSandboxForFilesFromOpenPanel(WTFMove(sandboxExtensionHandles))); ++ pageProxyChannel->page().legacyMainFrameProcess().send(Messages::WebPage::ExtendSandboxForFilesFromOpenPanel(WTFMove(sandboxExtensionHandles)), pageProxyChannel->page().webPageIDInMainFrameProcess()); +#endif + return { }; +} @@ -15707,11 +15951,50 @@ index 0000000000000000000000000000000000000000..e7a3dcc533294bb6e12f65d79b5b716b +} // namespace WebKit + +#endif // ENABLE(REMOTE_INSPECTOR) +diff --git a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp +index c5df687a8093a3ee9bdddbecb69629584c197012..f09af9804e7a587a3c1a444317ba1a16ca52fb7f 100644 +--- a/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp ++++ b/Source/WebKit/UIProcess/Launcher/glib/ProcessLauncherGLib.cpp +@@ -188,6 +188,13 @@ void ProcessLauncher::launchProcess() + nargs++; + } + #endif ++// Playwright begin ++ bool enableSharedArrayBuffer = false; ++ if (m_launchOptions.processType == ProcessLauncher::ProcessType::Web && m_client && m_client->shouldEnableSharedArrayBuffer()) { ++ enableSharedArrayBuffer = true; ++ nargs++; ++ } ++// Playwright end + + char** argv = g_newa(char*, nargs); + unsigned i = 0; +@@ -203,6 +210,10 @@ void ProcessLauncher::launchProcess() + if (configureJSCForTesting) + argv[i++] = const_cast("--configure-jsc-for-testing"); + #endif ++// Playwright begin ++ if (enableSharedArrayBuffer) ++ argv[i++] = const_cast("--enable-shared-array-buffer"); ++// Playwright end + argv[i++] = nullptr; + + // Warning: we want GIO to be able to spawn with posix_spawn() rather than fork()/exec(), in diff --git a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp -index fac881d7c3d44758591d7a9f392a3992ce9f9a72..ad56113497f21d2916664ffe605489e939c736f4 100644 +index fac881d7c3d44758591d7a9f392a3992ce9f9a72..35eba5a0b31fc6e2d6e5c05c9f866c03d2e1c7d0 100644 --- a/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp +++ b/Source/WebKit/UIProcess/Launcher/win/ProcessLauncherWin.cpp -@@ -97,8 +97,11 @@ void ProcessLauncher::launchProcess() +@@ -91,14 +91,21 @@ void ProcessLauncher::launchProcess() + commandLineBuilder.append(" -configure-jsc-for-testing"_s); + if (!m_client->isJITEnabled()) + commandLineBuilder.append(" -disable-jit"_s); ++// Playwright begin ++ if (m_launchOptions.processType == ProcessLauncher::ProcessType::Web && m_client->shouldEnableSharedArrayBuffer()) ++ commandLineBuilder.append(" -enable-shared-array-buffer"_s); ++// Playwright end + commandLineBuilder.append('\0'); + + auto commandLine = commandLineBuilder.toString().wideCharacters(); STARTUPINFO startupInfo { }; startupInfo.cb = sizeof(startupInfo); @@ -15725,7 +16008,7 @@ index fac881d7c3d44758591d7a9f392a3992ce9f9a72..ad56113497f21d2916664ffe605489e9 BOOL result = ::CreateProcess(0, commandLine.data(), 0, 0, true, 0, 0, 0, &startupInfo, &processInformation); diff --git a/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp b/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp -index 4dbbd6c6206b214541217f6b49f4ba441855f8f9..6b4b3d7448a64e9b0519f37ce75e364deba62b6f 100644 +index 919dede3e9653f6e16d6772a90a023223c0845a9..8e0a214d02468c900dedc803204d4704b4aa6d12 100644 --- a/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp +++ b/Source/WebKit/UIProcess/Media/RemoteMediaSessionCoordinatorProxy.cpp @@ -30,6 +30,7 @@ @@ -15737,7 +16020,7 @@ index 4dbbd6c6206b214541217f6b49f4ba441855f8f9..6b4b3d7448a64e9b0519f37ce75e364d #include "RemoteMediaSessionCoordinatorProxyMessages.h" #include "WebPageProxy.h" diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h -index b368e79479e84e95eebbaaea5e3d0e0dd4c70d62..1ad4b36568d33e7fd52dbabfa1ef6e5bbe6a8433 100644 +index cc9598fc619fb1bf3f4070d52a7587e209d4a147..58d92b530a60ce327cad1b47566bbb57450e955e 100644 --- a/Source/WebKit/UIProcess/PageClient.h +++ b/Source/WebKit/UIProcess/PageClient.h @@ -72,6 +72,11 @@ @@ -15765,7 +16048,7 @@ index b368e79479e84e95eebbaaea5e3d0e0dd4c70d62..1ad4b36568d33e7fd52dbabfa1ef6e5b namespace WebKit { class PageClient; } -@@ -357,7 +368,20 @@ public: +@@ -373,7 +384,20 @@ public: virtual void selectionDidChange() = 0; #endif @@ -16251,7 +16534,7 @@ index d499ee31f32b9dcdb456ba0b476d211fba115673..43b349887d18e21162b59fa8174df32c namespace WebCore { class PlatformWheelEvent; diff --git a/Source/WebKit/UIProcess/RemotePageProxy.cpp b/Source/WebKit/UIProcess/RemotePageProxy.cpp -index b89ab7f35c6a3bfda89f1575b65d192f8237d1eb..d2bba95b349634674240c964511606e49cb11912 100644 +index f08f1ae907d39f75ec5043921c44dfeb1c581511..a892f5050b0f7a37c1231c9ca41dfb6030249aba 100644 --- a/Source/WebKit/UIProcess/RemotePageProxy.cpp +++ b/Source/WebKit/UIProcess/RemotePageProxy.cpp @@ -43,6 +43,7 @@ @@ -16263,7 +16546,7 @@ index b89ab7f35c6a3bfda89f1575b65d192f8237d1eb..d2bba95b349634674240c964511606e4 namespace WebKit { diff --git a/Source/WebKit/UIProcess/RemotePageProxy.h b/Source/WebKit/UIProcess/RemotePageProxy.h -index 34cd273d199470e42f3bfe152642d565b0d53485..53241e02fdbfb33d128ea4c7942a501b843c20fd 100644 +index b2019b6e792c58c9aa258d571f24dbe35c5eb926..bac988e367c158292f6e5dab957bdafcd23d91de 100644 --- a/Source/WebKit/UIProcess/RemotePageProxy.h +++ b/Source/WebKit/UIProcess/RemotePageProxy.h @@ -73,7 +73,6 @@ class WebProcessProxy; @@ -16275,13 +16558,13 @@ index 34cd273d199470e42f3bfe152642d565b0d53485..53241e02fdbfb33d128ea4c7942a501b class RemotePageProxy : public IPC::MessageReceiver { WTF_MAKE_FAST_ALLOCATED; diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp -index 777ab704b262e00208193dee7738e14d853b102a..12a66a3ff48565d6a5682207b94f39572545f786 100644 +index 40531b866fda1c35dbddb90f2ac1027688b2a09c..82003f78d7d2c9fbf2d393187636cf8b0bcf228f 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp +++ b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp @@ -37,6 +37,7 @@ #include #include - #include + #include +#include #define U2F_RELEASE_LOG(fmt, ...) RELEASE_LOG(WebAuthn, "%p [transport=%s] - U2fAuthenticator::" fmt, this, transportForDebugging().utf8().data(), ##__VA_ARGS__) @@ -16311,7 +16594,7 @@ index e2ded3c65b9680346be2534a3e970e2f425a83a8..b0c006c1dcbfae4b33530f8eae04f986 WebPageProxy* page() const { return m_page.get(); } diff --git a/Source/WebKit/UIProcess/WebFrameProxy.cpp b/Source/WebKit/UIProcess/WebFrameProxy.cpp -index 992ebbfcd3094576076084ef394dd4802c5dcc8e..2a1e09b4da5e67ba524f769e3de239b77043cf16 100644 +index 21a9f2d213db48f58881d0873cfd17ce962080b8..7932e3de12dc1af7f3aad4a9cdbb8bf0004a67ba 100644 --- a/Source/WebKit/UIProcess/WebFrameProxy.cpp +++ b/Source/WebKit/UIProcess/WebFrameProxy.cpp @@ -31,6 +31,7 @@ @@ -16599,10 +16882,10 @@ index 0000000000000000000000000000000000000000..b70bfe0411571f4d181a7fae3186aaae +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..8e48dfabe2a520deec08b771cf6699b22e27c9da +index 0000000000000000000000000000000000000000..247c1817e85e5935eacef5e5ecdc07737dbf4a85 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.cpp -@@ -0,0 +1,334 @@ +@@ -0,0 +1,394 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -16635,8 +16918,9 @@ index 0000000000000000000000000000000000000000..8e48dfabe2a520deec08b771cf6699b2 +#include "NativeWebKeyboardEvent.h" +#include "NativeWebMouseEvent.h" +#include "NativeWebWheelEvent.h" -+#include "WebWheelEvent.h" +#include "WebPageProxy.h" ++#include "WebTouchEvent.h" ++#include "WebWheelEvent.h" +#include +#include +#include @@ -16902,10 +17186,69 @@ index 0000000000000000000000000000000000000000..8e48dfabe2a520deec08b771cf6699b2 +#endif +} + -+void WebPageInspectorInputAgent::dispatchTapEvent(int x, int y, std::optional&& modifiers, Ref&& callback) { -+ m_page.sendWithAsyncReply(Messages::WebPage::FakeTouchTap(WebCore::IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() { ++void WebPageInspectorInputAgent::dispatchTapEvent(int x, int y, std::optional&& modifiers, Ref&& callback) ++{ ++ m_page.legacyMainFrameProcess().sendWithAsyncReply(Messages::WebPage::FakeTouchTap(WebCore::IntPoint(x, y), modifiers ? *modifiers : 0), [callback]() { + callback->sendSuccess(); -+ }); ++ }, m_page.webPageIDInMainFrameProcess()); ++} ++ ++void WebPageInspectorInputAgent::dispatchTouchEvent(const String& type, std::optional&& modifiers, RefPtr&& in_touchPoints, Ref&& callback) ++{ ++ float rotationAngle = 0.0; ++ float force = 1.0; ++ const WebCore::IntSize radius(1, 1); ++ ++ uint8_t unsignedModifiers = modifiers ? static_cast(*modifiers) : 0; ++ OptionSet eventModifiers; ++ eventModifiers = eventModifiers.fromRaw(unsignedModifiers); ++ ++ WebPlatformTouchPoint::State state; ++ if (type == "touchStart"_s) ++ state = WebPlatformTouchPoint::State::Pressed; ++ else if (type == "touchMove"_s) ++ state = WebPlatformTouchPoint::State::Moved; ++ else if (type == "touchEnd"_s) ++ state = WebPlatformTouchPoint::State::Released; ++ else if (type == "touchCancel"_s) ++ state = WebPlatformTouchPoint::State::Cancelled; ++ else { ++ callback->sendFailure("Unsupported event type"_s); ++ return; ++ } ++ ++ Vector touchPoints; ++ for (unsigned i = 0; i < in_touchPoints->length(); ++i) { ++ RefPtr item = in_touchPoints->get(i); ++ RefPtr obj = item->asObject(); ++ if (!obj) { ++ callback->sendFailure("Invalid TouchPoint format"_s); ++ return; ++ } ++ std::optional x = obj->getInteger("x"_s); ++ if (!x) { ++ callback->sendFailure("TouchPoint does not have x"_s); ++ return; ++ } ++ std::optional y = obj->getInteger("y"_s); ++ if (!y) { ++ callback->sendFailure("TouchPoint does not have y"_s); ++ return; ++ } ++ std::optional optionalId = obj->getInteger("id"_s); ++ int id = optionalId ? *optionalId : 0; ++ const WebCore::IntPoint position(*x, *y); ++ touchPoints.append(WebPlatformTouchPoint(id, state, position, position, radius, rotationAngle, force)); ++ } ++ ++ WebTouchEvent touchEvent({WebEventType::TouchStart, eventModifiers, WallTime::now()}, WTFMove(touchPoints)); ++ m_page.legacyMainFrameProcess().sendWithAsyncReply(Messages::WebPage::TouchEvent(touchEvent), [callback] (std::optional eventType, bool) { ++ if (!eventType) { ++ callback->sendFailure("Failed to dispatch touch event."_s); ++ return; ++ } ++ callback->sendSuccess(); ++ }, m_page.webPageIDInMainFrameProcess()); +} + +void WebPageInspectorInputAgent::dispatchWheelEvent(int x, int y, std::optional&& modifiers, std::optional&& deltaX, std::optional&& deltaY, Ref&& callback) @@ -16939,10 +17282,10 @@ index 0000000000000000000000000000000000000000..8e48dfabe2a520deec08b771cf6699b2 +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h new file mode 100644 -index 0000000000000000000000000000000000000000..3e87bf40ced2301f4fb145c6cb31f2cf7fa15dd6 +index 0000000000000000000000000000000000000000..26a2a3c0791c334f811ec99a630314f8e8521d02 --- /dev/null +++ b/Source/WebKit/UIProcess/WebPageInspectorInputAgent.h -@@ -0,0 +1,86 @@ +@@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -17007,6 +17350,7 @@ index 0000000000000000000000000000000000000000..3e87bf40ced2301f4fb145c6cb31f2cf + void dispatchKeyEvent(const String& type, std::optional&& modifiers, const String& text, const String& unmodifiedText, const String& code, const String& key, std::optional&& windowsVirtualKeyCode, std::optional&& nativeVirtualKeyCode, std::optional&& autoRepeat, std::optional&& isKeypad, std::optional&& isSystemKey, RefPtr&&, Ref&& callback) override; + void dispatchMouseEvent(const String& type, int x, int y, std::optional&& modifiers, const String& button, std::optional&& buttons, std::optional&& clickCount, std::optional&& deltaX, std::optional&& deltaY, Ref&& callback) override; + void dispatchTapEvent(int x, int y, std::optional&& modifiers, Ref&& callback) override; ++ void dispatchTouchEvent(const String& type, std::optional&& modifiers, RefPtr&& touchPoints, Ref&& callback) override; + void dispatchWheelEvent(int x, int y, std::optional&& modifiers, std::optional&& deltaX, std::optional&& deltaY, Ref&& callback) override; + +private: @@ -17030,10 +17374,10 @@ index 0000000000000000000000000000000000000000..3e87bf40ced2301f4fb145c6cb31f2cf + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp -index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a4de493a3 100644 +index f96981fa78e5d08faeaa261cf4ccb64e1c9241f8..a112a30315ed7708ea140c876d10ce14e4716584 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.cpp +++ b/Source/WebKit/UIProcess/WebPageProxy.cpp -@@ -186,12 +186,14 @@ +@@ -190,12 +190,14 @@ #include #include #include @@ -17048,7 +17392,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a #include #include #include -@@ -212,6 +214,7 @@ +@@ -216,6 +218,7 @@ #include #include #include @@ -17056,7 +17400,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a #include #include #include -@@ -219,12 +222,15 @@ +@@ -223,12 +226,15 @@ #include #include #include @@ -17072,7 +17416,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a #include #include #include -@@ -299,6 +305,9 @@ +@@ -310,6 +316,9 @@ #include "AcceleratedBackingStoreDMABuf.h" #endif #include "GtkSettingsManager.h" @@ -17082,7 +17426,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a #include #endif -@@ -421,6 +430,8 @@ static constexpr Seconds tryCloseTimeoutDelay = 50_ms; +@@ -432,6 +441,8 @@ static constexpr Seconds tryCloseTimeoutDelay = 50_ms; static constexpr Seconds audibleActivityClearDelay = 10_s; #endif @@ -17091,7 +17435,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy")); #if PLATFORM(COCOA) -@@ -826,6 +837,10 @@ WebPageProxy::~WebPageProxy() +@@ -846,6 +857,10 @@ WebPageProxy::~WebPageProxy() if (preferences->mediaSessionCoordinatorEnabled()) GroupActivitiesSessionNotifier::sharedNotifier().removeWebPage(*this); #endif @@ -17102,7 +17446,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } void WebPageProxy::addAllMessageReceivers() -@@ -1364,6 +1379,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason) +@@ -1414,6 +1429,7 @@ void WebPageProxy::finishAttachingToWebProcess(ProcessLaunchReason reason) protectedPageClient()->didRelaunchProcess(); internals().pageLoadState.didSwapWebProcesses(); @@ -17110,7 +17454,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } void WebPageProxy::didAttachToRunningProcess() -@@ -1372,7 +1388,7 @@ void WebPageProxy::didAttachToRunningProcess() +@@ -1422,7 +1438,7 @@ void WebPageProxy::didAttachToRunningProcess() #if ENABLE(FULLSCREEN_API) ASSERT(!m_fullScreenManager); @@ -17119,7 +17463,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a #endif #if ENABLE(VIDEO_PRESENTATION_MODE) ASSERT(!m_playbackSessionManager); -@@ -1767,6 +1783,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess() +@@ -1823,6 +1839,21 @@ WebProcessProxy& WebPageProxy::ensureRunningProcess() return m_legacyMainFrameProcess; } @@ -17134,14 +17478,14 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a + loadParameters.request = WTFMove(request); + loadParameters.shouldOpenExternalURLsPolicy = WebCore::ShouldOpenExternalURLsPolicy::ShouldNotAllow; + loadParameters.shouldTreatAsContinuingLoad = ShouldTreatAsContinuingLoad::No; -+ legacyMainFrameProcess().send(Messages::WebPage::LoadRequestInFrameForInspector(WTFMove(loadParameters), frame->frameID()), internals().webPageID); ++ m_legacyMainFrameProcess->send(Messages::WebPage::LoadRequestInFrameForInspector(WTFMove(loadParameters), frame->frameID()), internals().webPageID); + return navigation; +} + RefPtr WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData) { if (m_isClosed) -@@ -2365,6 +2396,61 @@ void WebPageProxy::setControlledByAutomation(bool controlled) +@@ -2422,6 +2453,61 @@ void WebPageProxy::setControlledByAutomation(bool controlled) websiteDataStore().protectedNetworkProcess()->send(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation), 0); } @@ -17172,7 +17516,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a + auto deviceOrientation = toScreenOrientationType(angle.value_or(0)); + if (m_screenOrientationManager) + m_screenOrientationManager->setCurrentOrientation(deviceOrientation); -+ legacyMainFrameProcess().send(Messages::WebPage::SetDeviceOrientation(angle.value_or(0)), webPageID()); ++ m_legacyMainFrameProcess->send(Messages::WebPage::SetDeviceOrientation(angle.value_or(0)), webPageIDInMainFrameProcess()); +} + +std::optional WebPageProxy::permissionForAutomation(const String& origin, const String& permission) const @@ -17200,10 +17544,10 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a + fprintf(stderr, "RENDERER: %s\n", str.utf8().data()); +} + - void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type) + void WebPageProxy::createInspectorTarget(IPC::Connection& connection, const String& targetId, Inspector::InspectorTargetType type) { - MESSAGE_CHECK(m_legacyMainFrameProcess, !targetId.isEmpty()); -@@ -2606,6 +2692,24 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpdate) + MESSAGE_CHECK_BASE(!targetId.isEmpty(), &connection); +@@ -2663,6 +2749,24 @@ void WebPageProxy::updateActivityState(OptionSet flagsToUpdate) bool wasVisible = isViewVisible(); Ref pageClient = this->pageClient(); internals().activityState.remove(flagsToUpdate); @@ -17228,7 +17572,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a if (flagsToUpdate & ActivityState::IsFocused && pageClient->isViewFocused()) internals().activityState.add(ActivityState::IsFocused); if (flagsToUpdate & ActivityState::WindowIsActive && pageClient->isViewWindowActive()) -@@ -3348,7 +3452,7 @@ void WebPageProxy::performDragOperation(DragData& dragData, const String& dragSt +@@ -3401,7 +3505,7 @@ void WebPageProxy::performDragOperation(DragData& dragData, const String& dragSt grantAccessToCurrentPasteboardData(dragStorageName); #endif @@ -17237,7 +17581,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a performDragControllerAction(DragControllerAction::PerformDragOperation, dragData); #else if (!hasRunningProcess()) -@@ -3365,6 +3469,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag +@@ -3418,6 +3522,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag if (!hasRunningProcess()) return; @@ -17246,16 +17590,16 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a auto completionHandler = [this, protectedThis = Ref { *this }, action, dragData] (std::optional dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect, const IntRect& editableElementRect, std::optional remoteUserInputEventData) mutable { if (!remoteUserInputEventData) { didPerformDragControllerAction(dragOperation, dragHandlingMethod, mouseIsOverFileInput, numberOfItemsToBeAccepted, insertionRect, editableElementRect); -@@ -3381,6 +3487,8 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag - protectedLegacyMainFrameProcess()->assumeReadAccessToBaseURL(*this, url); +@@ -3427,7 +3533,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag + performDragControllerAction(action, dragData, remoteUserInputEventData->targetFrameID); + }; - ASSERT(dragData.platformData()); -+#endif +-#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(WPE) - sendWithAsyncReply(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), *dragData.platformData(), dragData.flags()), WTFMove(completionHandler)); - #else - sendToProcessContainingFrame(frameID, Messages::WebPage::PerformDragControllerAction(frameID, action, dragData), WTFMove(completionHandler)); -@@ -3396,14 +3504,34 @@ void WebPageProxy::didPerformDragControllerAction(std::optionaldidPerformDragControllerAction(); @@ -17293,7 +17637,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a didStartDrag(); } #endif -@@ -3424,6 +3552,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo +@@ -3477,6 +3603,24 @@ void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& glo setDragCaretRect({ }); } @@ -17318,7 +17662,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a void WebPageProxy::didStartDrag() { if (!hasRunningProcess()) -@@ -3431,6 +3577,16 @@ void WebPageProxy::didStartDrag() +@@ -3484,6 +3628,16 @@ void WebPageProxy::didStartDrag() discardQueuedMouseEvents(); send(Messages::WebPage::DidStartDrag()); @@ -17335,7 +17679,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } void WebPageProxy::dragCancelled() -@@ -3590,16 +3746,37 @@ void WebPageProxy::processNextQueuedMouseEvent() +@@ -3622,16 +3776,37 @@ void WebPageProxy::processNextQueuedMouseEvent() process->startResponsivenessTimer(); } @@ -17374,12 +17718,12 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a + m_dragSelectionData = std::nullopt; + dragEnded(event.position(), event.globalPosition(), m_dragSourceOperationMask); + } -+ didReceiveEvent(eventType, true); ++ didReceiveEvent(eventType, true, std::nullopt); + } } void WebPageProxy::doAfterProcessingAllPendingMouseEvents(WTF::Function&& action) -@@ -3770,6 +3947,8 @@ void WebPageProxy::wheelEventHandlingCompleted(bool wasHandled) +@@ -3802,6 +3977,8 @@ void WebPageProxy::wheelEventHandlingCompleted(bool wasHandled) if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->wheelEventsFlushedForPage(*this); @@ -17388,7 +17732,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } void WebPageProxy::cacheWheelEventScrollingAccelerationCurve(const NativeWebWheelEvent& nativeWheelEvent) -@@ -3919,7 +4098,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) +@@ -3940,7 +4117,7 @@ static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b) void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent) { @@ -17397,7 +17741,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a for (auto& touchPoint : touchStartEvent.touchPoints()) { auto location = touchPoint.location(); auto update = [this, location](TrackingType& trackingType, EventTrackingRegions::EventType eventType) { -@@ -4529,6 +4708,7 @@ void WebPageProxy::receivedNavigationActionPolicyDecision(WebProcessProxy& proce +@@ -4547,6 +4724,7 @@ void WebPageProxy::receivedNavigationActionPolicyDecision(WebProcessProxy& proce void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, RefPtr&& websitePolicies, Ref&& navigationAction, WillContinueLoadInNewProcess willContinueLoadInNewProcess, std::optional sandboxExtensionHandle, std::optional&& consoleMessage, CompletionHandler&& completionHandler) { @@ -17405,19 +17749,20 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a if (!hasRunningProcess()) return completionHandler(PolicyDecision { }); -@@ -5460,6 +5640,11 @@ void WebPageProxy::pageScaleFactorDidChange(double scaleFactor) +@@ -5478,6 +5656,12 @@ void WebPageProxy::pageScaleFactorDidChange(IPC::Connection& connection, double m_pageScaleFactor = scaleFactor; } -+void WebPageProxy::viewScaleFactorDidChange(double scaleFactor) ++void WebPageProxy::viewScaleFactorDidChange(IPC::Connection& connection, double scaleFactor) +{ ++ MESSAGE_CHECK_BASE(scaleFactorIsValid(scaleFactor), &connection); + m_viewScaleFactor = scaleFactor; +} + - void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor) + void WebPageProxy::pluginScaleFactorDidChange(IPC::Connection& connection, double pluginScaleFactor) { - MESSAGE_CHECK(m_legacyMainFrameProcess, scaleFactorIsValid(pluginScaleFactor)); -@@ -6015,6 +6200,7 @@ void WebPageProxy::didDestroyNavigationShared(Ref&& process, ui + MESSAGE_CHECK_BASE(scaleFactorIsValid(pluginScaleFactor), &connection); +@@ -6033,6 +6217,7 @@ void WebPageProxy::didDestroyNavigationShared(Ref&& process, ui Ref protectedPageClient { pageClient() }; m_navigationState->didDestroyNavigation(process->coreProcessIdentifier(), navigationID); @@ -17425,7 +17770,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } void WebPageProxy::didStartProvisionalLoadForFrame(FrameIdentifier frameID, FrameInfoData&& frameInfo, ResourceRequest&& request, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData) -@@ -6282,6 +6468,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref&& p +@@ -6300,6 +6485,8 @@ void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref&& p m_failingProvisionalLoadURL = { }; @@ -17434,7 +17779,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a // If the provisional page's load fails then we destroy the provisional page. if (m_provisionalPage && m_provisionalPage->mainFrame() == &frame && willContinueLoading == WillContinueLoading::No) m_provisionalPage = nullptr; -@@ -6942,7 +7130,14 @@ void WebPageProxy::beginSafeBrowsingCheck(const URL&, bool, WebFramePolicyListen +@@ -6967,7 +7154,14 @@ void WebPageProxy::beginSafeBrowsingCheck(const URL&, bool, WebFramePolicyListen void WebPageProxy::decidePolicyForNavigationActionAsync(NavigationActionData&& data, CompletionHandler&& completionHandler) { @@ -17450,7 +17795,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } void WebPageProxy::decidePolicyForNavigationActionAsyncShared(Ref&& process, NavigationActionData&& data, CompletionHandler&& completionHandler) -@@ -7618,6 +7813,7 @@ void WebPageProxy::createNewPage(WindowFeatures&& windowFeatures, NavigationActi +@@ -7631,6 +7825,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w if (RefPtr page = originatingFrameInfo->page()) openerAppInitiatedState = page->lastNavigationWasAppInitiated(); @@ -17458,7 +17803,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a auto completionHandler = [ this, protectedThis = Ref { *this }, -@@ -7690,6 +7886,7 @@ void WebPageProxy::createNewPage(WindowFeatures&& windowFeatures, NavigationActi +@@ -7703,6 +7898,7 @@ void WebPageProxy::createNewPage(IPC::Connection& connection, WindowFeatures&& w void WebPageProxy::showPage() { m_uiClient->showPage(this); @@ -17466,7 +17811,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } bool WebPageProxy::hasOpenedPage() const -@@ -7776,6 +7973,10 @@ void WebPageProxy::closePage() +@@ -7813,6 +8009,10 @@ void WebPageProxy::closePage() if (isClosed()) return; @@ -17477,7 +17822,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a WEBPAGEPROXY_RELEASE_LOG(Process, "closePage:"); protectedPageClient()->clearAllEditCommands(); m_uiClient->close(this); -@@ -7812,6 +8013,8 @@ void WebPageProxy::runJavaScriptAlert(FrameIdentifier frameID, FrameInfoData&& f +@@ -7849,6 +8049,8 @@ void WebPageProxy::runJavaScriptAlert(IPC::Connection& connection, FrameIdentifi } runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler&& completion) mutable { @@ -17486,7 +17831,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a page.m_uiClient->runJavaScriptAlert(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)]() mutable { reply(); completion(); -@@ -7833,6 +8036,8 @@ void WebPageProxy::runJavaScriptConfirm(FrameIdentifier frameID, FrameInfoData&& +@@ -7870,6 +8072,8 @@ void WebPageProxy::runJavaScriptConfirm(IPC::Connection& connection, FrameIdenti if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } @@ -17495,7 +17840,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply)](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler&& completion) mutable { page.m_uiClient->runJavaScriptConfirm(page, message, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](bool result) mutable { -@@ -7856,6 +8061,8 @@ void WebPageProxy::runJavaScriptPrompt(FrameIdentifier frameID, FrameInfoData&& +@@ -7893,6 +8097,8 @@ void WebPageProxy::runJavaScriptPrompt(IPC::Connection& connection, FrameIdentif if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->willShowJavaScriptDialog(*this); } @@ -17504,7 +17849,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a runModalJavaScriptDialog(WTFMove(frame), WTFMove(frameInfo), message, [reply = WTFMove(reply), defaultValue](WebPageProxy& page, WebFrameProxy* frame, FrameInfoData&& frameInfo, const String& message, CompletionHandler&& completion) mutable { page.m_uiClient->runJavaScriptPrompt(page, message, defaultValue, frame, WTFMove(frameInfo), [reply = WTFMove(reply), completion = WTFMove(completion)](auto& result) mutable { -@@ -7972,6 +8179,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(FrameIdentifier frameID, FrameInf +@@ -8009,6 +8215,8 @@ void WebPageProxy::runBeforeUnloadConfirmPanel(IPC::Connection& connection, Fram return; } } @@ -17513,7 +17858,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer and the tryClose timer. protectedLegacyMainFrameProcess()->stopResponsivenessTimer(); -@@ -8464,6 +8673,11 @@ void WebPageProxy::resourceLoadDidCompleteWithError(ResourceLoadInfo&& loadInfo, +@@ -8501,6 +8709,11 @@ void WebPageProxy::resourceLoadDidCompleteWithError(ResourceLoadInfo&& loadInfo, } #if ENABLE(FULLSCREEN_API) @@ -17525,7 +17870,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a WebFullScreenManagerProxy* WebPageProxy::fullScreenManager() { return m_fullScreenManager.get(); -@@ -8564,6 +8778,17 @@ void WebPageProxy::requestDOMPasteAccess(DOMPasteAccessCategory pasteAccessCateg +@@ -8606,6 +8819,17 @@ void WebPageProxy::requestDOMPasteAccess(DOMPasteAccessCategory pasteAccessCateg } } @@ -17540,10 +17885,10 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a + return; + } + - m_pageClient->requestDOMPasteAccess(pasteAccessCategory, elementRect, originIdentifier, WTFMove(completionHandler)); + m_pageClient->requestDOMPasteAccess(pasteAccessCategory, requiresInteraction, elementRect, originIdentifier, WTFMove(completionHandler)); } -@@ -9424,6 +9649,8 @@ void WebPageProxy::mouseEventHandlingCompleted(std::optional event +@@ -9461,6 +9685,8 @@ void WebPageProxy::mouseEventHandlingCompleted(std::optional event if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->mouseEventsFlushedForPage(*this); didFinishProcessingAllPendingMouseEvents(); @@ -17552,7 +17897,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } } -@@ -9458,6 +9685,7 @@ void WebPageProxy::keyEventHandlingCompleted(std::optional eventTy +@@ -9495,6 +9721,7 @@ void WebPageProxy::keyEventHandlingCompleted(std::optional eventTy if (!canProcessMoreKeyEvents) { if (RefPtr automationSession = configuration().processPool().automationSession()) automationSession->keyboardEventsFlushedForPage(*this); @@ -17560,7 +17905,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a } } -@@ -9863,7 +10091,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) +@@ -9906,7 +10133,10 @@ void WebPageProxy::dispatchProcessDidTerminate(ProcessTerminationReason reason) { WEBPAGEPROXY_RELEASE_LOG_ERROR(Loading, "dispatchProcessDidTerminate: reason=%" PUBLIC_LOG_STRING, processTerminationReasonToString(reason).characters()); @@ -17572,7 +17917,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a if (m_loaderClient) handledByClient = reason != ProcessTerminationReason::RequestedByClient && m_loaderClient->processDidCrash(*this); else -@@ -10237,6 +10468,7 @@ bool WebPageProxy::useGPUProcessForDOMRenderingEnabled() const +@@ -10292,6 +10522,7 @@ bool WebPageProxy::useGPUProcessForDOMRenderingEnabled() const WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process, DrawingAreaProxy& drawingArea, std::optional&& remotePageParameters, bool isProcessSwap, RefPtr&& websitePolicies, std::optional&& mainFrameIdentifier) { @@ -17580,7 +17925,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a WebPageCreationParameters parameters; parameters.processDisplayName = configuration().processDisplayName(); -@@ -10461,6 +10693,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc +@@ -10516,6 +10747,8 @@ WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& proc parameters.httpsUpgradeEnabled = preferences().upgradeKnownHostsToHTTPSEnabled() ? m_configuration->httpsUpgradeEnabled() : false; @@ -17589,7 +17934,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a #if PLATFORM(IOS) || PLATFORM(VISION) // FIXME: This is also being passed over the to WebProcess via the PreferencesStore. parameters.allowsDeprecatedSynchronousXMLHttpRequestDuringUnload = allowsDeprecatedSynchronousXMLHttpRequestDuringUnload(); -@@ -10590,8 +10824,42 @@ void WebPageProxy::gamepadsRecentlyAccessed() +@@ -10648,8 +10881,42 @@ void WebPageProxy::gamepadsRecentlyAccessed() #endif // ENABLE(GAMEPAD) @@ -17632,7 +17977,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a if (negotiatedLegacyTLS == NegotiatedLegacyTLS::Yes) { m_navigationClient->shouldAllowLegacyTLS(*this, authenticationChallenge.get(), [this, protectedThis = Ref { *this }, authenticationChallenge] (bool shouldAllowLegacyTLS) { if (shouldAllowLegacyTLS) -@@ -10686,6 +10954,12 @@ void WebPageProxy::requestGeolocationPermissionForFrame(GeolocationIdentifier ge +@@ -10744,6 +11011,12 @@ void WebPageProxy::requestGeolocationPermissionForFrame(IPC::Connection& connect request->deny(); }; @@ -17645,7 +17990,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a // FIXME: Once iOS migrates to the new WKUIDelegate SPI, clean this up // and make it one UIClient call that calls the completionHandler with false // if there is no delegate instead of returning the completionHandler -@@ -10748,6 +11022,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi +@@ -10806,6 +11079,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi shouldChangeDeniedToPrompt = false; if (sessionID().isEphemeral()) { @@ -17658,7 +18003,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a completionHandler(shouldChangeDeniedToPrompt ? PermissionState::Prompt : PermissionState::Denied); return; } -@@ -10762,6 +11042,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi +@@ -10820,6 +11099,12 @@ void WebPageProxy::queryPermission(const ClientOrigin& clientOrigin, const Permi return; } @@ -17672,7 +18017,7 @@ index a9f735f67fb71479cce369e020529fe9dd5a1e67..58571b1025ac41d2349e64ba0ea58e0a completionHandler(shouldChangeDeniedToPrompt ? PermissionState::Prompt : PermissionState::Denied); return; diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h -index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb870731bbb871 100644 +index 1c4d43a5025741a37708e99c398f03836de80182..df2e31590e9936525cb5037ea4456237a938de91 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.h +++ b/Source/WebKit/UIProcess/WebPageProxy.h @@ -26,6 +26,7 @@ @@ -17680,10 +18025,10 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 #include "APIObject.h" +#include "APIWebsitePolicies.h" - #include "IdentifierTypes.h" #include "MessageReceiver.h" - #include "MessageSender.h" -@@ -39,6 +40,20 @@ + #include + #include +@@ -37,6 +38,20 @@ #include #include #include @@ -17704,7 +18049,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 #if USE(DICTATION_ALTERNATIVES) #include -@@ -110,6 +125,7 @@ class DestinationColorSpace; +@@ -112,6 +127,7 @@ class DestinationColorSpace; class DragData; class FloatPoint; class FloatQuad; @@ -17712,7 +18057,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 class FloatRect; class FloatSize; class FontAttributeChanges; -@@ -426,6 +442,7 @@ class WebExtensionController; +@@ -446,6 +462,7 @@ class WebExtensionController; class WebFramePolicyListenerProxy; class WebFrameProxy; class WebFullScreenManagerProxy; @@ -17720,7 +18065,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 class WebInspectorUIProxy; class WebKeyboardEvent; class WebMouseEvent; -@@ -661,6 +678,8 @@ public: +@@ -674,6 +691,8 @@ public: void setControlledByAutomation(bool); WebPageInspectorController& inspectorController() { return *m_inspectorController; } @@ -17729,7 +18074,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 #if PLATFORM(IOS_FAMILY) void showInspectorIndication(); -@@ -694,6 +713,7 @@ public: +@@ -707,6 +726,7 @@ public: bool hasSleepDisabler() const; #if ENABLE(FULLSCREEN_API) @@ -17737,7 +18082,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 WebFullScreenManagerProxy* fullScreenManager(); API::FullscreenClient& fullscreenClient() const { return *m_fullscreenClient; } -@@ -782,6 +802,12 @@ public: +@@ -795,6 +815,12 @@ public: void setPageLoadStateObserver(std::unique_ptr&&); @@ -17750,7 +18095,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 void initializeWebPage(); void setDrawingArea(std::unique_ptr&&); -@@ -808,6 +834,7 @@ public: +@@ -821,6 +847,7 @@ public: void addPlatformLoadParameters(WebProcessProxy&, LoadParameters&); RefPtr loadRequest(WebCore::ResourceRequest&&); RefPtr loadRequest(WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData = nullptr); @@ -17758,23 +18103,23 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 RefPtr loadFile(const String& fileURL, const String& resourceDirectoryURL, bool isAppInitiated = true, API::Object* userData = nullptr); RefPtr loadData(std::span, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData = nullptr); RefPtr loadData(std::span, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldOpenExternalURLsPolicy); -@@ -874,6 +901,7 @@ public: - +@@ -888,6 +915,7 @@ public: PageClient& pageClient() const; Ref protectedPageClient() const; + RefPtr optionalProtectedPageClient() const; + bool hasPageClient() const { return !!m_pageClient; } void setViewNeedsDisplay(const WebCore::Region&); void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, WebCore::ScrollIsAnimated); -@@ -1400,6 +1428,7 @@ public: +@@ -1414,6 +1442,7 @@ public: #endif - void pageScaleFactorDidChange(double); -+ void viewScaleFactorDidChange(double); - void pluginScaleFactorDidChange(double); - void pluginZoomFactorDidChange(double); + void pageScaleFactorDidChange(IPC::Connection&, double); ++ void viewScaleFactorDidChange(IPC::Connection&, double); + void pluginScaleFactorDidChange(IPC::Connection&, double); + void pluginZoomFactorDidChange(IPC::Connection&, double); -@@ -1484,14 +1513,20 @@ public: +@@ -1498,14 +1527,20 @@ public: void didStartDrag(); void dragCancelled(); void setDragCaretRect(const WebCore::IntRect&); @@ -17782,7 +18127,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 + bool cancelDragIfNeeded(); #if PLATFORM(COCOA) void startDrag(const WebCore::DragItem&, WebCore::ShareableBitmapHandle&& dragImageHandle); - void setPromisedDataForImage(const String& pasteboardName, WebCore::SharedMemoryHandle&& imageHandle, const String& filename, const String& extension, + void setPromisedDataForImage(IPC::Connection&, const String& pasteboardName, WebCore::SharedMemoryHandle&& imageHandle, const String& filename, const String& extension, const String& title, const String& url, const String& visibleURL, WebCore::SharedMemoryHandle&& archiveHandle, const String& originIdentifier); + void releaseInspectorDragPasteboard(); #endif @@ -17796,7 +18141,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 #endif void processDidBecomeUnresponsive(); -@@ -1724,6 +1759,7 @@ public: +@@ -1739,6 +1774,7 @@ public: void setViewportSizeForCSSViewportUnits(const WebCore::FloatSize&); WebCore::FloatSize viewportSizeForCSSViewportUnits() const; @@ -17804,7 +18149,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 void didReceiveAuthenticationChallengeProxy(Ref&&, NegotiatedLegacyTLS); void negotiatedLegacyTLS(); void didNegotiateModernTLS(const URL&); -@@ -1758,6 +1794,8 @@ public: +@@ -1771,6 +1807,8 @@ public: #if PLATFORM(COCOA) || PLATFORM(GTK) RefPtr takeViewSnapshot(std::optional&&); @@ -17812,8 +18157,8 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 + RefPtr takeViewSnapshot(std::optional&&) { return nullptr; } #endif - void wrapCryptoKey(const Vector&, CompletionHandler>&&)>&&); -@@ -2666,6 +2704,7 @@ private: + void wrapCryptoKey(Vector&&, CompletionHandler>&&)>&&); +@@ -2672,6 +2710,7 @@ private: RefPtr launchProcessForReload(); void requestNotificationPermission(const String& originString, CompletionHandler&&); @@ -17821,7 +18166,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 void didChangeContentSize(const WebCore::IntSize&); void didChangeIntrinsicContentSize(const WebCore::IntSize&); -@@ -3178,8 +3217,10 @@ private: +@@ -3191,8 +3230,10 @@ private: String m_overrideContentSecurityPolicy; RefPtr m_inspector; @@ -17832,7 +18177,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 std::unique_ptr m_fullScreenManager; std::unique_ptr m_fullscreenClient; #endif -@@ -3371,6 +3412,22 @@ private: +@@ -3384,6 +3425,22 @@ private: std::optional m_currentDragOperation; bool m_currentDragIsOverFileInput { false }; unsigned m_currentDragNumberOfFilesToBeAccepted { 0 }; @@ -17855,7 +18200,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 #endif bool m_mainFrameHasHorizontalScrollbar { false }; -@@ -3542,6 +3599,10 @@ private: +@@ -3555,6 +3612,10 @@ private: RefPtr messageBody; }; Vector m_pendingInjectedBundleMessages; @@ -17867,7 +18212,7 @@ index c2ee994879f2f26a8ccbfccb330acdbc85b42898..7d5c35038d16bfaabbe55905b8fb8707 #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION) std::unique_ptr m_webDeviceOrientationUpdateProviderProxy; diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in -index cf1a795016100a37361cad1902723c11c571fdba..2462eb77a81b5a904e1ed9bf06927f839bc6f391 100644 +index 488af1f4066de0b8adaa595cb2f4028fbce4b177..529a1b8d2f2b0dd9face3ce38cf68758ce381d2f 100644 --- a/Source/WebKit/UIProcess/WebPageProxy.messages.in +++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in @@ -29,6 +29,7 @@ messages -> WebPageProxy { @@ -17877,7 +18222,7 @@ index cf1a795016100a37361cad1902723c11c571fdba..2462eb77a81b5a904e1ed9bf06927f83 + LogToStderr(String text) DidChangeViewportProperties(struct WebCore::ViewportAttributes attributes) - DidReceiveEvent(enum:uint8_t WebKit::WebEventType eventType, bool handled) + DidReceiveEvent(enum:uint8_t WebKit::WebEventType eventType, bool handled, struct std::optional remoteUserInputEventData) @@ -182,6 +183,7 @@ messages -> WebPageProxy { #endif @@ -17886,7 +18231,7 @@ index cf1a795016100a37361cad1902723c11c571fdba..2462eb77a81b5a904e1ed9bf06927f83 PluginScaleFactorDidChange(double zoomFactor) PluginZoomFactorDidChange(double zoomFactor) -@@ -310,10 +312,14 @@ messages -> WebPageProxy { +@@ -305,10 +307,14 @@ messages -> WebPageProxy { StartDrag(struct WebCore::DragItem dragItem, WebCore::ShareableBitmapHandle dragImage) SetPromisedDataForImage(String pasteboardName, WebCore::SharedMemory::Handle imageHandle, String filename, String extension, String title, String url, String visibleURL, WebCore::SharedMemory::Handle archiveHandle, String originIdentifier) #endif @@ -17918,7 +18263,7 @@ index c909cd634d6acd72695de8372866691269ad6a04..ff5b37e3b4a17eab4bd3f8e9a2a6ef84 } diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp -index 3a3655d43728126604dc246de49ba7c9210038b2..6d2552c13caadb09a5c8fed13e6034a087465ddb 100644 +index c3ff67230baf4dec44f5d7232a8351ec1f77b79c..3fed70aa8f568cd9a3a4fa460ed565658405f63f 100644 --- a/Source/WebKit/UIProcess/WebProcessPool.cpp +++ b/Source/WebKit/UIProcess/WebProcessPool.cpp @@ -426,10 +426,10 @@ void WebProcessPool::setAutomationClient(std::unique_ptr& @@ -17956,10 +18301,10 @@ index 3a3655d43728126604dc246de49ba7c9210038b2..6d2552c13caadb09a5c8fed13e6034a0 parameters.urlSchemesRegisteredAsEmptyDocument = copyToVector(m_schemesToRegisterAsEmptyDocument); diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp -index bec37fb35fb6e2077f6ad3a73d06b1b7d105ffc4..a5764d995f015b7f343303b4896c44abd38e024d 100644 +index 9411228a77d83f24384a0b9cf57f44351b48d75e..3510caa0b246b9794977f4fc99efddc9de1aceee 100644 --- a/Source/WebKit/UIProcess/WebProcessProxy.cpp +++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp -@@ -188,6 +188,11 @@ Vector> WebProcessProxy::allProcesses() +@@ -189,6 +189,11 @@ Vector> WebProcessProxy::allProcesses() }); } @@ -17971,7 +18316,7 @@ index bec37fb35fb6e2077f6ad3a73d06b1b7d105ffc4..a5764d995f015b7f343303b4896c44ab RefPtr WebProcessProxy::processForIdentifier(ProcessIdentifier identifier) { return allProcessMap().get(identifier); -@@ -561,6 +566,26 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt +@@ -562,6 +567,26 @@ void WebProcessProxy::getLaunchOptions(ProcessLauncher::LaunchOptions& launchOpt if (WebKit::isInspectorProcessPool(processPool())) launchOptions.extraInitializationData.add("inspector-process"_s, "1"_s); @@ -17999,10 +18344,10 @@ index bec37fb35fb6e2077f6ad3a73d06b1b7d105ffc4..a5764d995f015b7f343303b4896c44ab if (isPrewarmed()) diff --git a/Source/WebKit/UIProcess/WebProcessProxy.h b/Source/WebKit/UIProcess/WebProcessProxy.h -index d154105bcabd3fe11657b484712aee58deb2d450..111e6b272fc3b1700b82bf3df98c5e501126daeb 100644 +index 7ac34410441b471cfe9bc3d9a96a7f082283813d..7a39d5f45d7b422330b8cd444ebe78cfa145c692 100644 --- a/Source/WebKit/UIProcess/WebProcessProxy.h +++ b/Source/WebKit/UIProcess/WebProcessProxy.h -@@ -175,6 +175,7 @@ public: +@@ -178,6 +178,7 @@ public: static void forWebPagesWithOrigin(PAL::SessionID, const WebCore::SecurityOriginData&, const Function&); static Vector> allowedFirstPartiesForCookies(); @@ -18011,10 +18356,10 @@ index d154105bcabd3fe11657b484712aee58deb2d450..111e6b272fc3b1700b82bf3df98c5e50 void initializeWebProcess(WebProcessCreationParameters&&); diff --git a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp -index f3b3f0101a88eefff3b3dde49017d0d918758bfa..09f4b3d331d6f44bdce4ba4895da2e600183e6b8 100644 +index 3311783c3e193b7b3e6f4b1aeddc40560308859a..ceb002bdce785ac39ed86c4f809813c32148bfc8 100644 --- a/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp +++ b/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp -@@ -305,7 +305,8 @@ SOAuthorizationCoordinator& WebsiteDataStore::soAuthorizationCoordinator(const W +@@ -306,7 +306,8 @@ SOAuthorizationCoordinator& WebsiteDataStore::soAuthorizationCoordinator(const W static Ref networkProcessForSession(PAL::SessionID sessionID) { @@ -18024,7 +18369,7 @@ index f3b3f0101a88eefff3b3dde49017d0d918758bfa..09f4b3d331d6f44bdce4ba4895da2e60 if (sessionID.isEphemeral()) { // Reuse a previous persistent session network process for ephemeral sessions. for (auto& dataStore : allDataStores().values()) { -@@ -2278,6 +2279,12 @@ void WebsiteDataStore::originDirectoryForTesting(WebCore::ClientOrigin&& origin, +@@ -2279,6 +2280,12 @@ void WebsiteDataStore::originDirectoryForTesting(WebCore::ClientOrigin&& origin, protectedNetworkProcess()->websiteDataOriginDirectoryForTesting(m_sessionID, WTFMove(origin), type, WTFMove(completionHandler)); } @@ -18124,10 +18469,10 @@ index 165885137ca032390c6b55baacc30a8c4c423eb5..930ceeca56587636993f9a0c0e0a21d0 std::unique_ptr m_soAuthorizationCoordinator; #endif diff --git a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp -index cfb4be2f7b34d1ecc97989d4bfefa6e8c1a3c864..f250d43ad30903ffa93cce52e1d3843f7c428ecf 100644 +index 7c6139c6b0d8c7c3cddd08164317794a519a7b53..027d05bdd0e4bf94d70797ab195e656f81541300 100644 --- a/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp +++ b/Source/WebKit/UIProcess/geoclue/GeoclueGeolocationProvider.cpp -@@ -101,6 +101,14 @@ void GeoclueGeolocationProvider::stop() +@@ -102,6 +102,14 @@ void GeoclueGeolocationProvider::stop() } m_sourceType = LocationProviderSource::Unknown; @@ -18142,7 +18487,7 @@ index cfb4be2f7b34d1ecc97989d4bfefa6e8c1a3c864..f250d43ad30903ffa93cce52e1d3843f } void GeoclueGeolocationProvider::setEnableHighAccuracy(bool enabled) -@@ -373,6 +381,8 @@ void GeoclueGeolocationProvider::createGeoclueClient(const char* clientPath) +@@ -374,6 +382,8 @@ void GeoclueGeolocationProvider::createGeoclueClient(const char* clientPath) return; } @@ -18461,10 +18806,10 @@ index b02c70d85fe1a93899640a8b909b0cf734d28b18..b1dc8e89eb265be81e083bf337109561 virtual void unrealize() { }; virtual int renderHostFileDescriptor() { return -1; } diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp -index b71fb0a8ac0605edc6466ac1a5b12607fb8f211b..bcbfd33dfe367e1b04426f8162dd1552b4dbbcc1 100644 +index 66329bbc7f97ca577842dd93e28d4143b16e69dc..cd10bd6a29e64a1356e5a14a3a6339c4ca43327e 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp -@@ -662,4 +662,30 @@ RendererBufferFormat AcceleratedBackingStoreDMABuf::bufferFormat() const +@@ -675,4 +675,30 @@ RendererBufferFormat AcceleratedBackingStoreDMABuf::bufferFormat() const return buffer ? buffer->format() : RendererBufferFormat { }; } @@ -18496,10 +18841,10 @@ index b71fb0a8ac0605edc6466ac1a5b12607fb8f211b..bcbfd33dfe367e1b04426f8162dd1552 + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h -index cd95ceb063fc776b5d68ff45262c4d84e572c509..041c562551cd467c320b8f566264885d00d1434b 100644 +index 68d4bb329c2e116fe720c98d3e38b6672c88e389..a4a36dd35ee9330f8b9edfb09f607a12dbac7c0b 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.h -@@ -88,6 +88,7 @@ private: +@@ -90,6 +90,7 @@ private: #else bool paint(cairo_t*, const WebCore::IntRect&) override; #endif @@ -18507,9 +18852,9 @@ index cd95ceb063fc776b5d68ff45262c4d84e572c509..041c562551cd467c320b8f566264885d void unrealize() override; void update(const LayerTreeContext&) override; RendererBufferFormat bufferFormat() const override; -@@ -243,6 +244,9 @@ private: - RefPtr m_pendingBuffer; +@@ -246,6 +247,9 @@ private: RefPtr m_committedBuffer; + std::optional m_pendingDamageRegion; HashMap> m_buffers; +// Playwright begin + RefPtr m_flippedSurface; @@ -18572,12 +18917,12 @@ index 0000000000000000000000000000000000000000..5a255b0389470c4fd1baaff5e8e4882e + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp b/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp -index 6029857cfcd6c4fea14de28243f1955138a62844..8a1bda8f2637670cf88baca998cbff09157d2a6f 100644 +index 97191083e1c5b5283599e394e56553fc5e5cd6a1..e8c7cbb6cd9431b1720aafb8dfd0abdc97f17a39 100644 --- a/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp +++ b/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp -@@ -34,6 +34,8 @@ - #include +@@ -35,6 +35,8 @@ #include + #include +using namespace WebCore; + @@ -18586,10 +18931,10 @@ index 6029857cfcd6c4fea14de28243f1955138a62844..8a1bda8f2637670cf88baca998cbff09 Ref WebDateTimePickerGtk::create(WebPageProxy& page) diff --git a/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp new file mode 100644 -index 0000000000000000000000000000000000000000..a75642f1d3765efa6fcc7c07cc51beb2ddf450d2 +index 0000000000000000000000000000000000000000..7d9672b0f831b5b7f6acf14ede26e1e8e9a65389 --- /dev/null +++ b/Source/WebKit/UIProcess/gtk/WebPageInspectorEmulationAgentGtk.cpp -@@ -0,0 +1,115 @@ +@@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019 Microsoft Corporation. + * @@ -18687,6 +19032,8 @@ index 0000000000000000000000000000000000000000..a75642f1d3765efa6fcc7c07cc51beb2 + } + callback("Failed to resize window"_s); +#else ++ UNUSED_PARAM(this); ++ UNUSED_PARAM(didNotHaveInitialAllocation); + UNUSED_PARAM(drawingArea); + callback(String()); +#endif @@ -18788,10 +19135,10 @@ index 0000000000000000000000000000000000000000..36ab6e9aec9f8d79fb13a8a49beadaaf + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp b/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp -index d18b3e777203ef5d0f33884f909bc598d3526831..aef80b47359d7a2e4805a006dc59cd60d499a60e 100644 +index 2a17b59c9be6ecc76b0ec0a16d9f4866dffa0bf4..0d5c58a88b0e5197254d0eb5bd6eee045d99d299 100644 --- a/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp +++ b/Source/WebKit/UIProcess/gtk/WebPasteboardProxyGtk.cpp -@@ -77,8 +77,10 @@ void WebPasteboardProxy::setPrimarySelectionOwner(WebFrameProxy* frame) +@@ -78,8 +78,10 @@ void WebPasteboardProxy::setPrimarySelectionOwner(WebFrameProxy* frame) if (m_primarySelectionOwner == frame) return; @@ -18805,7 +19152,7 @@ index d18b3e777203ef5d0f33884f909bc598d3526831..aef80b47359d7a2e4805a006dc59cd60 m_primarySelectionOwner = frame; } diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm -index d45b06876bac4046a05a03fbaf734af33071191d..8c136ce12155bda85cc31d2422a0bd5ff7dfdea9 100644 +index f5290e15ec912a36766509dd2414444a8c97e06d..2563926ff72e0b8bcb35e250141549a69578a52f 100644 --- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm +++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm @@ -503,6 +503,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) @@ -19027,7 +19374,7 @@ index 0000000000000000000000000000000000000000..721826c8c98fc85b68a4f45deaee69c1 + +#endif diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h -index 708c5d11dec4797db15b51293a94089869024e8a..ee05508c06f739c27df3d5e6c6b5234bad8a82bf 100644 +index 4c99b44dbdd37e73c349ea8d5a3422075d2eff65..7c6dc33bf047706f13332c726a7e2364d834f7ae 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h @@ -54,6 +54,8 @@ class PageClientImpl final : public PageClientImplCocoa @@ -19039,7 +19386,7 @@ index 708c5d11dec4797db15b51293a94089869024e8a..ee05508c06f739c27df3d5e6c6b5234b PageClientImpl(NSView *, WKWebView *); virtual ~PageClientImpl(); -@@ -171,6 +173,9 @@ private: +@@ -170,6 +172,9 @@ private: void updateAcceleratedCompositingMode(const LayerTreeContext&) override; void didFirstLayerFlush(const LayerTreeContext&) override; @@ -19049,7 +19396,7 @@ index 708c5d11dec4797db15b51293a94089869024e8a..ee05508c06f739c27df3d5e6c6b5234b RefPtr takeViewSnapshot(std::optional&&) override; void wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent&) override; #if ENABLE(MAC_GESTURE_EVENTS) -@@ -225,6 +230,10 @@ private: +@@ -224,6 +229,10 @@ private: void beganExitFullScreen(const WebCore::IntRect& initialFrame, const WebCore::IntRect& finalFrame) override; #endif @@ -19061,18 +19408,10 @@ index 708c5d11dec4797db15b51293a94089869024e8a..ee05508c06f739c27df3d5e6c6b5234b void navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem&) override; void navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem&) override; diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm -index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f3050926a9f 100644 +index 0116071f4359eac661cc6de71eee2d43ce2d56e0..c93c40e2064e15ccecf08a147f4189e98810a6d3 100644 --- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm +++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm -@@ -79,6 +79,7 @@ - #import - #import - #import -+#import - #import - #import - #import -@@ -105,6 +106,13 @@ namespace WebKit { +@@ -110,6 +110,13 @@ namespace WebKit { using namespace WebCore; @@ -19086,7 +19425,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView) : PageClientImplCocoa(webView) , m_view(view) -@@ -158,6 +166,9 @@ NSWindow *PageClientImpl::activeWindow() const +@@ -163,6 +170,9 @@ NSWindow *PageClientImpl::activeWindow() const bool PageClientImpl::isViewWindowActive() { @@ -19096,7 +19435,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer)); NSWindow *activeViewWindow = activeWindow(); return activeViewWindow.isKeyWindow || (activeViewWindow && [NSApp keyWindow] == activeViewWindow); -@@ -165,6 +176,9 @@ bool PageClientImpl::isViewWindowActive() +@@ -170,6 +180,9 @@ bool PageClientImpl::isViewWindowActive() bool PageClientImpl::isViewFocused() { @@ -19106,7 +19445,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 // FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl. // Once WebViewImpl and PageClient merge, this won't be a problem. if (!m_impl) -@@ -188,6 +202,9 @@ void PageClientImpl::makeFirstResponder() +@@ -193,6 +206,9 @@ void PageClientImpl::makeFirstResponder() bool PageClientImpl::isViewVisible() { @@ -19116,7 +19455,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 NSView *activeView = this->activeView(); NSWindow *activeViewWindow = activeWindow(); -@@ -271,7 +288,8 @@ void PageClientImpl::didRelaunchProcess() +@@ -276,7 +292,8 @@ void PageClientImpl::didRelaunchProcess() void PageClientImpl::preferencesDidChange() { @@ -19126,7 +19465,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 } void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) -@@ -474,6 +492,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) +@@ -479,6 +496,8 @@ IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect) void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled) { @@ -19135,7 +19474,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled); } -@@ -493,6 +513,8 @@ void PageClientImpl::computeHasVisualSearchResults(const URL& imageURL, Shareabl +@@ -498,6 +517,8 @@ void PageClientImpl::computeHasVisualSearchResults(const URL& imageURL, Shareabl RefPtr PageClientImpl::createPopupMenuProxy(WebPageProxy& page) { @@ -19144,7 +19483,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 return WebPopupMenuProxyMac::create(m_view, page.popupMenuClient()); } -@@ -634,6 +656,12 @@ CALayer *PageClientImpl::footerBannerLayer() const +@@ -639,6 +660,12 @@ CALayer *PageClientImpl::footerBannerLayer() const return m_impl->footerBannerLayer(); } @@ -19157,7 +19496,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 RefPtr PageClientImpl::takeViewSnapshot(std::optional&&) { return m_impl->takeViewSnapshot(); -@@ -824,6 +852,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR +@@ -829,6 +856,13 @@ void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntR #endif // ENABLE(FULLSCREEN_API) @@ -19171,7 +19510,7 @@ index c17d3e660de168d07772480800099730562675ed..6ebec657486366f970817f511b840f30 void PageClientImpl::navigationGestureDidBegin() { m_impl->dismissContentRelativeChildWindowsWithAnimation(true); -@@ -1011,6 +1046,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c +@@ -1017,6 +1051,9 @@ void PageClientImpl::requestScrollToRect(const WebCore::FloatRect& targetRect, c bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event) { @@ -19199,11 +19538,23 @@ index 21c925bafb662dbe961baaad7f25bf4296236d76..5496a33c558a00a5ba96d10223e600aa } +#endif +diff --git a/Source/WebKit/UIProcess/mac/WKImmediateActionController.mm b/Source/WebKit/UIProcess/mac/WKImmediateActionController.mm +index 63c423a74cf983ab7a0be49f0376d227c49724e1..5818c786d5fb0fb4a60c549b68ec989656223e5c 100644 +--- a/Source/WebKit/UIProcess/mac/WKImmediateActionController.mm ++++ b/Source/WebKit/UIProcess/mac/WKImmediateActionController.mm +@@ -31,6 +31,7 @@ + #import "APIHitTestResult.h" + #import "MessageSenderInlines.h" + #import "WKNSURLExtras.h" ++#import "WebFrameProxy.h" + #import "WebPageMessages.h" + #import "WebPageProxy.h" + #import "WebPageProxyMessages.h" diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h -index 6ab7aacaebfda818e3010bb06db72c8552ac598a..3e19cba50d73084392f62f176ad4c3153803e579 100644 +index e34faa8ae2933154efdbf0492a2f17af7a46f83b..54b509837bb767ac3ab28d1d7059462ca7a1170b 100644 --- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h +++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.h -@@ -68,6 +68,7 @@ private: +@@ -78,6 +78,7 @@ private: void show() override; void showContextMenuWithItems(Vector>&&) override; void useContextMenuItems(Vector>&&) override; @@ -19212,10 +19563,10 @@ index 6ab7aacaebfda818e3010bb06db72c8552ac598a..3e19cba50d73084392f62f176ad4c315 bool showAfterPostProcessingContextData(); diff --git a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm -index 26db4b48e75b3e65febc8cbfb314a4c22e9bdfb3..138ea13ab34b83ed190436afea7d994cb4dfa70e 100644 +index bb4822a1ca6c0b209baed338f267f366424f61c6..aaffc9579deda3a1f5c8fe71747833a5d0e2e8bf 100644 --- a/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm +++ b/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm -@@ -478,6 +478,12 @@ void WebContextMenuProxyMac::getShareMenuItem(CompletionHandlersetIntrinsicDeviceScaleFactor(deviceScaleFactorForWindow(hwnd)); +- // If there are no m_page, use intrinsic device scale factor. +- float deviceScaleFactor = m_page ? m_page->deviceScaleFactor() : deviceScaleFactorForWindow(hwnd); +- m_viewSize = expandedIntSize(FloatSize(LOWORD(lParam), HIWORD(lParam)) / deviceScaleFactor); ++ ++ m_viewSize = expandedIntSize(FloatSize(LOWORD(lParam), HIWORD(lParam))); + + if (m_page && m_page->drawingArea()) { + // FIXME specify correctly layerPosition. diff --git a/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/InspectorTargetProxyWPE.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7453194ca6f032ba86a4c67f5bf12688ab6ec1be @@ -20223,22 +20590,37 @@ index 0000000000000000000000000000000000000000..a7d88f8c745f95af21db71dcfce368ba + +} // namespace WebKit diff --git a/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -index b6536b74452c26a4d661bcf6039af54824f258d0..ade7c4ad1cef7bc69c452bef404eb38437c93088 100644 +index ff2377628995b6095d7cd75f447d904847da0dc0..345aebe075a5b710303eeb8d46f94cf9dc901706 100644 --- a/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp +++ b/Source/WebKit/UIProcess/wpe/WebPageProxyWPE.cpp -@@ -29,6 +29,7 @@ - #include "EditorState.h" +@@ -30,6 +30,7 @@ #include "InputMethodState.h" #include "PageClientImpl.h" + #include "WebProcessProxy.h" +#include #include #if USE(ATK) +diff --git a/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp b/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp +index 41307f5fe61b92785a493f68aeca475521708d55..f02e9d93c96ac6c0abedba9ced97b02f9250ac82 100644 +--- a/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp ++++ b/Source/WebKit/UIProcess/wpe/WebPreferencesWPE.cpp +@@ -34,6 +34,10 @@ void WebPreferences::platformInitializeStore() + setForceCompositingMode(true); + setThreadedScrollingEnabled(true); + ++ // Playwright override begin ++ setThreadedScrollingEnabled(false); ++ // Playwright override end ++ + #if USE(SKIA) + // FIXME: Expose this as a setting when we switch to Skia. + static const char* disableAccelerated2DCanvas = getenv("WEBKIT_DISABLE_ACCELERATED_2D_CANVAS"); diff --git a/Source/WebKit/WPEPlatform/CMakeLists.txt b/Source/WebKit/WPEPlatform/CMakeLists.txt -index 74f395b50b2d4668c521a8d72a5581113cf16698..75496b3c36a58c8da1bd8382cecddc8f81c62119 100644 +index 2b64d1b5b013d53b18b7757fe3b3f3d9a0501571..e8f28808f5ef0532319a4462fd285c0770d7ce52 100644 --- a/Source/WebKit/WPEPlatform/CMakeLists.txt +++ b/Source/WebKit/WPEPlatform/CMakeLists.txt -@@ -89,6 +89,7 @@ set(WPEPlatform_SYSTEM_INCLUDE_DIRECTORIES +@@ -96,6 +96,7 @@ set(WPEPlatform_SYSTEM_INCLUDE_DIRECTORIES set(WPEPlatform_LIBRARIES Epoxy::Epoxy @@ -20247,10 +20629,10 @@ index 74f395b50b2d4668c521a8d72a5581113cf16698..75496b3c36a58c8da1bd8382cecddc8f ${GLIB_GIO_LIBRARIES} ${GLIB_GOBJECT_LIBRARIES} diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj -index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce659aeb8a 100644 +index 3cf46d518a1920a5c6c8e9537f71b1b0b25b00a0..3c7e8c09640d82630864f41569f3229076088a93 100644 --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj -@@ -1540,6 +1540,7 @@ +@@ -1547,6 +1547,7 @@ 5CABDC8722C40FED001EDE8E /* APIMessageListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CABDC8322C40FA7001EDE8E /* APIMessageListener.h */; }; 5CADDE05215046BD0067D309 /* WKWebProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C74300E21500492004BFA17 /* WKWebProcess.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5CAECB6627465AE400AB78D0 /* UnifiedSource115.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CAECB5E27465AE300AB78D0 /* UnifiedSource115.cpp */; }; @@ -20258,7 +20640,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5CAF7AA726F93AB00003F19E /* adattributiond.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CAF7AA526F93A950003F19E /* adattributiond.cpp */; }; 5CAFDE452130846300B1F7E1 /* _WKInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAFDE422130843500B1F7E1 /* _WKInspector.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5CAFDE472130846A00B1F7E1 /* _WKInspectorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CAFDE442130843600B1F7E1 /* _WKInspectorInternal.h */; }; -@@ -2370,6 +2371,18 @@ +@@ -2379,6 +2380,18 @@ DF0C5F28252ECB8E00D921DB /* WKDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F24252ECB8D00D921DB /* WKDownload.h */; settings = {ATTRIBUTES = (Public, ); }; }; DF0C5F2A252ECB8E00D921DB /* WKDownloadDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; DF0C5F2B252ED44000D921DB /* WKDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */; }; @@ -20277,7 +20659,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce DF462E0F23F22F5500EFF35F /* WKHTTPCookieStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; DF462E1223F338BE00EFF35F /* WKContentWorldPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; DF7A231C291B088D00B98DF3 /* WKSnapshotConfigurationPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF7A231B291B088D00B98DF3 /* WKSnapshotConfigurationPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; -@@ -2458,6 +2471,8 @@ +@@ -2467,6 +2480,8 @@ E5BEF6822130C48000F31111 /* WebDataListSuggestionsDropdownIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = E5BEF6802130C47F00F31111 /* WebDataListSuggestionsDropdownIOS.h */; }; E5CB07DC20E1678F0022C183 /* WKFormColorControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E5CB07DA20E1678F0022C183 /* WKFormColorControl.h */; }; E5CBA76427A318E100DF7858 /* UnifiedSource120.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA75F27A3187800DF7858 /* UnifiedSource120.cpp */; }; @@ -20286,7 +20668,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce E5CBA76527A318E100DF7858 /* UnifiedSource118.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA76127A3187900DF7858 /* UnifiedSource118.cpp */; }; E5CBA76627A318E100DF7858 /* UnifiedSource116.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA76327A3187B00DF7858 /* UnifiedSource116.cpp */; }; E5CBA76727A318E100DF7858 /* UnifiedSource119.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E5CBA76027A3187900DF7858 /* UnifiedSource119.cpp */; }; -@@ -2478,6 +2493,9 @@ +@@ -2487,6 +2502,9 @@ EBA8D3B627A5E33F00CB7900 /* MockPushServiceConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBA8D3B027A5E33F00CB7900 /* MockPushServiceConnection.mm */; }; EBA8D3B727A5E33F00CB7900 /* PushServiceConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = EBA8D3B127A5E33F00CB7900 /* PushServiceConnection.mm */; }; ED82A7F2128C6FAF004477B3 /* WKBundlePageOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A22F0FF1289FCD90085E74F /* WKBundlePageOverlay.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -20296,7 +20678,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce F409BA181E6E64BC009DA28E /* WKDragDestinationAction.h in Headers */ = {isa = PBXBuildFile; fileRef = F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */; settings = {ATTRIBUTES = (Private, ); }; }; F40C3B712AB401C5007A3567 /* WKDatePickerPopoverController.h in Headers */ = {isa = PBXBuildFile; fileRef = F40C3B6F2AB40167007A3567 /* WKDatePickerPopoverController.h */; }; F41795A62AC61B78007F5F12 /* CompactContextMenuPresenter.h in Headers */ = {isa = PBXBuildFile; fileRef = F41795A42AC619A2007F5F12 /* CompactContextMenuPresenter.h */; }; -@@ -6210,6 +6228,7 @@ +@@ -6230,6 +6248,7 @@ 5CABDC8522C40FCC001EDE8E /* WKMessageListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKMessageListener.h; sourceTree = ""; }; 5CABE07A28F60E8A00D83FD9 /* WebPushMessage.serialization.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebPushMessage.serialization.in; sourceTree = ""; }; 5CADDE0D2151AA010067D309 /* AuthenticationChallengeDisposition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthenticationChallengeDisposition.h; sourceTree = ""; }; @@ -20304,7 +20686,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5CAECB5E27465AE300AB78D0 /* UnifiedSource115.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource115.cpp; sourceTree = ""; }; 5CAF7AA426F93A750003F19E /* adattributiond */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = adattributiond; sourceTree = BUILT_PRODUCTS_DIR; }; 5CAF7AA526F93A950003F19E /* adattributiond.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = adattributiond.cpp; sourceTree = ""; }; -@@ -7908,6 +7927,19 @@ +@@ -7930,6 +7949,19 @@ DF0C5F24252ECB8D00D921DB /* WKDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownload.h; sourceTree = ""; }; DF0C5F25252ECB8E00D921DB /* WKDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadInternal.h; sourceTree = ""; }; DF0C5F26252ECB8E00D921DB /* WKDownloadDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDownloadDelegate.h; sourceTree = ""; }; @@ -20324,7 +20706,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKHTTPCookieStorePrivate.h; sourceTree = ""; }; DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = ""; }; DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = ""; }; -@@ -8061,6 +8093,8 @@ +@@ -8082,6 +8114,8 @@ E5CBA76127A3187900DF7858 /* UnifiedSource118.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource118.cpp; sourceTree = ""; }; E5CBA76227A3187900DF7858 /* UnifiedSource117.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource117.cpp; sourceTree = ""; }; E5CBA76327A3187B00DF7858 /* UnifiedSource116.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = UnifiedSource116.cpp; sourceTree = ""; }; @@ -20333,7 +20715,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce E5DEFA6726F8F42600AB68DB /* PhotosUISPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhotosUISPI.h; sourceTree = ""; }; EB0D312D275AE13300863D8F /* com.apple.webkit.webpushd.mac.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.webkit.webpushd.mac.plist; sourceTree = ""; }; EB0D312E275AE13300863D8F /* com.apple.webkit.webpushd.ios.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.webkit.webpushd.ios.plist; sourceTree = ""; }; -@@ -8085,6 +8119,14 @@ +@@ -8111,6 +8145,14 @@ ECA680D31E6904B500731D20 /* ExtraPrivateSymbolsForTAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtraPrivateSymbolsForTAPI.h; sourceTree = ""; }; ECBFC1DB1E6A4D66000300C7 /* ExtraPublicSymbolsForTAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtraPublicSymbolsForTAPI.h; sourceTree = ""; }; F036978715F4BF0500C3A80E /* WebColorPicker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebColorPicker.cpp; sourceTree = ""; }; @@ -20348,7 +20730,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce F409BA171E6E64B3009DA28E /* WKDragDestinationAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDragDestinationAction.h; sourceTree = ""; }; F40C3B6F2AB40167007A3567 /* WKDatePickerPopoverController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKDatePickerPopoverController.h; path = ios/forms/WKDatePickerPopoverController.h; sourceTree = ""; }; F40C3B702AB40167007A3567 /* WKDatePickerPopoverController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKDatePickerPopoverController.mm; path = ios/forms/WKDatePickerPopoverController.mm; sourceTree = ""; }; -@@ -8389,6 +8431,7 @@ +@@ -8415,6 +8457,7 @@ 3766F9EE189A1241003CF19B /* JavaScriptCore.framework in Frameworks */, 3766F9F1189A1254003CF19B /* libicucore.dylib in Frameworks */, 7B9FC5BB28A5233B007570E7 /* libWebKitPlatform.a in Frameworks */, @@ -20356,7 +20738,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 3766F9EF189A1244003CF19B /* QuartzCore.framework in Frameworks */, 37694525184FC6B600CDE21F /* Security.framework in Frameworks */, 37BEC4DD1948FC6A008B4286 /* WebCore.framework in Frameworks */, -@@ -11262,6 +11305,7 @@ +@@ -11296,6 +11339,7 @@ 99788ACA1F421DCA00C08000 /* _WKAutomationSessionConfiguration.mm */, 990D28A81C6404B000986977 /* _WKAutomationSessionDelegate.h */, 990D28AF1C65203900986977 /* _WKAutomationSessionInternal.h */, @@ -20364,7 +20746,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5C4609E222430E4C009943C2 /* _WKContentRuleListAction.h */, 5C4609E322430E4D009943C2 /* _WKContentRuleListAction.mm */, 5C4609E422430E4D009943C2 /* _WKContentRuleListActionInternal.h */, -@@ -12572,6 +12616,7 @@ +@@ -12603,6 +12647,7 @@ E34B110C27C46BC6006D2F2E /* libWebCoreTestShim.dylib */, E34B110F27C46D09006D2F2E /* libWebCoreTestSupport.dylib */, DDE992F4278D06D900F60D26 /* libWebKitAdditions.a */, @@ -20372,7 +20754,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 57A9FF15252C6AEF006A2040 /* libWTF.a */, 5750F32A2032D4E500389347 /* LocalAuthentication.framework */, 570DAAB0230273D200E8FC04 /* NearField.framework */, -@@ -13142,6 +13187,12 @@ +@@ -13173,6 +13218,12 @@ children = ( 9197940423DBC4BB00257892 /* InspectorBrowserAgent.cpp */, 9197940323DBC4BB00257892 /* InspectorBrowserAgent.h */, @@ -20385,7 +20767,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce ); path = Agents; sourceTree = ""; -@@ -13150,6 +13201,7 @@ +@@ -13181,6 +13232,7 @@ isa = PBXGroup; children = ( A5D3504D1D78F0D2005124A9 /* RemoteWebInspectorUIProxyMac.mm */, @@ -20393,7 +20775,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 1CA8B935127C774E00576C2B /* WebInspectorUIProxyMac.mm */, 99A7ACE326012919006D57FD /* WKInspectorResourceURLSchemeHandler.h */, 99A7ACE42601291A006D57FD /* WKInspectorResourceURLSchemeHandler.mm */, -@@ -13866,6 +13918,7 @@ +@@ -13898,6 +13950,7 @@ E1513C65166EABB200149FCB /* AuxiliaryProcessProxy.h */, 46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */, 46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */, @@ -20401,7 +20783,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5C6D69352AC3935D0099BDAF /* BrowsingContextGroup.cpp */, 5C6D69362AC3935D0099BDAF /* BrowsingContextGroup.h */, 07297F9C1C1711EA003F0735 /* DeviceIdHashSaltStorage.cpp */, -@@ -13889,6 +13942,8 @@ +@@ -13921,6 +13974,8 @@ BC06F43912DBCCFB002D78DE /* GeolocationPermissionRequestProxy.cpp */, BC06F43812DBCCFB002D78DE /* GeolocationPermissionRequestProxy.h */, 2DD5A72A1EBF09A7009BA597 /* HiddenPageThrottlingAutoIncreasesCounter.h */, @@ -20410,7 +20792,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5CEABA2B2333251400797797 /* LegacyGlobalSettings.cpp */, 5CEABA2A2333247700797797 /* LegacyGlobalSettings.h */, 31607F3819627002009B87DA /* LegacySessionStateCoding.h */, -@@ -13922,6 +13977,7 @@ +@@ -13954,6 +14009,7 @@ 1A0C227D2451130A00ED614D /* QuickLookThumbnailingSoftLink.mm */, 1AEE57232409F142002005D6 /* QuickLookThumbnailLoader.h */, 1AEE57242409F142002005D6 /* QuickLookThumbnailLoader.mm */, @@ -20418,7 +20800,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5CCB54DC2A4FEA6A0005FAA8 /* RemotePageDrawingAreaProxy.cpp */, 5CCB54DB2A4FEA6A0005FAA8 /* RemotePageDrawingAreaProxy.h */, 5C907E9A294D507100B3402D /* RemotePageProxy.cpp */, -@@ -14024,6 +14080,8 @@ +@@ -14056,6 +14112,8 @@ BC7B6204129A0A6700D174A4 /* WebPageGroup.h */, 2D9EA3101A96D9EB002D2807 /* WebPageInjectedBundleClient.cpp */, 2D9EA30E1A96CBFF002D2807 /* WebPageInjectedBundleClient.h */, @@ -20427,7 +20809,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce BC111B0B112F5E4F00337BAB /* WebPageProxy.cpp */, BC032DCB10F4389F0058C15A /* WebPageProxy.h */, BCBD38FA125BAB9A00D2C29F /* WebPageProxy.messages.in */, -@@ -14190,6 +14248,7 @@ +@@ -14224,6 +14282,7 @@ BC646C1911DD399F006455B0 /* WKBackForwardListItemRef.h */, BC646C1611DD399F006455B0 /* WKBackForwardListRef.cpp */, BC646C1711DD399F006455B0 /* WKBackForwardListRef.h */, @@ -20435,17 +20817,17 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce BCB9E24A1120E15C00A137E0 /* WKContext.cpp */, BCB9E2491120E15C00A137E0 /* WKContext.h */, 1AE52F9319201F6B00A1FA37 /* WKContextConfigurationRef.cpp */, -@@ -14771,6 +14830,9 @@ - 7AFA6F682A9F57C50055322A /* DisplayLinkMac.mm */, +@@ -14805,6 +14864,9 @@ + 7AFA6F682A9F57C50055322A /* DisplayLinkMac.cpp */, 31ABA79C215AF9E000C90E31 /* HighPerformanceGPUManager.h */, 31ABA79D215AF9E000C90E31 /* HighPerformanceGPUManager.mm */, + D71A94302370E025002C4D9E /* InspectorPlaywrightAgentClientMac.h */, + D7EB04E62372A73B00F744CE /* InspectorPlaywrightAgentClientMac.mm */, + D79902AF236E9404005D6F7E /* InspectorTargetProxyMac.mm */, - 7139CA3F2BF670BC00CA613A /* LegacyDisplayLinkMac.cpp */, 1AFDE65B1954E8D500C48FFA /* LegacySessionStateCoding.cpp */, 0FCB4E5818BBE3D9000FCFC9 /* PageClientImplMac.h */, -@@ -14795,6 +14857,8 @@ + 0FCB4E5918BBE3D9000FCFC9 /* PageClientImplMac.mm */, +@@ -14828,6 +14890,8 @@ E568B92120A3AC6A00E3C856 /* WebDataListSuggestionsDropdownMac.mm */, E55CD20124D09F1F0042DB9C /* WebDateTimePickerMac.h */, E55CD20224D09F1F0042DB9C /* WebDateTimePickerMac.mm */, @@ -20454,7 +20836,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce BC857E8512B71EBB00EDEB2E /* WebPageProxyMac.mm */, BC5750951268F3C6006F0F12 /* WebPopupMenuProxyMac.h */, BC5750961268F3C6006F0F12 /* WebPopupMenuProxyMac.mm */, -@@ -15797,6 +15861,7 @@ +@@ -15857,6 +15921,7 @@ 99788ACB1F421DDA00C08000 /* _WKAutomationSessionConfiguration.h in Headers */, 990D28AC1C6420CF00986977 /* _WKAutomationSessionDelegate.h in Headers */, 990D28B11C65208D00986977 /* _WKAutomationSessionInternal.h in Headers */, @@ -20462,7 +20844,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 5C4609E7224317B4009943C2 /* _WKContentRuleListAction.h in Headers */, 5C4609E8224317BB009943C2 /* _WKContentRuleListActionInternal.h in Headers */, 1A5704F81BE01FF400874AF1 /* _WKContextMenuElementInfo.h in Headers */, -@@ -16108,6 +16173,7 @@ +@@ -16168,6 +16233,7 @@ E170876C16D6CA6900F99226 /* BlobRegistryProxy.h in Headers */, 4F601432155C5AA2001FBDE0 /* BlockingResponseMap.h in Headers */, 1A5705111BE410E600874AF1 /* BlockSPI.h in Headers */, @@ -20470,7 +20852,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce A7E69BCC2B2117A100D43D3F /* BufferAndBackendInfo.h in Headers */, BC3065FA1259344E00E71278 /* CacheModel.h in Headers */, 935BF7FC2936BF1A00B41326 /* CacheStorageCache.h in Headers */, -@@ -16288,7 +16354,11 @@ +@@ -16348,7 +16414,11 @@ BC14DF77120B5B7900826C0C /* InjectedBundleScriptWorld.h in Headers */, CE550E152283752200D28791 /* InsertTextOptions.h in Headers */, 9197940523DBC4BB00257892 /* InspectorBrowserAgent.h in Headers */, @@ -20482,7 +20864,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce A5E391FD2183C1F800C8FB31 /* InspectorTargetProxy.h in Headers */, C5BCE5DF1C50766A00CDE3FA /* InteractionInformationAtPosition.h in Headers */, 2D4D2C811DF60BF3002EB10C /* InteractionInformationRequest.h in Headers */, -@@ -16547,6 +16617,7 @@ +@@ -16610,6 +16680,7 @@ CDAC20C923FC2F750021DEE3 /* RemoteCDMInstanceSessionIdentifier.h in Headers */, F451C0FE2703B263002BA03B /* RemoteDisplayListRecorderProxy.h in Headers */, A78A5FE42B0EB39E005036D3 /* RemoteImageBufferSetIdentifier.h in Headers */, @@ -20490,7 +20872,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 2D47B56D1810714E003A3AEE /* RemoteLayerBackingStore.h in Headers */, 2DDF731518E95060004F5A66 /* RemoteLayerBackingStoreCollection.h in Headers */, 1AB16AEA164B3A8800290D62 /* RemoteLayerTreeContext.h in Headers */, -@@ -16601,6 +16672,7 @@ +@@ -16664,6 +16735,7 @@ E1E552C516AE065F004ED653 /* SandboxInitializationParameters.h in Headers */, E36FF00327F36FBD004BE21A /* SandboxStateVariables.h in Headers */, 7BAB111025DD02B3008FC479 /* ScopedActiveMessageReceiveQueue.h in Headers */, @@ -20498,7 +20880,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 463BB93A2B9D08D80098C5C3 /* ScriptMessageHandlerIdentifier.h in Headers */, E4D54D0421F1D72D007E3C36 /* ScrollingTreeFrameScrollingNodeRemoteIOS.h in Headers */, 0F931C1C18C5711900DBA7C3 /* ScrollingTreeOverflowScrollingNodeIOS.h in Headers */, -@@ -16947,6 +17019,8 @@ +@@ -17011,6 +17083,8 @@ 939EF87029D112EE00F23AEE /* WebPageInlines.h in Headers */, 9197940823DBC4CB00257892 /* WebPageInspectorAgentBase.h in Headers */, A513F5402154A5D700662841 /* WebPageInspectorController.h in Headers */, @@ -20507,7 +20889,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce A543E30C215C8A8D00279CD9 /* WebPageInspectorTarget.h in Headers */, A543E30D215C8A9000279CD9 /* WebPageInspectorTargetController.h in Headers */, A543E307215AD13700279CD9 /* WebPageInspectorTargetFrontendChannel.h in Headers */, -@@ -19338,6 +19412,8 @@ +@@ -19422,6 +19496,8 @@ 522F792928D50EBB0069B45B /* HidService.mm in Sources */, 2749F6442146561B008380BF /* InjectedBundleNodeHandle.cpp in Sources */, 2749F6452146561E008380BF /* InjectedBundleRangeHandle.cpp in Sources */, @@ -20516,7 +20898,7 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce 1CC94E532AC92F190045F269 /* JSWebExtensionAPIAction.mm in Sources */, 1C2B4D4B2A819D0D00C528A1 /* JSWebExtensionAPIAlarms.mm in Sources */, 1C8ECFEA2AFC7DCB007BAA62 /* JSWebExtensionAPICommands.mm in Sources */, -@@ -19777,6 +19853,8 @@ +@@ -19864,6 +19940,8 @@ E3816B3D27E2463A005EAFC0 /* WebMockContentFilterManager.cpp in Sources */, 31BA924D148831260062EDB5 /* WebNotificationManagerMessageReceiver.cpp in Sources */, 2DF6FE52212E110900469030 /* WebPage.cpp in Sources */, @@ -20524,9 +20906,9 @@ index 72fd5ec5a539c5375f4c9203166470d80170c3a0..8921f3a62e95ea9bc944bbbdf84953ce + D79902B3236E9404005D6F7E /* WebPageInspectorInputAgentMac.mm in Sources */, C0CE72A01247E71D00BC0EC4 /* WebPageMessageReceiver.cpp in Sources */, BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */, - 7CE9CE101FA0767A000177DE /* WebPageUpdatePreferences.cpp in Sources */, + C0CE72A01B47E71D00BC0EC4 /* WebPageTestingMessageReceiver.cpp in Sources */, diff --git a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp -index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748b64ce144 100644 +index a3444c240790680684a09a929f5ba07d6e68e793..6167b8d1fb42bef261aed6bb3e9581447decb1a9 100644 --- a/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp +++ b/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp @@ -233,6 +233,11 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou @@ -20541,7 +20923,30 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 #if ENABLE(PDFJS) if (tryLoadingUsingPDFJSHandler(resourceLoader, trackingParameters)) return; -@@ -366,7 +371,8 @@ static void addParametersShared(const LocalFrame* frame, NetworkResourceLoadPara +@@ -242,12 +247,16 @@ void WebLoaderStrategy::scheduleLoad(ResourceLoader& resourceLoader, CachedResou + return; + + if (InspectorInstrumentationWebKit::shouldInterceptRequest(resourceLoader)) { +- InspectorInstrumentationWebKit::interceptRequest(resourceLoader, [this, protectedResourceLoader = Ref { resourceLoader }, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, resource](const ResourceRequest& request) { +- auto& resourceLoader = protectedResourceLoader.get(); +- WEBLOADERSTRATEGY_RELEASE_LOG("scheduleLoad: intercepted URL will be scheduled with the NetworkProcess"); +- scheduleLoadFromNetworkProcess(resourceLoader, request, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource)); +- }); +- return; ++ bool isMainFrameNavigation = resourceLoader.frame() && resourceLoader.frame()->isMainFrame() && resourceLoader.options().mode == FetchOptions::Mode::Navigate; ++ // Do not intercept navigation request which could already have been intercepted and resumed. ++ if (!(isMainFrameNavigation && m_existingNetworkResourceLoadIdentifierToResume)) { ++ InspectorInstrumentationWebKit::interceptRequest(resourceLoader, [this, protectedResourceLoader = Ref { resourceLoader }, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, resource](const ResourceRequest& request) { ++ auto& resourceLoader = protectedResourceLoader.get(); ++ WEBLOADERSTRATEGY_RELEASE_LOG("scheduleLoad: intercepted URL will be scheduled with the NetworkProcess"); ++ scheduleLoadFromNetworkProcess(resourceLoader, request, trackingParameters, shouldClearReferrerOnHTTPSToHTTPRedirect, maximumBufferingTime(resource)); ++ }); ++ return; ++ } + } + + WEBLOADERSTRATEGY_RELEASE_LOG("scheduleLoad: URL will be scheduled with the NetworkProcess"); +@@ -366,7 +375,8 @@ static void addParametersShared(const LocalFrame* frame, NetworkResourceLoadPara parameters.linkPreconnectEarlyHintsEnabled = mainFrame->settings().linkPreconnectEarlyHintsEnabled(); } @@ -20551,7 +20956,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 { auto identifier = resourceLoader.identifier(); ASSERT(identifier); -@@ -382,7 +388,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -382,7 +392,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL RunLoop::main().dispatch([resourceLoader = Ref { resourceLoader }, error = blockedError(request)] { resourceLoader->didFail(error); }); @@ -20560,7 +20965,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 } } -@@ -392,7 +398,6 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -392,7 +402,6 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL LOG(NetworkScheduling, "(WebProcess) WebLoaderStrategy::scheduleLoad, url '%s' will be scheduled with the NetworkProcess with priority %d, storedCredentialsPolicy %i", resourceLoader.url().string().latin1().data(), static_cast(resourceLoader.request().priority()), (int)storedCredentialsPolicy); @@ -20568,7 +20973,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 loadParameters.identifier = identifier; loadParameters.webPageProxyID = trackingParameters.webPageProxyID; loadParameters.webPageID = trackingParameters.pageID; -@@ -482,14 +487,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -482,14 +491,11 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL if (loadParameters.options.mode != FetchOptions::Mode::Navigate) { ASSERT(loadParameters.sourceOrigin); @@ -20586,7 +20991,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 loadParameters.isMainFrameNavigation = isMainFrameNavigation; if (loadParameters.isMainFrameNavigation && document) -@@ -529,6 +531,17 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -529,6 +535,17 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL } ASSERT((loadParameters.webPageID && loadParameters.webFrameID) || loadParameters.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials); @@ -20604,7 +21009,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 std::optional existingNetworkResourceLoadIdentifierToResume; if (loadParameters.isMainFrameNavigation) -@@ -544,7 +557,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL +@@ -544,7 +561,7 @@ void WebLoaderStrategy::scheduleLoadFromNetworkProcess(ResourceLoader& resourceL } auto loader = WebResourceLoader::create(resourceLoader, trackingParameters); @@ -20613,7 +21018,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 } void WebLoaderStrategy::scheduleInternallyFailedLoad(WebCore::ResourceLoader& resourceLoader) -@@ -954,7 +967,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier +@@ -954,7 +971,7 @@ void WebLoaderStrategy::didFinishPreconnection(WebCore::ResourceLoaderIdentifier bool WebLoaderStrategy::isOnLine() const { @@ -20622,7 +21027,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 } void WebLoaderStrategy::addOnlineStateChangeListener(Function&& listener) -@@ -981,6 +994,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet +@@ -981,6 +998,11 @@ void WebLoaderStrategy::isResourceLoadFinished(CachedResource& resource, Complet void WebLoaderStrategy::setOnLineState(bool isOnLine) { @@ -20634,7 +21039,7 @@ index a3444c240790680684a09a929f5ba07d6e68e793..4b27fb80a9b81d91eb4e661c743f5748 if (m_isOnLine == isOnLine) return; -@@ -989,6 +1007,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) +@@ -989,6 +1011,12 @@ void WebLoaderStrategy::setOnLineState(bool isOnLine) listener(isOnLine); } @@ -20678,10 +21083,10 @@ index 3ef86cc236b8acee2fbe5d0b9c3fd755fcc9f06f..75951fc0fc5e4ef566582c0a49482793 } // namespace WebKit diff --git a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp -index 1707b38220552075313bac33a735756abad53ced..f7bd60794a52bb64c37a51ac34af379dfab0e976 100644 +index 17a0fe5d7a30883febe90e9984d36d8ea222872a..c3804fd499bdd3663e32318012f507af6b434aa7 100644 --- a/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp +++ b/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp -@@ -189,9 +189,6 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR +@@ -190,9 +190,6 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR } m_coreLoader->didReceiveResponse(inspectorResponse, [this, protectedThis = WTFMove(protectedThis), interceptedRequestIdentifier, policyDecisionCompletionHandler = WTFMove(policyDecisionCompletionHandler), overrideData = WTFMove(overrideData)]() mutable { @@ -20691,7 +21096,7 @@ index 1707b38220552075313bac33a735756abad53ced..f7bd60794a52bb64c37a51ac34af379d if (!m_coreLoader || !m_coreLoader->identifier()) { m_interceptController.continueResponse(interceptedRequestIdentifier); return; -@@ -209,6 +206,8 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR +@@ -210,6 +207,8 @@ void WebResourceLoader::didReceiveResponse(ResourceResponse&& response, PrivateR } }); }); @@ -20701,7 +21106,7 @@ index 1707b38220552075313bac33a735756abad53ced..f7bd60794a52bb64c37a51ac34af379d } diff --git a/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp b/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp -index ee9c3c4f48c328daaa015e2122235e51349bd999..5b3a4d3e742147195e0ff9e88176759df1b799db 100644 +index e314c2987e348a0abee8b655caff3a1c3b3c4564..882746d581bd8db6f2fad5944f09ee9fe9e0e55b 100644 --- a/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp +++ b/Source/WebKit/WebProcess/Notifications/NotificationPermissionRequestManager.cpp @@ -85,7 +85,7 @@ void NotificationPermissionRequestManager::startRequest(const SecurityOriginData @@ -20714,10 +21119,10 @@ index ee9c3c4f48c328daaa015e2122235e51349bd999..5b3a4d3e742147195e0ff9e88176759d auto permissionHandlers = m_requestsPerOrigin.take(securityOrigin); diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp -index d07821c8847c094bbce9e742f7dd4048b9d4d319..ab301c87d8ec84580e3e502427037440092aece4 100644 +index e22824697734a6fc65de8bdcf37afee5d5b1d508..1385b96bef6ab891d359e022974c77fc734ff18d 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp -@@ -471,6 +471,8 @@ void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel lev +@@ -472,6 +472,8 @@ void WebChromeClient::addMessageToConsole(MessageSource source, MessageLevel lev { // Notify the bundle client. auto page = protectedPage(); @@ -20750,13 +21155,13 @@ index 2eb0886f13ed035a53b8eaa60605de4dfe53fbe3..c3a216415ab588cde1f1e524e0a232ef { } diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -index 2c6c166b8f287a66e914722fe46e5f6400a4c1e2..980a5a9fb54c355d1766e8b7d4f944bb6792bb53 100644 +index 1fbb60e23b8d338f05ff0daa284724afafe29282..a15410b5b492254634e1aa300af405ba12ae8e80 100644 --- a/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp +++ b/Source/WebKit/WebProcess/WebCoreSupport/WebLocalFrameLoaderClient.cpp -@@ -1586,14 +1586,6 @@ void WebLocalFrameLoaderClient::transitionToCommittedForNewPage(InitializingIfra +@@ -1588,14 +1588,6 @@ void WebLocalFrameLoaderClient::transitionToCommittedForNewPage(InitializingIfra if (initializingIframe == InitializingIframe::No) - webPage->clearEditorStateAfterPageTransition(); + webPage->scheduleFullEditorStateUpdate(); - -#if USE(COORDINATED_GRAPHICS) - if (shouldUseFixedLayout) { @@ -20962,12 +21367,12 @@ index c0dd11d1a720907b1e2d863302a483eea1d39765..a4ad1b5acc545d98aea99c58fc5a5ca3 void DrawingAreaCoordinatedGraphics::scheduleDisplay() diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -index 9792a2310ecae603e83eefd602beab20c47d696c..2744b289afd8341f05d72a6c205d347fbdff4dd1 100644 +index d81997b98996b258f43ce13496ec06c6dc06d467..16e191b5ed4cf0e3b223fb9547699a05ede2f6d6 100644 --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp -@@ -193,8 +193,16 @@ void LayerTreeHost::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer) - void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect) - { +@@ -204,8 +204,16 @@ void LayerTreeHost::scrollNonCompositedContents(const IntRect& rect) + m_scrolledSinceLastFrame = true; + auto* frameView = m_webPage.localMainFrameView(); + +// Playwright begin @@ -20982,7 +21387,7 @@ index 9792a2310ecae603e83eefd602beab20c47d696c..2744b289afd8341f05d72a6c205d347f m_viewportController.didScroll(rect.location()); didChangeViewport(); -@@ -313,6 +321,10 @@ void LayerTreeHost::didChangeViewport() +@@ -325,6 +333,10 @@ void LayerTreeHost::didChangeViewport() if (!view->useFixedLayout()) view->notifyScrollPositionChanged(m_lastScrollPosition); @@ -20994,10 +21399,10 @@ index 9792a2310ecae603e83eefd602beab20c47d696c..2744b289afd8341f05d72a6c205d347f if (m_lastPageScaleFactor != pageScale) { diff --git a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h -index d2630055562da015318b5863de64693161bb1b58..a537e2d6db6a49698c5646ca7f9d2c20c6872692 100644 +index 468d6f8c574ea3298e502ce5776b624e295d863d..7039d3b26db1586e8c2a693b8cf5daa36088dd33 100644 --- a/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h +++ b/Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h -@@ -115,6 +115,13 @@ public: +@@ -116,6 +116,13 @@ public: #if PLATFORM(WPE) && USE(GBM) && ENABLE(WPE_PLATFORM) void preferredBufferFormatsDidChange(); #endif @@ -21090,10 +21495,18 @@ index b6e5283f51db82b60091320df44ef0bbf20c33c6..0d82fbb98b93e760cecf5fa7a41327d0 WebCookieJar(); diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp -index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f079f3489 100644 +index 8ed6c5c3f4bb342435f1ac6bb40020ba0fdd9364..2bbf3db029ab95cfda418fa39f2654db966dc2af 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp +++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp -@@ -1047,6 +1047,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) +@@ -233,6 +233,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1053,6 +1054,9 @@ WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters) #endif #endif // HAVE(SANDBOX_STATE_FLAGS) @@ -21103,7 +21516,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f updateThrottleState(); #if ENABLE(ACCESSIBILITY_ANIMATION_CONTROL) updateImageAnimationEnabled(); -@@ -2027,6 +2030,22 @@ void WebPage::loadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, st +@@ -2018,6 +2022,22 @@ void WebPage::loadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, st frame->loadDidCommitInAnotherProcess(layerHostingContextIdentifier); } @@ -21126,7 +21539,17 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f void WebPage::loadRequest(LoadParameters&& loadParameters) { WEBPAGE_RELEASE_LOG(Loading, "loadRequest: navigationID=%" PRIu64 ", shouldTreatAsContinuingLoad=%u, lastNavigationWasAppInitiated=%d, existingNetworkResourceLoadIdentifierToResume=%" PRIu64, loadParameters.navigationID, static_cast(loadParameters.shouldTreatAsContinuingLoad), loadParameters.request.isAppInitiated(), valueOrDefault(loadParameters.existingNetworkResourceLoadIdentifierToResume).toUInt64()); -@@ -2312,17 +2331,14 @@ void WebPage::setSize(const WebCore::IntSize& viewSize) +@@ -2200,7 +2220,9 @@ void WebPage::stopLoading() + void WebPage::stopLoadingDueToProcessSwap() + { + SetForScope isStoppingLoadingDueToProcessSwap(m_isStoppingLoadingDueToProcessSwap, true); ++ InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwap(m_page.get(), true); + stopLoading(); ++ InspectorInstrumentationWebKit::setStoppingLoadingDueToProcessSwap(m_page.get(), false); + } + + bool WebPage::defersLoading() const +@@ -2301,17 +2323,14 @@ void WebPage::setSize(const WebCore::IntSize& viewSize) view->resize(viewSize); m_drawingArea->setNeedsDisplay(); @@ -21144,7 +21567,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArguments) { RefPtr localMainFrame = dynamicDowncast(m_page->mainFrame()); -@@ -2347,20 +2363,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg +@@ -2336,20 +2355,18 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg ViewportAttributes attr = computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize); @@ -21172,7 +21595,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f #if USE(COORDINATED_GRAPHICS) m_drawingArea->didChangeViewportAttributes(WTFMove(attr)); -@@ -2368,7 +2382,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg +@@ -2357,7 +2374,6 @@ void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArg send(Messages::WebPageProxy::DidChangeViewportProperties(attr)); #endif } @@ -21180,7 +21603,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset) { -@@ -2670,6 +2683,7 @@ void WebPage::scaleView(double scale) +@@ -2659,6 +2675,7 @@ void WebPage::scaleView(double scale) } m_page->setViewScaleFactor(scale); @@ -21188,7 +21611,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f scalePage(pageScale, scrollPositionAtNewScale); } -@@ -2849,18 +2863,14 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum +@@ -2838,18 +2855,14 @@ void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArgum viewportConfigurationChanged(); #endif @@ -21208,7 +21631,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f } #if !PLATFORM(IOS_FAMILY) -@@ -3578,6 +3588,13 @@ void WebPage::setLastKnownMousePosition(WebCore::FrameIdentifier frameID, IntPoi +@@ -3571,6 +3584,13 @@ void WebPage::setLastKnownMousePosition(WebCore::FrameIdentifier frameID, IntPoi frame->coreLocalFrame()->eventHandler().setLastKnownMousePosition(eventPoint, globalPoint); } @@ -21221,8 +21644,8 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f + void WebPage::flushDeferredDidReceiveMouseEvent() { - if (auto info = std::exchange(m_deferredMouseEventCompletionHandler, std::nullopt)) -@@ -3862,6 +3879,97 @@ void WebPage::touchEvent(const WebTouchEvent& touchEvent, CompletionHandlersendMessageToTargetBackend(targetId, message); } @@ -21332,7 +21755,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f void WebPage::insertNewlineInQuotedContent() { RefPtr frame = m_page->checkedFocusController()->focusedOrMainFrame(); -@@ -4185,6 +4298,7 @@ void WebPage::didCompletePageTransition() +@@ -4178,6 +4294,7 @@ void WebPage::didCompletePageTransition() void WebPage::show() { send(Messages::WebPageProxy::ShowPage()); @@ -21340,7 +21763,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f } void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension) -@@ -5296,7 +5410,7 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana +@@ -5378,7 +5495,7 @@ NotificationPermissionRequestManager* WebPage::notificationPermissionRequestMana #if ENABLE(DRAG_SUPPORT) @@ -21349,7 +21772,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f void WebPage::performDragControllerAction(DragControllerAction action, const IntPoint& clientPosition, const IntPoint& globalPosition, OptionSet draggingSourceOperationMask, SelectionData&& selectionData, OptionSet flags, CompletionHandler, DragHandlingMethod, bool, unsigned, IntRect, IntRect, std::optional)>&& completionHandler) { if (!m_page) -@@ -7646,6 +7760,10 @@ void WebPage::didCommitLoad(WebFrame* frame) +@@ -7748,6 +7865,10 @@ void WebPage::didCommitLoad(WebFrame* frame) #endif flushDeferredDidReceiveMouseEvent(); @@ -21360,7 +21783,7 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f } void WebPage::didFinishDocumentLoad(WebFrame& frame) -@@ -7915,6 +8033,9 @@ Ref WebPage::createDocumentLoader(LocalFrame& frame, const Resou +@@ -8028,6 +8149,9 @@ Ref WebPage::createDocumentLoader(LocalFrame& frame, const Resou WebsitePoliciesData::applyToDocumentLoader(WTFMove(*m_pendingWebsitePolicies), documentLoader); m_pendingWebsitePolicies = std::nullopt; } @@ -21371,18 +21794,18 @@ index 302b6fc3639e3bfe5a3f7624c21c518a6e142781..2a799f3454f6d51712f27cbc0b86036f return documentLoader; diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h -index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57c664d616 100644 +index dade474046440584b2579c3c0e72d7daf9aafc68..35be816bd0ba41b6f6c31e4dec1906fbfe0533ee 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.h +++ b/Source/WebKit/WebProcess/WebPage/WebPage.h -@@ -70,6 +70,7 @@ - #include +@@ -71,6 +71,7 @@ #include #include + #include +#include #include #include #include -@@ -1155,11 +1156,11 @@ public: +@@ -1173,11 +1174,11 @@ public: void clearSelection(); void restoreSelectionInFocusedEditableElement(); @@ -21396,7 +21819,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 void performDragControllerAction(std::optional, DragControllerAction, WebCore::DragData&&, CompletionHandler, WebCore::DragHandlingMethod, bool, unsigned, WebCore::IntRect, WebCore::IntRect, std::optional)>&&); void performDragOperation(WebCore::DragData&&, SandboxExtension::Handle&&, Vector&&, CompletionHandler&&); #endif -@@ -1174,6 +1175,9 @@ public: +@@ -1192,6 +1193,9 @@ public: void didStartDrag(); void dragCancelled(); OptionSet allowedDragSourceActions() const { return m_allowedDragSourceActions; } @@ -21406,7 +21829,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 #endif void beginPrinting(WebCore::FrameIdentifier, const PrintInfo&); -@@ -1249,8 +1253,11 @@ public: +@@ -1267,8 +1271,11 @@ public: void gestureEvent(WebCore::FrameIdentifier, const WebGestureEvent&, CompletionHandler, bool, std::optional)>&&); #endif @@ -21419,7 +21842,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 void dynamicViewportSizeUpdate(const DynamicViewportSizeUpdate&); bool scaleWasSetByUIProcess() const { return m_scaleWasSetByUIProcess; } void willStartUserTriggeredZooming(); -@@ -1397,6 +1404,7 @@ public: +@@ -1415,6 +1422,7 @@ public: void connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType); void disconnectInspector(const String& targetId); void sendMessageToTargetBackend(const String& targetId, const String& message); @@ -21427,7 +21850,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 void insertNewlineInQuotedContent(); -@@ -1883,6 +1891,7 @@ private: +@@ -1921,6 +1929,7 @@ private: void createProvisionalFrame(ProvisionalFrameCreationParameters&&, WebCore::FrameIdentifier); void destroyProvisionalFrame(WebCore::FrameIdentifier); void loadDidCommitInAnotherProcess(WebCore::FrameIdentifier, std::optional); @@ -21435,7 +21858,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 void loadRequest(LoadParameters&&); [[noreturn]] void loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool); void loadData(LoadParameters&&); -@@ -1924,6 +1933,7 @@ private: +@@ -1962,6 +1971,7 @@ private: void updatePotentialTapSecurityOrigin(const WebTouchEvent&, bool wasHandled); #elif ENABLE(TOUCH_EVENTS) void touchEvent(const WebTouchEvent&, CompletionHandler, bool)>&&); @@ -21443,7 +21866,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 #endif void cancelPointer(WebCore::PointerID, const WebCore::IntPoint&); -@@ -2070,9 +2080,7 @@ private: +@@ -2108,9 +2118,7 @@ private: void addLayerForFindOverlay(CompletionHandler&&); void removeLayerForFindOverlay(CompletionHandler&&); @@ -21453,7 +21876,7 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex); void setTextForActivePopupMenu(int32_t index); -@@ -2676,6 +2684,7 @@ private: +@@ -2713,6 +2721,7 @@ private: UserActivity m_userActivity; uint64_t m_pendingNavigationID { 0 }; @@ -21462,12 +21885,12 @@ index 1cb204697117b143bd031cfd1a0ff8e7116864ba..1f8abf4d4dada0543b5aefc0b2640d57 bool m_mainFrameProgressCompleted { false }; diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in -index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0ddb1f9b0a8 100644 +index 148cbc222395ba878b51a233331e45e0e2d1604f..0bb93d61e68587cbd27e24fbef0eb875783ff8ff 100644 --- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in +++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in -@@ -55,10 +55,13 @@ messages -> WebPage LegacyReceiver { - ClearNotificationPermissionState() - #endif +@@ -51,10 +51,13 @@ messages -> WebPage LegacyReceiver { + MouseEvent(WebCore::FrameIdentifier frameID, WebKit::WebMouseEvent event, std::optional> sandboxExtensions) + SetLastKnownMousePosition(WebCore::FrameIdentifier frameID, WebCore::IntPoint eventPoint, WebCore::IntPoint globalPoint); +#if ENABLE(ORIENTATION_EVENTS) + SetDeviceOrientation(WebCore::IntDegrees deviceOrientation) @@ -21480,7 +21903,7 @@ index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0dd SetOverrideViewportArguments(std::optional arguments) DynamicViewportSizeUpdate(struct WebKit::DynamicViewportSizeUpdate target) -@@ -148,6 +151,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -144,6 +147,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType ConnectInspector(String targetId, Inspector::FrontendChannel::ConnectionType connectionType) DisconnectInspector(String targetId) SendMessageToTargetBackend(String targetId, String message) @@ -21488,7 +21911,7 @@ index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0dd #if ENABLE(REMOTE_INSPECTOR) SetIndicating(bool indicating); -@@ -158,6 +162,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -154,6 +158,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType #endif #if !ENABLE(IOS_TOUCH_EVENTS) && ENABLE(TOUCH_EVENTS) TouchEvent(WebKit::WebTouchEvent event) -> (std::optional eventType, bool handled) @@ -21496,7 +21919,7 @@ index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0dd #endif CancelPointer(WebCore::PointerID pointerId, WebCore::IntPoint documentPoint) -@@ -191,6 +196,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -187,6 +192,7 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType CreateProvisionalFrame(struct WebKit::ProvisionalFrameCreationParameters creationParameters, WebCore::FrameIdentifier frameID) DestroyProvisionalFrame(WebCore::FrameIdentifier frameID); LoadDidCommitInAnotherProcess(WebCore::FrameIdentifier frameID, std::optional layerHostingContextIdentifier) @@ -21504,7 +21927,7 @@ index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0dd LoadRequestWaitingForProcessLaunch(struct WebKit::LoadParameters loadParameters, URL resourceDirectoryURL, WebKit::WebPageProxyIdentifier pageID, bool checkAssumedReadAccessToResourceURL) LoadData(struct WebKit::LoadParameters loadParameters) LoadSimulatedRequestAndResponse(struct WebKit::LoadParameters loadParameters, WebCore::ResourceResponse simulatedResponse) -@@ -355,10 +361,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -351,10 +357,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType RemoveLayerForFindOverlay() -> () # Drag and drop. @@ -21517,7 +21940,7 @@ index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0dd PerformDragControllerAction(std::optional frameID, enum:uint8_t WebKit::DragControllerAction action, WebCore::DragData dragData) -> (std::optional dragOperation, enum:uint8_t WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, WebCore::IntRect insertionRect, WebCore::IntRect editableElementRect, struct std::optional remoteUserInputEventData) PerformDragOperation(WebCore::DragData dragData, WebKit::SandboxExtensionHandle sandboxExtensionHandle, Vector sandboxExtensionsForUpload) -> (bool handled) #endif -@@ -368,6 +374,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType +@@ -364,6 +370,10 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType DragCancelled() #endif @@ -21529,7 +21952,7 @@ index e1925f00bdbcabf1d9509a4dac169490000ef48d..75c54167747fc391179449ba22dda0dd RequestDragStart(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet allowedActionsMask) diff --git a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm -index a95a86568072d78053ccd8cf758aad9ba3f1bcc4..661923b01c15d9b3ec4b351d657c2e650642762d 100644 +index 678294ec1a7b6a05ed91730a723210a66af2f918..aafa6cfaff690bcbf6a69870576844f8894b8613 100644 --- a/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm +++ b/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm @@ -802,21 +802,37 @@ String WebPage::platformUserAgent(const URL&) const @@ -21621,7 +22044,7 @@ index f17f5d719d892309ed9c7093384945866b5117b9..1dba47bbf0dbd0362548423a74b38034 } diff --git a/Source/WebKit/WebProcess/WebProcess.cpp b/Source/WebKit/WebProcess/WebProcess.cpp -index fb283adec78aec2bc00f4db13f243bb814b84d5a..5e13f718081dc6da8c9105bcde23408c21bbed14 100644 +index df3c9d0ebbc3665c3ec4fcac259bee402ef19f45..9ff1d77c609c6b483eb3b9c620ef5742f5477069 100644 --- a/Source/WebKit/WebProcess/WebProcess.cpp +++ b/Source/WebKit/WebProcess/WebProcess.cpp @@ -88,6 +88,7 @@ @@ -21632,7 +22055,22 @@ index fb283adec78aec2bc00f4db13f243bb814b84d5a..5e13f718081dc6da8c9105bcde23408c #include #include #include -@@ -371,6 +372,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter +@@ -364,6 +365,14 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter + { + JSC::Options::AllowUnfinalizedAccessScope scope; + JSC::Options::allowNonSPTagging() = false; ++ // Playwright begin ++ // SharedBufferArray is enabled only on Mac via XPC sercvice "enable-shared-array-buffer" option. ++ // For other platforms, enable it here. ++#if !PLATFORM(COCOA) ++ if (parameters.shouldEnableSharedArrayBuffer) ++ JSC::Options::useSharedArrayBuffer() = true; ++#endif ++ // Playwright end + JSC::Options::notifyOptionsChanged(); + } + +@@ -371,6 +380,8 @@ void WebProcess::initializeProcess(const AuxiliaryProcessInitializationParameter platformInitializeProcess(parameters); updateCPULimit(); @@ -21657,10 +22095,10 @@ index 8987c3964a9308f2454759de7f8972215a3ae416..bcac0afeb94ed8123d1f9fb0b932c849 SetProcessDPIAware(); return true; diff --git a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm -index 7c01c6e5509f448a3ebdf10376ef2974403e37c0..7a9c9e3a197dc723e7a94dce5ddbddf05ba5111b 100644 +index d694170887445e2eed73340666bc4847aef4f9a6..6ced22d0953a39582285201e0946d68f954644ad 100644 --- a/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm +++ b/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm -@@ -4214,7 +4214,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END +@@ -4223,7 +4223,7 @@ ALLOW_DEPRECATED_DECLARATIONS_END _private->handlingMouseDownEvent = NO; } @@ -21723,7 +22161,7 @@ index 0000000000000000000000000000000000000000..dd6a53e2d57318489b7e49dd7373706d + LIBVPX_LIBRARIES +) diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake -index fa9c8766ea53612b9651e03375eb8b6bf4f15e76..621fb9f05c620f486feed36c4f23f66188a7ee88 100644 +index 7528273e7832716ef8cb900f89728d4003130d92..32826feac62d3d4132df79febd01b8a8b9ce16ff 100644 --- a/Source/cmake/OptionsGTK.cmake +++ b/Source/cmake/OptionsGTK.cmake @@ -11,8 +11,13 @@ if (${CMAKE_VERSION} VERSION_LESS "3.20" AND NOT ${CMAKE_GENERATOR} STREQUAL "Ni @@ -21780,14 +22218,14 @@ index fa9c8766ea53612b9651e03375eb8b6bf4f15e76..621fb9f05c620f486feed36c4f23f661 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ON) @@ -131,7 +140,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_CACHE_SPECULATIVE_REVALIDATION P WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_NETWORK_CACHE_STALE_WHILE_REVALIDATE PRIVATE ON) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) - WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS PRIVATE ON) + WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ON) -WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE ${ENABLE_DEVELOPER_MODE}) +WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_THUNDER PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PERIODIC_MEMORY_MONITOR PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_POINTER_LOCK PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON) -@@ -147,6 +156,14 @@ else () +@@ -149,6 +158,14 @@ else () WEBKIT_OPTION_DEFAULT_PORT_VALUE(USE_SKIA PRIVATE OFF) endif () @@ -21803,7 +22241,7 @@ index fa9c8766ea53612b9651e03375eb8b6bf4f15e76..621fb9f05c620f486feed36c4f23f661 # Finalize the value for all options. Do not attempt to use an option before diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake -index 8d5c7b97d0b717e4da818baaef1a681629332edb..df125a4c00c79daa73e9959a6b8b8fe0e3929e99 100644 +index a70706b67e0313e084eed2d1682ef85b296c80a6..21a610a7c0ddd838ed152bc1de4440ae4e6ff7ea 100644 --- a/Source/cmake/OptionsWPE.cmake +++ b/Source/cmake/OptionsWPE.cmake @@ -9,6 +9,8 @@ if (${CMAKE_VERSION} VERSION_LESS "3.20" AND NOT ${CMAKE_GENERATOR} STREQUAL "Ni @@ -21848,7 +22286,7 @@ index 8d5c7b97d0b717e4da818baaef1a681629332edb..df125a4c00c79daa73e9959a6b8b8fe0 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_SESSION_PLAYLIST PRIVATE OFF) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MEDIA_STREAM PRIVATE ON) -@@ -72,7 +77,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ${EN +@@ -72,7 +77,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_OFFSCREEN_CANVAS_IN_WORKERS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_PERIODIC_MEMORY_MONITOR PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SHAREABLE_RESOURCE PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_SPEECH_SYNTHESIS PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) @@ -21857,7 +22295,7 @@ index 8d5c7b97d0b717e4da818baaef1a681629332edb..df125a4c00c79daa73e9959a6b8b8fe0 WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_TOUCH_EVENTS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_VARIATION_FONTS PRIVATE ON) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_CODECS PRIVATE ON) -@@ -89,6 +94,23 @@ if (WPE_VERSION VERSION_GREATER_EQUAL 1.13.90) +@@ -91,6 +96,23 @@ if (WPE_VERSION VERSION_GREATER_EQUAL 1.13.90) WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_GAMEPAD PUBLIC ON) endif () @@ -21881,7 +22319,7 @@ index 8d5c7b97d0b717e4da818baaef1a681629332edb..df125a4c00c79daa73e9959a6b8b8fe0 # Public options specific to the WPE port. Do not add any options here unless # there is a strong reason we should support changing the value of the option, # and the option is not relevant to other WebKit ports. -@@ -98,7 +120,7 @@ WEBKIT_OPTION_DEFINE(ENABLE_JOURNALD_LOG "Whether to enable journald logging" PU +@@ -100,7 +122,7 @@ WEBKIT_OPTION_DEFINE(ENABLE_JOURNALD_LOG "Whether to enable journald logging" PU WEBKIT_OPTION_DEFINE(ENABLE_WPE_PLATFORM_DRM "Whether to enable support for DRM platform" PUBLIC ON) WEBKIT_OPTION_DEFINE(ENABLE_WPE_PLATFORM_HEADLESS "Whether to enable support for headless platform" PUBLIC ON) WEBKIT_OPTION_DEFINE(ENABLE_WPE_PLATFORM_WAYLAND "Whether to enable support for Wayland platform" PUBLIC ON) @@ -21891,10 +22329,10 @@ index 8d5c7b97d0b717e4da818baaef1a681629332edb..df125a4c00c79daa73e9959a6b8b8fe0 WEBKIT_OPTION_DEFINE(USE_ATK "Whether to enable usage of ATK." PUBLIC ON) WEBKIT_OPTION_DEFINE(USE_GBM "Whether to enable usage of GBM." PUBLIC ON) diff --git a/Source/cmake/OptionsWin.cmake b/Source/cmake/OptionsWin.cmake -index 92171930d24d199ebe5e7ff13252a6561ce57379..4d0b67710fa8a68dd604fb5c41ae16dd1a29e797 100644 +index 75b07257a0f116511fafc947e64f3f98f9086a82..5e65d3e455c9fb1f03551c4561e74247952a68e4 100644 --- a/Source/cmake/OptionsWin.cmake +++ b/Source/cmake/OptionsWin.cmake -@@ -86,6 +86,29 @@ find_package(ZLIB 1.2.11 REQUIRED) +@@ -67,6 +67,29 @@ find_package(ZLIB 1.2.11 REQUIRED) find_package(LibPSL 0.20.2 REQUIRED) find_package(WebP REQUIRED COMPONENTS demux) @@ -21924,7 +22362,7 @@ index 92171930d24d199ebe5e7ff13252a6561ce57379..4d0b67710fa8a68dd604fb5c41ae16dd WEBKIT_OPTION_BEGIN() # FIXME: Most of these options should not be public. -@@ -156,6 +179,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) +@@ -133,6 +156,14 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_FTPDIR PRIVATE OFF) SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_KEYBOARD_INTERACTIONS ON) SET_AND_EXPOSE_TO_BUILD(ENABLE_WEBDRIVER_MOUSE_INTERACTIONS ON) @@ -21940,7 +22378,7 @@ index 92171930d24d199ebe5e7ff13252a6561ce57379..4d0b67710fa8a68dd604fb5c41ae16dd set(USE_ANGLE_EGL ON) diff --git a/Source/cmake/WebKitCompilerFlags.cmake b/Source/cmake/WebKitCompilerFlags.cmake -index 4db77baa1f6f1b66a6c84e7577ee4169797b474b..cc57a3a95dcf7863aeeda489b25554f4172ca10b 100644 +index edac4df57e4da23a7cdf234eefc3879c35c607c2..df575fa5d0c8574a8b248362167e160704bab41c 100644 --- a/Source/cmake/WebKitCompilerFlags.cmake +++ b/Source/cmake/WebKitCompilerFlags.cmake @@ -122,7 +122,7 @@ macro(WEBKIT_ADD_TARGET_CXX_FLAGS _target) @@ -21953,7 +22391,7 @@ index 4db77baa1f6f1b66a6c84e7577ee4169797b474b..cc57a3a95dcf7863aeeda489b25554f4 if (MSVC) set(FATAL_WARNINGS_FLAG /WX) diff --git a/Tools/DumpRenderTree/DerivedSources.make b/Tools/DumpRenderTree/DerivedSources.make -index 57aae19f1a16d08ba1579562eeff264c8768af4d..6ce36f40cc954bd02b86f84bd9a0bd2928459938 100644 +index 576835410df6deac60f0158f1d2d1ef1e5f4c78d..9b492cfe5fef8de340a80f2af70a7d68672ef2e4 100644 --- a/Tools/DumpRenderTree/DerivedSources.make +++ b/Tools/DumpRenderTree/DerivedSources.make @@ -73,8 +73,8 @@ $(IDL_FILE_NAMES_LIST) : $(UICONTEXT_INTERFACES:%=%.idl) @@ -22022,7 +22460,7 @@ index 61616b96e2f4e21aa6d098445e0f1a933e512a9c..33732da18013679a869ff8eb2b445434 } diff --git a/Tools/MiniBrowser/gtk/BrowserWindow.c b/Tools/MiniBrowser/gtk/BrowserWindow.c -index f8f78a9b2e711d8250e770d73f0f7af6dc1520ed..101313a9ba3c1ddcfa10561d582ce485f0212765 100644 +index d39b809a879babcdbbf4b5f7687204df5ccc43f3..2862876cb515da09db653e71659d64215a636758 100644 --- a/Tools/MiniBrowser/gtk/BrowserWindow.c +++ b/Tools/MiniBrowser/gtk/BrowserWindow.c @@ -73,7 +73,7 @@ struct _BrowserWindowClass { @@ -22055,7 +22493,7 @@ index f8f78a9b2e711d8250e770d73f0f7af6dc1520ed..101313a9ba3c1ddcfa10561d582ce485 gtk_window_set_title(GTK_WINDOW(window), privateTitle ? privateTitle : title); g_free(privateTitle); } -@@ -520,8 +514,12 @@ static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision +@@ -524,8 +518,12 @@ static gboolean webViewDecidePolicy(WebKitWebView *webView, WebKitPolicyDecision return FALSE; WebKitNavigationAction *navigationAction = webkit_navigation_policy_decision_get_navigation_action(WEBKIT_NAVIGATION_POLICY_DECISION(decision)); @@ -22070,7 +22508,7 @@ index f8f78a9b2e711d8250e770d73f0f7af6dc1520ed..101313a9ba3c1ddcfa10561d582ce485 return FALSE; /* Multiple tabs are not allowed in editor mode. */ -@@ -1498,6 +1496,28 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event) +@@ -1502,6 +1500,28 @@ static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event) } #endif @@ -22099,7 +22537,7 @@ index f8f78a9b2e711d8250e770d73f0f7af6dc1520ed..101313a9ba3c1ddcfa10561d582ce485 static void browser_window_class_init(BrowserWindowClass *klass) { GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); -@@ -1511,6 +1531,19 @@ static void browser_window_class_init(BrowserWindowClass *klass) +@@ -1515,6 +1535,19 @@ static void browser_window_class_init(BrowserWindowClass *klass) GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass); widgetClass->delete_event = browserWindowDeleteEvent; #endif @@ -22333,10 +22771,10 @@ index 0dd4a639e69f52e674c6bbe257e35daabd25d077..1c0af52edd19d19d30136158f25ede26 g_clear_object(&interfaceSettings); diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp -index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1f03a8746 100644 +index d340d90d8d6650b8499cf5593df481e06a3178a3..8534bc30f863e4eafdb1cc7b205034d35bd3c0ff 100644 --- a/Tools/MiniBrowser/wpe/main.cpp +++ b/Tools/MiniBrowser/wpe/main.cpp -@@ -45,6 +45,9 @@ static gboolean headlessMode; +@@ -49,6 +49,9 @@ static gboolean headlessMode; static gboolean privateMode; static gboolean automationMode; static gboolean ignoreTLSErrors; @@ -22346,9 +22784,9 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 static const char* contentFilter; static const char* cookiesFile; static const char* cookiesPolicy; -@@ -78,6 +81,9 @@ static const GOptionEntry commandLineOptions[] = - { "use-wpe-platform-api", 0, 0, G_OPTION_ARG_NONE, &useWPEPlatformAPI, "Use the WPE platform API", nullptr }, +@@ -125,6 +128,9 @@ static const GOptionEntry commandLineOptions[] = #endif + { "size", 's', 0, G_OPTION_ARG_CALLBACK, reinterpret_cast(parseWindowSize), "Specify the window size to use, e.g. --size=\"800x600\"", nullptr }, { "version", 'v', 0, G_OPTION_ARG_NONE, &printVersion, "Print the WPE version", nullptr }, + { "inspector-pipe", 'v', 0, G_OPTION_ARG_NONE, &inspectorPipe, "Expose remote debugging protocol over pipe", nullptr }, + { "user-data-dir", 0, 0, G_OPTION_ARG_STRING, &userDataDir, "Default profile persistence folder location", "FILE" }, @@ -22356,7 +22794,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" }, { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr } }; -@@ -220,15 +226,38 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul +@@ -276,15 +282,38 @@ static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResul g_main_loop_quit(data->mainLoop); } @@ -22395,9 +22833,9 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 + +static WebKitWebView* createWebViewImpl(WebKitWebView* webView, WebKitWebContext *webContext, gpointer user_data) { - - auto backend = createViewBackend(1280, 720); -@@ -244,18 +273,37 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi + auto backend = createViewBackend(defaultWindowWidthLegacyAPI, defaultWindowHeightLegacyAPI); + WebKitWebViewBackend* viewBackend = nullptr; +@@ -299,12 +328,27 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi }, backend.release()); } @@ -22429,8 +22867,9 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 + nullptr)); + } - g_signal_connect(newWebView, "create", G_CALLBACK(createWebView), user_data); - g_signal_connect(newWebView, "close", G_CALLBACK(webViewClose), user_data); + #if ENABLE_WPE_PLATFORM + if (auto* wpeView = webkit_web_view_get_wpe_view(newWebView)) { +@@ -319,6 +363,10 @@ static WebKitWebView* createWebView(WebKitWebView* webView, WebKitNavigationActi g_hash_table_add(openViews, newWebView); @@ -22441,7 +22880,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 return newWebView; } -@@ -269,13 +317,89 @@ static WebKitFeature* findFeature(WebKitFeatureList* featureList, const char* id +@@ -376,13 +424,89 @@ static WebKitFeature* findFeature(WebKitFeatureList* featureList, const char* id return nullptr; } @@ -22532,7 +22971,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 webkit_network_session_set_itp_enabled(networkSession, enableITP); if (proxy) { -@@ -302,10 +426,18 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -409,10 +533,18 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* webkit_cookie_manager_set_persistent_storage(cookieManager, cookiesFile, storageType); } } @@ -22553,7 +22992,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 webkit_website_data_manager_set_itp_enabled(manager, enableITP); if (proxy) { -@@ -336,6 +468,7 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -443,6 +575,7 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* } #endif @@ -22561,7 +23000,7 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 WebKitUserContentManager* userContentManager = nullptr; if (contentFilter) { GFile* contentFilterFile = g_file_new_for_commandline_arg(contentFilter); -@@ -408,6 +541,15 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* +@@ -521,6 +654,15 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* "autoplay", WEBKIT_AUTOPLAY_ALLOW, nullptr); @@ -22577,16 +23016,16 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, "backend", viewBackend, "web-context", webContext, -@@ -436,8 +578,6 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* - g_signal_connect(wpeView, "event", G_CALLBACK(wpeViewEventCallback), webView); +@@ -565,8 +707,6 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* + } #endif - openViews = g_hash_table_new_full(nullptr, nullptr, g_object_unref, nullptr); - - webkit_web_context_set_automation_allowed(webContext, automationMode); g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView); g_signal_connect(webView, "permission-request", G_CALLBACK(decidePermissionRequest), nullptr); -@@ -450,16 +590,9 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* + g_signal_connect(webView, "create", G_CALLBACK(createWebView), application); +@@ -578,16 +718,11 @@ static void activate(GApplication* application, WPEToolingBackends::ViewBackend* webkit_web_view_set_background_color(webView, &color); if (uriArguments) { @@ -22599,14 +23038,16 @@ index 3c2476471ef67299da6312d0f995fc0738aa96c9..bdbc645f41d254e75ae8aba6eb2850c1 - g_object_unref(file); - webkit_web_view_load_uri(webView, url); - g_free(url); -- } else if (automationMode) +- } else if (!automationMode) + // Playwright: avoid weird url transformation like http://trac.webkit.org/r240840 + webkit_web_view_load_uri(webView, uriArguments[0]); + } else if (automationMode || inspectorPipe) - webkit_web_view_load_uri(webView, "about:blank"); - else ++ webkit_web_view_load_uri(webView, "about:blank"); ++ else webkit_web_view_load_uri(webView, "https://wpewebkit.org"); -@@ -533,8 +666,14 @@ int main(int argc, char *argv[]) + + g_object_unref(webContext); +@@ -683,8 +818,14 @@ int main(int argc, char *argv[]) } } @@ -22634,7 +23075,7 @@ index 1067b31bc989748dfcc5502209d36d001b9b239e..7629263fb8bc93dca6dfc01c75eed8d2 + add_subdirectory(Playwright/win) +endif () diff --git a/Tools/Scripts/build-webkit b/Tools/Scripts/build-webkit -index 39c351abbdd7b1b7f7016c5fd071ec2ae59b4a42..dc804e1d5284b15da6fa0679932d6cca8ece499a 100755 +index 39f91de9501cf38331ce567d30c9cefa25b28510..af2eeec87bb43f9ddfc6d583c35a8e7a87d5127c 100755 --- a/Tools/Scripts/build-webkit +++ b/Tools/Scripts/build-webkit @@ -273,7 +273,7 @@ if (isAppleCocoaWebKit()) { @@ -22662,7 +23103,7 @@ index 9e53f459e444b9c10fc5248f0e8059df6c1e0041..c17c875a7dd3ca05c4489578ab32378b "${WebKitTestRunner_DIR}/InjectedBundle/Bindings/AccessibilityController.idl" "${WebKitTestRunner_DIR}/InjectedBundle/Bindings/AccessibilityTextMarker.idl" diff --git a/Tools/WebKitTestRunner/TestController.cpp b/Tools/WebKitTestRunner/TestController.cpp -index 02656db352f2d52dd24e7886e9119edb562be1c1..21366de86e0c2caeb9c040cd9f9f5b966b29438b 100644 +index 076ad1f7005f732f8529955cfe3b6a8dd5212949..dee6f57eb5fff12de9cdaad230e894b0b9b15b88 100644 --- a/Tools/WebKitTestRunner/TestController.cpp +++ b/Tools/WebKitTestRunner/TestController.cpp @@ -964,6 +964,7 @@ void TestController::createWebViewWithOptions(const TestOptions& options) From 5127efdc2a4f9b78e34fe3bd6f2a3edc1fab5a73 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 5 Sep 2024 05:57:20 -0700 Subject: [PATCH 004/805] feat(chromium): roll to r1134 (#32470) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 4 +- packages/playwright-core/browsers.json | 4 +- .../src/server/deviceDescriptorsSource.json | 96 +++++++++---------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 5d21174879b8c..48c001491445b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-129.0.6668.22-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-130.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-129.0.6668.29-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-130.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 129.0.6668.22 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 129.0.6668.29 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 130.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 0fa17af4f0c7c..0ea21f1ecca6d 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,9 +3,9 @@ "browsers": [ { "name": "chromium", - "revision": "1133", + "revision": "1134", "installByDefault": true, - "browserVersion": "129.0.6668.22" + "browserVersion": "129.0.6668.29" }, { "name": "chromium-tip-of-tree", diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index c2bca627fb099..384f6f2377db7 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -110,7 +110,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S5": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -121,7 +121,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -132,7 +132,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 360, "height": 740 @@ -143,7 +143,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 740, "height": 360 @@ -154,7 +154,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 320, "height": 658 @@ -165,7 +165,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+ landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 658, "height": 320 @@ -176,7 +176,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "viewport": { "width": 712, "height": 1138 @@ -187,7 +187,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -1098,7 +1098,7 @@ "defaultBrowserType": "webkit" }, "LG Optimus L70": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,7 @@ "defaultBrowserType": "chromium" }, "LG Optimus L70 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,7 @@ "defaultBrowserType": "webkit" }, "Pixel 2": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36 Edg/129.0.6668.22", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36 Edg/129.0.6668.29", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36 Edg/129.0.6668.22", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36 Edg/129.0.6668.29", "screen": { "width": 1920, "height": 1080 From d4c77ce260141ed4ed51f7552cfdf6e8b69e699d Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 5 Sep 2024 06:52:11 -0700 Subject: [PATCH 005/805] chore: make find-related-test-files work through plugins (#32465) Also switches it to the task runner. --- packages/playwright-ct-core/index.js | 3 +- .../playwright-ct-core/src/cliOverrides.ts | 8 +- packages/playwright/src/program.ts | 3 +- packages/playwright/src/runner/reporters.ts | 16 +++- packages/playwright/src/runner/runner.ts | 51 ++++--------- packages/playwright/src/runner/tasks.ts | 19 ++++- packages/playwright/src/runner/testServer.ts | 27 ++++--- .../find-related-tests.spec.ts | 20 ++++- tests/playwright-test/test-server.spec.ts | 73 ++++++++++++++----- 9 files changed, 136 insertions(+), 84 deletions(-) diff --git a/packages/playwright-ct-core/index.js b/packages/playwright-ct-core/index.js index 9583273ac2eed..e11dd84ace7e4 100644 --- a/packages/playwright-ct-core/index.js +++ b/packages/playwright-ct-core/index.js @@ -16,7 +16,7 @@ const { test: baseTest, expect, devices, defineConfig: originalDefineConfig } = require('playwright/test'); const { fixtures } = require('./lib/mount'); -const { clearCacheCommand, findRelatedTestFilesCommand } = require('./lib/cliOverrides'); +const { clearCacheCommand } = require('./lib/cliOverrides'); const { createPlugin } = require('./lib/vitePlugin'); const defineConfig = (...configs) => { @@ -31,7 +31,6 @@ const defineConfig = (...configs) => { ], cli: { 'clear-cache': clearCacheCommand, - 'find-related-test-files': findRelatedTestFilesCommand, }, } }; diff --git a/packages/playwright-ct-core/src/cliOverrides.ts b/packages/playwright-ct-core/src/cliOverrides.ts index 1b069a7177d62..3173ce7f9dc6f 100644 --- a/packages/playwright-ct-core/src/cliOverrides.ts +++ b/packages/playwright-ct-core/src/cliOverrides.ts @@ -15,8 +15,7 @@ * limitations under the License. */ -import { affectedTestFiles, cacheDir } from 'playwright/lib/transform/compilationCache'; -import { buildBundle } from './vitePlugin'; +import { cacheDir } from 'playwright/lib/transform/compilationCache'; import { resolveDirs } from './viteUtils'; import type { FullConfigInternal } from 'playwright/lib/common/config'; import { removeFolderAndLogToConsole } from 'playwright/lib/runner/testServer'; @@ -27,8 +26,3 @@ export async function clearCacheCommand(config: FullConfigInternal) { await removeFolderAndLogToConsole(dirs.outDir); await removeFolderAndLogToConsole(cacheDir); } - -export async function findRelatedTestFilesCommand(files: string[], config: FullConfigInternal) { - await buildBundle(config.config, config.configDir); - return { testFiles: affectedTestFiles(files) }; -} diff --git a/packages/playwright/src/program.ts b/packages/playwright/src/program.ts index 5d1f687e1e1fa..349915c47b4e5 100644 --- a/packages/playwright/src/program.ts +++ b/packages/playwright/src/program.ts @@ -86,7 +86,8 @@ function addFindRelatedTestFilesCommand(program: Command) { command.description('Returns the list of related tests to the given files'); command.option('-c, --config ', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`); command.action(async (files, options) => { - await withRunnerAndMutedWrite(options.config, runner => runner.findRelatedTestFiles('in-process', files)); + const resolvedFiles = (files as string[]).map(file => path.resolve(process.cwd(), file)); + await withRunnerAndMutedWrite(options.config, runner => runner.findRelatedTestFiles(resolvedFiles)); }); } diff --git a/packages/playwright/src/runner/reporters.ts b/packages/playwright/src/runner/reporters.ts index 5b7d3a83cbbb5..4a2b3f970e7e3 100644 --- a/packages/playwright/src/runner/reporters.ts +++ b/packages/playwright/src/runner/reporters.ts @@ -86,12 +86,22 @@ export async function createReporterForTestServer(file: string, messageSink: (me })); } -export function createConsoleReporter() { - return wrapReporterAsV2({ +interface ErrorCollectingReporter extends ReporterV2 { + errors(): TestError[]; +} + +export function createErrorCollectingReporter(writeToConsole?: boolean): ErrorCollectingReporter { + const errors: TestError[] = []; + const reporterV2 = wrapReporterAsV2({ onError(error: TestError) { - process.stdout.write(formatError(error, colors.enabled).message + '\n'); + errors.push(error); + if (writeToConsole) + process.stdout.write(formatError(error, colors.enabled).message + '\n'); } }); + const reporter = reporterV2 as ErrorCollectingReporter; + reporter.errors = () => errors; + return reporter; } function reporterOptions(config: FullConfigInternal, mode: 'list' | 'test' | 'merge', isTestServer: boolean) { diff --git a/packages/playwright/src/runner/runner.ts b/packages/playwright/src/runner/runner.ts index 2b762f9350619..a58276ac260aa 100644 --- a/packages/playwright/src/runner/runner.ts +++ b/packages/playwright/src/runner/runner.ts @@ -21,11 +21,9 @@ import { monotonicTime } from 'playwright-core/lib/utils'; import type { FullResult, TestError } from '../../types/testReporter'; import { webServerPluginsForConfig } from '../plugins/webServerPlugin'; import { collectFilesForProject, filterProjects } from './projectUtils'; -import { createConsoleReporter, createReporters } from './reporters'; -import { TestRun, createTaskRunner, createTaskRunnerForDevServer, createTaskRunnerForList } from './tasks'; +import { createErrorCollectingReporter, createReporters } from './reporters'; +import { TestRun, createTaskRunner, createTaskRunnerForDevServer, createTaskRunnerForList, createTaskRunnerForRelatedTestFiles } from './tasks'; import type { FullConfigInternal } from '../common/config'; -import type { Suite } from '../common/test'; -import { wrapReporterAsV2 } from '../reporters/reporterV2'; import { affectedTestFiles } from '../transform/compilationCache'; import { InternalReporter } from '../reporters/internalReporter'; @@ -109,43 +107,22 @@ export class Runner { return status; } - async loadAllTests(mode: 'in-process' | 'out-of-process' = 'in-process'): Promise<{ status: FullResult['status'], suite?: Suite, errors: TestError[] }> { - const config = this._config; - const errors: TestError[] = []; - const reporter = new InternalReporter([wrapReporterAsV2({ - onError(error: TestError) { - errors.push(error); - } - })]); - const taskRunner = createTaskRunnerForList(config, reporter, mode, { failOnLoadErrors: true }); - const testRun = new TestRun(config); - reporter.onConfigure(config.config); - - const taskStatus = await taskRunner.run(testRun, 0); - let status: FullResult['status'] = testRun.failureTracker.result(); - if (status === 'passed' && taskStatus !== 'passed') - status = taskStatus; - const modifiedResult = await reporter.onEnd({ status }); - if (modifiedResult && modifiedResult.status) - status = modifiedResult.status; + async findRelatedTestFiles(files: string[]): Promise { + const errorReporter = createErrorCollectingReporter(); + const reporter = new InternalReporter([errorReporter]); + const taskRunner = createTaskRunnerForRelatedTestFiles(this._config, reporter, 'in-process', true); + const testRun = new TestRun(this._config); + reporter.onConfigure(this._config.config); + const status = await taskRunner.run(testRun, 0); + await reporter.onEnd({ status }); await reporter.onExit(); - return { status, suite: testRun.rootSuite, errors }; - } - - async findRelatedTestFiles(mode: 'in-process' | 'out-of-process', files: string[]): Promise { - const result = await this.loadAllTests(mode); - if (result.status !== 'passed' || !result.suite) - return { errors: result.errors, testFiles: [] }; - - const resolvedFiles = (files as string[]).map(file => path.resolve(process.cwd(), file)); - const override = (this._config.config as any)['@playwright/test']?.['cli']?.['find-related-test-files']; - if (override) - return await override(resolvedFiles, this._config); - return { testFiles: affectedTestFiles(resolvedFiles) }; + if (status !== 'passed') + return { errors: errorReporter.errors(), testFiles: [] }; + return { testFiles: affectedTestFiles(files) }; } async runDevServer() { - const reporter = new InternalReporter([createConsoleReporter()]); + const reporter = new InternalReporter([createErrorCollectingReporter(true)]); const taskRunner = createTaskRunnerForDevServer(this._config, reporter, 'in-process', true); const testRun = new TestRun(this._config); reporter.onConfigure(this._config.config); diff --git a/packages/playwright/src/runner/tasks.ts b/packages/playwright/src/runner/tasks.ts index b90b02904f99a..8f94a8d19a6a1 100644 --- a/packages/playwright/src/runner/tasks.ts +++ b/packages/playwright/src/runner/tasks.ts @@ -129,6 +129,16 @@ export function createTaskRunnerForDevServer(config: FullConfigInternal, reporte return taskRunner; } +export function createTaskRunnerForRelatedTestFiles(config: FullConfigInternal, reporter: InternalReporter, mode: 'in-process' | 'out-of-process', setupPlugins: boolean): TaskRunner { + const taskRunner = TaskRunner.create(reporter, config.config.globalTimeout); + if (setupPlugins) { + for (const plugin of config.plugins) + taskRunner.addTask('plugin setup', createPluginSetupTask(plugin)); + } + taskRunner.addTask('load tests', createLoadTask(mode, { failOnLoadErrors: true, filterOnly: false, populateDependencies: true })); + return taskRunner; +} + function createReportBeginTask(): Task { return { setup: async (reporter, { rootSuite }) => { @@ -231,16 +241,19 @@ function createListFilesTask(): Task { }; } -function createLoadTask(mode: 'out-of-process' | 'in-process', options: { filterOnly: boolean, failOnLoadErrors: boolean, doNotRunDepsOutsideProjectFilter?: boolean }): Task { +function createLoadTask(mode: 'out-of-process' | 'in-process', options: { filterOnly: boolean, failOnLoadErrors: boolean, doNotRunDepsOutsideProjectFilter?: boolean, populateDependencies?: boolean }): Task { return { setup: async (reporter, testRun, errors, softErrors) => { await collectProjectsAndTestFiles(testRun, !!options.doNotRunDepsOutsideProjectFilter); await loadFileSuites(testRun, mode, options.failOnLoadErrors ? errors : softErrors); - let cliOnlyChangedMatcher: Matcher | undefined = undefined; - if (testRun.config.cliOnlyChanged) { + if (testRun.config.cliOnlyChanged || options.populateDependencies) { for (const plugin of testRun.config.plugins) await plugin.instance?.populateDependencies?.(); + } + + let cliOnlyChangedMatcher: Matcher | undefined = undefined; + if (testRun.config.cliOnlyChanged) { const changedFiles = await detectChangedTestFiles(testRun.config.cliOnlyChanged, testRun.config.configDir); cliOnlyChangedMatcher = file => changedFiles.has(file); } diff --git a/packages/playwright/src/runner/testServer.ts b/packages/playwright/src/runner/testServer.ts index f0444cbc4305b..cd6b7ca0ce7fa 100644 --- a/packages/playwright/src/runner/testServer.ts +++ b/packages/playwright/src/runner/testServer.ts @@ -20,16 +20,15 @@ import { installRootRedirect, openTraceInBrowser, openTraceViewerApp, registry, import { ManualPromise, gracefullyProcessExitDoNotHang, isUnderTest } from 'playwright-core/lib/utils'; import type { Transport, HttpServer } from 'playwright-core/lib/utils'; import type * as reporterTypes from '../../types/testReporter'; -import { collectAffectedTestFiles, dependenciesForTestFile } from '../transform/compilationCache'; +import { affectedTestFiles, collectAffectedTestFiles, dependenciesForTestFile } from '../transform/compilationCache'; import type { ConfigLocation, FullConfigInternal } from '../common/config'; -import { createReporterForTestServer, createReporters } from './reporters'; -import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer, createTaskRunnerForWatchSetup, createTaskRunnerForListFiles, createTaskRunnerForDevServer } from './tasks'; +import { createErrorCollectingReporter, createReporterForTestServer, createReporters } from './reporters'; +import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer, createTaskRunnerForWatchSetup, createTaskRunnerForListFiles, createTaskRunnerForDevServer, createTaskRunnerForRelatedTestFiles } from './tasks'; import { open } from 'playwright-core/lib/utilsBundle'; import ListReporter from '../reporters/list'; import { SigIntWatcher } from './sigIntWatcher'; import { Watcher } from '../fsWatcher'; import type { ReportEntry, TestServerInterface, TestServerInterfaceEventEmitters } from '../isomorphic/testServerInterface'; -import { Runner } from './runner'; import type { ConfigCLIOverrides } from '../common/ipc'; import { loadConfig, resolveConfigLocation, restartWithExperimentalTsEsm } from '../common/configLoader'; import { webServerPluginsForConfig } from '../plugins/webServerPlugin'; @@ -362,11 +361,21 @@ export class TestServerDispatcher implements TestServerInterface { } async findRelatedTestFiles(params: Parameters[0]): ReturnType { - const { config, error } = await this._loadConfig(); - if (error) - return { testFiles: [], errors: [error] }; - const runner = new Runner(config!); - return runner.findRelatedTestFiles('out-of-process', params.files); + const errorReporter = createErrorCollectingReporter(); + const reporter = new InternalReporter([errorReporter]); + const config = await this._loadConfigOrReportError(reporter); + if (!config) + return { errors: errorReporter.errors(), testFiles: [] }; + + const taskRunner = createTaskRunnerForRelatedTestFiles(config, reporter, 'out-of-process', false); + const testRun = new TestRun(config); + reporter.onConfigure(config.config); + const status = await taskRunner.run(testRun, 0); + await reporter.onEnd({ status }); + await reporter.onExit(); + if (status !== 'passed') + return { errors: errorReporter.errors(), testFiles: [] }; + return { testFiles: affectedTestFiles(params.files) }; } async stopTests() { diff --git a/tests/playwright-test/find-related-tests.spec.ts b/tests/playwright-test/find-related-tests.spec.ts index 981395ade1f2f..66c7af012262e 100644 --- a/tests/playwright-test/find-related-tests.spec.ts +++ b/tests/playwright-test/find-related-tests.spec.ts @@ -15,9 +15,6 @@ */ import { test, expect } from './playwright-test-fixtures'; -import path from 'path'; - -export const ctReactCliEntrypoint = path.join(__dirname, '../../packages/playwright-ct-react/cli.js'); test('should list related tests', async ({ runCLICommand }) => { const result = await runCLICommand({ @@ -77,7 +74,7 @@ test('should list related tests for ct', async ({ runCLICommand }) => { await mount(; + `, + 'src/button.test.tsx': ` + import { test, expect } from '@playwright/experimental-ct-react'; + import { Button } from './button'; + + test('pass', async ({ mount }) => { + const component = await mount(); + await expect(component).toHaveText('Button', { timeout: 1 }); + }); + `, +}; + test('file watching', async ({ startTestServer, writeFiles }, testInfo) => { await writeFiles({ 'utils.ts': ` @@ -125,23 +143,7 @@ test('stdio interception', async ({ startTestServer, writeFiles }) => { }); test('start dev server', async ({ startTestServer, writeFiles, runInlineTest }) => { - await writeFiles({ - 'playwright.config.ts': playwrightCtConfigText, - 'playwright/index.html': ``, - 'playwright/index.ts': ``, - 'src/button.tsx': ` - export const Button = () => ; - `, - 'src/button.test.tsx': ` - import { test, expect } from '@playwright/experimental-ct-react'; - import { Button } from './button'; - - test('pass', async ({ mount }) => { - const component = await mount(); - await expect(component).toHaveText('Button', { timeout: 1 }); - }); - `, - }); + await writeFiles(ctFiles); const testServerConnection = await startTestServer(); await testServerConnection.initialize({ interceptStdio: true }); @@ -156,3 +158,38 @@ test('start dev server', async ({ startTestServer, writeFiles, runInlineTest }) expect((await testServerConnection.stopDevServer({})).status).toBe('passed'); expect((await testServerConnection.runGlobalTeardown({})).status).toBe('passed'); }); + +test('find related test files errors', async ({ startTestServer, writeFiles }) => { + await writeFiles({ + 'a.spec.ts': ` + const a = 1; + const a = 2; + `, + }); + const testServerConnection = await startTestServer(); + await testServerConnection.initialize({ interceptStdio: true }); + expect((await testServerConnection.runGlobalSetup({})).status).toBe('passed'); + + const aSpecTs = test.info().outputPath('a.spec.ts'); + const result = await testServerConnection.findRelatedTestFiles({ files: [aSpecTs] }); + expect(result).toEqual({ testFiles: [], errors: [ + expect.objectContaining({ message: expect.stringContaining(`Identifier 'a' has already been declared`) }), + expect.objectContaining({ message: expect.stringContaining(`No tests found`) }), + ] }); + + expect((await testServerConnection.runGlobalTeardown({})).status).toBe('passed'); +}); + +test('find related test files', async ({ startTestServer, writeFiles }) => { + await writeFiles(ctFiles); + const testServerConnection = await startTestServer(); + await testServerConnection.initialize({ interceptStdio: true }); + expect((await testServerConnection.runGlobalSetup({})).status).toBe('passed'); + + const buttonTsx = test.info().outputPath('src/button.tsx'); + const buttonTestTsx = test.info().outputPath('src/button.test.tsx'); + const result = await testServerConnection.findRelatedTestFiles({ files: [buttonTsx] }); + expect(result).toEqual({ testFiles: [buttonTestTsx] }); + + expect((await testServerConnection.runGlobalTeardown({})).status).toBe('passed'); +}); From 1ba3db68641cf8412f4d90d8dee840ea18620776 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 5 Sep 2024 13:50:16 -0700 Subject: [PATCH 006/805] chore: implement clear-cache through plugins (#32471) Also switches it to task runner. --- packages/playwright-ct-core/index.js | 4 -- .../playwright-ct-core/src/cliOverrides.ts | 28 -------------- packages/playwright-ct-core/src/vitePlugin.ts | 8 ++++ packages/playwright/package.json | 2 - packages/playwright/src/plugins/index.ts | 1 + packages/playwright/src/program.ts | 10 +++-- packages/playwright/src/runner/runner.ts | 13 ++++++- packages/playwright/src/runner/tasks.ts | 19 +++++++++- packages/playwright/src/runner/testServer.ts | 37 ++++++------------- packages/playwright/src/util.ts | 11 ++++++ tests/playwright-test/clear-cache.spec.ts | 5 +-- .../playwright-test-fixtures.ts | 10 ++--- tests/playwright-test/test-server.spec.ts | 9 +++++ 13 files changed, 83 insertions(+), 74 deletions(-) delete mode 100644 packages/playwright-ct-core/src/cliOverrides.ts diff --git a/packages/playwright-ct-core/index.js b/packages/playwright-ct-core/index.js index e11dd84ace7e4..1a4f185a3177a 100644 --- a/packages/playwright-ct-core/index.js +++ b/packages/playwright-ct-core/index.js @@ -16,7 +16,6 @@ const { test: baseTest, expect, devices, defineConfig: originalDefineConfig } = require('playwright/test'); const { fixtures } = require('./lib/mount'); -const { clearCacheCommand } = require('./lib/cliOverrides'); const { createPlugin } = require('./lib/vitePlugin'); const defineConfig = (...configs) => { @@ -29,9 +28,6 @@ const defineConfig = (...configs) => { babelPlugins: [ [require.resolve('./lib/tsxTransform')] ], - cli: { - 'clear-cache': clearCacheCommand, - }, } }; }; diff --git a/packages/playwright-ct-core/src/cliOverrides.ts b/packages/playwright-ct-core/src/cliOverrides.ts deleted file mode 100644 index 3173ce7f9dc6f..0000000000000 --- a/packages/playwright-ct-core/src/cliOverrides.ts +++ /dev/null @@ -1,28 +0,0 @@ - -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { cacheDir } from 'playwright/lib/transform/compilationCache'; -import { resolveDirs } from './viteUtils'; -import type { FullConfigInternal } from 'playwright/lib/common/config'; -import { removeFolderAndLogToConsole } from 'playwright/lib/runner/testServer'; - -export async function clearCacheCommand(config: FullConfigInternal) { - const dirs = await resolveDirs(config.configDir, config.config); - if (dirs) - await removeFolderAndLogToConsole(dirs.outDir); - await removeFolderAndLogToConsole(cacheDir); -} diff --git a/packages/playwright-ct-core/src/vitePlugin.ts b/packages/playwright-ct-core/src/vitePlugin.ts index f954fcd2b2356..462730c61ca21 100644 --- a/packages/playwright-ct-core/src/vitePlugin.ts +++ b/packages/playwright-ct-core/src/vitePlugin.ts @@ -32,6 +32,7 @@ import type { ComponentRegistry } from './viteUtils'; import { createConfig, frameworkConfig, hasJSComponents, populateComponentsFromTests, resolveDirs, resolveEndpoint, transformIndexFile } from './viteUtils'; import { resolveHook } from 'playwright/lib/transform/transform'; import { runDevServer } from './devServer'; +import { removeDirAndLogToConsole } from 'playwright/lib/util'; const log = debug('pw:vite'); @@ -78,6 +79,13 @@ export function createPlugin(): TestRunnerPlugin { startDevServer: async () => { return await runDevServer(config); }, + + clearCache: async () => { + const configDir = config.configFile ? path.dirname(config.configFile) : config.rootDir; + const dirs = await resolveDirs(configDir, config); + if (dirs) + await removeDirAndLogToConsole(dirs.outDir); + }, }; } diff --git a/packages/playwright/package.json b/packages/playwright/package.json index 519c33171cbd8..16c3bd24c777d 100644 --- a/packages/playwright/package.json +++ b/packages/playwright/package.json @@ -24,8 +24,6 @@ "./lib/program": "./lib/program.js", "./lib/transform/babelBundle": "./lib/transform/babelBundle.js", "./lib/transform/compilationCache": "./lib/transform/compilationCache.js", - "./lib/runner/runner": "./lib/runner/runner.js", - "./lib/runner/testServer": "./lib/runner/testServer.js", "./lib/transform/esmLoader": "./lib/transform/esmLoader.js", "./lib/transform/transform": "./lib/transform/transform.js", "./lib/internalsForTest": "./lib/internalsForTest.js", diff --git a/packages/playwright/src/plugins/index.ts b/packages/playwright/src/plugins/index.ts index c3b6f52bf4e4d..2f7995cb2ffbe 100644 --- a/packages/playwright/src/plugins/index.ts +++ b/packages/playwright/src/plugins/index.ts @@ -22,6 +22,7 @@ export interface TestRunnerPlugin { setup?(config: FullConfig, configDir: string, reporter: ReporterV2): Promise; populateDependencies?(): Promise; startDevServer?(): Promise<() => Promise>; + clearCache?(): Promise; begin?(suite: Suite): Promise; end?(): Promise; teardown?(): Promise; diff --git a/packages/playwright/src/program.ts b/packages/playwright/src/program.ts index 349915c47b4e5..e57c0a3328dd9 100644 --- a/packages/playwright/src/program.ts +++ b/packages/playwright/src/program.ts @@ -34,7 +34,6 @@ export { program } from 'playwright-core/lib/cli/program'; import type { ReporterDescription } from '../types/test'; import { prepareErrorStack } from './reporters/base'; import * as testServer from './runner/testServer'; -import { clearCacheAndLogToConsole } from './runner/testServer'; import { runWatchModeLoop } from './runner/watchMode'; function addTestCommand(program: Command) { @@ -74,10 +73,13 @@ function addClearCacheCommand(program: Command) { command.description('clears build and test caches'); command.option('-c, --config ', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`); command.action(async opts => { - const configInternal = await loadConfigFromFileRestartIfNeeded(opts.config); - if (!configInternal) + const config = await loadConfigFromFileRestartIfNeeded(opts.config); + if (!config) return; - await clearCacheAndLogToConsole(configInternal); + const runner = new Runner(config); + const { status } = await runner.clearCache(); + const exitCode = status === 'interrupted' ? 130 : (status === 'passed' ? 0 : 1); + gracefullyProcessExitDoNotHang(exitCode); }); } diff --git a/packages/playwright/src/runner/runner.ts b/packages/playwright/src/runner/runner.ts index a58276ac260aa..2744fd273070e 100644 --- a/packages/playwright/src/runner/runner.ts +++ b/packages/playwright/src/runner/runner.ts @@ -22,7 +22,7 @@ import type { FullResult, TestError } from '../../types/testReporter'; import { webServerPluginsForConfig } from '../plugins/webServerPlugin'; import { collectFilesForProject, filterProjects } from './projectUtils'; import { createErrorCollectingReporter, createReporters } from './reporters'; -import { TestRun, createTaskRunner, createTaskRunnerForDevServer, createTaskRunnerForList, createTaskRunnerForRelatedTestFiles } from './tasks'; +import { TestRun, createTaskRunner, createTaskRunnerForClearCache, createTaskRunnerForDevServer, createTaskRunnerForList, createTaskRunnerForRelatedTestFiles } from './tasks'; import type { FullConfigInternal } from '../common/config'; import { affectedTestFiles } from '../transform/compilationCache'; import { InternalReporter } from '../reporters/internalReporter'; @@ -131,6 +131,17 @@ export class Runner { await reporter.onExit(); return { status }; } + + async clearCache() { + const reporter = new InternalReporter([createErrorCollectingReporter(true)]); + const taskRunner = createTaskRunnerForClearCache(this._config, reporter, 'in-process', true); + const testRun = new TestRun(this._config); + reporter.onConfigure(this._config.config); + const status = await taskRunner.run(testRun, 0); + await reporter.onEnd({ status }); + await reporter.onExit(); + return { status }; + } } export type LastRunInfo = { diff --git a/packages/playwright/src/runner/tasks.ts b/packages/playwright/src/runner/tasks.ts index 8f94a8d19a6a1..6b8c9f7464156 100644 --- a/packages/playwright/src/runner/tasks.ts +++ b/packages/playwright/src/runner/tasks.ts @@ -26,12 +26,13 @@ import type { Task } from './taskRunner'; import { TaskRunner } from './taskRunner'; import type { FullConfigInternal, FullProjectInternal } from '../common/config'; import { collectProjectsAndTestFiles, createRootSuite, loadFileSuites, loadGlobalHook } from './loadUtils'; -import type { Matcher } from '../util'; +import { removeDirAndLogToConsole, type Matcher } from '../util'; import { Suite } from '../common/test'; import { buildDependentProjects, buildTeardownToSetupsMap, filterProjects } from './projectUtils'; import { FailureTracker } from './failureTracker'; import { detectChangedTestFiles } from './vcs'; import type { InternalReporter } from '../reporters/internalReporter'; +import { cacheDir } from '../transform/compilationCache'; const readDirAsync = promisify(fs.readdir); @@ -139,6 +140,22 @@ export function createTaskRunnerForRelatedTestFiles(config: FullConfigInternal, return taskRunner; } +export function createTaskRunnerForClearCache(config: FullConfigInternal, reporter: InternalReporter, mode: 'in-process' | 'out-of-process', setupPlugins: boolean): TaskRunner { + const taskRunner = TaskRunner.create(reporter, config.config.globalTimeout); + if (setupPlugins) { + for (const plugin of config.plugins) + taskRunner.addTask('plugin setup', createPluginSetupTask(plugin)); + } + taskRunner.addTask('clear cache', { + setup: async () => { + await removeDirAndLogToConsole(cacheDir); + for (const plugin of config.plugins) + await plugin.instance?.clearCache?.(); + }, + }); + return taskRunner; +} + function createReportBeginTask(): Task { return { setup: async (reporter, { rootSuite }) => { diff --git a/packages/playwright/src/runner/testServer.ts b/packages/playwright/src/runner/testServer.ts index cd6b7ca0ce7fa..e6522bad46930 100644 --- a/packages/playwright/src/runner/testServer.ts +++ b/packages/playwright/src/runner/testServer.ts @@ -23,7 +23,7 @@ import type * as reporterTypes from '../../types/testReporter'; import { affectedTestFiles, collectAffectedTestFiles, dependenciesForTestFile } from '../transform/compilationCache'; import type { ConfigLocation, FullConfigInternal } from '../common/config'; import { createErrorCollectingReporter, createReporterForTestServer, createReporters } from './reporters'; -import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer, createTaskRunnerForWatchSetup, createTaskRunnerForListFiles, createTaskRunnerForDevServer, createTaskRunnerForRelatedTestFiles } from './tasks'; +import { TestRun, createTaskRunnerForList, createTaskRunnerForTestServer, createTaskRunnerForWatchSetup, createTaskRunnerForListFiles, createTaskRunnerForDevServer, createTaskRunnerForRelatedTestFiles, createTaskRunnerForClearCache } from './tasks'; import { open } from 'playwright-core/lib/utilsBundle'; import ListReporter from '../reporters/list'; import { SigIntWatcher } from './sigIntWatcher'; @@ -35,7 +35,6 @@ import { webServerPluginsForConfig } from '../plugins/webServerPlugin'; import type { TraceViewerRedirectOptions, TraceViewerServerOptions } from 'playwright-core/lib/server/trace/viewer/traceViewer'; import type { TestRunnerPluginRegistration } from '../plugins'; import { serializeError } from '../util'; -import { cacheDir } from '../transform/compilationCache'; import { baseFullConfig } from '../isomorphic/teleReceiver'; import { InternalReporter } from '../reporters/internalReporter'; import type { ReporterV2 } from '../reporters/reporterV2'; @@ -202,9 +201,17 @@ export class TestServerDispatcher implements TestServerInterface { } async clearCache(params: Parameters[0]): ReturnType { - const { config } = await this._loadConfig(); - if (config) - await clearCacheAndLogToConsole(config); + const reporter = new InternalReporter([]); + const config = await this._loadConfigOrReportError(reporter); + if (!config) + return; + + const taskRunner = createTaskRunnerForClearCache(config, reporter, 'out-of-process', false); + const testRun = new TestRun(config); + reporter.onConfigure(config.config); + const status = await taskRunner.run(testRun, 0); + await reporter.onEnd({ status }); + await reporter.onExit(); } async listFiles(params: Parameters[0]): ReturnType { @@ -525,23 +532,3 @@ export async function resolveCtDirs(config: FullConfigInternal) { templateDir }; } - -export async function clearCacheAndLogToConsole(config: FullConfigInternal) { - const override = (config.config as any)['@playwright/test']?.['cli']?.['clear-cache']; - if (override) { - await override(config); - return; - } - await removeFolderAndLogToConsole(cacheDir); -} - -export async function removeFolderAndLogToConsole(folder: string) { - try { - if (!fs.existsSync(folder)) - return; - // eslint-disable-next-line no-console - console.log(`Removing ${await fs.promises.realpath(folder)}`); - await fs.promises.rm(folder, { recursive: true, force: true }); - } catch { - } -} diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 367bb721d9bbd..06e18f206aa7c 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -348,3 +348,14 @@ function fileExists(resolved: string) { function dirExists(resolved: string) { return fs.statSync(resolved, { throwIfNoEntry: false })?.isDirectory(); } + +export async function removeDirAndLogToConsole(dir: string) { + try { + if (!fs.existsSync(dir)) + return; + // eslint-disable-next-line no-console + console.log(`Removing ${await fs.promises.realpath(dir)}`); + await fs.promises.rm(dir, { recursive: true, force: true }); + } catch { + } +} diff --git a/tests/playwright-test/clear-cache.spec.ts b/tests/playwright-test/clear-cache.spec.ts index ffd0ec3cf46c5..128896c2e3ecc 100644 --- a/tests/playwright-test/clear-cache.spec.ts +++ b/tests/playwright-test/clear-cache.spec.ts @@ -15,9 +15,6 @@ */ import { test, expect } from './playwright-test-fixtures'; -import path from 'path'; - -export const ctReactCliEntrypoint = path.join(__dirname, '../../packages/playwright-ct-react/cli.js'); test('should clear cache with type:module', async ({ runCLICommand }) => { const result = await runCLICommand({ @@ -46,6 +43,6 @@ test('should clear cache for ct', async ({ runCLICommand }) => { import { test } from '@playwright/test'; test('example', () => {}); `, - }, 'clear-cache', [], ctReactCliEntrypoint); + }, 'clear-cache', []); expect(result.exitCode).toBe(0); }); diff --git a/tests/playwright-test/playwright-test-fixtures.ts b/tests/playwright-test/playwright-test-fixtures.ts index f9670fa305632..23c26a3e3c33e 100644 --- a/tests/playwright-test/playwright-test-fixtures.ts +++ b/tests/playwright-test/playwright-test-fixtures.ts @@ -203,9 +203,9 @@ async function runPlaywrightTest(childProcess: CommonFixtures['childProcess'], b }; } -async function runPlaywrightCLI(childProcess: CommonFixtures['childProcess'], args: string[], baseDir: string, env: NodeJS.ProcessEnv, entryPoint?: string): Promise<{ output: string, stdout: string, stderr: string, exitCode: number }> { +async function runPlaywrightCLI(childProcess: CommonFixtures['childProcess'], args: string[], baseDir: string, env: NodeJS.ProcessEnv): Promise<{ output: string, stdout: string, stderr: string, exitCode: number }> { const testProcess = childProcess({ - command: ['node', entryPoint || cliEntrypoint, ...args], + command: ['node', cliEntrypoint, ...args], env: cleanEnv(env), cwd: baseDir, }); @@ -249,7 +249,7 @@ type Fixtures = { writeFiles: (files: Files) => Promise; deleteFile: (file: string) => Promise; runInlineTest: (files: Files, params?: Params, env?: NodeJS.ProcessEnv, options?: RunOptions) => Promise; - runCLICommand: (files: Files, command: string, args?: string[], entryPoint?: string) => Promise<{ stdout: string, stderr: string, exitCode: number }>; + runCLICommand: (files: Files, command: string, args?: string[]) => Promise<{ stdout: string, stderr: string, exitCode: number }>; startCLICommand: (files: Files, command: string, args?: string[], options?: RunOptions) => Promise; runWatchTest: (files: Files, params?: Params, env?: NodeJS.ProcessEnv, options?: RunOptions) => Promise; interactWithTestRunner: (files: Files, params?: Params, env?: NodeJS.ProcessEnv, options?: RunOptions) => Promise; @@ -285,9 +285,9 @@ export const test = base runCLICommand: async ({ childProcess }, use, testInfo: TestInfo) => { const cacheDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'playwright-test-cache-')); - await use(async (files: Files, command: string, args?: string[], entryPoint?: string) => { + await use(async (files: Files, command: string, args?: string[]) => { const baseDir = await writeFiles(testInfo, files, true); - return await runPlaywrightCLI(childProcess, [command, ...(args || [])], baseDir, { PWTEST_CACHE_DIR: cacheDir }, entryPoint); + return await runPlaywrightCLI(childProcess, [command, ...(args || [])], baseDir, { PWTEST_CACHE_DIR: cacheDir }); }); await removeFolders([cacheDir]); }, diff --git a/tests/playwright-test/test-server.spec.ts b/tests/playwright-test/test-server.spec.ts index 26b393538fff7..6f03b2c80429f 100644 --- a/tests/playwright-test/test-server.spec.ts +++ b/tests/playwright-test/test-server.spec.ts @@ -193,3 +193,12 @@ test('find related test files', async ({ startTestServer, writeFiles }) => { expect((await testServerConnection.runGlobalTeardown({})).status).toBe('passed'); }); + +test('clear cache', async ({ startTestServer, writeFiles }) => { + await writeFiles(ctFiles); + const testServerConnection = await startTestServer(); + await testServerConnection.initialize({ interceptStdio: true }); + expect((await testServerConnection.runGlobalSetup({})).status).toBe('passed'); + await testServerConnection.clearCache({}); + expect((await testServerConnection.runGlobalTeardown({})).status).toBe('passed'); +}); From 1989589edd83b35ac324d8bf4e72e5d137a35a6b Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 5 Sep 2024 13:59:54 -0700 Subject: [PATCH 007/805] docs: update browsers version in release notes (#32475) --- docs/src/release-notes-csharp.md | 2 +- docs/src/release-notes-java.md | 2 +- docs/src/release-notes-js.md | 2 +- docs/src/release-notes-python.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index 1693149933b68..f4532376de712 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -26,7 +26,7 @@ And for fonts, it now shows a nice preview: ### Browser Versions -- Chromium 129.0.6668.22 +- Chromium 129.0.6668.29 - Mozilla Firefox 130.0 - WebKit 18.0 diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index 686a444634fe7..4eab504435bc2 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -26,7 +26,7 @@ And for fonts, it now shows a nice preview: ### Browser Versions -- Chromium 129.0.6668.22 +- Chromium 129.0.6668.29 - Mozilla Firefox 130.0 - WebKit 18.0 diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md index aa62541ce5b05..386fa4abf8a28 100644 --- a/docs/src/release-notes-js.md +++ b/docs/src/release-notes-js.md @@ -58,7 +58,7 @@ test('query params', async ({ request }) => { ### Browser Versions -- Chromium 129.0.6668.22 +- Chromium 129.0.6668.29 - Mozilla Firefox 130.0 - WebKit 18.0 diff --git a/docs/src/release-notes-python.md b/docs/src/release-notes-python.md index 599e3e889d687..5fbf11873b6a1 100644 --- a/docs/src/release-notes-python.md +++ b/docs/src/release-notes-python.md @@ -26,7 +26,7 @@ And for fonts, it now shows a nice preview: ### Browser Versions -- Chromium 129.0.6668.22 +- Chromium 129.0.6668.29 - Mozilla Firefox 130.0 - WebKit 18.0 From 752b171a13cd0d368561668890c377fc2e6b9f49 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 5 Sep 2024 14:56:07 -0700 Subject: [PATCH 008/805] chore: support bidi connection to chromium (#32474) --- package-lock.json | 43 ++++ package.json | 1 + .../playwright-core/src/server/bidi/DEPS.list | 6 + .../src/server/bidi/bidiBrowser.ts | 3 - .../src/server/bidi/bidiBrowserType.ts | 206 ++++++++++++++++++ .../src/server/bidi/bidiFirefox.ts | 112 ---------- .../src/server/bidi/bidiOverCdp.ts | 100 +++++++++ .../src/server/bidi/bidiPage.ts | 13 +- .../playwright-core/src/server/browserType.ts | 19 +- .../src/server/chromium/chromium.ts | 15 +- .../src/server/firefox/firefox.ts | 20 +- .../playwright-core/src/server/playwright.ts | 4 +- .../src/server/registry/index.ts | 7 +- tests/bidi/playwright.config.ts | 53 ++--- 14 files changed, 415 insertions(+), 187 deletions(-) create mode 100644 packages/playwright-core/src/server/bidi/bidiBrowserType.ts delete mode 100644 packages/playwright-core/src/server/bidi/bidiFirefox.ts create mode 100644 packages/playwright-core/src/server/bidi/bidiOverCdp.ts diff --git a/package-lock.json b/package-lock.json index 6c65c8e2470f2..4e24bcfa49943 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@vitejs/plugin-react": "^4.2.1", "@zip.js/zip.js": "^2.7.29", "chokidar": "^3.5.3", + "chromium-bidi": "^0.6.4", "colors": "^1.4.0", "concurrently": "^6.2.1", "cross-env": "^7.0.3", @@ -2828,6 +2829,20 @@ "fsevents": "~2.3.2" } }, + "node_modules/chromium-bidi": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.5.tgz", + "integrity": "sha512-RuLrmzYrxSb0s9SgpB+QN5jJucPduZQ/9SIe76MDxYJuecPW5mxMdacJ1f4EtgiV+R0p3sCkznTMvH0MPGFqjA==", + "dev": true, + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -3258,6 +3273,13 @@ "dev": true, "optional": true }, + "node_modules/devtools-protocol": { + "version": "0.0.1349977", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1349977.tgz", + "integrity": "sha512-5JcwlDKinshGSm+4AVLFCkokJUAKTgjmiorNmrGgYYKix1h8Ts9/fplQeK1xg/rACYw1JlEM2PwIEvny5QswKQ==", + "dev": true, + "peer": true + }, "node_modules/dezalgo": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", @@ -5454,6 +5476,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -7120,6 +7148,12 @@ "punycode": "^2.1.0" } }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true + }, "node_modules/util-extend": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz", @@ -7905,6 +7939,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "packages/html-reporter": { "version": "0.0.0", "dependencies": { diff --git a/package.json b/package.json index 84634dcb64cb6..44d259d7a4d2c 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "@vitejs/plugin-react": "^4.2.1", "@zip.js/zip.js": "^2.7.29", "chokidar": "^3.5.3", + "chromium-bidi": "^0.6.4", "colors": "^1.4.0", "concurrently": "^6.2.1", "cross-env": "^7.0.3", diff --git a/packages/playwright-core/src/server/bidi/DEPS.list b/packages/playwright-core/src/server/bidi/DEPS.list index 5f9ffe919defe..a97787788d517 100644 --- a/packages/playwright-core/src/server/bidi/DEPS.list +++ b/packages/playwright-core/src/server/bidi/DEPS.list @@ -3,3 +3,9 @@ ../ ../isomorphic/ ./third_party/ + +[bidiOverCdp.ts] +*** + +[bidiBrowserType.ts] +../chromium/chromiumSwitches.ts diff --git a/packages/playwright-core/src/server/bidi/bidiBrowser.ts b/packages/playwright-core/src/server/bidi/bidiBrowser.ts index 878d01b0d7480..cc3fbc0562622 100644 --- a/packages/playwright-core/src/server/bidi/bidiBrowser.ts +++ b/packages/playwright-core/src/server/bidi/bidiBrowser.ts @@ -43,9 +43,6 @@ export class BidiBrowser extends Browser { const browser = new BidiBrowser(parent, transport, options); if ((options as any).__testHookOnConnectToBrowser) await (options as any).__testHookOnConnectToBrowser(); - const sessionStatus = await browser._browserSession.send('session.status', {}); - if (!sessionStatus.ready) - throw new Error('Bidi session is not ready. ' + sessionStatus.message); let proxy: bidi.Session.ManualProxyConfiguration | undefined; if (options.proxy) { diff --git a/packages/playwright-core/src/server/bidi/bidiBrowserType.ts b/packages/playwright-core/src/server/bidi/bidiBrowserType.ts new file mode 100644 index 0000000000000..841beb71ad4c8 --- /dev/null +++ b/packages/playwright-core/src/server/bidi/bidiBrowserType.ts @@ -0,0 +1,206 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import os from 'os'; +import path from 'path'; +import { assert, wrapInASCIIBox } from '../../utils'; +import type { Env } from '../../utils/processLauncher'; +import type { BrowserOptions } from '../browser'; +import { BrowserReadyState } from '../browserType'; +import { BrowserType, kNoXServerRunningError } from '../browserType'; +import type { SdkObject } from '../instrumentation'; +import type { ProtocolError } from '../protocolError'; +import type { ConnectionTransport } from '../transport'; +import type * as types from '../types'; +import { BidiBrowser } from './bidiBrowser'; +import { kBrowserCloseMessageId } from './bidiConnection'; +import { chromiumSwitches } from '../chromium/chromiumSwitches'; + +export class BidiBrowserType extends BrowserType { + constructor(parent: SdkObject) { + super(parent, 'bidi'); + this._useBidi = true; + } + + override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise { + if (options.channel?.includes('chrome')) { + // Chrome doesn't support Bidi, we create Bidi over CDP which is used by Chrome driver. + // bidiOverCdp depends on chromium-bidi which we only have in devDependencies, so + // we load bidiOverCdp dynamically. + const bidiTransport = await require('./bidiOverCdp').connectBidiOverCdp(transport); + (transport as any)[kBidiOverCdpWrapper] = bidiTransport; + transport = bidiTransport; + } + return BidiBrowser.connect(this.attribution.playwright, transport, options); + } + + override doRewriteStartupLog(error: ProtocolError): ProtocolError { + if (!error.logs) + return error; + // https://github.com/microsoft/playwright/issues/6500 + if (error.logs.includes(`as root in a regular user's session is not supported.`)) + error.logs = '\n' + wrapInASCIIBox(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.\nWorkaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? ' in your GitHub Actions workflow file' : ''} when running Playwright.`, 1); + if (error.logs.includes('no DISPLAY environment variable specified')) + error.logs = '\n' + wrapInASCIIBox(kNoXServerRunningError, 1); + return error; + } + + override amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env { + if (!path.isAbsolute(os.homedir())) + throw new Error(`Cannot launch Firefox with relative home directory. Did you set ${os.platform() === 'win32' ? 'USERPROFILE' : 'HOME'} to a relative path?`); + if (os.platform() === 'linux') { + // Always remove SNAP_NAME and SNAP_INSTANCE_NAME env variables since they + // confuse Firefox: in our case, builds never come from SNAP. + // See https://github.com/microsoft/playwright/issues/20555 + return { ...env, SNAP_NAME: undefined, SNAP_INSTANCE_NAME: undefined }; + } + return env; + } + + override attemptToGracefullyCloseBrowser(transport: ConnectionTransport): void { + const bidiTransport = (transport as any)[kBidiOverCdpWrapper]; + if (bidiTransport) + transport = bidiTransport; + transport.send({ method: 'browser.close', params: {}, id: kBrowserCloseMessageId }); + } + + override defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { + if (options.channel === 'bidi-firefox-stable') + return this._defaultFirefoxArgs(options, isPersistent, userDataDir); + else if (options.channel === 'bidi-chrome-canary') + return this._defaultChromiumArgs(options, isPersistent, userDataDir); + throw new Error(`Unknown Bidi channel "${options.channel}"`); + } + + override readyState(options: types.LaunchOptions): BrowserReadyState | undefined { + assert(options.useWebSocket); + if (options.channel?.includes('firefox')) + return new FirefoxReadyState(); + if (options.channel?.includes('chrome')) + return new ChromiumReadyState(); + return undefined; + } + + private _defaultFirefoxArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { + const { args = [], headless } = options; + const userDataDirArg = args.find(arg => arg.startsWith('-profile') || arg.startsWith('--profile')); + if (userDataDirArg) + throw this._createUserDataDirArgMisuseError('--profile'); + const firefoxArguments = ['--remote-debugging-port=0']; + if (headless) + firefoxArguments.push('--headless'); + else + firefoxArguments.push('--foreground'); + firefoxArguments.push(`--profile`, userDataDir); + firefoxArguments.push(...args); + // TODO: make ephemeral context work without this argument. + firefoxArguments.push('about:blank'); + // if (isPersistent) + // firefoxArguments.push('about:blank'); + // else + // firefoxArguments.push('-silent'); + return firefoxArguments; + } + + private _defaultChromiumArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { + const chromeArguments = this._innerDefaultArgs(options); + chromeArguments.push(`--user-data-dir=${userDataDir}`); + chromeArguments.push('--remote-debugging-port=0'); + if (isPersistent) + chromeArguments.push('about:blank'); + else + chromeArguments.push('--no-startup-window'); + return chromeArguments; + } + + private _innerDefaultArgs(options: types.LaunchOptions): string[] { + const { args = [], proxy } = options; + const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir')); + if (userDataDirArg) + throw this._createUserDataDirArgMisuseError('--user-data-dir'); + if (args.find(arg => arg.startsWith('--remote-debugging-pipe'))) + throw new Error('Playwright manages remote debugging connection itself.'); + if (args.find(arg => !arg.startsWith('-'))) + throw new Error('Arguments can not specify page to be opened'); + const chromeArguments = [...chromiumSwitches]; + + if (os.platform() === 'darwin') { + // See https://github.com/microsoft/playwright/issues/7362 + chromeArguments.push('--enable-use-zoom-for-dsf=false'); + // See https://bugs.chromium.org/p/chromium/issues/detail?id=1407025. + if (options.headless) + chromeArguments.push('--use-angle'); + } + + if (options.devtools) + chromeArguments.push('--auto-open-devtools-for-tabs'); + if (options.headless) { + if (process.env.PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW) + chromeArguments.push('--headless=new'); + else + chromeArguments.push('--headless=old'); + + chromeArguments.push( + '--hide-scrollbars', + '--mute-audio', + '--blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4', + ); + } + if (options.chromiumSandbox !== true) + chromeArguments.push('--no-sandbox'); + if (proxy) { + const proxyURL = new URL(proxy.server); + const isSocks = proxyURL.protocol === 'socks5:'; + // https://www.chromium.org/developers/design-documents/network-settings + if (isSocks && !this.attribution.playwright.options.socksProxyPort) { + // https://www.chromium.org/developers/design-documents/network-stack/socks-proxy + chromeArguments.push(`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`); + } + chromeArguments.push(`--proxy-server=${proxy.server}`); + const proxyBypassRules = []; + // https://source.chromium.org/chromium/chromium/src/+/master:net/docs/proxy.md;l=548;drc=71698e610121078e0d1a811054dcf9fd89b49578 + if (this.attribution.playwright.options.socksProxyPort) + proxyBypassRules.push('<-loopback>'); + if (proxy.bypass) + proxyBypassRules.push(...proxy.bypass.split(',').map(t => t.trim()).map(t => t.startsWith('.') ? '*' + t : t)); + if (!process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK && !proxyBypassRules.includes('<-loopback>')) + proxyBypassRules.push('<-loopback>'); + if (proxyBypassRules.length > 0) + chromeArguments.push(`--proxy-bypass-list=${proxyBypassRules.join(';')}`); + } + chromeArguments.push(...args); + return chromeArguments; + } +} + +class FirefoxReadyState extends BrowserReadyState { + override onBrowserOutput(message: string): void { + // Bidi WebSocket in Firefox. + const match = message.match(/WebDriver BiDi listening on (ws:\/\/.*)$/); + if (match) + this._wsEndpoint.resolve(match[1] + '/session'); + } +} + +class ChromiumReadyState extends BrowserReadyState { + override onBrowserOutput(message: string): void { + const match = message.match(/DevTools listening on (.*)/); + if (match) + this._wsEndpoint.resolve(match[1]); + } +} + +const kBidiOverCdpWrapper = Symbol('kBidiConnectionWrapper'); diff --git a/packages/playwright-core/src/server/bidi/bidiFirefox.ts b/packages/playwright-core/src/server/bidi/bidiFirefox.ts deleted file mode 100644 index 499ab7f4c7a04..0000000000000 --- a/packages/playwright-core/src/server/bidi/bidiFirefox.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import os from 'os'; -import path from 'path'; -import { assert, ManualPromise, wrapInASCIIBox } from '../../utils'; -import type { Env } from '../../utils/processLauncher'; -import type { BrowserOptions } from '../browser'; -import type { BrowserReadyState } from '../browserType'; -import { BrowserType, kNoXServerRunningError } from '../browserType'; -import type { SdkObject } from '../instrumentation'; -import type { ProtocolError } from '../protocolError'; -import type { ConnectionTransport } from '../transport'; -import type * as types from '../types'; -import { BidiBrowser } from './bidiBrowser'; -import { kBrowserCloseMessageId } from './bidiConnection'; - -export class BidiFirefox extends BrowserType { - constructor(parent: SdkObject) { - super(parent, 'bidi'); - this._useBidi = true; - } - - override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise { - return BidiBrowser.connect(this.attribution.playwright, transport, options); - } - - override doRewriteStartupLog(error: ProtocolError): ProtocolError { - if (!error.logs) - return error; - // https://github.com/microsoft/playwright/issues/6500 - if (error.logs.includes(`as root in a regular user's session is not supported.`)) - error.logs = '\n' + wrapInASCIIBox(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.\nWorkaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? ' in your GitHub Actions workflow file' : ''} when running Playwright.`, 1); - if (error.logs.includes('no DISPLAY environment variable specified')) - error.logs = '\n' + wrapInASCIIBox(kNoXServerRunningError, 1); - return error; - } - - override amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env { - if (!path.isAbsolute(os.homedir())) - throw new Error(`Cannot launch Firefox with relative home directory. Did you set ${os.platform() === 'win32' ? 'USERPROFILE' : 'HOME'} to a relative path?`); - if (os.platform() === 'linux') { - // Always remove SNAP_NAME and SNAP_INSTANCE_NAME env variables since they - // confuse Firefox: in our case, builds never come from SNAP. - // See https://github.com/microsoft/playwright/issues/20555 - return { ...env, SNAP_NAME: undefined, SNAP_INSTANCE_NAME: undefined }; - } - return env; - } - - override attemptToGracefullyCloseBrowser(transport: ConnectionTransport): void { - transport.send({ method: 'browser.close', params: {}, id: kBrowserCloseMessageId }); - } - - override defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { - const { args = [], headless } = options; - const userDataDirArg = args.find(arg => arg.startsWith('-profile') || arg.startsWith('--profile')); - if (userDataDirArg) - throw this._createUserDataDirArgMisuseError('--profile'); - const firefoxArguments = ['--remote-debugging-port=0']; - if (headless) - firefoxArguments.push('--headless'); - else - firefoxArguments.push('--foreground'); - firefoxArguments.push(`--profile`, userDataDir); - firefoxArguments.push(...args); - // TODO: make ephemeral context work without this argument. - firefoxArguments.push('about:blank'); - // if (isPersistent) - // firefoxArguments.push('about:blank'); - // else - // firefoxArguments.push('-silent'); - return firefoxArguments; - } - - override readyState(options: types.LaunchOptions): BrowserReadyState | undefined { - assert(options.useWebSocket); - return new BidiReadyState(); - } -} - -class BidiReadyState implements BrowserReadyState { - private readonly _wsEndpoint = new ManualPromise(); - - onBrowserOutput(message: string): void { - // Bidi WebSocket in Firefox. - const match = message.match(/WebDriver BiDi listening on (ws:\/\/.*)$/); - if (match) - this._wsEndpoint.resolve(match[1] + '/session'); - } - onBrowserExit(): void { - // Unblock launch when browser prematurely exits. - this._wsEndpoint.resolve(undefined); - } - async waitUntilReady(): Promise<{ wsEndpoint?: string }> { - const wsEndpoint = await this._wsEndpoint; - return { wsEndpoint }; - } -} diff --git a/packages/playwright-core/src/server/bidi/bidiOverCdp.ts b/packages/playwright-core/src/server/bidi/bidiOverCdp.ts new file mode 100644 index 0000000000000..1d01317c1e455 --- /dev/null +++ b/packages/playwright-core/src/server/bidi/bidiOverCdp.ts @@ -0,0 +1,100 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as bidiMapper from 'chromium-bidi/lib/cjs/bidiMapper/BidiMapper'; +import * as bidiCdpConnection from 'chromium-bidi/lib/cjs/cdp/CdpConnection'; +import type * as bidiTransport from 'chromium-bidi/lib/cjs/utils/transport'; +import type { ChromiumBidi } from 'chromium-bidi/lib/cjs/protocol/protocol'; +import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; +import { debugLogger } from '../../utils/debugLogger'; + +const bidiServerLogger = (prefix: string, ...args: unknown[]): void => { + debugLogger.log(prefix as any, args); +}; + +export async function connectBidiOverCdp(cdp: ConnectionTransport): Promise { + let server: bidiMapper.BidiServer | undefined = undefined; + const bidiTransport = new BidiTransportImpl(); + const bidiConnection = new BidiConnection(bidiTransport, () => server?.close()); + const cdpTransportImpl = new CdpTransportImpl(cdp); + const cdpConnection = new bidiCdpConnection.MapperCdpConnection(cdpTransportImpl, bidiServerLogger); + // Make sure onclose event is propagated. + cdp.onclose = () => bidiConnection.onclose?.(); + server = await bidiMapper.BidiServer.createAndStart( + bidiTransport, + cdpConnection, + await cdpConnection.createBrowserSession(), + /* selfTargetId= */ '', + undefined, + bidiServerLogger); + return bidiConnection; +} + +class BidiTransportImpl implements bidiMapper.BidiTransport { + _handler?: (message: ChromiumBidi.Command) => Promise | void; + _bidiConnection!: BidiConnection; + + setOnMessage(handler: (message: ChromiumBidi.Command) => Promise | void) { + this._handler = handler; + } + sendMessage(message: ChromiumBidi.Message): Promise | void { + return this._bidiConnection.onmessage?.(message as any); + } + close() { + this._bidiConnection.onclose?.(); + } +} + +class BidiConnection implements ConnectionTransport { + private _bidiTransport: BidiTransportImpl; + private _closeCallback: () => void; + + constructor(bidiTransport: BidiTransportImpl, closeCallback: () => void) { + this._bidiTransport = bidiTransport; + this._bidiTransport._bidiConnection = this; + this._closeCallback = closeCallback; + } + send(s: ProtocolRequest): void { + this._bidiTransport._handler?.(s as any); + } + close(): void { + this._closeCallback(); + } + onmessage?: ((message: ProtocolResponse) => void) | undefined; + onclose?: ((reason?: string) => void) | undefined; +} + +class CdpTransportImpl implements bidiTransport.Transport { + private _connection: ConnectionTransport; + private _handler?: (message: string) => Promise | void; + _bidiConnection!: BidiConnection; + + constructor(connection: ConnectionTransport) { + this._connection = connection; + this._connection.onmessage = message => { + this._handler?.(JSON.stringify(message)); + }; + } + setOnMessage(handler: (message: string) => Promise | void) { + this._handler = handler; + } + sendMessage(message: string): Promise | void { + return this._connection.send(JSON.parse(message)); + } + close(): void { + this._connection.close(); + } +} diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index 0028b9fc9596f..2802aa1452b14 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -86,8 +86,8 @@ export class BidiPage implements PageDelegate { } private async _initialize() { - const { contexts } = await this._session.send('browsingContext.getTree', { root: this._session.sessionId }); - this._handleFrameTree(contexts[0]); + // Initialize main frame. + this._onFrameAttached(this._session.sessionId, null); await Promise.all([ this.updateHttpCredentials(), this.updateRequestInterception(), @@ -95,15 +95,6 @@ export class BidiPage implements PageDelegate { ]); } - private _handleFrameTree(frameTree: bidi.BrowsingContext.Info) { - this._onFrameAttached(frameTree.context, frameTree.parent || null); - if (!frameTree.children) - return; - - for (const child of frameTree.children) - this._handleFrameTree(child); - } - potentiallyUninitializedPage(): Page { return this._page; } diff --git a/packages/playwright-core/src/server/browserType.ts b/packages/playwright-core/src/server/browserType.ts index 19cee87cb3e1b..d0c3174a599ad 100644 --- a/packages/playwright-core/src/server/browserType.ts +++ b/packages/playwright-core/src/server/browserType.ts @@ -32,7 +32,7 @@ import { ProgressController } from './progress'; import type * as types from './types'; import type * as channels from '@protocol/channels'; import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings'; -import { debugMode } from '../utils'; +import { debugMode, ManualPromise } from '../utils'; import { existsAsync } from '../utils/fileUtils'; import { helper } from './helper'; import { RecentLogsCollector } from '../utils/debugLogger'; @@ -44,10 +44,19 @@ export const kNoXServerRunningError = 'Looks like you launched a headed browser 'Set either \'headless: true\' or use \'xvfb-run \' before running Playwright.\n\n<3 Playwright Team'; -export interface BrowserReadyState { - onBrowserOutput(message: string): void; - onBrowserExit(): void; - waitUntilReady(): Promise<{ wsEndpoint?: string }>; +export abstract class BrowserReadyState { + protected readonly _wsEndpoint = new ManualPromise(); + + onBrowserExit(): void { + // Unblock launch when browser prematurely exits. + this._wsEndpoint.resolve(undefined); + } + async waitUntilReady(): Promise<{ wsEndpoint?: string }> { + const wsEndpoint = await this._wsEndpoint; + return { wsEndpoint }; + } + + abstract onBrowserOutput(message: string): void; } export abstract class BrowserType extends SdkObject { diff --git a/packages/playwright-core/src/server/chromium/chromium.ts b/packages/playwright-core/src/server/chromium/chromium.ts index 04177b46900e8..d84ae3952e3d5 100644 --- a/packages/playwright-core/src/server/chromium/chromium.ts +++ b/packages/playwright-core/src/server/chromium/chromium.ts @@ -24,7 +24,7 @@ import type { Env } from '../../utils/processLauncher'; import { gracefullyCloseSet } from '../../utils/processLauncher'; import { kBrowserCloseMessageId } from './crConnection'; import { BrowserType, kNoXServerRunningError } from '../browserType'; -import type { BrowserReadyState } from '../browserType'; +import { BrowserReadyState } from '../browserType'; import type { ConnectionTransport, ProtocolRequest } from '../transport'; import { WebSocketTransport } from '../transport'; import { CRDevTools } from './crDevTools'; @@ -352,21 +352,12 @@ export class Chromium extends BrowserType { } } -class ChromiumReadyState implements BrowserReadyState { - private readonly _wsEndpoint = new ManualPromise(); - - onBrowserOutput(message: string): void { +class ChromiumReadyState extends BrowserReadyState { + override onBrowserOutput(message: string): void { const match = message.match(/DevTools listening on (.*)/); if (match) this._wsEndpoint.resolve(match[1]); } - onBrowserExit(): void { - this._wsEndpoint.resolve(undefined); - } - async waitUntilReady(): Promise<{ wsEndpoint?: string }> { - const wsEndpoint = await this._wsEndpoint; - return { wsEndpoint }; - } } async function urlToWSEndpoint(progress: Progress, endpointURL: string, headers: { [key: string]: string; }) { diff --git a/packages/playwright-core/src/server/firefox/firefox.ts b/packages/playwright-core/src/server/firefox/firefox.ts index ed2709b685126..9fbc409a56698 100644 --- a/packages/playwright-core/src/server/firefox/firefox.ts +++ b/packages/playwright-core/src/server/firefox/firefox.ts @@ -20,12 +20,12 @@ import path from 'path'; import { FFBrowser } from './ffBrowser'; import { kBrowserCloseMessageId } from './ffConnection'; import { BrowserType, kNoXServerRunningError } from '../browserType'; -import type { BrowserReadyState } from '../browserType'; +import { BrowserReadyState } from '../browserType'; import type { Env } from '../../utils/processLauncher'; import type { ConnectionTransport } from '../transport'; import type { BrowserOptions } from '../browser'; import type * as types from '../types'; -import { ManualPromise, wrapInASCIIBox } from '../../utils'; +import { wrapInASCIIBox } from '../../utils'; import type { SdkObject } from '../instrumentation'; import type { ProtocolError } from '../protocolError'; @@ -95,20 +95,10 @@ export class Firefox extends BrowserType { } } -class JugglerReadyState implements BrowserReadyState { - private readonly _jugglerPromise = new ManualPromise(); - - onBrowserOutput(message: string): void { +class JugglerReadyState extends BrowserReadyState { + override onBrowserOutput(message: string): void { if (message.includes('Juggler listening to the pipe')) - this._jugglerPromise.resolve(); - } - onBrowserExit(): void { - // Unblock launch when browser prematurely exits. - this._jugglerPromise.resolve(); - } - async waitUntilReady(): Promise<{ wsEndpoint?: string }> { - await this._jugglerPromise; - return { }; + this._wsEndpoint.resolve(undefined); } } diff --git a/packages/playwright-core/src/server/playwright.ts b/packages/playwright-core/src/server/playwright.ts index b4ebbed0988db..10d1942e3480e 100644 --- a/packages/playwright-core/src/server/playwright.ts +++ b/packages/playwright-core/src/server/playwright.ts @@ -28,7 +28,7 @@ import { debugLogger, type Language } from '../utils'; import type { Page } from './page'; import { DebugController } from './debugController'; import type { BrowserType } from './browserType'; -import { BidiFirefox } from './bidi/bidiFirefox'; +import { BidiBrowserType } from './bidi/bidiBrowserType'; type PlaywrightOptions = { socksProxyPort?: number; @@ -64,7 +64,7 @@ export class Playwright extends SdkObject { } }, null); this.chromium = new Chromium(this); - this.bidi = new BidiFirefox(this); + this.bidi = new BidiBrowserType(this); this.firefox = new Firefox(this); this.webkit = new WebKit(this); this.electron = new Electron(this); diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index 6069b765f67ab..cafef726fb37a 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -354,7 +354,7 @@ function readDescriptors(browsersJSON: BrowsersJSON) { export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi'; type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'android'; -type BidiChannel = 'bidi-firefox-stable'; +type BidiChannel = 'bidi-firefox-stable' | 'bidi-chrome-canary'; type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree']; @@ -530,6 +530,11 @@ export class Registry { 'darwin': '/Applications/Firefox.app/Contents/MacOS/firefox', 'win32': '\\Mozilla Firefox\\firefox.exe', })); + this._executables.push(this._createBidiChannel('bidi-chrome-canary', { + 'linux': '', + 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', + 'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`, + })); const firefox = descriptors.find(d => d.name === 'firefox')!; const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox'); diff --git a/tests/bidi/playwright.config.ts b/tests/bidi/playwright.config.ts index a0c7becf19a7f..3bde84756a5de 100644 --- a/tests/bidi/playwright.config.ts +++ b/tests/bidi/playwright.config.ts @@ -26,7 +26,6 @@ const getExecutablePath = () => { }; const headed = process.argv.includes('--headed'); -const channel = process.env.PWTEST_CHANNEL as any; const trace = !!process.env.PWTEST_TRACE; const outputDir = path.join(__dirname, '..', '..', 'test-results'); @@ -64,32 +63,34 @@ const executablePath = getExecutablePath(); if (executablePath && !process.env.TEST_WORKER_INDEX) console.error(`Using executable at ${executablePath}`); const testIgnore: RegExp[] = []; -for (const folder of ['library', 'page']) { - config.projects.push({ - name: `${browserName}-${folder}`, - testDir: path.join(testDir, folder), - testIgnore, - snapshotPathTemplate: `{testDir}/{testFileDir}/{testFileName}-snapshots/{arg}-${browserName}{ext}`, - use: { - browserName, - headless: !headed, - channel, - video: 'off', - launchOptions: { - channel: 'bidi-firefox-stable', - executablePath, +for (const channel of ['bidi-chrome-canary', 'bidi-firefox-stable']) { + for (const folder of ['library', 'page']) { + config.projects.push({ + name: `${channel}-${folder}`, + testDir: path.join(testDir, folder), + testIgnore, + snapshotPathTemplate: `{testDir}/{testFileDir}/{testFileName}-snapshots/{arg}-${channel}{ext}`, + use: { + browserName, + headless: !headed, + channel, + video: 'off', + launchOptions: { + channel: 'bidi-chrome-canary', + executablePath, + }, + trace: trace ? 'on' : undefined, }, - trace: trace ? 'on' : undefined, - }, - metadata: { - platform: process.platform, - docker: !!process.env.INSIDE_DOCKER, - headless: !headed, - browserName, - channel, - trace: !!trace, - }, - }); + metadata: { + platform: process.platform, + docker: !!process.env.INSIDE_DOCKER, + headless: !headed, + browserName, + channel, + trace: !!trace, + }, + }); + } } export default config; From f0e13164d72494e161a37d2f6d6b05fddab5f4b1 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 5 Sep 2024 18:31:56 -0700 Subject: [PATCH 009/805] chore: split firefox and chromium bidi implementations (#32478) --- .../playwright-core/src/client/playwright.ts | 9 +- .../playwright-core/src/protocol/validator.ts | 3 +- .../playwright-core/src/server/bidi/DEPS.list | 2 +- .../{bidiBrowserType.ts => bidiChromium.ts} | 101 +++++------------- .../src/server/bidi/bidiFirefox.ts | 101 ++++++++++++++++++ .../dispatchers/playwrightDispatcher.ts | 3 +- .../playwright-core/src/server/playwright.ts | 9 +- packages/playwright-core/types/types.d.ts | 3 +- packages/playwright/src/index.ts | 6 +- packages/protocol/src/channels.ts | 3 +- packages/protocol/src/protocol.yml | 3 +- tests/bidi/playwright.config.ts | 60 ++++++----- tests/library/channels.spec.ts | 11 ++ utils/generate_types/overrides.d.ts | 3 +- 14 files changed, 201 insertions(+), 116 deletions(-) rename packages/playwright-core/src/server/bidi/{bidiBrowserType.ts => bidiChromium.ts} (61%) create mode 100644 packages/playwright-core/src/server/bidi/bidiFirefox.ts diff --git a/packages/playwright-core/src/client/playwright.ts b/packages/playwright-core/src/client/playwright.ts index 9415125be473c..9933ce15dea40 100644 --- a/packages/playwright-core/src/client/playwright.ts +++ b/packages/playwright-core/src/client/playwright.ts @@ -26,7 +26,8 @@ import { Selectors, SelectorsOwner } from './selectors'; export class Playwright extends ChannelOwner { readonly _android: Android; readonly _electron: Electron; - readonly _experimentalBidi: BrowserType; + readonly _bidiChromium: BrowserType; + readonly _bidiFirefox: BrowserType; readonly chromium: BrowserType; readonly firefox: BrowserType; readonly webkit: BrowserType; @@ -46,8 +47,10 @@ export class Playwright extends ChannelOwner { this.webkit._playwright = this; this._android = Android.from(initializer.android); this._electron = Electron.from(initializer.electron); - this._experimentalBidi = BrowserType.from(initializer.bidi); - this._experimentalBidi._playwright = this; + this._bidiChromium = BrowserType.from(initializer.bidiChromium); + this._bidiChromium._playwright = this; + this._bidiFirefox = BrowserType.from(initializer.bidiFirefox); + this._bidiFirefox._playwright = this; this.devices = this._connection.localUtils()?.devices ?? {}; this.selectors = new Selectors(); this.errors = { TimeoutError }; diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 0ec06e23b369d..b55303810e6bb 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -321,9 +321,10 @@ scheme.RootInitializeResult = tObject({ }); scheme.PlaywrightInitializer = tObject({ chromium: tChannel(['BrowserType']), - bidi: tChannel(['BrowserType']), firefox: tChannel(['BrowserType']), webkit: tChannel(['BrowserType']), + bidiChromium: tChannel(['BrowserType']), + bidiFirefox: tChannel(['BrowserType']), android: tChannel(['Android']), electron: tChannel(['Electron']), utils: tOptional(tChannel(['LocalUtils'])), diff --git a/packages/playwright-core/src/server/bidi/DEPS.list b/packages/playwright-core/src/server/bidi/DEPS.list index a97787788d517..9be31302c5a56 100644 --- a/packages/playwright-core/src/server/bidi/DEPS.list +++ b/packages/playwright-core/src/server/bidi/DEPS.list @@ -7,5 +7,5 @@ [bidiOverCdp.ts] *** -[bidiBrowserType.ts] +[bidiChromium.ts] ../chromium/chromiumSwitches.ts diff --git a/packages/playwright-core/src/server/bidi/bidiBrowserType.ts b/packages/playwright-core/src/server/bidi/bidiChromium.ts similarity index 61% rename from packages/playwright-core/src/server/bidi/bidiBrowserType.ts rename to packages/playwright-core/src/server/bidi/bidiChromium.ts index 841beb71ad4c8..e94dabf07280c 100644 --- a/packages/playwright-core/src/server/bidi/bidiBrowserType.ts +++ b/packages/playwright-core/src/server/bidi/bidiChromium.ts @@ -15,58 +15,55 @@ */ import os from 'os'; -import path from 'path'; import { assert, wrapInASCIIBox } from '../../utils'; import type { Env } from '../../utils/processLauncher'; import type { BrowserOptions } from '../browser'; -import { BrowserReadyState } from '../browserType'; -import { BrowserType, kNoXServerRunningError } from '../browserType'; +import { BrowserReadyState, BrowserType, kNoXServerRunningError } from '../browserType'; +import { chromiumSwitches } from '../chromium/chromiumSwitches'; import type { SdkObject } from '../instrumentation'; import type { ProtocolError } from '../protocolError'; import type { ConnectionTransport } from '../transport'; import type * as types from '../types'; import { BidiBrowser } from './bidiBrowser'; import { kBrowserCloseMessageId } from './bidiConnection'; -import { chromiumSwitches } from '../chromium/chromiumSwitches'; -export class BidiBrowserType extends BrowserType { +export class BidiChromium extends BrowserType { constructor(parent: SdkObject) { super(parent, 'bidi'); this._useBidi = true; } override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise { - if (options.channel?.includes('chrome')) { - // Chrome doesn't support Bidi, we create Bidi over CDP which is used by Chrome driver. - // bidiOverCdp depends on chromium-bidi which we only have in devDependencies, so - // we load bidiOverCdp dynamically. - const bidiTransport = await require('./bidiOverCdp').connectBidiOverCdp(transport); - (transport as any)[kBidiOverCdpWrapper] = bidiTransport; - transport = bidiTransport; - } - return BidiBrowser.connect(this.attribution.playwright, transport, options); + // Chrome doesn't support Bidi, we create Bidi over CDP which is used by Chrome driver. + // bidiOverCdp depends on chromium-bidi which we only have in devDependencies, so + // we load bidiOverCdp dynamically. + const bidiTransport = await require('./bidiOverCdp').connectBidiOverCdp(transport); + (transport as any)[kBidiOverCdpWrapper] = bidiTransport; + return BidiBrowser.connect(this.attribution.playwright, bidiTransport, options); } override doRewriteStartupLog(error: ProtocolError): ProtocolError { if (!error.logs) return error; - // https://github.com/microsoft/playwright/issues/6500 - if (error.logs.includes(`as root in a regular user's session is not supported.`)) - error.logs = '\n' + wrapInASCIIBox(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.\nWorkaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? ' in your GitHub Actions workflow file' : ''} when running Playwright.`, 1); - if (error.logs.includes('no DISPLAY environment variable specified')) + if (error.logs.includes('Missing X server')) error.logs = '\n' + wrapInASCIIBox(kNoXServerRunningError, 1); + // These error messages are taken from Chromium source code as of July, 2020: + // https://github.com/chromium/chromium/blob/70565f67e79f79e17663ad1337dc6e63ee207ce9/content/browser/zygote_host/zygote_host_impl_linux.cc + if (!error.logs.includes('crbug.com/357670') && !error.logs.includes('No usable sandbox!') && !error.logs.includes('crbug.com/638180')) + return error; + error.logs = [ + `Chromium sandboxing failed!`, + `================================`, + `To avoid the sandboxing issue, do either of the following:`, + ` - (preferred): Configure your environment to support sandboxing`, + ` - (alternative): Launch Chromium without sandbox using 'chromiumSandbox: false' option`, + `================================`, + ``, + ].join('\n'); return error; } override amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env { - if (!path.isAbsolute(os.homedir())) - throw new Error(`Cannot launch Firefox with relative home directory. Did you set ${os.platform() === 'win32' ? 'USERPROFILE' : 'HOME'} to a relative path?`); - if (os.platform() === 'linux') { - // Always remove SNAP_NAME and SNAP_INSTANCE_NAME env variables since they - // confuse Firefox: in our case, builds never come from SNAP. - // See https://github.com/microsoft/playwright/issues/20555 - return { ...env, SNAP_NAME: undefined, SNAP_INSTANCE_NAME: undefined }; - } return env; } @@ -78,44 +75,6 @@ export class BidiBrowserType extends BrowserType { } override defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { - if (options.channel === 'bidi-firefox-stable') - return this._defaultFirefoxArgs(options, isPersistent, userDataDir); - else if (options.channel === 'bidi-chrome-canary') - return this._defaultChromiumArgs(options, isPersistent, userDataDir); - throw new Error(`Unknown Bidi channel "${options.channel}"`); - } - - override readyState(options: types.LaunchOptions): BrowserReadyState | undefined { - assert(options.useWebSocket); - if (options.channel?.includes('firefox')) - return new FirefoxReadyState(); - if (options.channel?.includes('chrome')) - return new ChromiumReadyState(); - return undefined; - } - - private _defaultFirefoxArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { - const { args = [], headless } = options; - const userDataDirArg = args.find(arg => arg.startsWith('-profile') || arg.startsWith('--profile')); - if (userDataDirArg) - throw this._createUserDataDirArgMisuseError('--profile'); - const firefoxArguments = ['--remote-debugging-port=0']; - if (headless) - firefoxArguments.push('--headless'); - else - firefoxArguments.push('--foreground'); - firefoxArguments.push(`--profile`, userDataDir); - firefoxArguments.push(...args); - // TODO: make ephemeral context work without this argument. - firefoxArguments.push('about:blank'); - // if (isPersistent) - // firefoxArguments.push('about:blank'); - // else - // firefoxArguments.push('-silent'); - return firefoxArguments; - } - - private _defaultChromiumArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { const chromeArguments = this._innerDefaultArgs(options); chromeArguments.push(`--user-data-dir=${userDataDir}`); chromeArguments.push('--remote-debugging-port=0'); @@ -126,6 +85,11 @@ export class BidiBrowserType extends BrowserType { return chromeArguments; } + override readyState(options: types.LaunchOptions): BrowserReadyState | undefined { + assert(options.useWebSocket); + return new ChromiumReadyState(); + } + private _innerDefaultArgs(options: types.LaunchOptions): string[] { const { args = [], proxy } = options; const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir')); @@ -186,15 +150,6 @@ export class BidiBrowserType extends BrowserType { } } -class FirefoxReadyState extends BrowserReadyState { - override onBrowserOutput(message: string): void { - // Bidi WebSocket in Firefox. - const match = message.match(/WebDriver BiDi listening on (ws:\/\/.*)$/); - if (match) - this._wsEndpoint.resolve(match[1] + '/session'); - } -} - class ChromiumReadyState extends BrowserReadyState { override onBrowserOutput(message: string): void { const match = message.match(/DevTools listening on (.*)/); diff --git a/packages/playwright-core/src/server/bidi/bidiFirefox.ts b/packages/playwright-core/src/server/bidi/bidiFirefox.ts new file mode 100644 index 0000000000000..3a2da48c25614 --- /dev/null +++ b/packages/playwright-core/src/server/bidi/bidiFirefox.ts @@ -0,0 +1,101 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import os from 'os'; +import path from 'path'; +import { assert, wrapInASCIIBox } from '../../utils'; +import type { Env } from '../../utils/processLauncher'; +import type { BrowserOptions } from '../browser'; +import { BrowserReadyState, BrowserType, kNoXServerRunningError } from '../browserType'; +import type { SdkObject } from '../instrumentation'; +import type { ProtocolError } from '../protocolError'; +import type { ConnectionTransport } from '../transport'; +import type * as types from '../types'; +import { BidiBrowser } from './bidiBrowser'; +import { kBrowserCloseMessageId } from './bidiConnection'; + +export class BidiFirefox extends BrowserType { + constructor(parent: SdkObject) { + super(parent, 'bidi'); + this._useBidi = true; + } + + override async connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise { + return BidiBrowser.connect(this.attribution.playwright, transport, options); + } + + override doRewriteStartupLog(error: ProtocolError): ProtocolError { + if (!error.logs) + return error; + // https://github.com/microsoft/playwright/issues/6500 + if (error.logs.includes(`as root in a regular user's session is not supported.`)) + error.logs = '\n' + wrapInASCIIBox(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.\nWorkaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? ' in your GitHub Actions workflow file' : ''} when running Playwright.`, 1); + if (error.logs.includes('no DISPLAY environment variable specified')) + error.logs = '\n' + wrapInASCIIBox(kNoXServerRunningError, 1); + return error; + } + + override amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env { + if (!path.isAbsolute(os.homedir())) + throw new Error(`Cannot launch Firefox with relative home directory. Did you set ${os.platform() === 'win32' ? 'USERPROFILE' : 'HOME'} to a relative path?`); + if (os.platform() === 'linux') { + // Always remove SNAP_NAME and SNAP_INSTANCE_NAME env variables since they + // confuse Firefox: in our case, builds never come from SNAP. + // See https://github.com/microsoft/playwright/issues/20555 + return { ...env, SNAP_NAME: undefined, SNAP_INSTANCE_NAME: undefined }; + } + return env; + } + + override attemptToGracefullyCloseBrowser(transport: ConnectionTransport): void { + transport.send({ method: 'browser.close', params: {}, id: kBrowserCloseMessageId }); + } + + override defaultArgs(options: types.LaunchOptions, isPersistent: boolean, userDataDir: string): string[] { + const { args = [], headless } = options; + const userDataDirArg = args.find(arg => arg.startsWith('-profile') || arg.startsWith('--profile')); + if (userDataDirArg) + throw this._createUserDataDirArgMisuseError('--profile'); + const firefoxArguments = ['--remote-debugging-port=0']; + if (headless) + firefoxArguments.push('--headless'); + else + firefoxArguments.push('--foreground'); + firefoxArguments.push(`--profile`, userDataDir); + firefoxArguments.push(...args); + // TODO: make ephemeral context work without this argument. + firefoxArguments.push('about:blank'); + // if (isPersistent) + // firefoxArguments.push('about:blank'); + // else + // firefoxArguments.push('-silent'); + return firefoxArguments; + } + + override readyState(options: types.LaunchOptions): BrowserReadyState | undefined { + assert(options.useWebSocket); + return new FirefoxReadyState(); + } +} + +class FirefoxReadyState extends BrowserReadyState { + override onBrowserOutput(message: string): void { + // Bidi WebSocket in Firefox. + const match = message.match(/WebDriver BiDi listening on (ws:\/\/.*)$/); + if (match) + this._wsEndpoint.resolve(match[1] + '/session'); + } +} diff --git a/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts b/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts index cc0a259d75ae4..c411f93198046 100644 --- a/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/playwrightDispatcher.ts @@ -44,9 +44,10 @@ export class PlaywrightDispatcher extends Dispatcher(); @@ -64,7 +66,8 @@ export class Playwright extends SdkObject { } }, null); this.chromium = new Chromium(this); - this.bidi = new BidiBrowserType(this); + this.bidiChromium = new BidiChromium(this); + this.bidiFirefox = new BidiFirefox(this); this.firefox = new Firefox(this); this.webkit = new WebKit(this); this.electron = new Electron(this); diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 8970d336cc997..765c84c36e52b 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -15135,7 +15135,8 @@ export type AndroidKey = export const _electron: Electron; export const _android: Android; -export const _experimentalBidi: BrowserType; +export const _bidiChromium: BrowserType; +export const _bidiFirefox: BrowserType; // This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459 export {}; diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index 8273c5ef76eeb..add1661502828 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -83,15 +83,15 @@ const playwrightFixtures: Fixtures = ({ options.channel = channel; options.tracesDir = tracing().tracesDir(); - for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit, playwright._experimentalBidi]) + for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit, playwright._bidiChromium, playwright._bidiFirefox]) (browserType as any)._defaultLaunchOptions = options; await use(options); - for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit, playwright._experimentalBidi]) + for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit, playwright._bidiChromium, playwright._bidiFirefox]) (browserType as any)._defaultLaunchOptions = undefined; }, { scope: 'worker', auto: true, box: true }], browser: [async ({ playwright, browserName, _browserOptions, connectOptions, _reuseContext }, use, testInfo) => { - if (!['chromium', 'firefox', 'webkit', '_experimentalBidi'].includes(browserName)) + if (!['chromium', 'firefox', 'webkit', '_bidiChromium', '_bidiFirefox'].includes(browserName)) throw new Error(`Unexpected browserName "${browserName}", must be one of "chromium", "firefox" or "webkit"`); if (connectOptions) { diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index 0aead445ab728..c2896d169ed84 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -560,9 +560,10 @@ export interface RootEvents { // ----------- Playwright ----------- export type PlaywrightInitializer = { chromium: BrowserTypeChannel, - bidi: BrowserTypeChannel, firefox: BrowserTypeChannel, webkit: BrowserTypeChannel, + bidiChromium: BrowserTypeChannel, + bidiFirefox: BrowserTypeChannel, android: AndroidChannel, electron: ElectronChannel, utils?: LocalUtilsChannel, diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index 71fd44255d9ab..212fd7d1d90c3 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -668,9 +668,10 @@ Playwright: initializer: chromium: BrowserType - bidi: BrowserType firefox: BrowserType webkit: BrowserType + bidiChromium: BrowserType + bidiFirefox: BrowserType android: Android electron: Electron utils: LocalUtils? diff --git a/tests/bidi/playwright.config.ts b/tests/bidi/playwright.config.ts index 3bde84756a5de..7aa17f35ba9df 100644 --- a/tests/bidi/playwright.config.ts +++ b/tests/bidi/playwright.config.ts @@ -58,38 +58,44 @@ const config: Config { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [] }, + { _guid: 'browser-type', objects: [] }, { _guid: 'electron', objects: [] }, { _guid: 'localUtils', objects: [] }, { _guid: 'Playwright', objects: [] }, @@ -169,6 +174,7 @@ it('should scope browser handles', async ({ browserType, expectScopeState }) => { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [] }, + { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [ { _guid: 'browser', objects: [ @@ -206,6 +212,7 @@ it('should not generate dispatchers for subresources w/o listeners', async ({ pa { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [] }, + { _guid: 'browser-type', objects: [] }, { _guid: 'browser-type', objects: [ { _guid: 'browser', objects: [ @@ -289,6 +296,10 @@ it('exposeFunction should not leak', async ({ page, expectScopeState, server }) '_guid': 'browser-type', 'objects': [], }, + { + '_guid': 'browser-type', + 'objects': [], + }, { '_guid': 'browser-type', 'objects': [ diff --git a/utils/generate_types/overrides.d.ts b/utils/generate_types/overrides.d.ts index f2cb83997a1d0..be8ca9d71a8df 100644 --- a/utils/generate_types/overrides.d.ts +++ b/utils/generate_types/overrides.d.ts @@ -377,7 +377,8 @@ export type AndroidKey = export const _electron: Electron; export const _android: Android; -export const _experimentalBidi: BrowserType; +export const _bidiChromium: BrowserType; +export const _bidiFirefox: BrowserType; // This is required to not export everything by default. See https://github.com/Microsoft/TypeScript/issues/19545#issuecomment-340490459 export {}; From 16cef9901d328fc698bacfede7c58dae7c99807b Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 5 Sep 2024 21:36:13 -0700 Subject: [PATCH 010/805] chrome: cache tsconfig for folder (#32477) Fixes https://github.com/microsoft/playwright/issues/32459 --- .../src/third_party/tsconfig-loader.ts | 47 ++-------------- .../playwright/src/transform/transform.ts | 55 ++++++++++++++++--- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/packages/playwright/src/third_party/tsconfig-loader.ts b/packages/playwright/src/third_party/tsconfig-loader.ts index 490704c330d7f..61ad11a3bdd94 100644 --- a/packages/playwright/src/third_party/tsconfig-loader.ts +++ b/packages/playwright/src/third_party/tsconfig-loader.ts @@ -52,49 +52,12 @@ export interface LoadedTsConfig { allowJs?: boolean; } -export function tsConfigLoader(tsconfigPathOrDirecotry: string): LoadedTsConfig[] { - const configPath = resolveConfigPath(tsconfigPathOrDirecotry); - - if (!configPath) - return []; - +export function loadTsConfig(configPath: string): LoadedTsConfig[] { const references: LoadedTsConfig[] = []; - const config = loadTsConfig(configPath, references); + const config = innerLoadTsConfig(configPath, references); return [config, ...references]; } -function resolveConfigPath(tsconfigPathOrDirecotry: string): string | undefined { - if (fs.statSync(tsconfigPathOrDirecotry).isFile()) { - return path.resolve(tsconfigPathOrDirecotry); - } - - const configAbsolutePath = walkForTsConfig(tsconfigPathOrDirecotry); - return configAbsolutePath ? path.resolve(configAbsolutePath) : undefined; -} - -export function walkForTsConfig( - directory: string, - existsSync: (path: string) => boolean = fs.existsSync -): string | undefined { - const tsconfigPath = path.join(directory, "./tsconfig.json"); - if (existsSync(tsconfigPath)) { - return tsconfigPath; - } - const jsconfigPath = path.join(directory, "./jsconfig.json"); - if (existsSync(jsconfigPath)) { - return jsconfigPath; - } - - const parentDirectory = path.join(directory, "../"); - - // If we reached the top - if (directory === parentDirectory) { - return undefined; - } - - return walkForTsConfig(parentDirectory, existsSync); -} - function resolveConfigFile(baseConfigFile: string, referencedConfigFile: string) { if (!referencedConfigFile.endsWith('.json')) referencedConfigFile += '.json'; @@ -106,7 +69,7 @@ function resolveConfigFile(baseConfigFile: string, referencedConfigFile: string) return resolvedConfigFile; } -function loadTsConfig( +function innerLoadTsConfig( configFilePath: string, references: LoadedTsConfig[], visited = new Map(), @@ -130,7 +93,7 @@ function loadTsConfig( const extendsArray = Array.isArray(parsedConfig.extends) ? parsedConfig.extends : (parsedConfig.extends ? [parsedConfig.extends] : []); for (const extendedConfig of extendsArray) { const extendedConfigPath = resolveConfigFile(configFilePath, extendedConfig); - const base = loadTsConfig(extendedConfigPath, references, visited); + const base = innerLoadTsConfig(extendedConfigPath, references, visited); // Retain result instance, so that caching works. Object.assign(result, base, { tsConfigPath: configFilePath }); } @@ -154,7 +117,7 @@ function loadTsConfig( } for (const ref of parsedConfig.references || []) - references.push(loadTsConfig(resolveConfigFile(configFilePath, ref.path), references, visited)); + references.push(innerLoadTsConfig(resolveConfigFile(configFilePath, ref.path), references, visited)); if (path.basename(configFilePath) === 'jsconfig.json' && result.allowJs === undefined) result.allowJs = true; diff --git a/packages/playwright/src/transform/transform.ts b/packages/playwright/src/transform/transform.ts index 925cf7a83e739..52d05dde90369 100644 --- a/packages/playwright/src/transform/transform.ts +++ b/packages/playwright/src/transform/transform.ts @@ -15,12 +15,13 @@ */ import crypto from 'crypto'; +import fs from 'fs'; import path from 'path'; import url from 'url'; import { sourceMapSupport, pirates } from '../utilsBundle'; import type { Location } from '../../types/testReporter'; import type { LoadedTsConfig } from '../third_party/tsconfig-loader'; -import { tsConfigLoader } from '../third_party/tsconfig-loader'; +import { loadTsConfig } from '../third_party/tsconfig-loader'; import Module from 'module'; import type { BabelPlugin, BabelTransformFunction } from './babelBundle'; import { createFileMatcher, fileIsModule, resolveImportSpecifierExtension } from '../util'; @@ -57,14 +58,15 @@ export function transformConfig(): TransformConfig { return _transformConfig; } -let _singleTSConfig: string | undefined; +let _singleTSConfigPath: string | undefined; +let _singleTSConfig: ParsedTsConfigData[] | undefined; export function setSingleTSConfig(value: string | undefined) { - _singleTSConfig = value; + _singleTSConfigPath = value; } export function singleTSConfig(): string | undefined { - return _singleTSConfig; + return _singleTSConfigPath; } function validateTsConfig(tsconfig: LoadedTsConfig): ParsedTsConfigData { @@ -81,12 +83,47 @@ function validateTsConfig(tsconfig: LoadedTsConfig): ParsedTsConfigData { } function loadAndValidateTsconfigsForFile(file: string): ParsedTsConfigData[] { - const tsconfigPathOrDirecotry = _singleTSConfig || path.dirname(file); - if (!cachedTSConfigs.has(tsconfigPathOrDirecotry)) { - const loaded = tsConfigLoader(tsconfigPathOrDirecotry); - cachedTSConfigs.set(tsconfigPathOrDirecotry, loaded.map(validateTsConfig)); + if (_singleTSConfigPath && !_singleTSConfig) + _singleTSConfig = loadTsConfig(_singleTSConfigPath).map(validateTsConfig); + if (_singleTSConfig) + return _singleTSConfig; + return loadAndValidateTsconfigsForFolder(path.dirname(file)); +} + +function loadAndValidateTsconfigsForFolder(folder: string): ParsedTsConfigData[] { + const foldersWithConfig: string[] = []; + let currentFolder = path.resolve(folder); + let result: ParsedTsConfigData[] | undefined; + while (true) { + const cached = cachedTSConfigs.get(currentFolder); + if (cached) { + result = cached; + break; + } + + foldersWithConfig.push(currentFolder); + + for (const name of ['tsconfig.json', 'jsconfig.json']) { + const configPath = path.join(currentFolder, name); + if (fs.existsSync(configPath)) { + const loaded = loadTsConfig(configPath); + result = loaded.map(validateTsConfig); + break; + } + } + if (result) + break; + + const parentFolder = path.resolve(currentFolder, '../'); + if (currentFolder === parentFolder) + break; + currentFolder = parentFolder; } - return cachedTSConfigs.get(tsconfigPathOrDirecotry)!; + + result = result || []; + for (const folder of foldersWithConfig) + cachedTSConfigs.set(folder, result); + return result; } const pathSeparator = process.platform === 'win32' ? ';' : ':'; From a52eb0c9a08c7781a797553611695321445b37ca Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 5 Sep 2024 21:36:51 -0700 Subject: [PATCH 011/805] chore: expose matcherResult on TestError (#32455) --- .../class-testinfoerror-matcherresult.md | 35 +++++ docs/src/test-api/class-testinfoerror.md | 6 + .../class-testerror-matcherresult.md | 35 +++++ docs/src/test-reporter-api/class-testerror.md | 6 + packages/playwright/src/reporters/base.ts | 3 + packages/playwright/src/util.ts | 16 +- packages/playwright/types/test.d.ts | 36 +++++ packages/playwright/types/testReporter.d.ts | 36 +++++ tests/playwright-test/reporter-errors.spec.ts | 145 ++++++++++++++++++ utils/generate_types/overrides-test.d.ts | 1 + .../overrides-testReporter.d.ts | 1 + 11 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 docs/src/test-api/class-testinfoerror-matcherresult.md create mode 100644 docs/src/test-reporter-api/class-testerror-matcherresult.md create mode 100644 tests/playwright-test/reporter-errors.spec.ts diff --git a/docs/src/test-api/class-testinfoerror-matcherresult.md b/docs/src/test-api/class-testinfoerror-matcherresult.md new file mode 100644 index 0000000000000..f68e2db1ae908 --- /dev/null +++ b/docs/src/test-api/class-testinfoerror-matcherresult.md @@ -0,0 +1,35 @@ +# class: TestInfoErrorMatcherResult +* since: v1.48 +* langs: js + +Matcher-specific details for the error thrown during the `expect` call. + +## property: TestInfoErrorMatcherResult.actual +* since: v1.48 +- type: ?<[unknown]> + +Actual value. + +## property: TestInfoErrorMatcherResult.expected +* since: v1.48 +- type: ?<[unknown]> + +Expected value. + +## property: TestInfoErrorMatcherResult.name +* since: v1.48 +- type: ?<[string]> + +Matcher name. + +## property: TestInfoErrorMatcherResult.pass +* since: v1.48 +- type: <[string]> + +Whether the matcher passed. + +## property: TestInfoErrorMatcherResult.timeout +* since: v1.48 +- type: ?<[int]> + +Timeout that was used during matching. diff --git a/docs/src/test-api/class-testinfoerror.md b/docs/src/test-api/class-testinfoerror.md index 66e78ecabdafc..b084aaf54b65e 100644 --- a/docs/src/test-api/class-testinfoerror.md +++ b/docs/src/test-api/class-testinfoerror.md @@ -4,6 +4,12 @@ Information about an error thrown during test execution. +## property: TestInfoError.matcherResult +* since: v1.48 +- type: ?<[TestInfoErrorMatcherResult]> + +Matcher result details. + ## property: TestInfoError.message * since: v1.10 - type: ?<[string]> diff --git a/docs/src/test-reporter-api/class-testerror-matcherresult.md b/docs/src/test-reporter-api/class-testerror-matcherresult.md new file mode 100644 index 0000000000000..b8d0f1dce70c1 --- /dev/null +++ b/docs/src/test-reporter-api/class-testerror-matcherresult.md @@ -0,0 +1,35 @@ +# class: TestErrorMatcherResult +* since: v1.48 +* langs: js + +Matcher-specific details for the error thrown during the `expect` call. + +## property: TestErrorMatcherResult.actual +* since: v1.48 +- type: ?<[unknown]> + +Actual value. + +## property: TestErrorMatcherResult.expected +* since: v1.48 +- type: ?<[unknown]> + +Expected value. + +## property: TestErrorMatcherResult.name +* since: v1.48 +- type: ?<[string]> + +Matcher name. + +## property: TestErrorMatcherResult.pass +* since: v1.48 +- type: <[string]> + +Whether the matcher passed. + +## property: TestErrorMatcherResult.timeout +* since: v1.48 +- type: ?<[int]> + +Timeout that was used during matching. diff --git a/docs/src/test-reporter-api/class-testerror.md b/docs/src/test-reporter-api/class-testerror.md index 7a872c63fcb8a..cc59c3a4c68c9 100644 --- a/docs/src/test-reporter-api/class-testerror.md +++ b/docs/src/test-reporter-api/class-testerror.md @@ -4,6 +4,12 @@ Information about an error thrown during test execution. +## property: TestError.matcherResult +* since: v1.48 +- type: ?<[TestErrorMatcherResult]> + +Matcher result details. + ## property: TestError.message * since: v1.10 - type: ?<[string]> diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index c9ce2f7bcd4cd..22470b0954d10 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -32,6 +32,7 @@ type Annotation = { type ErrorDetails = { message: string; location?: Location; + matcherResult?: TestError['matcherResult']; }; type TestSummary = { @@ -399,6 +400,7 @@ export function formatResultFailure(test: TestCase, result: TestResult, initialI errorDetails.push({ message: indent(formattedError.message, initialIndent), location: formattedError.location, + matcherResult: formattedError.matcherResult }); } return errorDetails; @@ -489,6 +491,7 @@ export function formatError(error: TestError, highlightCode: boolean): ErrorDeta return { location, message: tokens.join('\n'), + matcherResult: error.matcherResult }; } diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 06e18f206aa7c..4c75d9d84136e 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -63,8 +63,20 @@ export function filteredStackTrace(rawStack: RawStack): StackFrame[] { } export function serializeError(error: Error | any): TestInfoError { - if (error instanceof Error) - return filterStackTrace(error); + if (error instanceof Error) { + const result: TestInfoError = filterStackTrace(error); + if ('matcherResult' in error && error.matcherResult) { + const matcherResult = (error.matcherResult as TestInfoError['matcherResult'])!; + result.matcherResult = { + pass: matcherResult.pass, + name: matcherResult.name, + expected: matcherResult.expected, + actual: matcherResult.actual, + timeout: matcherResult.timeout, + }; + } + return result; + } return { value: util.inspect(error) }; diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 21bd59af5d10d..09b5c7efdb82c 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -6546,6 +6546,7 @@ export type MatcherReturnType = { expected?: unknown; actual?: any; log?: string[]; + timeout?: number; }; type MakeMatchers = { @@ -8221,10 +8222,45 @@ export interface TestInfo { workerIndex: number; } +/** + * Matcher-specific details for the error thrown during the `expect` call. + */ +export interface TestInfoErrorMatcherResult { + /** + * Actual value. + */ + actual?: unknown; + + /** + * Expected value. + */ + expected?: unknown; + + /** + * Matcher name. + */ + name?: string; + + /** + * Whether the matcher passed. + */ + pass: string; + + /** + * Timeout that was used during matching. + */ + timeout?: number; +} + /** * Information about an error thrown during test execution. */ export interface TestInfoError { + /** + * Matcher result details. + */ + matcherResult?: TestInfoErrorMatcherResult; + /** * Error message. Set when [Error] (or its subclass) has been thrown. */ diff --git a/packages/playwright/types/testReporter.d.ts b/packages/playwright/types/testReporter.d.ts index 52073066f0efb..b600e3c80178e 100644 --- a/packages/playwright/types/testReporter.d.ts +++ b/packages/playwright/types/testReporter.d.ts @@ -284,6 +284,7 @@ export interface JSONReportTest { export interface JSONReportError { message: string; location?: Location; + matcherResult?: TestErrorMatcherResult; } export interface JSONReportTestResult { @@ -567,6 +568,36 @@ export interface TestCase { type: "test"; } +/** + * Matcher-specific details for the error thrown during the `expect` call. + */ +export interface TestErrorMatcherResult { + /** + * Actual value. + */ + actual?: unknown; + + /** + * Expected value. + */ + expected?: unknown; + + /** + * Matcher name. + */ + name?: string; + + /** + * Whether the matcher passed. + */ + pass: string; + + /** + * Timeout that was used during matching. + */ + timeout?: number; +} + /** * Information about an error thrown during test execution. */ @@ -576,6 +607,11 @@ export interface TestError { */ location?: Location; + /** + * Matcher result details. + */ + matcherResult?: TestErrorMatcherResult; + /** * Error message. Set when [Error] (or its subclass) has been thrown. */ diff --git a/tests/playwright-test/reporter-errors.spec.ts b/tests/playwright-test/reporter-errors.spec.ts new file mode 100644 index 0000000000000..ad0923723426e --- /dev/null +++ b/tests/playwright-test/reporter-errors.spec.ts @@ -0,0 +1,145 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { test, expect } from './playwright-test-fixtures'; + +test('should report matcherResults for generic matchers', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.js': ` + import { test, expect as baseExpect } from '@playwright/test'; + const expect = baseExpect.soft; + test('fail', ({}) => { + expect(1).toBe(2); + expect(1).toBeCloseTo(2); + expect(undefined).toBeDefined(); + expect(1).toBeFalsy(); + expect(1).toBeGreaterThan(2); + expect(1).toBeGreaterThanOrEqual(2); + expect('a').toBeInstanceOf(Number); + expect(2).toBeLessThan(1); + expect(2).toBeLessThanOrEqual(1); + expect(1).toBeNaN(); + expect(1).toBeNull(); + expect(0).toBeTruthy(); + expect(1).toBeUndefined(); + expect([1]).toContain(2); + expect([1]).toContainEqual(2); + expect([1]).toEqual([2]); + expect([1]).toHaveLength(2); + expect({ a: 1 }).toHaveProperty('b'); + expect('a').toMatch(/b/); + expect({ a: 1 }).toMatchObject({ b: 2 }); + expect({ a: 1 }).toStrictEqual({ b: 2 }); + expect(() => {}).toThrow(); + expect(() => {}).toThrowError('a'); + }); + ` + }, { }); + expect(result.exitCode).toBe(1); + + const { errors } = result.report.suites[0].specs[0].tests[0].results[0]; + const matcherResults = errors.map(e => e.matcherResult); + expect(matcherResults).toEqual([ + { name: 'toBe', pass: false, expected: 2, actual: 1 }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { name: 'toEqual', pass: false, expected: [2], actual: [1] }, + { pass: false }, + { pass: false }, + { pass: false }, + { pass: false }, + { name: 'toStrictEqual', pass: false, expected: { b: 2 }, actual: { a: 1 } }, + { pass: false }, + { pass: false }, + ]); +}); + +test('should report matcherResults for web matchers', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.js': ` + import { test, expect as baseExpect } from '@playwright/test'; + + const expect = baseExpect.configure({ soft: true, timeout: 1 }); + test('fail', async ({ page }) => { + await page.setContent('Hello
World
'); + await expect(page.locator('input')).toBeChecked(); + await expect(page.locator('input')).toBeDisabled(); + await expect(page.locator('textarea')).not.toBeEditable(); + await expect(page.locator('span')).toBeEmpty(); + await expect(page.locator('button')).not.toBeEnabled(); + await expect(page.locator('button')).toBeFocused(); + await expect(page.locator('span')).toBeHidden(); + await expect(page.locator('div')).not.toBeInViewport(); + await expect(page.locator('div')).not.toBeVisible(); + await expect(page.locator('span')).toContainText('World'); + await expect(page.locator('span')).toHaveAccessibleDescription('World'); + await expect(page.locator('span')).toHaveAccessibleName('World'); + await expect(page.locator('span')).toHaveAttribute('name', 'value'); + await expect(page.locator('span')).toHaveAttribute('name'); + await expect(page.locator('span')).toHaveClass('name'); + await expect(page.locator('span')).toHaveCount(2); + await expect(page.locator('span')).toHaveCSS('width', '10'); + await expect(page.locator('span')).toHaveId('id'); + await expect(page.locator('span')).toHaveJSProperty('name', 'value'); + await expect(page.locator('span')).toHaveRole('role'); + await expect(page.locator('span')).toHaveText('World'); + await expect(page.locator('textarea')).toHaveValue('value'); + await expect(page.locator('select')).toHaveValues(['value']); + }); + ` + }, { }); + expect(result.exitCode).toBe(1); + + const { errors } = result.report.suites[0].specs[0].tests[0].results[0]; + const matcherResults = errors.map(e => e.matcherResult); + expect(matcherResults).toEqual([ + { name: 'toBeChecked', pass: false, expected: 'checked', actual: 'unchecked', timeout: 1 }, + { name: 'toBeDisabled', pass: false, expected: 'disabled', actual: 'enabled', timeout: 1 }, + { name: 'toBeEditable', pass: true, expected: 'editable', actual: 'editable', timeout: 1 }, + { name: 'toBeEmpty', pass: false, expected: 'empty', actual: 'notEmpty', timeout: 1 }, + { name: 'toBeEnabled', pass: true, expected: 'enabled', actual: 'enabled', timeout: 1 }, + { name: 'toBeFocused', pass: false, expected: 'focused', actual: 'inactive', timeout: 1 }, + { name: 'toBeHidden', pass: false, expected: 'hidden', actual: 'visible', timeout: 1 }, + { name: 'toBeInViewport', pass: true, expected: 'in viewport', actual: 'in viewport', timeout: 1 }, + { name: 'toBeVisible', pass: true, expected: 'visible', actual: 'visible', timeout: 1 }, + { name: 'toContainText', pass: false, expected: 'World', actual: 'Hello', timeout: 1 }, + { name: 'toHaveAccessibleDescription', pass: false, expected: 'World', actual: '', timeout: 1 }, + { name: 'toHaveAccessibleName', pass: false, expected: 'World', actual: '', timeout: 1 }, + { name: 'toHaveAttribute', pass: false, expected: 'value', actual: null, timeout: 1 }, + { name: 'toHaveAttribute', pass: false, expected: 'have attribute', actual: 'not have attribute', timeout: 1 }, + { name: 'toHaveClass', pass: false, expected: 'name', actual: '', timeout: 1 }, + { name: 'toHaveCount', pass: false, expected: 2, actual: 1, timeout: 1 }, + { name: 'toHaveCSS', pass: false, expected: '10', actual: 'auto', timeout: 1 }, + { name: 'toHaveId', pass: false, expected: 'id', actual: '', timeout: 1 }, + { name: 'toHaveJSProperty', pass: false, expected: 'value', timeout: 1 }, + { name: 'toHaveRole', pass: false, expected: 'role', actual: '', timeout: 1 }, + { name: 'toHaveText', pass: false, expected: 'World', actual: 'Hello', timeout: 1 }, + { name: 'toHaveValue', pass: false, expected: 'value', actual: '', timeout: 1 }, + { name: 'toHaveValues', pass: false, expected: ['value'], actual: [], timeout: 1 }, + ]); +}); diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 8494671c7617a..90ef7fa75a52c 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -384,6 +384,7 @@ export type MatcherReturnType = { expected?: unknown; actual?: any; log?: string[]; + timeout?: number; }; type MakeMatchers = { diff --git a/utils/generate_types/overrides-testReporter.d.ts b/utils/generate_types/overrides-testReporter.d.ts index 51eab7e370508..0b81724373048 100644 --- a/utils/generate_types/overrides-testReporter.d.ts +++ b/utils/generate_types/overrides-testReporter.d.ts @@ -105,6 +105,7 @@ export interface JSONReportTest { export interface JSONReportError { message: string; location?: Location; + matcherResult?: TestErrorMatcherResult; } export interface JSONReportTestResult { From 5d4a65b31835fcec13fccb84f703f92606a20b0d Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Fri, 6 Sep 2024 10:28:17 +0200 Subject: [PATCH 012/805] docs: update release notes for 1.47 to our changes from yesterday (#32482) I'll also cherry-pick this into the release branch and update playwright.dev. --- docs/src/release-notes-csharp.md | 10 +++++----- docs/src/release-notes-java.md | 10 +++++----- docs/src/release-notes-js.md | 10 +++++----- docs/src/release-notes-python.md | 10 +++++----- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index f4532376de712..6c357ba3b510a 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -8,13 +8,13 @@ toc_max_heading_level: 2 ### Network Tab improvements -The Network tab in the trace viewer now allows searching and filtering by asset type: +The Network tab in the trace viewer has several nice improvements: -![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) - -And for fonts, it now shows a nice preview: +- filtering by asset type and URL +- better display of query string parameters +- preview of font assets -![Font requests have a preview now](https://github.com/user-attachments/assets/769d64cc-cdcb-421d-9849-227d2f874d1f) +![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) ### Miscellaneous diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index 4eab504435bc2..2b9789e8bce99 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -8,13 +8,13 @@ toc_max_heading_level: 2 ### Network Tab improvements -The Network tab in the trace viewer now allows searching and filtering by asset type: +The Network tab in the trace viewer has several nice improvements: -![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) - -And for fonts, it now shows a nice preview: +- filtering by asset type and URL +- better display of query string parameters +- preview of font assets -![Font requests have a preview now](https://github.com/user-attachments/assets/769d64cc-cdcb-421d-9849-227d2f874d1f) +![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) ### Miscellaneous diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md index 386fa4abf8a28..a89b79c5ce330 100644 --- a/docs/src/release-notes-js.md +++ b/docs/src/release-notes-js.md @@ -10,13 +10,13 @@ import LiteYouTube from '@site/src/components/LiteYouTube'; ### Network Tab improvements -The Network tab in the UI mode and trace viewer now allows searching and filtering by asset type: +The Network tab in the UI mode and trace viewer has several nice improvements: -![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) - -And for fonts, it now shows a nice preview: +- filtering by asset type and URL +- better display of query string parameters +- preview of font assets -![Font requests have a preview now](https://github.com/user-attachments/assets/769d64cc-cdcb-421d-9849-227d2f874d1f) +![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) ### `--tsconfig` CLI option diff --git a/docs/src/release-notes-python.md b/docs/src/release-notes-python.md index 5fbf11873b6a1..985c19d388e41 100644 --- a/docs/src/release-notes-python.md +++ b/docs/src/release-notes-python.md @@ -8,13 +8,13 @@ toc_max_heading_level: 2 ### Network Tab improvements -The Network tab in the trace viewer now allows searching and filtering by asset type: +The Network tab in the trace viewer has several nice improvements: -![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) - -And for fonts, it now shows a nice preview: +- filtering by asset type and URL +- better display of query string parameters +- preview of font assets -![Font requests have a preview now](https://github.com/user-attachments/assets/769d64cc-cdcb-421d-9849-227d2f874d1f) +![Network tab now has filters](https://github.com/user-attachments/assets/4bd1b67d-90bd-438b-a227-00b9e86872e2) ### Miscellaneous From a8f67a42b8995d0e3f8dbf82ca755e93de7ee0b0 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 6 Sep 2024 11:27:35 +0200 Subject: [PATCH 013/805] docs(dotnet): fix wrong snippets (#32484) Fixes https://github.com/microsoft/playwright-dotnet/issues/2994 --- docs/src/api/class-pageassertions.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/api/class-pageassertions.md b/docs/src/api/class-pageassertions.md index 2dcd17b3ac7b5..5e56907656d32 100644 --- a/docs/src/api/class-pageassertions.md +++ b/docs/src/api/class-pageassertions.md @@ -83,7 +83,7 @@ assertThat(page).not().hasURL("error"); ``` ```csharp -await Expect(Page).Not.ToHaveURL("error"); +await Expect(Page).Not.ToHaveURLAsync("error"); ``` ## async method: PageAssertions.NotToHaveTitle @@ -271,7 +271,7 @@ expect(page).to_have_title(re.compile(r".*checkout")) ``` ```csharp -await Expect(Page).ToHaveTitle("Playwright"); +await Expect(Page).ToHaveTitleAsync("Playwright"); ``` ### param: PageAssertions.toHaveTitle.titleOrRegExp @@ -320,7 +320,7 @@ expect(page).to_have_url(re.compile(".*checkout")) ``` ```csharp -await Expect(Page).ToHaveURL(new Regex(".*checkout")); +await Expect(Page).ToHaveURLAsync(new Regex(".*checkout")); ``` ### param: PageAssertions.toHaveURL.urlOrRegExp From 0e3f4736cc5f31823174e4b57c9c30ac2320d168 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Fri, 6 Sep 2024 11:35:20 +0200 Subject: [PATCH 014/805] fix(test runner): always show all projects in selection (#32450) Follow-up to https://github.com/microsoft/playwright/pull/32156#discussion_r1741628770, alternative solution to https://github.com/microsoft/playwright/pull/32425. Ensures we always show all projects in the watch mode project selector by performing the initial `listTests` without any filters, and using its result for the project selector. --- packages/playwright/src/runner/watchMode.ts | 6 ++++-- tests/playwright-test/watch.spec.ts | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/playwright/src/runner/watchMode.ts b/packages/playwright/src/runner/watchMode.ts index 924449adce7e4..ba2c5a34e7651 100644 --- a/packages/playwright/src/runner/watchMode.ts +++ b/packages/playwright/src/runner/watchMode.ts @@ -125,9 +125,11 @@ export async function runWatchModeLoop(configLocation: ConfigLocation, initialOp await testServerConnection.initialize({ interceptStdio: false, watchTestDirs: true }); await testServerConnection.runGlobalSetup({}); - const { report } = await testServerConnection.listTests({ locations: options.files, projects: options.projects, grep: options.grep }); + const { report } = await testServerConnection.listTests({}); teleSuiteUpdater.processListReport(report); + const projectNames = teleSuiteUpdater.rootSuite!.suites.map(s => s.title); + let lastRun: { type: 'changed' | 'regular' | 'failed', failedTestIds?: string[], dirtyTestIds?: string[] } = { type: 'regular' }; let result: FullResult['status'] = 'passed'; @@ -167,7 +169,7 @@ export async function runWatchModeLoop(configLocation: ConfigLocation, initialOp type: 'multiselect', name: 'selectedProjects', message: 'Select projects', - choices: teleSuiteUpdater.rootSuite!.suites.map(s => s.title), + choices: projectNames, }).catch(() => ({ selectedProjects: null })); if (!selectedProjects) continue; diff --git a/tests/playwright-test/watch.spec.ts b/tests/playwright-test/watch.spec.ts index 0dba9dd861b3c..f4d1fd72cedb1 100644 --- a/tests/playwright-test/watch.spec.ts +++ b/tests/playwright-test/watch.spec.ts @@ -282,8 +282,8 @@ test('should respect file filter P', async ({ runWatchTest }) => { await testProcess.waitForOutput('Waiting for file changes.'); }); -test('should respect project filter C', async ({ runWatchTest }) => { - const testProcess = await runWatchTest({ +test('should respect project filter C', async ({ runWatchTest, writeFiles }) => { + const files = { 'playwright.config.ts': ` import { defineConfig } from '@playwright/test'; export default defineConfig({ projects: [{name: 'foo'}, {name: 'bar'}] }); @@ -292,9 +292,9 @@ test('should respect project filter C', async ({ runWatchTest }) => { import { test, expect } from '@playwright/test'; test('passes', () => {}); `, - }); + }; + const testProcess = await runWatchTest(files, { project: 'foo' }); await testProcess.waitForOutput('[foo] › a.test.ts:3:11 › passes'); - await testProcess.waitForOutput('[bar] › a.test.ts:3:11 › passes'); await testProcess.waitForOutput('Waiting for file changes.'); testProcess.clearOutput(); testProcess.write('c'); @@ -306,6 +306,16 @@ test('should respect project filter C', async ({ runWatchTest }) => { await testProcess.waitForOutput('npx playwright test --project foo #1'); await testProcess.waitForOutput('[foo] › a.test.ts:3:11 › passes'); expect(testProcess.output).not.toContain('[bar] › a.test.ts:3:11 › passes'); + + testProcess.clearOutput(); + + await writeFiles(files); // file change triggers listTests with project filter + await testProcess.waitForOutput('[foo] › a.test.ts:3:11 › passes'); + + testProcess.write('c'); + await testProcess.waitForOutput('Select projects'); + await testProcess.waitForOutput('foo'); + await testProcess.waitForOutput('bar'); // second selection should still show all }); test('should respect file filter P and split files', async ({ runWatchTest }) => { From ed303208b3750ac9662894fbeb5d655ae21b3f9c Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 6 Sep 2024 14:27:56 +0200 Subject: [PATCH 015/805] test: update to android-35 SDK (Android 15) (#32430) --- tests/android/webview.spec.ts | 4 ++++ tests/page/page-request-intercept.spec.ts | 3 ++- utils/avd_install.sh | 2 +- utils/avd_recreate.sh | 6 +++--- utils/avd_start.sh | 6 +++--- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/android/webview.spec.ts b/tests/android/webview.spec.ts index 46e0e385a05fe..ca7a114bb1279 100644 --- a/tests/android/webview.spec.ts +++ b/tests/android/webview.spec.ts @@ -16,6 +16,10 @@ import { androidTest as test, expect } from './androidTest'; +test.beforeEach(async ({ androidDevice }) => { + await androidDevice.shell('am force-stop com.google.android.googlequicksearchbox'); +}); + test.afterEach(async ({ androidDevice }) => { await androidDevice.shell('am force-stop org.chromium.webview_shell'); await androidDevice.shell('am force-stop com.android.chrome'); diff --git a/tests/page/page-request-intercept.spec.ts b/tests/page/page-request-intercept.spec.ts index 33516606e7971..eb9baae47e260 100644 --- a/tests/page/page-request-intercept.spec.ts +++ b/tests/page/page-request-intercept.spec.ts @@ -284,8 +284,9 @@ it('should fulfill popup main request using alias', async ({ page, server, isEle it('request.postData is not null when fetching FormData with a Blob', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/24077' } -}, async ({ server, page, browserName, isElectron, electronMajorVersion }) => { +}, async ({ server, page, browserName, isElectron, electronMajorVersion, isAndroid }) => { it.skip(isElectron && electronMajorVersion < 31); + it.fixme(isAndroid, 'postData is null for some reason'); it.fixme(browserName === 'webkit', 'The body is empty in WebKit when intercepting'); await page.goto(server.EMPTY_PAGE); await page.setContent(` diff --git a/utils/avd_install.sh b/utils/avd_install.sh index 6beb8bf43f846..a0586d6936e4a 100755 --- a/utils/avd_install.sh +++ b/utils/avd_install.sh @@ -24,7 +24,7 @@ echo Installing emulator... yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install platform-tools emulator echo Installing platform SDK... -yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "platforms;android-33" +yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "platforms;android-35" echo Starting ADB... ${ANDROID_HOME}/platform-tools/adb devices diff --git a/utils/avd_recreate.sh b/utils/avd_recreate.sh index 0877e76ed1630..81c348490725b 100755 --- a/utils/avd_recreate.sh +++ b/utils/avd_recreate.sh @@ -13,7 +13,7 @@ if [[ "$(uname -m)" == "arm64" ]]; then ANDROID_ARCH="arm64-v8a" fi -${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager delete avd --name android33 || true -yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "system-images;android-33;google_apis;$ANDROID_ARCH" platform-tools emulator -echo "no" | ${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager create avd --force --name android33 --device "Nexus 5X" --package "system-images;android-33;google_apis;$ANDROID_ARCH" +${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager delete avd --name android35 || true +yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --install "system-images;android-35;google_apis;$ANDROID_ARCH" platform-tools emulator +echo "no" | ${ANDROID_HOME}/cmdline-tools/latest/bin/avdmanager create avd --force --name android35 --device "Nexus 5X" --package "system-images;android-35;google_apis;$ANDROID_ARCH" ${ANDROID_HOME}/emulator/emulator -list-avds diff --git a/utils/avd_start.sh b/utils/avd_start.sh index 67acb1c63e1c9..1c3bc53418338 100755 --- a/utils/avd_start.sh +++ b/utils/avd_start.sh @@ -9,15 +9,15 @@ fi bash $PWD/utils/avd_stop.sh echo "Starting emulator" -# nohup ${ANDROID_HOME}/emulator/emulator -avd android33 -gpu swiftshader & -nohup ${ANDROID_HOME}/emulator/emulator -avd android33 -no-audio -no-window -no-boot-anim -no-snapshot & +# nohup ${ANDROID_HOME}/emulator/emulator -avd android35 -gpu swiftshader & +nohup ${ANDROID_HOME}/emulator/emulator -avd android35 -no-audio -no-window -no-boot-anim -no-snapshot & ${ANDROID_HOME}/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82' ${ANDROID_HOME}/platform-tools/adb devices echo "Emulator started" echo "Installing Chromium WebView" # See here for the latest revision: https://storage.googleapis.com/chromium-browser-snapshots/Android/LAST_CHANGE -CHROMIUM_ANDROID_REVISION="1190572" +CHROMIUM_ANDROID_REVISION="1340145" WEBVIEW_TMP_DIR="$(mktemp -d)" WEBVIEW_TMP_FILE="$WEBVIEW_TMP_DIR/chrome-android-zip" curl -s -o "${WEBVIEW_TMP_FILE}" "https://storage.googleapis.com/chromium-browser-snapshots/Android/${CHROMIUM_ANDROID_REVISION}/chrome-android.zip" From 3fe1263643b3b8590c63b0f4df677d174a626bc8 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Fri, 6 Sep 2024 16:24:33 +0200 Subject: [PATCH 016/805] feat(trace viewer): show Screenshot instead of Snapshot (#32248) Closes https://github.com/microsoft/playwright/issues/23964. Trace snapshots are a best-effort snapshots of the browser DOM, but we can't guarantee them to be exactly what the browser showed. One example of this is `canvas` elements, where you just can't see their contents. That makes snapshots useful, but not perfect. For those cases where the snapshot doesn't show everything, this PR introduces a new setting to show a screenshot instead. You won't be able to scroll or inspect the DOM or select a locator anymore. But if the snapshot was missing something, or displaying something wrong, you can now check the screenshot instead. --- packages/trace-viewer/src/entries.ts | 1 + packages/trace-viewer/src/snapshotServer.ts | 3 +- packages/trace-viewer/src/traceModernizer.ts | 1 + packages/trace-viewer/src/ui/inspectorTab.tsx | 6 ++- packages/trace-viewer/src/ui/modelUtil.ts | 6 +++ packages/trace-viewer/src/ui/snapshotTab.tsx | 38 +++++++++++++++---- packages/trace-viewer/src/ui/uiModeView.tsx | 3 ++ packages/trace-viewer/src/ui/workbench.tsx | 8 +++- packages/web/src/uiUtils.ts | 2 +- tests/config/traceViewerFixtures.ts | 6 +-- tests/library/trace-viewer.spec.ts | 30 +++++++++++++++ 11 files changed, 88 insertions(+), 16 deletions(-) diff --git a/packages/trace-viewer/src/entries.ts b/packages/trace-viewer/src/entries.ts index bca5751ab2712..98d39927f732f 100644 --- a/packages/trace-viewer/src/entries.ts +++ b/packages/trace-viewer/src/entries.ts @@ -41,6 +41,7 @@ export type ContextEntry = { }; export type PageEntry = { + pageId: string, screencastFrames: { sha1: string, timestamp: number, diff --git a/packages/trace-viewer/src/snapshotServer.ts b/packages/trace-viewer/src/snapshotServer.ts index b1dd371cb373f..d41dcbdbbdd7b 100644 --- a/packages/trace-viewer/src/snapshotServer.ts +++ b/packages/trace-viewer/src/snapshotServer.ts @@ -44,7 +44,8 @@ export class SnapshotServer { const snapshot = this._snapshot(pathname.substring('/snapshotInfo'.length), searchParams); return this._respondWithJson(snapshot ? { viewport: snapshot.viewport(), - url: snapshot.snapshot().frameUrl + url: snapshot.snapshot().frameUrl, + timestamp: snapshot.snapshot().timestamp, } : { error: 'No snapshot found' }); diff --git a/packages/trace-viewer/src/traceModernizer.ts b/packages/trace-viewer/src/traceModernizer.ts index b15ad527b0a4a..7c6ff19ce621c 100644 --- a/packages/trace-viewer/src/traceModernizer.ts +++ b/packages/trace-viewer/src/traceModernizer.ts @@ -58,6 +58,7 @@ export class TraceModernizer { let pageEntry = this._pageEntries.get(pageId); if (!pageEntry) { pageEntry = { + pageId, screencastFrames: [], }; this._pageEntries.set(pageId, pageEntry); diff --git a/packages/trace-viewer/src/ui/inspectorTab.tsx b/packages/trace-viewer/src/ui/inspectorTab.tsx index 7b3a90b709a32..ba37cf1bd1d84 100644 --- a/packages/trace-viewer/src/ui/inspectorTab.tsx +++ b/packages/trace-viewer/src/ui/inspectorTab.tsx @@ -17,7 +17,7 @@ import { CodeMirrorWrapper } from '@web/components/codeMirrorWrapper'; import type { Language } from '@web/components/codeMirrorWrapper'; import { ToolbarButton } from '@web/components/toolbarButton'; -import { copy } from '@web/uiUtils'; +import { copy, useSetting } from '@web/uiUtils'; import * as React from 'react'; import './sourceTab.css'; @@ -27,10 +27,12 @@ export const InspectorTab: React.FunctionComponent<{ highlightedLocator: string, setHighlightedLocator: (locator: string) => void, }> = ({ sdkLanguage, setIsInspecting, highlightedLocator, setHighlightedLocator }) => { + const [showScreenshot] = useSetting('screenshot-instead-of-snapshot', false); + return
Locator
- { + { // Updating text needs to go first - react can squeeze a render between the state updates. setHighlightedLocator(text); setIsInspecting(false); diff --git a/packages/trace-viewer/src/ui/modelUtil.ts b/packages/trace-viewer/src/ui/modelUtil.ts index c82cbc99a69ce..0c22d954f465f 100644 --- a/packages/trace-viewer/src/ui/modelUtil.ts +++ b/packages/trace-viewer/src/ui/modelUtil.ts @@ -22,6 +22,7 @@ import type { ContextEntry, PageEntry } from '../entries'; import type { StackFrame } from '@protocol/channels'; const contextSymbol = Symbol('context'); +const pageSymbol = Symbol('page'); const nextInContextSymbol = Symbol('next'); const prevInListSymbol = Symbol('prev'); const eventsSymbol = Symbol('events'); @@ -148,6 +149,7 @@ function indexModel(context: ContextEntry) { for (let i = 0; i < context.actions.length; ++i) { const action = context.actions[i] as any; action[contextSymbol] = context; + action[pageSymbol] = context.pages.find(page => page.pageId === action.pageId); } let lastNonRouteAction = undefined; for (let i = context.actions.length - 1; i >= 0; i--) { @@ -356,6 +358,10 @@ export function prevInList(action: ActionTraceEvent): ActionTraceEvent { return (action as any)[prevInListSymbol]; } +export function pageForAction(action: ActionTraceEvent): PageEntry { + return (action as any)[pageSymbol]; +} + export function stats(action: ActionTraceEvent): { errors: number, warnings: number } { let errors = 0; let warnings = 0; diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 4faa6686777aa..229d9f8cefa99 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -17,10 +17,10 @@ import './snapshotTab.css'; import * as React from 'react'; import type { ActionTraceEvent } from '@trace/trace'; -import { context, prevInList } from './modelUtil'; +import { context, type MultiTraceModel, pageForAction, prevInList } from './modelUtil'; import { Toolbar } from '@web/components/toolbar'; import { ToolbarButton } from '@web/components/toolbarButton'; -import { clsx, useMeasure } from '@web/uiUtils'; +import { clsx, useMeasure, useSetting } from '@web/uiUtils'; import { InjectedScript } from '@injected/injectedScript'; import { Recorder } from '@injected/recorder/recorder'; import ConsoleAPI from '@injected/consoleApi'; @@ -30,8 +30,18 @@ import { locatorOrSelectorAsSelector } from '@isomorphic/locatorParser'; import { TabbedPaneTab } from '@web/components/tabbedPane'; import { BrowserFrame } from './browserFrame'; +function findClosest(items: T[], target: number) { + return items.find((item, index) => { + if (index === items.length - 1) + return true; + const next = items[index + 1]; + return Math.abs(item.timestamp - target) < Math.abs(next.timestamp - target); + }); +} + export const SnapshotTab: React.FunctionComponent<{ action: ActionTraceEvent | undefined, + model?: MultiTraceModel, sdkLanguage: Language, testIdAttributeName: string, isInspecting: boolean, @@ -39,9 +49,10 @@ export const SnapshotTab: React.FunctionComponent<{ highlightedLocator: string, setHighlightedLocator: (locator: string) => void, openPage?: (url: string, target?: string) => Window | any, -}> = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator, openPage }) => { +}> = ({ action, model, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator, openPage }) => { const [measure, ref] = useMeasure(); const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action'); + const [showScreenshotInsteadOfSnapshot] = useSetting('screenshot-instead-of-snapshot', false); type Snapshot = { action: ActionTraceEvent, snapshotName: string, point?: { x: number, y: number } }; const { snapshots } = React.useMemo(() => { @@ -90,7 +101,7 @@ export const SnapshotTab: React.FunctionComponent<{ const iframeRef0 = React.useRef(null); const iframeRef1 = React.useRef(null); - const [snapshotInfo, setSnapshotInfo] = React.useState({ viewport: kDefaultViewport, url: '' }); + const [snapshotInfo, setSnapshotInfo] = React.useState<{ viewport: typeof kDefaultViewport, url: string, timestamp?: number }>({ viewport: kDefaultViewport, url: '', timestamp: undefined }); const loadingRef = React.useRef({ iteration: 0, visibleIframe: 0 }); React.useEffect(() => { @@ -99,13 +110,14 @@ export const SnapshotTab: React.FunctionComponent<{ const newVisibleIframe = 1 - loadingRef.current.visibleIframe; loadingRef.current.iteration = thisIteration; - const newSnapshotInfo = { url: '', viewport: kDefaultViewport }; + const newSnapshotInfo = { url: '', viewport: kDefaultViewport, timestamp: undefined }; if (snapshotInfoUrl) { const response = await fetch(snapshotInfoUrl); const info = await response.json(); if (!info.error) { newSnapshotInfo.url = info.url; newSnapshotInfo.viewport = info.viewport; + newSnapshotInfo.timestamp = info.timestamp; } } @@ -154,6 +166,15 @@ export const SnapshotTab: React.FunctionComponent<{ y: (measure.height - snapshotContainerSize.height) / 2, }; + const page = action ? pageForAction(action) : undefined; + const screencastFrame = React.useMemo( + () => { + if (snapshotInfo.timestamp && page?.screencastFrames) + return findClosest(page.screencastFrames, snapshotInfo.timestamp); + }, + [page?.screencastFrames, snapshotInfo.timestamp] + ); + return
- setIsInspecting(!isInspecting)} /> + setIsInspecting(!isInspecting)} disabled={showScreenshotInsteadOfSnapshot} /> {['action', 'before', 'after'].map(tab => { return ; })}
- { + { if (!openPage) openPage = window.open; const win = openPage(popoutUrl || '', '_blank'); @@ -209,7 +230,8 @@ export const SnapshotTab: React.FunctionComponent<{ transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})`, }}> -
+ {(showScreenshotInsteadOfSnapshot && screencastFrame) && {`Screenshot ${renderTitle(snapshotTab)}`} src={`sha1/${screencastFrame.sha1}`} width={screencastFrame.width} height={screencastFrame.height} />} +
diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index 86e6bff80e85a..cad1c2eb58bdd 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -107,6 +107,8 @@ export const UIModeView: React.FC<{}> = ({ const [updateSnapshots, setUpdateSnapshots] = React.useState(queryParams.updateSnapshots === 'all'); const [showRouteActions, setShowRouteActions] = useSetting('show-route-actions', true); const [darkMode, setDarkMode] = useDarkModeSetting(); + const [showScreenshot, setShowScreenshot] = useSetting('screenshot-instead-of-snapshot', false); + const inputRef = React.useRef(null); @@ -517,6 +519,7 @@ export const UIModeView: React.FC<{}> = ({ {settingsVisible && }
} diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index 491a8eac16672..3565eb385053d 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -73,6 +73,8 @@ export const Workbench: React.FunctionComponent<{ const [selectedTime, setSelectedTime] = React.useState(); const [sidebarLocation, setSidebarLocation] = useSetting<'bottom' | 'right'>('propertiesSidebarLocation', 'bottom'); const [showRouteActions, setShowRouteActions] = useSetting('show-route-actions', true); + const [showScreenshot, setShowScreenshot] = useSetting('screenshot-instead-of-snapshot', false); + const filteredActions = React.useMemo(() => { return (model?.actions || []).filter(action => showRouteActions || !isRouteAction(action)); @@ -299,7 +301,10 @@ export const Workbench: React.FunctionComponent<{ const settingsTab: TabbedPaneTabModel = { id: 'settings', title: 'Settings', - component: , + component: , }; return
@@ -325,6 +330,7 @@ export const Workbench: React.FunctionComponent<{ settingName='actionListSidebar' main={(name: string | undefined, defaultValue: S, title?: string): [S, React.Dispatch>] { +export function useSetting(name: string | undefined, defaultValue: S): [S, React.Dispatch>] { if (name) defaultValue = settings.getObject(name, defaultValue); const [value, setValue] = React.useState(defaultValue); diff --git a/tests/config/traceViewerFixtures.ts b/tests/config/traceViewerFixtures.ts index 7044e30a29644..3b79a55e984c5 100644 --- a/tests/config/traceViewerFixtures.ts +++ b/tests/config/traceViewerFixtures.ts @@ -31,7 +31,7 @@ type BaseWorkerFixtures = { export type TraceViewerFixtures = { showTraceViewer: (trace: string[], options?: {host?: string, port?: number}) => Promise; - runAndTrace: (body: () => Promise) => Promise; + runAndTrace: (body: () => Promise, optsOverrides?: Parameters[0]) => Promise; }; class TraceViewerPage { @@ -127,9 +127,9 @@ export const traceViewerFixtures: Fixtures { - await use(async (body: () => Promise) => { + await use(async (body: () => Promise, optsOverrides = {}) => { const traceFile = testInfo.outputPath('trace.zip'); - await context.tracing.start({ snapshots: true, screenshots: true, sources: true }); + await context.tracing.start({ snapshots: true, screenshots: true, sources: true, ...optsOverrides }); await body(); await context.tracing.stop({ path: traceFile }); return showTraceViewer([traceFile]); diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 4ebffc1f42754..f8aaf9d0df06a 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1465,3 +1465,33 @@ test('should serve css without content-type', async ({ page, runAndTrace, server const snapshotFrame = await traceViewer.snapshotFrame('page.goto'); await expect(snapshotFrame.locator('body')).toHaveCSS('background-color', 'rgb(255, 0, 0)', { timeout: 0 }); }); + +test('should allow showing screenshots instead of snapshots', async ({ runAndTrace, page, server }) => { + const traceViewer = await runAndTrace(async () => { + await page.goto(server.PREFIX + '/one-style.html'); + }); + + const screenshot = traceViewer.page.getByAltText(`Screenshot of page.goto > Action`); + const snapshot = (await traceViewer.snapshotFrame('page.goto')).owner(); + await expect(snapshot).toBeVisible(); + await expect(screenshot).not.toBeVisible(); + + await traceViewer.page.getByTitle('Settings').click(); + await traceViewer.page.getByText('Show screenshot instead of snapshot').setChecked(true); + + await expect(snapshot).not.toBeVisible(); + await expect(screenshot).toBeVisible(); +}); + +test('should handle case where neither snapshots nor screenshots exist', async ({ runAndTrace, page, server }) => { + const traceViewer = await runAndTrace(async () => { + await page.goto(server.PREFIX + '/one-style.html'); + }, { snapshots: false, screenshots: false }); + + await traceViewer.page.getByTitle('Settings').click(); + await traceViewer.page.getByText('Show screenshot instead of snapshot').setChecked(true); + + const screenshot = traceViewer.page.getByAltText(`Screenshot of page.goto > Action`); + await expect(screenshot).not.toBeVisible(); +}); + From 1402dee9e6589d0d01130809e9114048d23d2fc9 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 6 Sep 2024 12:08:10 -0700 Subject: [PATCH 017/805] Revert "fix(test runner): align with typescript behaviour for resolving `index.js` and `package.json` through path mapping (#32078)" (#32492) This reverts commit effb1ae2349aeef1c0bfb0b6cd886b9b4b32c8e5. This broke path mapping into directories in ESM mode. References #32480. --- packages/playwright-ct-core/src/vitePlugin.ts | 2 +- packages/playwright-ct-core/src/viteUtils.ts | 6 +- .../playwright/src/transform/esmLoader.ts | 2 +- .../playwright/src/transform/transform.ts | 18 +-- packages/playwright/src/util.ts | 19 +-- tests/playwright-test/resolver.spec.ts | 135 ------------------ 6 files changed, 15 insertions(+), 167 deletions(-) diff --git a/packages/playwright-ct-core/src/vitePlugin.ts b/packages/playwright-ct-core/src/vitePlugin.ts index 462730c61ca21..ec738c87009f0 100644 --- a/packages/playwright-ct-core/src/vitePlugin.ts +++ b/packages/playwright-ct-core/src/vitePlugin.ts @@ -262,7 +262,7 @@ function vitePlugin(registerSource: string, templateDir: string, buildInfo: Buil async writeBundle(this: PluginContext) { for (const importInfo of importInfos.values()) { - const importPath = resolveHook(importInfo.filename, importInfo.importSource, true); + const importPath = resolveHook(importInfo.filename, importInfo.importSource); if (!importPath) continue; const deps = new Set(); diff --git a/packages/playwright-ct-core/src/viteUtils.ts b/packages/playwright-ct-core/src/viteUtils.ts index d1160c16f0994..a9f7020999e90 100644 --- a/packages/playwright-ct-core/src/viteUtils.ts +++ b/packages/playwright-ct-core/src/viteUtils.ts @@ -147,13 +147,13 @@ export async function populateComponentsFromTests(componentRegistry: ComponentRe for (const importInfo of importList) componentRegistry.set(importInfo.id, importInfo); if (componentsByImportingFile) - componentsByImportingFile.set(file, importList.map(i => resolveHook(i.filename, i.importSource, true)).filter(Boolean) as string[]); + componentsByImportingFile.set(file, importList.map(i => resolveHook(i.filename, i.importSource)).filter(Boolean) as string[]); } } export function hasJSComponents(components: ImportInfo[]): boolean { for (const component of components) { - const importPath = resolveHook(component.filename, component.importSource, true); + const importPath = resolveHook(component.filename, component.importSource); const extname = importPath ? path.extname(importPath) : ''; if (extname === '.js' || (importPath && !extname && fs.existsSync(importPath + '.js'))) return true; @@ -183,7 +183,7 @@ export function transformIndexFile(id: string, content: string, templateDir: str lines.push(registerSource); for (const value of importInfos.values()) { - const importPath = resolveHook(value.filename, value.importSource, true) || value.importSource; + const importPath = resolveHook(value.filename, value.importSource) || value.importSource; lines.push(`const ${value.id} = () => import('${importPath?.replaceAll(path.sep, '/')}').then((mod) => mod.${value.remoteName || 'default'});`); } diff --git a/packages/playwright/src/transform/esmLoader.ts b/packages/playwright/src/transform/esmLoader.ts index 0ef0f29eaf083..c84d15146b8fb 100644 --- a/packages/playwright/src/transform/esmLoader.ts +++ b/packages/playwright/src/transform/esmLoader.ts @@ -26,7 +26,7 @@ import { fileIsModule } from '../util'; async function resolve(specifier: string, context: { parentURL?: string }, defaultResolve: Function) { if (context.parentURL && context.parentURL.startsWith('file://')) { const filename = url.fileURLToPath(context.parentURL); - const resolved = resolveHook(filename, specifier, true); + const resolved = resolveHook(filename, specifier); if (resolved !== undefined) specifier = url.pathToFileURL(resolved).toString(); } diff --git a/packages/playwright/src/transform/transform.ts b/packages/playwright/src/transform/transform.ts index 52d05dde90369..9ca80399fb7f5 100644 --- a/packages/playwright/src/transform/transform.ts +++ b/packages/playwright/src/transform/transform.ts @@ -129,21 +129,15 @@ function loadAndValidateTsconfigsForFolder(folder: string): ParsedTsConfigData[] const pathSeparator = process.platform === 'win32' ? ';' : ':'; const builtins = new Set(Module.builtinModules); -export function resolveHook(filename: string, specifier: string, isESM: boolean): string | undefined { +export function resolveHook(filename: string, specifier: string): string | undefined { if (specifier.startsWith('node:') || builtins.has(specifier)) return; if (!shouldTransform(filename)) return; if (isRelativeSpecifier(specifier)) - return resolveImportSpecifierExtension(path.resolve(path.dirname(filename), specifier), false, isESM); - - /** - * TypeScript discourages path-mapping into node_modules - * (https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages). - * It seems like TypeScript tries path-mapping first, but does not look at the `package.json` or `index.js` files in ESM. - * If path-mapping doesn't yield a result, TypeScript falls back to the default resolution (typically node_modules). - */ + return resolveImportSpecifierExtension(path.resolve(path.dirname(filename), specifier)); + const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx'); const tsconfigs = loadAndValidateTsconfigsForFile(filename); for (const tsconfig of tsconfigs) { @@ -185,7 +179,7 @@ export function resolveHook(filename: string, specifier: string, isESM: boolean) if (value.includes('*')) candidate = candidate.replace('*', matchedPartOfSpecifier); candidate = path.resolve(tsconfig.pathsBase!, candidate); - const existing = resolveImportSpecifierExtension(candidate, true, isESM); + const existing = resolveImportSpecifierExtension(candidate); if (existing) { longestPrefixLength = keyPrefix.length; pathMatchedByLongestPrefix = existing; @@ -199,7 +193,7 @@ export function resolveHook(filename: string, specifier: string, isESM: boolean) if (path.isAbsolute(specifier)) { // Handle absolute file paths like `import '/path/to/file'` // Do not handle module imports like `import 'fs'` - return resolveImportSpecifierExtension(specifier, false, isESM); + return resolveImportSpecifierExtension(specifier); } } @@ -281,7 +275,7 @@ function installTransformIfNeeded() { const originalResolveFilename = (Module as any)._resolveFilename; function resolveFilename(this: any, specifier: string, parent: Module, ...rest: any[]) { if (parent) { - const resolved = resolveHook(parent.filename, specifier, false); + const resolved = resolveHook(parent.filename, specifier); if (resolved !== undefined) specifier = resolved; } diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 4c75d9d84136e..0531f167a0442 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -316,7 +316,7 @@ const kExtLookups = new Map([ ['.mjs', ['.mts']], ['', ['.js', '.ts', '.jsx', '.tsx', '.cjs', '.mjs', '.cts', '.mts']], ]); -export function resolveImportSpecifierExtension(resolved: string, isPathMapping: boolean, isESM: boolean): string | undefined { +export function resolveImportSpecifierExtension(resolved: string): string | undefined { if (fileExists(resolved)) return resolved; @@ -331,25 +331,14 @@ export function resolveImportSpecifierExtension(resolved: string, isPathMapping: break; // Do not try '' when a more specific extension like '.jsx' matched. } - // After TypeScript path mapping, here's how directories with a `package.json` are resolved: - // - `package.json#exports` is not respected - // - `package.json#main` is respected only in CJS mode - // - `index.js` default is respected only in CJS mode - // - // More info: - // - https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages - // - https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution - // - https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules - - const shouldNotResolveDirectory = isPathMapping && isESM; - - if (!shouldNotResolveDirectory && dirExists(resolved)) { + if (dirExists(resolved)) { // If we import a package, let Node.js figure out the correct import based on package.json. if (fileExists(path.join(resolved, 'package.json'))) return resolved; + // Otherwise, try to find a corresponding index file. const dirImport = path.join(resolved, 'index'); - return resolveImportSpecifierExtension(dirImport, isPathMapping, isESM); + return resolveImportSpecifierExtension(dirImport); } } diff --git a/tests/playwright-test/resolver.spec.ts b/tests/playwright-test/resolver.spec.ts index b87e22babbe45..5a0e91b099412 100644 --- a/tests/playwright-test/resolver.spec.ts +++ b/tests/playwright-test/resolver.spec.ts @@ -606,79 +606,6 @@ test('should import packages with non-index main script through path resolver', expect(result.output).toContain(`foo=42`); }); -test('should not honor `package.json#main` field in ESM mode', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'app/pkg/main.ts': ` - export const foo = 42; - `, - 'app/pkg/package.json': ` - { "main": "main.ts" } - `, - 'package.json': ` - { "name": "example-project", "type": "module" } - `, - 'playwright.config.ts': ` - export default {}; - `, - 'tsconfig.json': `{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "app/*": ["app/*"], - }, - }, - }`, - 'example.spec.ts': ` - import { foo } from 'app/pkg'; - import { test, expect } from '@playwright/test'; - test('test', ({}) => { - console.log('foo=' + foo); - }); - `, - }); - - expect(result.exitCode).toBe(1); - expect(result.output).toContain(`Cannot find package 'app'`); -}); - - -test('does not honor `exports` field after type mapping', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'app/pkg/main.ts': ` - export const filename = 'main.ts'; - `, - 'app/pkg/index.js': ` - export const filename = 'index.js'; - `, - 'app/pkg/package.json': JSON.stringify({ - exports: { '.': { require: './main.ts' } } - }), - 'package.json': JSON.stringify({ - name: 'example-project' - }), - 'playwright.config.ts': ` - export default {}; - `, - 'tsconfig.json': JSON.stringify({ - compilerOptions: { - baseUrl: '.', - paths: { - 'app/*': ['app/*'], - }, - } - }), - 'example.spec.ts': ` - import { filename } from 'app/pkg'; - import { test, expect } from '@playwright/test'; - test('test', ({}) => { - console.log('filename=' + filename); - }); - `, - }); - - expect(result.output).toContain('filename=index.js'); -}); - test('should respect tsconfig project references', async ({ runInlineTest }) => { test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29256' }); @@ -766,65 +693,3 @@ test('should respect --tsconfig option', async ({ runInlineTest }) => { expect(result.exitCode).toBe(0); expect(result.output).not.toContain(`Could not`); }); - - -test('should resolve index.js in CJS after path mapping', async ({ runInlineTest }) => { - test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' }); - - const result = await runInlineTest({ - '@acme/lib/index.js': ` - exports.greet = () => console.log('hello playwright'); - `, - '@acme/lib/index.d.ts': ` - export const greet: () => void; - `, - 'tests/hello.test.ts': ` - import { greet } from '@acme/lib'; - import { test } from '@playwright/test'; - test('hello', async ({}) => { - greet(); - }); - `, - 'tests/tsconfig.json': JSON.stringify({ - compilerOptions: { - 'paths': { - '@acme/*': ['../@acme/*'], - } - } - }) - }); - - expect(result.exitCode).toBe(0); - expect(result.passed).toBe(1); -}); - -test('should not resolve index.js in ESM after path mapping', async ({ runInlineTest }) => { - test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' }); - - const result = await runInlineTest({ - '@acme/lib/index.js': ` - export const greet = () => console.log('hello playwright'); - `, - '@acme/lib/index.d.ts': ` - export const greet: () => void; - `, - 'tests/hello.test.ts': ` - import { greet } from '@acme/lib'; - import { test } from '@playwright/test'; - test('hello', async ({}) => { - greet(); - }); - `, - 'tests/tsconfig.json': JSON.stringify({ - compilerOptions: { - 'paths': { - '@acme/*': ['../@acme/*'], - } - } - }), - 'package.json': JSON.stringify({ type: 'module' }), - }); - - expect(result.exitCode).toBe(1); - expect(result.output).toContain(`Cannot find package '@acme/lib'`); -}); From d85527e9f63b0bc067d0209ed29ec4a5cb4a774c Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 6 Sep 2024 13:13:44 -0700 Subject: [PATCH 018/805] test: some tests for expected API behavior (#32495) Adding some tests discussed in https://github.com/microsoft/playwright/pull/32434 --- tests/library/chromium/oopif.spec.ts | 10 ++++++++++ tests/page/frame-frame-element.spec.ts | 16 +++++++++++++++ tests/page/interception.spec.ts | 19 +++++++++++++++++- tests/page/page-mouse.spec.ts | 27 ++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/library/chromium/oopif.spec.ts b/tests/library/chromium/oopif.spec.ts index cc1279b8af2b8..0143120629415 100644 --- a/tests/library/chromium/oopif.spec.ts +++ b/tests/library/chromium/oopif.spec.ts @@ -297,6 +297,16 @@ it('should click', async function({ page, browser, server }) { expect(await handle1.evaluate(() => (window as any)['_clicked'])).toBe(true); }); +it('contentFrame should work', async ({ page, browser, server }) => { + await page.goto(server.PREFIX + '/dynamic-oopif.html'); + expect(page.frames().length).toBe(2); + expect(await countOOPIFs(browser)).toBe(1); + expect(await page.locator('iframe').contentFrame().locator('div').count()).toBe(200); + const oopif = await page.$('iframe'); + const content = await oopif.contentFrame(); + expect(await content.locator('div').count()).toBe(200); +}); + it('should allow cdp sessions on oopifs', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(await countOOPIFs(browser)).toBe(1); diff --git a/tests/page/frame-frame-element.spec.ts b/tests/page/frame-frame-element.spec.ts index e3b25a8fe1a0a..e44e7deb3ec26 100644 --- a/tests/page/frame-frame-element.spec.ts +++ b/tests/page/frame-frame-element.spec.ts @@ -75,3 +75,19 @@ it('should work inside closed shadow root', async ({ page, server, browserName } const element = await frame.frameElement(); expect(await element.getAttribute('name')).toBe('myframe'); }); + +it('should work inside declarative shadow root', async ({ page, server, browserName }) => { + await page.goto(server.EMPTY_PAGE); + await page.setContent(` +
+ + footer +
+ `); + const frame = page.frame({ name: 'myframe' }); + const element = await frame.frameElement(); + expect(await element.getAttribute('name')).toBe('myframe'); +}); diff --git a/tests/page/interception.spec.ts b/tests/page/interception.spec.ts index fd798cb715bf4..7f3ef9800062b 100644 --- a/tests/page/interception.spec.ts +++ b/tests/page/interception.spec.ts @@ -164,7 +164,7 @@ it('should work with regular expression passed from a different context', async expect(intercepted).toBe(true); }); -it('should not break remote worker importScripts', async ({ page, server, browserName, browserMajorVersion }) => { +it('should not break remote worker importScripts', async ({ page, server }) => { await page.route('**', async route => { await route.continue(); }); @@ -189,3 +189,20 @@ it('should disable memory cache when intercepting', async ({ page, server }) => await expect(page).toHaveURL(server.PREFIX + '/page.html'); expect(interceted).toBe(2); }); + +it('should intercept blob url requests', async function({ page, server, browserName }) { + it.fixme(browserName !== 'webkit'); + await page.goto(server.EMPTY_PAGE); + await page.route('**/*', route => { + route.fulfill({ + status: 200, + body: 'intercepted', + }).catch(e => null); + }); + page.on('console', msg => console.log(msg.text())); + const response = await page.evaluate(async () => { + const blobUrl = URL.createObjectURL(new Blob(['failed to intercept'], { type: 'text/plain' })); + return await fetch(blobUrl).then(response => response.text()); + }); + expect(response).toBe('intercepted'); +}); diff --git a/tests/page/page-mouse.spec.ts b/tests/page/page-mouse.spec.ts index 3e7223319f61f..5d29be2bb7ed4 100644 --- a/tests/page/page-mouse.spec.ts +++ b/tests/page/page-mouse.spec.ts @@ -78,6 +78,33 @@ it('should dblclick the div', async ({ page, server }) => { expect(event.button).toBe(0); }); +it('down and up should generate click', async ({ page, server }) => { + await page.evaluate(() => { + window['clickPromise'] = new Promise(resolve => { + document.addEventListener('click', event => { + resolve({ + type: event.type, + detail: event.detail, + clientX: event.clientX, + clientY: event.clientY, + isTrusted: event.isTrusted, + button: event.button + }); + }); + }); + }); + await page.mouse.move(50, 60); + await page.mouse.down(); + await page.mouse.up(); + const event = await page.evaluate(() => window['clickPromise']); + expect(event.type).toBe('click'); + expect(event.detail).toBe(1); + expect(event.clientX).toBe(50); + expect(event.clientY).toBe(60); + expect(event.isTrusted).toBe(true); + expect(event.button).toBe(0); +}); + it('should pointerdown the div with a custom button', async ({ page, server, browserName }) => { await page.setContent(`
Click me
`); await page.evaluate(() => { From 11441c0fe1407b2448ad1a8b806b06a7e0b7a532 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 6 Sep 2024 13:17:32 -0700 Subject: [PATCH 019/805] fix: add missing await in adoptIfNeeded (#32497) Otherwise it throws in Bidi. --- packages/playwright-core/src/server/frameSelectors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/src/server/frameSelectors.ts b/packages/playwright-core/src/server/frameSelectors.ts index 66f2e2e514382..4be2a9c2853df 100644 --- a/packages/playwright-core/src/server/frameSelectors.ts +++ b/packages/playwright-core/src/server/frameSelectors.ts @@ -160,7 +160,7 @@ export class FrameSelectors { async function adoptIfNeeded(handle: ElementHandle, context: FrameExecutionContext): Promise> { if (handle._context === context) return handle; - const adopted = handle._page._delegate.adoptElementHandle(handle, context); + const adopted = await handle._page._delegate.adoptElementHandle(handle, context); handle.dispose(); return adopted; } From df2bc2d0dc59017493e9f2733aab3e6c9c309f01 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 6 Sep 2024 13:17:49 -0700 Subject: [PATCH 020/805] test: worker interception for existing workers (#32494) Failing test for https://github.com/microsoft/playwright/issues/32355 --- tests/page/interception.spec.ts | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tests/page/interception.spec.ts b/tests/page/interception.spec.ts index 7f3ef9800062b..338ac97a05dd7 100644 --- a/tests/page/interception.spec.ts +++ b/tests/page/interception.spec.ts @@ -100,8 +100,7 @@ it('should work with glob', async () => { expect(globToRegex('$^+.\\*()|\\?\\{\\}\\[\\]')).toEqual(/^\$\^\+\.\*\(\)\|\?\{\}\[\]$/); }); -it('should intercept network activity from worker', async function({ page, server, isAndroid, browserName, browserMajorVersion }) { - it.skip(browserName === 'firefox' && browserMajorVersion < 114, 'https://github.com/microsoft/playwright/issues/21760'); +it('should intercept network activity from worker', async function({ page, server, isAndroid }) { it.skip(isAndroid); await page.goto(server.EMPTY_PAGE); @@ -122,6 +121,35 @@ it('should intercept network activity from worker', async function({ page, serve expect(msg.text()).toBe('intercepted'); }); +it('should intercept worker requests when enabled after worker creation', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32355' } +}, async function({ page, server, isAndroid, browserName }) { + it.skip(isAndroid); + it.fixme(browserName === 'chromium'); + + await page.goto(server.EMPTY_PAGE); + server.setRoute('/data_for_worker', (req, res) => res.end('failed to intercept')); + const url = server.PREFIX + '/data_for_worker'; + await page.evaluate(url => { + (window as any).w = new Worker(URL.createObjectURL(new Blob([` + onmessage = function(e) { + fetch("${url}").then(response => response.text()).then(console.log); + }; + `], { type: 'application/javascript' }))); + }, url); + await page.route(url, route => { + route.fulfill({ + status: 200, + body: 'intercepted', + }).catch(e => null); + }); + const [msg] = await Promise.all([ + page.waitForEvent('console'), + page.evaluate(() => (window as any).w.postMessage('')) + ]); + expect(msg.text()).toBe('intercepted'); +}); + it('should intercept network activity from worker 2', async function({ page, server, isAndroid }) { it.skip(isAndroid); From a113553f1468b5c8d14e85cd87dd018fda5cb49f Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 6 Sep 2024 13:49:37 -0700 Subject: [PATCH 021/805] test: allow running oopif test without newBrowserCDPSession (#32496) --- tests/bidi/playwright.config.ts | 1 - tests/library/chromium/oopif.spec.ts | 58 +++++++++++++++------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/tests/bidi/playwright.config.ts b/tests/bidi/playwright.config.ts index 7aa17f35ba9df..7adaa56638e59 100644 --- a/tests/bidi/playwright.config.ts +++ b/tests/bidi/playwright.config.ts @@ -81,7 +81,6 @@ for (const [key, channels] of Object.entries(browserToChannels)) { channel, video: 'off', launchOptions: { - channel: 'bidi-chrome-canary', executablePath, }, trace: trace ? 'on' : undefined, diff --git a/tests/library/chromium/oopif.spec.ts b/tests/library/chromium/oopif.spec.ts index 0143120629415..bea16bdb75705 100644 --- a/tests/library/chromium/oopif.spec.ts +++ b/tests/library/chromium/oopif.spec.ts @@ -25,14 +25,14 @@ it.use({ it('should report oopif frames', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); }); it('should handle oopif detach', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); const frame = page.frames()[1]; expect(await frame.evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); @@ -46,20 +46,20 @@ it('should handle oopif detach', async function({ page, browser, server }) { it('should handle remote -> local -> remote transitions', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); await Promise.all([ page.frames()[1].waitForNavigation(), page.evaluate('goLocal()'), ]); expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.PREFIX + '/grid.html'); - expect(await countOOPIFs(browser)).toBe(0); + await assertOOPIFCount(browser, 0); await Promise.all([ page.frames()[1].waitForNavigation(), page.evaluate('goRemote()'), ]); expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); }); it('should get the proper viewport', async ({ page, browser, server }) => { @@ -68,7 +68,7 @@ it('should get the proper viewport', async ({ page, browser, server }) => { expect(page.viewportSize()).toEqual({ width: 1280, height: 720 }); await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const oopif = page.frames()[1]; expect(await oopif.evaluate(() => screen.width)).toBe(1280); expect(await oopif.evaluate(() => screen.height)).toBe(720); @@ -86,7 +86,7 @@ it('should get the proper viewport', async ({ page, browser, server }) => { it('should expose function', async ({ page, browser, server }) => { await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const oopif = page.frames()[1]; await page.exposeFunction('mul', (a: number, b: number) => a * b); const result = await oopif.evaluate(async function() { @@ -98,7 +98,7 @@ it('should expose function', async ({ page, browser, server }) => { it('should emulate media', async ({ page, browser, server }) => { await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const oopif = page.frames()[1]; expect(await oopif.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(false); await page.emulateMedia({ colorScheme: 'dark' }); @@ -108,7 +108,7 @@ it('should emulate media', async ({ page, browser, server }) => { it('should emulate offline', async ({ page, browser, server }) => { await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const oopif = page.frames()[1]; expect(await oopif.evaluate(() => navigator.onLine)).toBe(true); await page.context().setOffline(true); @@ -125,7 +125,7 @@ it('should support context options', async ({ browser, server, playwright }) => page.goto(server.PREFIX + '/dynamic-oopif.html'), ]); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const oopif = page.frames()[1]; expect(await oopif.evaluate(() => 'ontouchstart' in window)).toBe(true); @@ -145,7 +145,7 @@ it('should respect route', async ({ page, browser, server }) => { }); await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(intercepted).toBe(true); }); @@ -153,14 +153,14 @@ it('should take screenshot', async ({ page, browser, server }) => { await page.setViewportSize({ width: 500, height: 500 }); await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(await page.screenshot()).toMatchSnapshot('screenshot-oopif.png'); }); it('should load oopif iframes with subresources and route', async function({ page, browser, server }) { await page.route('**/*', route => route.continue()); await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); }); it('should report main requests', async function({ page, browser, server }) { @@ -192,7 +192,7 @@ it('should report main requests', async function({ page, browser, server }) { const grandChild = child.childFrames()[0]; await grandChild.waitForLoadState('domcontentloaded'); - expect(await countOOPIFs(browser)).toBe(2); + await assertOOPIFCount(browser, 2); expect(requestFrames[0]).toBe(main); expect(finishedFrames[0]).toBe(main); expect(requestFrames[1]).toBe(child); @@ -205,7 +205,7 @@ it('should support exposeFunction', async function({ page, browser, server }) { await page.context().exposeFunction('dec', (a: number) => a - 1); await page.exposeFunction('inc', (a: number) => a + 1); await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); expect(await page.frames()[0].evaluate(() => (window as any)['inc'](3))).toBe(4); expect(await page.frames()[1].evaluate(() => (window as any)['inc'](4))).toBe(5); @@ -217,7 +217,7 @@ it('should support addInitScript', async function({ page, browser, server }) { await page.context().addInitScript(() => (window as any)['bar'] = 17); await page.addInitScript(() => (window as any)['foo'] = 42); await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); expect(await page.frames()[0].evaluate(() => (window as any)['foo'])).toBe(42); expect(await page.frames()[1].evaluate(() => (window as any)['foo'])).toBe(42); @@ -227,7 +227,7 @@ it('should support addInitScript', async function({ page, browser, server }) { // @see https://github.com/microsoft/playwright/issues/1240 it('should click a button when it overlays oopif', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/button-overlay-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); await page.click('button'); expect(await page.evaluate(() => (window as any)['BUTTON_CLICKED'])).toBe(true); }); @@ -248,7 +248,7 @@ it('should report google.com frame with headed', async ({ browserType, server }) return new Promise(x => frame.onload = x); }); await page.waitForSelector('iframe[src="https://google.com/"]'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const urls = page.frames().map(frame => frame.url()); expect(urls).toEqual([ server.EMPTY_PAGE, @@ -267,7 +267,7 @@ it('ElementHandle.boundingBox() should work', async function({ page, browser, se }); await page.frames()[1].goto(page.frames()[1].url()); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const handle1 = await page.frames()[1].$('.box:nth-of-type(13)'); expect(await handle1!.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); @@ -275,7 +275,7 @@ it('ElementHandle.boundingBox() should work', async function({ page, browser, se page.frames()[1].waitForNavigation(), page.evaluate('goLocal()'), ]); - expect(await countOOPIFs(browser)).toBe(0); + await assertOOPIFCount(browser, 0); const handle2 = await page.frames()[1].$('.box:nth-of-type(13)'); expect(await handle2!.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); }); @@ -290,7 +290,7 @@ it('should click', async function({ page, browser, server }) { }); await page.frames()[1].goto(page.frames()[1].url()); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); const handle1 = (await page.frames()[1].$('.box:nth-of-type(13)'))!; await handle1.evaluate(div => div.addEventListener('click', () => (window as any)['_clicked'] = true, false)); await handle1.click(); @@ -300,7 +300,7 @@ it('should click', async function({ page, browser, server }) { it('contentFrame should work', async ({ page, browser, server }) => { await page.goto(server.PREFIX + '/dynamic-oopif.html'); expect(page.frames().length).toBe(2); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(await page.locator('iframe').contentFrame().locator('div').count()).toBe(200); const oopif = await page.$('iframe'); const content = await oopif.contentFrame(); @@ -309,7 +309,7 @@ it('contentFrame should work', async ({ page, browser, server }) => { it('should allow cdp sessions on oopifs', async function({ page, browser, server }) { await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); expect(await page.frames()[1].evaluate(() => '' + location.href)).toBe(server.CROSS_PROCESS_PREFIX + '/grid.html'); @@ -326,7 +326,7 @@ it('should emit filechooser event for iframe', async ({ page, server, browser }) // Add listener before OOPIF is created. const chooserPromise = page.waitForEvent('filechooser'); await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); const frame = page.frames()[1]; await frame.setContent(``); @@ -340,7 +340,7 @@ it('should emit filechooser event for iframe', async ({ page, server, browser }) it('should be able to click in iframe', async ({ page, server, browser }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/28023' }); await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); expect(page.frames().length).toBe(2); const frame = page.frames()[1]; await frame.setContent(``); @@ -353,7 +353,7 @@ it('should be able to click in iframe', async ({ page, server, browser }) => { it('should not throw on exposeFunction when oopif detaches', async ({ page, browser, server }) => { await page.goto(server.PREFIX + '/dynamic-oopif.html'); - expect(await countOOPIFs(browser)).toBe(1); + await assertOOPIFCount(browser, 1); await Promise.all([ page.exposeFunction('myFunc', () => 2022), page.evaluate(() => document.querySelector('iframe')!.remove()), @@ -370,6 +370,12 @@ it('should intercept response body from oopif', async function({ page, browser, expect(await response.text()).toBeTruthy(); }); +async function assertOOPIFCount(browser: Browser, count: number) { + if (browser.browserType().name() !== 'chromium') + return; + expect(await countOOPIFs(browser)).toBe(count); +} + async function countOOPIFs(browser: Browser) { const browserSession = await browser.newBrowserCDPSession(); const oopifs = []; From 37bc4858273d3cc63ca4fed1eaeadf0433e7a448 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 6 Sep 2024 16:40:24 -0700 Subject: [PATCH 022/805] chore: remove browser-specific bidi hacks (#32498) Those were just workarounds for browser-specific bugs, they should be fixed upstream. * individual mouse down/up/down/up events don't trigger dblclick event in Firefox * setContent throws when document.open/write is called in the utility context in Firefox --- .../src/server/bidi/bidiInput.ts | 18 ------------------ .../src/server/bidi/bidiPage.ts | 4 ---- packages/playwright-core/src/server/frames.ts | 2 +- packages/playwright-core/src/server/input.ts | 3 --- packages/playwright-core/src/server/page.ts | 2 -- 5 files changed, 1 insertion(+), 28 deletions(-) diff --git a/packages/playwright-core/src/server/bidi/bidiInput.ts b/packages/playwright-core/src/server/bidi/bidiInput.ts index 29d1dd48dbb1e..e14e90529c6b6 100644 --- a/packages/playwright-core/src/server/bidi/bidiInput.ts +++ b/packages/playwright-core/src/server/bidi/bidiInput.ts @@ -90,24 +90,6 @@ export class RawMouseImpl implements input.RawMouse { await this._performActions([{ type: 'pointerUp', button: toBidiButton(button) }]); } - async click(x: number, y: number, options: { delay?: number, button?: types.MouseButton, clickCount?: number } = {}) { - x = Math.round(x); - y = Math.round(y); - const button = toBidiButton(options.button || 'left'); - const { delay = null, clickCount = 1 } = options; - const actions: bidi.Input.PointerSourceAction[] = []; - actions.push({ type: 'pointerMove', x, y }); - for (let cc = 1; cc <= clickCount; ++cc) { - actions.push({ type: 'pointerDown', button }); - if (delay) - actions.push({ type: 'pause', duration: delay }); - actions.push({ type: 'pointerUp', button }); - if (delay && cc < clickCount) - actions.push({ type: 'pause', duration: delay }); - } - await this._performActions(actions); - } - async wheel(x: number, y: number, buttons: Set, modifiers: Set, deltaX: number, deltaY: number): Promise { } diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index 2802aa1452b14..9ecb5c789b41a 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -505,10 +505,6 @@ export class BidiPage implements PageDelegate { shouldToggleStyleSheetToSyncAnimations(): boolean { return true; } - - useMainWorldForSetContent(): boolean { - return true; - } } function toBidiExecutionContext(executionContext: dom.FrameExecutionContext): BidiExecutionContext { diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 32699a199f999..3b952ea02ad54 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -900,7 +900,7 @@ export class Frame extends SdkObject { const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil; progress.log(`setting frame content, waiting until "${waitUntil}"`); const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`; - const context = this._page._delegate.useMainWorldForSetContent?.() ? await this._mainContext() : await this._utilityContext(); + const context = await this._utilityContext(); const lifecyclePromise = new Promise((resolve, reject) => { this._page._frameManager._consoleMessageTags.set(tag, () => { // Clear lifecycle right after document.open() - see 'tag' below. diff --git a/packages/playwright-core/src/server/input.ts b/packages/playwright-core/src/server/input.ts index a4407d36d7960..4e4c95a8f3356 100644 --- a/packages/playwright-core/src/server/input.ts +++ b/packages/playwright-core/src/server/input.ts @@ -162,7 +162,6 @@ export interface RawMouse { move(x: number, y: number, button: types.MouseButton | 'none', buttons: Set, modifiers: Set, forClick: boolean): Promise; down(x: number, y: number, button: types.MouseButton, buttons: Set, modifiers: Set, clickCount: number): Promise; up(x: number, y: number, button: types.MouseButton, buttons: Set, modifiers: Set, clickCount: number): Promise; - click?(x: number, y: number, options: { delay?: number, button?: types.MouseButton, clickCount?: number }): Promise; wheel(x: number, y: number, buttons: Set, modifiers: Set, deltaX: number, deltaY: number): Promise; } @@ -217,8 +216,6 @@ export class Mouse { async click(x: number, y: number, options: { delay?: number, button?: types.MouseButton, clickCount?: number } = {}, metadata?: CallMetadata) { if (metadata) metadata.point = { x, y }; - if (this._raw.click) - return await this._raw.click(x, y, options); const { delay = null, clickCount = 1 } = options; if (delay) { this.move(x, y, { forClick: true }); diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 144b34c28e236..25394b1b5c40f 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -98,8 +98,6 @@ export interface PageDelegate { resetForReuse(): Promise; // WebKit hack. shouldToggleStyleSheetToSyncAnimations(): boolean; - // Bidi throws on attempt to document.open() in utility context. - useMainWorldForSetContent?(): boolean; } type EmulatedSize = { screen: types.Size, viewport: types.Size }; From f3ada9c6540ad6e2b0fe93f6204b63d27d9c42b4 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 6 Sep 2024 17:10:14 -0700 Subject: [PATCH 023/805] chore: wheel input in bidi (#32499) --- .../playwright-core/src/server/bidi/bidiInput.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/server/bidi/bidiInput.ts b/packages/playwright-core/src/server/bidi/bidiInput.ts index e14e90529c6b6..3550051a6a71f 100644 --- a/packages/playwright-core/src/server/bidi/bidiInput.ts +++ b/packages/playwright-core/src/server/bidi/bidiInput.ts @@ -76,7 +76,7 @@ export class RawMouseImpl implements input.RawMouse { } async move(x: number, y: number, button: types.MouseButton | 'none', buttons: Set, modifiers: Set, forClick: boolean): Promise { - // TODO: bidi throws when x/y are not integers. + // Bidi throws when x/y are not integers. x = Math.round(x); y = Math.round(y); await this._performActions([{ type: 'pointerMove', x, y }]); @@ -91,6 +91,19 @@ export class RawMouseImpl implements input.RawMouse { } async wheel(x: number, y: number, buttons: Set, modifiers: Set, deltaX: number, deltaY: number): Promise { + // Bidi throws when x/y are not integers. + x = Math.round(x); + y = Math.round(y); + await this._session.send('input.performActions', { + context: this._session.sessionId, + actions: [ + { + type: 'wheel', + id: 'pw_mouse_wheel', + actions: [{ type: 'scroll', x, y, deltaX, deltaY }], + } + ] + }); } private async _performActions(actions: bidi.Input.PointerSourceAction[]) { From 718bd9b35fd206245401a9ecb320289f427592d9 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Sat, 7 Sep 2024 09:16:42 +0200 Subject: [PATCH 024/805] devops: run BiDi tests (#32493) --- .github/workflows/tests_bidi.yml | 42 +++++++++++++++++++ .../src/server/registry/index.ts | 7 +++- tests/bidi/playwright.config.ts | 8 ++-- 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/tests_bidi.yml diff --git a/.github/workflows/tests_bidi.yml b/.github/workflows/tests_bidi.yml new file mode 100644 index 0000000000000..433294dbea6a9 --- /dev/null +++ b/.github/workflows/tests_bidi.yml @@ -0,0 +1,42 @@ +name: tests BiDi + +on: + workflow_dispatch: + pull_request: + branches: + - main + paths: + - .github/workflows/tests_bidi.yml + schedule: + # Run every day at midnight + - cron: '0 0 * * *' + +env: + FORCE_COLOR: 1 + ELECTRON_SKIP_BINARY_DOWNLOAD: 1 + +jobs: + test_bidi: + name: BiDi + environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} + runs-on: ubuntu-24.04 + permissions: + id-token: write # This is required for OIDC login (azure/login) to succeed + contents: read # This is required for actions/checkout to succeed + strategy: + fail-fast: false + matrix: + # TODO: add Firefox + channel: [bidi-chrome-stable] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm ci + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' + - run: npm run build + - run: npx playwright install --with-deps chromium + - name: Run tests + run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run biditest -- --project=${{ matrix.channel }}* diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index cafef726fb37a..058e0bcbc34b4 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -354,7 +354,7 @@ function readDescriptors(browsersJSON: BrowsersJSON) { export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi'; type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'android'; -type BidiChannel = 'bidi-firefox-stable' | 'bidi-chrome-canary'; +type BidiChannel = 'bidi-firefox-stable' | 'bidi-chrome-canary' | 'bidi-chrome-stable'; type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree']; @@ -530,6 +530,11 @@ export class Registry { 'darwin': '/Applications/Firefox.app/Contents/MacOS/firefox', 'win32': '\\Mozilla Firefox\\firefox.exe', })); + this._executables.push(this._createBidiChannel('bidi-chrome-stable', { + 'linux': '/opt/google/chrome/chrome', + 'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', + 'win32': `\\Google\\Chrome\\Application\\chrome.exe`, + })); this._executables.push(this._createBidiChannel('bidi-chrome-canary', { 'linux': '', 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', diff --git a/tests/bidi/playwright.config.ts b/tests/bidi/playwright.config.ts index 7adaa56638e59..bc7b29e56bc8a 100644 --- a/tests/bidi/playwright.config.ts +++ b/tests/bidi/playwright.config.ts @@ -47,9 +47,9 @@ const config: Config Date: Mon, 9 Sep 2024 12:52:40 +0200 Subject: [PATCH 025/805] test: fix stress tests bots (#32513) --- tests/stress/heap.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/stress/heap.spec.ts b/tests/stress/heap.spec.ts index a88ab29005ae3..66bedfe9ff265 100644 --- a/tests/stress/heap.spec.ts +++ b/tests/stress/heap.spec.ts @@ -44,9 +44,9 @@ test('should not leak fixtures w/o page', async ({}) => { test('should not leak server-side objects', async ({ page }) => { expect(await queryObjectCount(require('../../packages/playwright-core/lib/server/page').Page)).toBe(1); - // 4 is because v8 heap creates objects for descendant classes, so WKContext, CRContext, FFContext and our context instance. - expect(await queryObjectCount(require('../../packages/playwright-core/lib/server/browserContext').BrowserContext)).toBe(4); - expect(await queryObjectCount(require('../../packages/playwright-core/lib/server/browser').Browser)).toBe(4); + // 4 is because v8 heap creates objects for descendant classes, so WKContext, CRContext, FFContext, BidiBrowserContext and our context instance. + expect(await queryObjectCount(require('../../packages/playwright-core/lib/server/browserContext').BrowserContext)).toBe(5); + expect(await queryObjectCount(require('../../packages/playwright-core/lib/server/browser').Browser)).toBe(5); }); test('should not leak dispatchers after closing page', async ({ context, server }) => { From 31e269ad06c8cada6e53313403682479349e6b4f Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 9 Sep 2024 14:00:22 +0200 Subject: [PATCH 026/805] feat(trace-viewer): show screenshot pointer (#32514) Follow-up to https://github.com/microsoft/playwright/pull/32248. Adds a glowing red circle that shows the click position. I made it glowing to show that its position is inaccurate. Screenshot 2024-09-09 at 11 33 45 --- packages/trace-viewer/src/ui/clickPointer.tsx | 48 +++++++++++++++++++ packages/trace-viewer/src/ui/snapshotTab.tsx | 12 +++-- 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 packages/trace-viewer/src/ui/clickPointer.tsx diff --git a/packages/trace-viewer/src/ui/clickPointer.tsx b/packages/trace-viewer/src/ui/clickPointer.tsx new file mode 100644 index 0000000000000..862f6522eab38 --- /dev/null +++ b/packages/trace-viewer/src/ui/clickPointer.tsx @@ -0,0 +1,48 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function ClickPointer({ point }: { point: { x: number; y: number } }) { + return ( +
+
+ ⚠ +
+
+ ); +} diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 229d9f8cefa99..05d0cc591892e 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -29,6 +29,7 @@ import type { Language } from '@isomorphic/locatorGenerators'; import { locatorOrSelectorAsSelector } from '@isomorphic/locatorParser'; import { TabbedPaneTab } from '@web/components/tabbedPane'; import { BrowserFrame } from './browserFrame'; +import { ClickPointer } from './clickPointer'; function findClosest(items: T[], target: number) { return items.find((item, index) => { @@ -73,7 +74,7 @@ export const SnapshotTab: React.FunctionComponent<{ return { snapshots: { action: actionSnapshot, before: beforeSnapshot, after: afterSnapshot } }; }, [action]); - const { snapshotInfoUrl, snapshotUrl, popoutUrl } = React.useMemo(() => { + const { snapshotInfoUrl, snapshotUrl, popoutUrl, point } = React.useMemo(() => { const snapshot = snapshots[snapshotTab]; if (!snapshot) return { snapshotUrl: kBlankSnapshotUrl }; @@ -96,7 +97,7 @@ export const SnapshotTab: React.FunctionComponent<{ popoutParams.set('pointY', String(snapshot.point.y)); } const popoutUrl = new URL(`snapshot.html?${popoutParams.toString()}`, window.location.href).toString(); - return { snapshots, snapshotInfoUrl, snapshotUrl, popoutUrl }; + return { snapshots, snapshotInfoUrl, snapshotUrl, popoutUrl, point: snapshot.point }; }, [snapshots, snapshotTab]); const iframeRef0 = React.useRef(null); @@ -230,7 +231,12 @@ export const SnapshotTab: React.FunctionComponent<{ transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})`, }}> - {(showScreenshotInsteadOfSnapshot && screencastFrame) && {`Screenshot ${renderTitle(snapshotTab)}`} src={`sha1/${screencastFrame.sha1}`} width={screencastFrame.width} height={screencastFrame.height} />} + {(showScreenshotInsteadOfSnapshot && screencastFrame) && ( + <> + {point && } + {`Screenshot ${renderTitle(snapshotTab)}`} src={`sha1/${screencastFrame.sha1}`} width={screencastFrame.width} height={screencastFrame.height} /> + + )}
From cc9c4cdd9a502ccbbe4b9c5cbb917010fd72799d Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 9 Sep 2024 14:00:38 +0200 Subject: [PATCH 027/805] chore: fix flaky screenshot test (#32517) In this test, the trace recording goes super fast. Sometimes, this means that the recording is finished before the screen recorder got a chance to take a screenshot. If that happens, the tests fail because we never show a screenshot. This PR fixes the flakiness by delaying the trace recording so that there's always a screenshot taken. --- tests/library/trace-viewer.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index f8aaf9d0df06a..8f8d69116f65b 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1469,6 +1469,7 @@ test('should serve css without content-type', async ({ page, runAndTrace, server test('should allow showing screenshots instead of snapshots', async ({ runAndTrace, page, server }) => { const traceViewer = await runAndTrace(async () => { await page.goto(server.PREFIX + '/one-style.html'); + await page.waitForTimeout(1000); // ensure we could take a screenshot }); const screenshot = traceViewer.page.getByAltText(`Screenshot of page.goto > Action`); From 4a53973fd07b4725e9485df33e40f3dc026fe3d6 Mon Sep 17 00:00:00 2001 From: Sander Date: Mon, 9 Sep 2024 14:09:18 +0200 Subject: [PATCH 028/805] docs(ct): vue + jsx and general improvements (#32212) partial fix for: https://github.com/microsoft/playwright/issues/31927#issuecomment-2267065378 --------- Signed-off-by: Sander Co-authored-by: Dmitry Gozman --- docs/src/test-components-js.md | 178 +++++++++++++++++++++++++-------- 1 file changed, 135 insertions(+), 43 deletions(-) diff --git a/docs/src/test-components-js.md b/docs/src/test-components-js.md index e0bdc000bfc9e..91d1860a26544 100644 --- a/docs/src/test-components-js.md +++ b/docs/src/test-components-js.md @@ -113,12 +113,10 @@ component is mounted using this script. It can be either a `.js`, `.ts`, `.jsx` }> -```js +```js title="app.spec.tsx" import { test, expect } from '@playwright/experimental-ct-react'; import App from './App'; -test.use({ viewport: { width: 500, height: 500 } }); - test('should work', async ({ mount }) => { const component = await mount(); await expect(component).toContainText('Learn React'); @@ -129,18 +127,25 @@ test('should work', async ({ mount }) => { -```js +```js title="app.spec.ts" import { test, expect } from '@playwright/experimental-ct-vue'; import App from './App.vue'; -test.use({ viewport: { width: 500, height: 500 } }); - test('should work', async ({ mount }) => { const component = await mount(App); - await expect(component).toContainText('Vite + Vue'); + await expect(component).toContainText('Learn Vue'); }); ``` +```js title="app.spec.tsx" +import { test, expect } from '@playwright/experimental-ct-vue'; +import App from './App.vue'; + +test('should work', async ({ mount }) => { + const component = await mount(); + await expect(component).toContainText('Learn Vue'); +}); +``` If using TypeScript and Vue make sure to add a `vue.d.ts` file to your project: ```js @@ -151,15 +156,13 @@ declare module '*.vue'; -```js +```js title="app.spec.ts" import { test, expect } from '@playwright/experimental-ct-svelte'; import App from './App.svelte'; -test.use({ viewport: { width: 500, height: 500 } }); - test('should work', async ({ mount }) => { const component = await mount(App); - await expect(component).toContainText('Vite + Svelte'); + await expect(component).toContainText('Learn Svelte'); }); ``` @@ -167,12 +170,10 @@ test('should work', async ({ mount }) => { -```js +```js title="app.spec.tsx" import { test, expect } from '@playwright/experimental-ct-solid'; import App from './App'; -test.use({ viewport: { width: 500, height: 500 } }); - test('should work', async ({ mount }) => { const component = await mount(); await expect(component).toContainText('Learn Solid'); @@ -261,7 +262,10 @@ export function InputMediaForTest(props: InputMediaForTestProps) { Then test the component via testing the story: -```js title="input-media.test.spec.tsx" +```js title="input-media.spec.tsx" +import { test, expect } from '@playwright/experimental-ct-react'; +import { InputMediaForTest } from './input-media.story.tsx'; + test('changes the image', async ({ mount }) => { let mediaSelected: string | null = null; @@ -313,7 +317,9 @@ Provide props to a component when mounted. -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-react'; + test('props', async ({ mount }) => { const component = await mount(); }); @@ -322,7 +328,9 @@ test('props', async ({ mount }) => { -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-solid'; + test('props', async ({ mount }) => { const component = await mount(); }); @@ -331,7 +339,9 @@ test('props', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-svelte'; + test('props', async ({ mount }) => { const component = await mount(Component, { props: { msg: 'greetings' } }); }); @@ -340,12 +350,23 @@ test('props', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-vue'; + test('props', async ({ mount }) => { const component = await mount(Component, { props: { msg: 'greetings' } }); }); ``` +```js title="component.spec.tsx" +// Or alternatively, using the `jsx` style +import { test } from '@playwright/experimental-ct-vue'; + +test('props', async ({ mount }) => { + const component = await mount(); +}); +``` + @@ -366,36 +387,53 @@ Provide callbacks/events to a component when mounted. -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-react'; + test('callback', async ({ mount }) => { - const component = await mount( {}} />); + const component = await mount( {}} />); }); ``` -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-solid'; + test('callback', async ({ mount }) => { - const component = await mount( {}} />); + const component = await mount( {}} />); }); ``` -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-svelte'; + test('event', async ({ mount }) => { - const component = await mount(Component, { on: { callback() {} } }); + const component = await mount(Component, { on: { click() {} } }); }); ``` -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-vue'; + +test('event', async ({ mount }) => { + const component = await mount(Component, { on: { click() {} } }); +}); +``` + +```js title="component.spec.tsx" +// Or alternatively, using the `jsx` style +import { test } from '@playwright/experimental-ct-vue'; + test('event', async ({ mount }) => { - const component = await mount(Component, { on: { callback() {} } }); + const component = await mount( {}} />); }); ``` @@ -419,7 +457,9 @@ Provide children/slots to a component when mounted. -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-react'; + test('children', async ({ mount }) => { const component = await mount(Child); }); @@ -428,7 +468,9 @@ test('children', async ({ mount }) => { -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-solid'; + test('children', async ({ mount }) => { const component = await mount(Child); }); @@ -437,7 +479,9 @@ test('children', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-svelte'; + test('slot', async ({ mount }) => { const component = await mount(Component, { slots: { default: 'Slot' } }); }); @@ -446,12 +490,23 @@ test('slot', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-vue'; + test('slot', async ({ mount }) => { const component = await mount(Component, { slots: { default: 'Slot' } }); }); ``` +```js title="component.spec.tsx" +// Or alternatively, using the `jsx` style +import { test } from '@playwright/experimental-ct-vue'; + +test('children', async ({ mount }) => { + const component = await mount(Child); +}); +``` + @@ -614,7 +669,9 @@ Unmount the mounted component from the DOM. This is useful for testing the compo -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-react'; + test('unmount', async ({ mount }) => { const component = await mount(); await component.unmount(); @@ -624,7 +681,9 @@ test('unmount', async ({ mount }) => { -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-solid'; + test('unmount', async ({ mount }) => { const component = await mount(); await component.unmount(); @@ -634,7 +693,9 @@ test('unmount', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-svelte'; + test('unmount', async ({ mount }) => { const component = await mount(Component); await component.unmount(); @@ -644,13 +705,24 @@ test('unmount', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-vue'; + test('unmount', async ({ mount }) => { const component = await mount(Component); await component.unmount(); }); ``` +```js title="component.spec.tsx" +// Or alternatively, using the `jsx` style +import { test } from '@playwright/experimental-ct-vue'; + +test('unmount', async ({ mount }) => { + const component = await mount(); + await component.unmount(); +}); +``` @@ -671,11 +743,13 @@ Update props, slots/children, and/or events/callbacks of a mounted component. Th -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-react'; + test('update', async ({ mount }) => { const component = await mount(); await component.update( - {}}>Child + {}}>Child ); }); ``` @@ -683,11 +757,13 @@ test('update', async ({ mount }) => { -```js +```js title="component.spec.tsx" +import { test } from '@playwright/experimental-ct-solid'; + test('update', async ({ mount }) => { const component = await mount(); await component.update( - {}}>Child + {}}>Child ); }); ``` @@ -695,12 +771,14 @@ test('update', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-svelte'; + test('update', async ({ mount }) => { const component = await mount(Component); await component.update({ props: { msg: 'greetings' }, - on: { callback: () => {} }, + on: { click() {} }, slots: { default: 'Child' } }); }); @@ -709,17 +787,31 @@ test('update', async ({ mount }) => { -```js +```js title="component.spec.ts" +import { test } from '@playwright/experimental-ct-vue'; + test('update', async ({ mount }) => { const component = await mount(Component); await component.update({ props: { msg: 'greetings' }, - on: { callback: () => {} }, + on: { click() {} }, slots: { default: 'Child' } }); }); ``` +```js title="component.spec.tsx" +// Or alternatively, using the `jsx` style +import { test } from '@playwright/experimental-ct-vue'; + +test('update', async ({ mount }) => { + const component = await mount(); + await component.update( + {}}>Child + ); +}); +``` + From 728083b435ac0d7ec379a22bf7f7edc09b416490 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 9 Sep 2024 15:49:59 +0200 Subject: [PATCH 029/805] chore: allow query as string in Python/.NET (#32516) https://github.com/microsoft/playwright-python/issues/2497 --- docs/src/api/class-apirequestcontext.md | 35 ++++++++++++++++++++----- docs/src/api/params.md | 10 +++++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/docs/src/api/class-apirequestcontext.md b/docs/src/api/class-apirequestcontext.md index a6333d6b0ad51..1d3e72823542c 100644 --- a/docs/src/api/class-apirequestcontext.md +++ b/docs/src/api/class-apirequestcontext.md @@ -141,7 +141,7 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.delete.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.delete.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.delete.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.delete.params = %%-python-fetch-option-params-%% @@ -150,6 +150,9 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.delete.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.delete.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.delete.headers = %%-js-python-csharp-fetch-option-headers-%% * since: v1.16 @@ -303,7 +306,7 @@ Target URL or Request to get all parameters from. ### option: APIRequestContext.fetch.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.fetch.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.fetch.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.fetch.params = %%-python-fetch-option-params-%% @@ -312,6 +315,9 @@ Target URL or Request to get all parameters from. ### option: APIRequestContext.fetch.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.fetch.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.fetch.method * since: v1.16 * langs: js, python, csharp @@ -418,7 +424,7 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query ### option: APIRequestContext.get.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.get.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.get.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.get.params = %%-python-fetch-option-params-%% @@ -427,6 +433,9 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query ### option: APIRequestContext.get.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.get.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.get.headers = %%-js-python-csharp-fetch-option-headers-%% * since: v1.16 @@ -477,7 +486,7 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.head.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.head.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.head.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.head.params = %%-python-fetch-option-params-%% @@ -486,6 +495,9 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.head.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.head.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.head.headers = %%-js-python-csharp-fetch-option-headers-%% * since: v1.16 @@ -536,7 +548,7 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.patch.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.patch.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.patch.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.patch.params = %%-python-fetch-option-params-%% @@ -545,6 +557,9 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.patch.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.patch.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.patch.headers = %%-js-python-csharp-fetch-option-headers-%% * since: v1.16 @@ -716,7 +731,7 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar ### option: APIRequestContext.post.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.post.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.post.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.post.params = %%-python-fetch-option-params-%% @@ -725,6 +740,9 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar ### option: APIRequestContext.post.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.post.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.post.headers = %%-js-python-csharp-fetch-option-headers-%% * since: v1.16 @@ -775,7 +793,7 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.put.params = %%-js-fetch-option-params-%% * since: v1.16 -### param: APIRequestContext.put.params = %%-java-csharp-fetch-params-%% +### param: APIRequestContext.put.params = %%-java-fetch-params-%% * since: v1.18 ### option: APIRequestContext.put.params = %%-python-fetch-option-params-%% @@ -784,6 +802,9 @@ context cookies from the response. The method will automatically follow redirect ### option: APIRequestContext.put.params = %%-csharp-fetch-option-params-%% * since: v1.16 +### option: APIRequestContext.put.paramsString = %%-csharp-fetch-option-paramsString-%% +* since: v1.47 + ### option: APIRequestContext.put.headers = %%-js-python-csharp-fetch-option-headers-%% * since: v1.16 diff --git a/docs/src/api/params.md b/docs/src/api/params.md index ccd6bae8fed34..cbec1a5e25c79 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -364,7 +364,7 @@ Query parameters to be sent with the URL. ## python-fetch-option-params * langs: python -- `params` <[Object]<[string], [string]|[float]|[boolean]>> +- `params` <[Object]<[string], [string]|[float]|[boolean]>|[string]> Query parameters to be sent with the URL. @@ -374,7 +374,13 @@ Query parameters to be sent with the URL. Query parameters to be sent with the URL. -## java-csharp-fetch-params +## csharp-fetch-option-paramsString +* langs: csharp +- `paramsString` <[string]> + +Query parameters to be sent with the URL. + +## java-fetch-params * langs: java - `options` ?<[RequestOptions]> From d0309656885728dfb8760426cfb54fae829b8287 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 9 Sep 2024 10:13:26 -0700 Subject: [PATCH 030/805] chore: addInitScript and auth (unsuccessful) in bidi (#32500) --- .../src/server/bidi/bidiBrowser.ts | 12 +++++++--- .../src/server/bidi/bidiPage.ts | 23 ++++++++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/playwright-core/src/server/bidi/bidiBrowser.ts b/packages/playwright-core/src/server/bidi/bidiBrowser.ts index cc3fbc0562622..0c658a82b4162 100644 --- a/packages/playwright-core/src/server/bidi/bidiBrowser.ts +++ b/packages/playwright-core/src/server/bidi/bidiBrowser.ts @@ -195,8 +195,12 @@ export class BidiBrowserContext extends BrowserContext { this._authenticateProxyViaHeader(); } + private _bidiPages() { + return [...this._browser._bidiPages.values()].filter(bidiPage => bidiPage._browserContext === this); + } + pages(): Page[] { - return []; + return this._bidiPages().map(bidiPage => bidiPage._initializedPage).filter(Boolean) as Page[]; } async newPageDelegate(): Promise { @@ -269,11 +273,13 @@ export class BidiBrowserContext extends BrowserContext { } async doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise { + this._options.httpCredentials = httpCredentials; + for (const page of this.pages()) + await (page._delegate as BidiPage).updateHttpCredentials(); } async doAddInitScript(initScript: InitScript) { - // for (const page of this.pages()) - // await (page._delegate as WKPage)._updateBootstrapScript(); + await Promise.all(this.pages().map(page => (page._delegate as BidiPage).addInitScript(initScript))); } async doRemoveNonInternalInitScripts() { diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index 9ecb5c789b41a..f06924d70f39c 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -47,6 +47,7 @@ export class BidiPage implements PageDelegate { readonly _browserContext: BidiBrowserContext; readonly _networkManager: BidiNetworkManager; _initializedPage: Page | null = null; + private _initScriptIds: string[] = []; constructor(browserContext: BidiBrowserContext, bidiSession: BidiSession, opener: BidiPage | null) { this._session = bidiSession; @@ -92,9 +93,14 @@ export class BidiPage implements PageDelegate { this.updateHttpCredentials(), this.updateRequestInterception(), this._updateViewport(), + this._addAllInitScripts(), ]); } + private async _addAllInitScripts() { + return Promise.all(this._page.allInitScripts().map(initScript => this.addInitScript(initScript))); + } + potentiallyUninitializedPage(): Page { return this._page; } @@ -318,15 +324,20 @@ export class BidiPage implements PageDelegate { } async addInitScript(initScript: InitScript): Promise { - await this._updateBootstrapScript(); + const { script } = await this._session.send('script.addPreloadScript', { + // TODO: remove function call from the source. + functionDeclaration: `() => { return ${initScript.source} }`, + // TODO: push to iframes? + contexts: [this._session.sessionId], + }); + if (!initScript.internal) + this._initScriptIds.push(script); } async removeNonInternalInitScripts() { - await this._updateBootstrapScript(); - } - - async _updateBootstrapScript(): Promise { - throw new Error('Method not implemented.'); + const promises = this._initScriptIds.map(script => this._session.send('script.removePreloadScript', { script })); + this._initScriptIds = []; + await Promise.all(promises); } async closePage(runBeforeUnload: boolean): Promise { From 363e79ee87feb309b6a1e187a81cd444d2251301 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:07:37 -0700 Subject: [PATCH 031/805] feat(webkit): roll to r2071 (#32521) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 0ea21f1ecca6d..2b0dc63ce7bb4 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -27,7 +27,7 @@ }, { "name": "webkit", - "revision": "2070", + "revision": "2071", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", From 4b5422a3c7ecfe871eb4da3036e31725271a69da Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 9 Sep 2024 22:07:28 +0200 Subject: [PATCH 032/805] fix(ui-mode): use server side path separator (#32523) Fixes https://github.com/microsoft/playwright/issues/32323 --- .../src/server/trace/viewer/traceViewer.ts | 2 ++ packages/trace-viewer/src/ui/uiModeTraceView.tsx | 10 ++++++++-- packages/trace-viewer/src/ui/uiModeView.tsx | 12 ++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts index d053a3e643d3a..6ca0319aa313c 100644 --- a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts +++ b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts @@ -109,6 +109,8 @@ export async function startTraceViewerServer(options?: TraceViewerServerOptions) export async function installRootRedirect(server: HttpServer, traceUrls: string[], options: TraceViewerRedirectOptions) { const params = new URLSearchParams(); + if (path.sep !== path.posix.sep) + params.set('pathSeparator', path.sep); for (const traceUrl of traceUrls) params.append('trace', traceUrl); if (server.wsGuid()) diff --git a/packages/trace-viewer/src/ui/uiModeTraceView.tsx b/packages/trace-viewer/src/ui/uiModeTraceView.tsx index e34ab6aedee87..8027005812123 100644 --- a/packages/trace-viewer/src/ui/uiModeTraceView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTraceView.tsx @@ -31,7 +31,8 @@ export const TraceView: React.FC<{ rootDir?: string, onOpenExternally?: (location: SourceLocation) => void, revealSource?: boolean, -}> = ({ item, rootDir, onOpenExternally, revealSource }) => { + pathSeparator: string, +}> = ({ item, rootDir, onOpenExternally, revealSource, pathSeparator }) => { const [model, setModel] = React.useState<{ model: MultiTraceModel, isLive: boolean } | undefined>(); const [counter, setCounter] = React.useState(0); const pollTimer = React.useRef(null); @@ -69,7 +70,12 @@ export const TraceView: React.FC<{ return; } - const traceLocation = `${outputDir}/${artifactsFolderName(result!.workerIndex)}/traces/${item.testCase?.id}.json`; + const traceLocation = [ + outputDir, + artifactsFolderName(result!.workerIndex), + 'traces', + `${item.testCase?.id}.json` + ].join(pathSeparator); // Start polling running test. pollTimer.current = setTimeout(async () => { try { diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index cad1c2eb58bdd..2c4b61fdadae1 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -38,8 +38,6 @@ import { TestListView } from './uiModeTestListView'; import { TraceView } from './uiModeTraceView'; import { SettingsView } from './settingsView'; -const pathSeparator = navigator.userAgent.toLowerCase().includes('windows') ? '\\' : '/'; - let xtermSize = { cols: 80, rows: 24 }; const xtermDataSource: XtermDataSource = { pending: [], @@ -63,6 +61,7 @@ const queryParams = { outputDir: searchParams.get('outputDir') || undefined, updateSnapshots: (searchParams.get('updateSnapshots') as 'all' | 'none' | 'missing' | undefined) || undefined, reporters: searchParams.has('reporter') ? searchParams.getAll('reporter') : undefined, + pathSeparator: searchParams.get('pathSeparator') || '/', }; if (queryParams.updateSnapshots && !['all', 'none', 'missing'].includes(queryParams.updateSnapshots)) queryParams.updateSnapshots = undefined; @@ -170,7 +169,7 @@ export const UIModeView: React.FC<{}> = ({ onError: error => { xtermDataSource.write((error.stack || error.value || '') + '\n'); }, - pathSeparator, + pathSeparator: queryParams.pathSeparator, }); setTeleSuiteUpdater(teleSuiteUpdater); @@ -242,8 +241,8 @@ export const UIModeView: React.FC<{}> = ({ // Test tree is built from the model and filters. const { testTree } = React.useMemo(() => { if (!testModel) - return { testTree: new TestTree('', new TeleSuite('', 'root'), [], projectFilters, pathSeparator) }; - const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, pathSeparator); + return { testTree: new TestTree('', new TeleSuite('', 'root'), [], projectFilters, queryParams.pathSeparator) }; + const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, queryParams.pathSeparator); testTree.filterTree(filterText, statusFilters, isRunningTest ? runningState?.testIds : undefined); testTree.sortAndPropagateStatus(); testTree.shortenRoot(); @@ -332,7 +331,7 @@ export const UIModeView: React.FC<{}> = ({ // run affected watched tests const testModel = teleSuiteUpdater.asModel(); - const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, pathSeparator); + const testTree = new TestTree('', testModel.rootSuite, testModel.loadErrors, projectFilters, queryParams.pathSeparator); const testIds: string[] = []; const set = new Set(params.testFiles); @@ -435,6 +434,7 @@ export const UIModeView: React.FC<{}> = ({
Date: Mon, 9 Sep 2024 13:12:20 -0700 Subject: [PATCH 033/805] chore: roll expect and move it to third party (#32458) --- package-lock.json | 161 +- package.json | 3 + packages/playwright/ThirdPartyNotices.txt | 254 +- .../bundles/expect/package-lock.json | 432 +- .../playwright/bundles/expect/package.json | 8 +- .../bundles/expect/src/expectBundleImpl.ts | 24 +- .../bundles/expect/third_party/LICENSE | 21 + .../expect/third_party/asymmetricMatchers.ts | 362 ++ .../extractExpectedAssertionsErrors.ts | 85 + .../bundles/expect/third_party/index.ts | 463 +++ .../expect/third_party/jestMatchersObject.ts | 144 + .../bundles/expect/third_party/matchers.ts | 983 +++++ .../bundles/expect/third_party/print.ts | 134 + .../bundles/expect/third_party/spyMatchers.ts | 1184 ++++++ .../expect/third_party/toThrowMatchers.ts | 481 +++ .../bundles/expect/third_party/types.ts | 353 ++ .../playwright/src/common/expectBundle.ts | 5 +- packages/web/src/ansi2html.ts | 5 +- tests/config/utils.ts | 35 + tests/expect/assertionCounts.test.ts | 78 + tests/expect/asymmetricMatchers.test.ts | 519 +++ tests/expect/customEqualityTesters.test.ts | 197 + .../customEqualityTestersRecursive.test.ts | 246 ++ tests/expect/extend.test.ts | 247 ++ tests/expect/fixtures.ts | 108 + tests/expect/matchers.snapshots.js | 3614 +++++++++++++++++ tests/expect/matchers.test.ts | 2338 +++++++++++ tests/expect/spyMatchers.snapshots.js | 2600 ++++++++++++ tests/expect/spyMatchers.test.ts | 1499 +++++++ tests/expect/stacktrace.test.ts | 71 + tests/expect/symbolInObjects.test.ts | 43 + tests/expect/toThrowMatchers.snapshots.js | 456 +++ tests/expect/toThrowMatchers.test.ts | 591 +++ tests/playwright-test/playwright.config.ts | 4 + utils/check_deps.js | 4 +- 35 files changed, 17336 insertions(+), 416 deletions(-) create mode 100644 packages/playwright/bundles/expect/third_party/LICENSE create mode 100644 packages/playwright/bundles/expect/third_party/asymmetricMatchers.ts create mode 100644 packages/playwright/bundles/expect/third_party/extractExpectedAssertionsErrors.ts create mode 100644 packages/playwright/bundles/expect/third_party/index.ts create mode 100644 packages/playwright/bundles/expect/third_party/jestMatchersObject.ts create mode 100644 packages/playwright/bundles/expect/third_party/matchers.ts create mode 100644 packages/playwright/bundles/expect/third_party/print.ts create mode 100644 packages/playwright/bundles/expect/third_party/spyMatchers.ts create mode 100644 packages/playwright/bundles/expect/third_party/toThrowMatchers.ts create mode 100644 packages/playwright/bundles/expect/third_party/types.ts create mode 100644 tests/expect/assertionCounts.test.ts create mode 100644 tests/expect/asymmetricMatchers.test.ts create mode 100644 tests/expect/customEqualityTesters.test.ts create mode 100644 tests/expect/customEqualityTestersRecursive.test.ts create mode 100644 tests/expect/extend.test.ts create mode 100644 tests/expect/fixtures.ts create mode 100644 tests/expect/matchers.snapshots.js create mode 100644 tests/expect/matchers.test.ts create mode 100644 tests/expect/spyMatchers.snapshots.js create mode 100644 tests/expect/spyMatchers.test.ts create mode 100644 tests/expect/stacktrace.test.ts create mode 100644 tests/expect/symbolInObjects.test.ts create mode 100644 tests/expect/toThrowMatchers.snapshots.js create mode 100644 tests/expect/toThrowMatchers.test.ts diff --git a/package-lock.json b/package-lock.json index 4e24bcfa49943..b7cdad125ec97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@types/babel__core": "^7.20.2", "@types/codemirror": "^5.60.7", "@types/formidable": "^2.0.4", + "@types/immutable": "^3.8.7", "@types/node": "^18.19.39", "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", @@ -37,6 +38,7 @@ "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-react": "^4.2.1", "@zip.js/zip.js": "^2.7.29", + "ansi-styles": "^4.3.0", "chokidar": "^3.5.3", "chromium-bidi": "^0.6.4", "colors": "^1.4.0", @@ -51,6 +53,7 @@ "eslint-plugin-react": "^7.35.0", "eslint-plugin-react-hooks": "^4.6.2", "formidable": "^2.1.1", + "immutable": "^4.3.7", "license-checker": "^25.0.1", "mime": "^3.0.0", "node-stream-zip": "^1.15.0", @@ -1832,6 +1835,16 @@ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true }, + "node_modules/@types/immutable": { + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@types/immutable/-/immutable-3.8.7.tgz", + "integrity": "sha512-nsHFDX48Tl3RaP4BF47HHe5njx40Pcp+0a8CIqzJata80Fp7JzkcuGB7UhZBGjH9aA1fMEahIqvPQQNmro5YLg==", + "deprecated": "This is a stub types definition for Facebook's Immutable (https://github.com/facebook/immutable-js). Facebook's Immutable provides its own type definitions, so you don't need @types/immutable installed!", + "dev": true, + "dependencies": { + "immutable": "*" + } + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -2359,16 +2372,38 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/ansi-to-html": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", @@ -2802,6 +2837,17 @@ "node": ">=4" } }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2942,21 +2988,6 @@ "node": ">=10.0.0" } }, - "node_modules/concurrently/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/concurrently/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2985,24 +3016,6 @@ "node": ">=8" } }, - "node_modules/concurrently/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/concurrently/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/concurrently/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3779,21 +3792,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3820,24 +3818,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4635,6 +4615,12 @@ "node": ">= 4" } }, + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -7772,39 +7758,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 44d259d7a4d2c..c095546c7d4f3 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@types/babel__core": "^7.20.2", "@types/codemirror": "^5.60.7", "@types/formidable": "^2.0.4", + "@types/immutable": "^3.8.7", "@types/node": "^18.19.39", "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", @@ -76,6 +77,7 @@ "@vitejs/plugin-basic-ssl": "^1.1.0", "@vitejs/plugin-react": "^4.2.1", "@zip.js/zip.js": "^2.7.29", + "ansi-styles": "^4.3.0", "chokidar": "^3.5.3", "chromium-bidi": "^0.6.4", "colors": "^1.4.0", @@ -90,6 +92,7 @@ "eslint-plugin-react": "^7.35.0", "eslint-plugin-react-hooks": "^4.6.2", "formidable": "^2.1.1", + "immutable": "^4.3.7", "license-checker": "^25.0.1", "mime": "^3.0.0", "node-stream-zip": "^1.15.0", diff --git a/packages/playwright/ThirdPartyNotices.txt b/packages/playwright/ThirdPartyNotices.txt index 020b2bc3f6882..f2bb64d661c29 100644 --- a/packages/playwright/ThirdPartyNotices.txt +++ b/packages/playwright/ThirdPartyNotices.txt @@ -5,8 +5,8 @@ THIRD-PARTY SOFTWARE NOTICES AND INFORMATION This project incorporates components from the projects listed below. The original copyright notices and the licenses under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted herein, whether by implication, estoppel or otherwise. - @ampproject/remapping@2.2.1 (https://github.com/ampproject/remapping) -- @babel/code-frame@7.22.5 (https://github.com/babel/babel) - @babel/code-frame@7.24.2 (https://github.com/babel/babel) +- @babel/code-frame@7.24.7 (https://github.com/babel/babel) - @babel/compat-data@7.23.5 (https://github.com/babel/babel) - @babel/core@7.24.4 (https://github.com/babel/babel) - @babel/generator@7.24.4 (https://github.com/babel/babel) @@ -27,11 +27,11 @@ This project incorporates components from the projects listed below. The origina - @babel/helper-split-export-declaration@7.22.6 (https://github.com/babel/babel) - @babel/helper-string-parser@7.23.4 (https://github.com/babel/babel) - @babel/helper-validator-identifier@7.22.20 (https://github.com/babel/babel) -- @babel/helper-validator-identifier@7.22.5 (https://github.com/babel/babel) +- @babel/helper-validator-identifier@7.24.7 (https://github.com/babel/babel) - @babel/helper-validator-option@7.23.5 (https://github.com/babel/babel) - @babel/helpers@7.24.4 (https://github.com/babel/babel) -- @babel/highlight@7.22.5 (https://github.com/babel/babel) - @babel/highlight@7.24.2 (https://github.com/babel/babel) +- @babel/highlight@7.24.7 (https://github.com/babel/babel) - @babel/parser@7.24.4 (https://github.com/babel/babel) - @babel/plugin-proposal-decorators@7.24.1 (https://github.com/babel/babel) - @babel/plugin-proposal-explicit-resource-management@7.24.1 (https://github.com/babel/babel) @@ -67,22 +67,22 @@ This project incorporates components from the projects listed below. The origina - @babel/template@7.24.0 (https://github.com/babel/babel) - @babel/traverse@7.24.1 (https://github.com/babel/babel) - @babel/types@7.24.0 (https://github.com/babel/babel) -- @jest/expect-utils@29.5.0 (https://github.com/facebook/jest) -- @jest/schemas@29.4.3 (https://github.com/facebook/jest) -- @jest/types@29.5.0 (https://github.com/facebook/jest) +- @jest/expect-utils@29.7.0 (https://github.com/jestjs/jest) +- @jest/schemas@29.6.3 (https://github.com/jestjs/jest) +- @jest/types@29.6.3 (https://github.com/jestjs/jest) - @jridgewell/gen-mapping@0.3.5 (https://github.com/jridgewell/gen-mapping) - @jridgewell/resolve-uri@3.1.1 (https://github.com/jridgewell/resolve-uri) - @jridgewell/set-array@1.2.1 (https://github.com/jridgewell/set-array) - @jridgewell/sourcemap-codec@1.4.15 (https://github.com/jridgewell/sourcemap-codec) - @jridgewell/trace-mapping@0.3.25 (https://github.com/jridgewell/trace-mapping) -- @sinclair/typebox@0.25.24 (https://github.com/sinclairzx81/typebox) -- @types/istanbul-lib-coverage@2.0.4 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- @types/istanbul-lib-report@3.0.0 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- @types/istanbul-reports@3.0.1 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- @types/node@20.2.5 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- @types/stack-utils@2.0.1 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- @types/yargs-parser@21.0.0 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- @types/yargs@17.0.24 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @sinclair/typebox@0.27.8 (https://github.com/sinclairzx81/typebox) +- @types/istanbul-lib-coverage@2.0.6 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @types/istanbul-lib-report@3.0.3 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @types/istanbul-reports@3.0.4 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @types/node@22.5.4 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @types/stack-utils@2.0.3 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @types/yargs-parser@21.0.3 (https://github.com/DefinitelyTyped/DefinitelyTyped) +- @types/yargs@17.0.33 (https://github.com/DefinitelyTyped/DefinitelyTyped) - ansi-colors@4.1.3 (https://github.com/doowb/ansi-colors) - ansi-styles@3.2.1 (https://github.com/chalk/ansi-styles) - ansi-styles@4.3.0 (https://github.com/chalk/ansi-styles) @@ -96,7 +96,7 @@ This project incorporates components from the projects listed below. The origina - chalk@2.4.2 (https://github.com/chalk/chalk) - chalk@4.1.2 (https://github.com/chalk/chalk) - chokidar@3.6.0 (https://github.com/paulmillr/chokidar) -- ci-info@3.8.0 (https://github.com/watson/ci-info) +- ci-info@3.9.0 (https://github.com/watson/ci-info) - codemirror-shadow-1@0.0.1 (https://github.com/codemirror/CodeMirror) - color-convert@1.9.3 (https://github.com/Qix-/color-convert) - color-convert@2.0.1 (https://github.com/Qix-/color-convert) @@ -104,13 +104,12 @@ This project incorporates components from the projects listed below. The origina - color-name@1.1.4 (https://github.com/colorjs/color-name) - convert-source-map@2.0.0 (https://github.com/thlorenz/convert-source-map) - debug@4.3.4 (https://github.com/debug-js/debug) -- diff-sequences@29.4.3 (https://github.com/facebook/jest) +- diff-sequences@29.6.3 (https://github.com/jestjs/jest) - electron-to-chromium@1.4.638 (https://github.com/kilian/electron-to-chromium) - enquirer@2.3.6 (https://github.com/enquirer/enquirer) - escalade@3.1.1 (https://github.com/lukeed/escalade) - escape-string-regexp@1.0.5 (https://github.com/sindresorhus/escape-string-regexp) - escape-string-regexp@2.0.0 (https://github.com/sindresorhus/escape-string-regexp) -- expect@29.5.0 (https://github.com/facebook/jest) - fill-range@7.1.1 (https://github.com/jonschlinkert/fill-range) - gensync@1.0.0-beta.2 (https://github.com/loganfsmyth/gensync) - glob-parent@5.1.2 (https://github.com/gulpjs/glob-parent) @@ -122,11 +121,12 @@ This project incorporates components from the projects listed below. The origina - is-extglob@2.1.1 (https://github.com/jonschlinkert/is-extglob) - is-glob@4.0.3 (https://github.com/micromatch/is-glob) - is-number@7.0.0 (https://github.com/jonschlinkert/is-number) -- jest-diff@29.5.0 (https://github.com/facebook/jest) -- jest-get-type@29.4.3 (https://github.com/facebook/jest) -- jest-matcher-utils@29.5.0 (https://github.com/facebook/jest) -- jest-message-util@29.5.0 (https://github.com/facebook/jest) -- jest-util@29.5.0 (https://github.com/facebook/jest) +- jest-diff@29.7.0 (https://github.com/jestjs/jest) +- jest-get-type@29.6.3 (https://github.com/jestjs/jest) +- jest-matcher-utils@29.7.0 (https://github.com/jestjs/jest) +- jest-message-util@29.7.0 (https://github.com/jestjs/jest) +- jest-mock@29.7.0 (https://github.com/jestjs/jest) +- jest-util@29.7.0 (https://github.com/jestjs/jest) - js-tokens@4.0.0 (https://github.com/lydell/js-tokens) - jsesc@2.5.2 (https://github.com/mathiasbynens/jsesc) - json5@2.2.3 (https://github.com/json5/json5) @@ -136,10 +136,11 @@ This project incorporates components from the projects listed below. The origina - node-releases@2.0.14 (https://github.com/chicoxyzzy/node-releases) - normalize-path@3.0.0 (https://github.com/jonschlinkert/normalize-path) - picocolors@1.0.0 (https://github.com/alexeyraspopov/picocolors) +- picocolors@1.1.0 (https://github.com/alexeyraspopov/picocolors) - picomatch@2.3.1 (https://github.com/micromatch/picomatch) - pirates@4.0.4 (https://github.com/danez/pirates) -- pretty-format@29.5.0 (https://github.com/facebook/jest) -- react-is@18.2.0 (https://github.com/facebook/react) +- pretty-format@29.7.0 (https://github.com/jestjs/jest) +- react-is@18.3.1 (https://github.com/facebook/react) - readdirp@3.6.0 (https://github.com/paulmillr/readdirp) - semver@6.3.1 (https://github.com/npm/node-semver) - slash@3.0.0 (https://github.com/sindresorhus/slash) @@ -151,6 +152,7 @@ This project incorporates components from the projects listed below. The origina - supports-color@7.2.0 (https://github.com/chalk/supports-color) - to-fast-properties@2.0.0 (https://github.com/sindresorhus/to-fast-properties) - to-regex-range@5.0.1 (https://github.com/micromatch/to-regex-range) +- undici-types@6.19.8 (https://github.com/nodejs/undici) - update-browserslist-db@1.0.13 (https://github.com/browserslist/update-db) - yallist@3.1.1 (https://github.com/isaacs/yallist) @@ -360,7 +362,7 @@ Apache License ========================================= END OF @ampproject/remapping@2.2.1 AND INFORMATION -%% @babel/code-frame@7.22.5 NOTICES AND INFORMATION BEGIN HERE +%% @babel/code-frame@7.24.2 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -385,9 +387,9 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @babel/code-frame@7.22.5 AND INFORMATION +END OF @babel/code-frame@7.24.2 AND INFORMATION -%% @babel/code-frame@7.24.2 NOTICES AND INFORMATION BEGIN HERE +%% @babel/code-frame@7.24.7 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -412,7 +414,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @babel/code-frame@7.24.2 AND INFORMATION +END OF @babel/code-frame@7.24.7 AND INFORMATION %% @babel/compat-data@7.23.5 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -954,7 +956,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF @babel/helper-validator-identifier@7.22.20 AND INFORMATION -%% @babel/helper-validator-identifier@7.22.5 NOTICES AND INFORMATION BEGIN HERE +%% @babel/helper-validator-identifier@7.24.7 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -979,7 +981,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @babel/helper-validator-identifier@7.22.5 AND INFORMATION +END OF @babel/helper-validator-identifier@7.24.7 AND INFORMATION %% @babel/helper-validator-option@7.23.5 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -1035,7 +1037,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF @babel/helpers@7.24.4 AND INFORMATION -%% @babel/highlight@7.22.5 NOTICES AND INFORMATION BEGIN HERE +%% @babel/highlight@7.24.2 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -1060,9 +1062,9 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @babel/highlight@7.22.5 AND INFORMATION +END OF @babel/highlight@7.24.2 AND INFORMATION -%% @babel/highlight@7.24.2 NOTICES AND INFORMATION BEGIN HERE +%% @babel/highlight@7.24.7 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -1087,7 +1089,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @babel/highlight@7.24.2 AND INFORMATION +END OF @babel/highlight@7.24.7 AND INFORMATION %% @babel/parser@7.24.4 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -2031,7 +2033,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF @babel/types@7.24.0 AND INFORMATION -%% @jest/expect-utils@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% @jest/expect-utils@29.7.0 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2055,9 +2057,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @jest/expect-utils@29.5.0 AND INFORMATION +END OF @jest/expect-utils@29.7.0 AND INFORMATION -%% @jest/schemas@29.4.3 NOTICES AND INFORMATION BEGIN HERE +%% @jest/schemas@29.6.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2081,9 +2083,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @jest/schemas@29.4.3 AND INFORMATION +END OF @jest/schemas@29.6.3 AND INFORMATION -%% @jest/types@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% @jest/types@29.6.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2107,7 +2109,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @jest/types@29.5.0 AND INFORMATION +END OF @jest/types@29.6.3 AND INFORMATION %% @jridgewell/gen-mapping@0.3.5 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -2231,7 +2233,7 @@ SOFTWARE. ========================================= END OF @jridgewell/trace-mapping@0.3.25 AND INFORMATION -%% @sinclair/typebox@0.25.24 NOTICES AND INFORMATION BEGIN HERE +%% @sinclair/typebox@0.27.8 NOTICES AND INFORMATION BEGIN HERE ========================================= TypeBox: JSON Schema Type Builder with Static Type Resolution for TypeScript @@ -2257,9 +2259,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF @sinclair/typebox@0.25.24 AND INFORMATION +END OF @sinclair/typebox@0.27.8 AND INFORMATION -%% @types/istanbul-lib-coverage@2.0.4 NOTICES AND INFORMATION BEGIN HERE +%% @types/istanbul-lib-coverage@2.0.6 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2283,13 +2285,13 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/istanbul-lib-coverage@2.0.4 AND INFORMATION +END OF @types/istanbul-lib-coverage@2.0.6 AND INFORMATION -%% @types/istanbul-lib-report@3.0.0 NOTICES AND INFORMATION BEGIN HERE +%% @types/istanbul-lib-report@3.0.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License - Copyright (c) Microsoft Corporation. All rights reserved. + Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -2309,9 +2311,9 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/istanbul-lib-report@3.0.0 AND INFORMATION +END OF @types/istanbul-lib-report@3.0.3 AND INFORMATION -%% @types/istanbul-reports@3.0.1 NOTICES AND INFORMATION BEGIN HERE +%% @types/istanbul-reports@3.0.4 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2335,9 +2337,9 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/istanbul-reports@3.0.1 AND INFORMATION +END OF @types/istanbul-reports@3.0.4 AND INFORMATION -%% @types/node@20.2.5 NOTICES AND INFORMATION BEGIN HERE +%% @types/node@22.5.4 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2361,9 +2363,9 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/node@20.2.5 AND INFORMATION +END OF @types/node@22.5.4 AND INFORMATION -%% @types/stack-utils@2.0.1 NOTICES AND INFORMATION BEGIN HERE +%% @types/stack-utils@2.0.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2387,9 +2389,9 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/stack-utils@2.0.1 AND INFORMATION +END OF @types/stack-utils@2.0.3 AND INFORMATION -%% @types/yargs-parser@21.0.0 NOTICES AND INFORMATION BEGIN HERE +%% @types/yargs-parser@21.0.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2413,9 +2415,9 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/yargs-parser@21.0.0 AND INFORMATION +END OF @types/yargs-parser@21.0.3 AND INFORMATION -%% @types/yargs@17.0.24 NOTICES AND INFORMATION BEGIN HERE +%% @types/yargs@17.0.33 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -2439,7 +2441,7 @@ MIT License OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ========================================= -END OF @types/yargs@17.0.24 AND INFORMATION +END OF @types/yargs@17.0.33 AND INFORMATION %% ansi-colors@4.1.3 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -3074,11 +3076,11 @@ THE SOFTWARE. ========================================= END OF chokidar@3.6.0 AND INFORMATION -%% ci-info@3.8.0 NOTICES AND INFORMATION BEGIN HERE +%% ci-info@3.9.0 NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) -Copyright (c) 2016-2023 Thomas Watson Steen +Copyright (c) 2016 Thomas Watson Steen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -3098,7 +3100,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF ci-info@3.8.0 AND INFORMATION +END OF ci-info@3.9.0 AND INFORMATION %% codemirror-shadow-1@0.0.1 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -3254,7 +3256,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF debug@4.3.4 AND INFORMATION -%% diff-sequences@29.4.3 NOTICES AND INFORMATION BEGIN HERE +%% diff-sequences@29.6.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3278,7 +3280,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF diff-sequences@29.4.3 AND INFORMATION +END OF diff-sequences@29.6.3 AND INFORMATION %% electron-to-chromium@1.4.638 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -3370,32 +3372,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ========================================= END OF escape-string-regexp@2.0.0 AND INFORMATION -%% expect@29.5.0 NOTICES AND INFORMATION BEGIN HERE -========================================= -MIT License - -Copyright (c) Meta Platforms, Inc. and affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -========================================= -END OF expect@29.5.0 AND INFORMATION - %% fill-range@7.1.1 NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -3608,7 +3584,7 @@ THE SOFTWARE. ========================================= END OF is-number@7.0.0 AND INFORMATION -%% jest-diff@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% jest-diff@29.7.0 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3632,9 +3608,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF jest-diff@29.5.0 AND INFORMATION +END OF jest-diff@29.7.0 AND INFORMATION -%% jest-get-type@29.4.3 NOTICES AND INFORMATION BEGIN HERE +%% jest-get-type@29.6.3 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3658,9 +3634,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF jest-get-type@29.4.3 AND INFORMATION +END OF jest-get-type@29.6.3 AND INFORMATION -%% jest-matcher-utils@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% jest-matcher-utils@29.7.0 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3684,9 +3660,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF jest-matcher-utils@29.5.0 AND INFORMATION +END OF jest-matcher-utils@29.7.0 AND INFORMATION -%% jest-message-util@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% jest-message-util@29.7.0 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3710,9 +3686,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF jest-message-util@29.5.0 AND INFORMATION +END OF jest-message-util@29.7.0 AND INFORMATION -%% jest-util@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% jest-mock@29.7.0 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3736,7 +3712,33 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF jest-util@29.5.0 AND INFORMATION +END OF jest-mock@29.7.0 AND INFORMATION + +%% jest-util@29.7.0 NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Copyright (c) Meta Platforms, Inc. and affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF jest-util@29.7.0 AND INFORMATION %% js-tokens@4.0.0 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -3961,6 +3963,26 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ========================================= END OF picocolors@1.0.0 AND INFORMATION +%% picocolors@1.1.0 NOTICES AND INFORMATION BEGIN HERE +========================================= +ISC License + +Copyright (c) 2021-2024 Oleksii Raspopov, Kostiantyn Denysov, Anton Verinov + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +========================================= +END OF picocolors@1.1.0 AND INFORMATION + %% picomatch@2.3.1 NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -4013,7 +4035,7 @@ SOFTWARE. ========================================= END OF pirates@4.0.4 AND INFORMATION -%% pretty-format@29.5.0 NOTICES AND INFORMATION BEGIN HERE +%% pretty-format@29.7.0 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -4037,9 +4059,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF pretty-format@29.5.0 AND INFORMATION +END OF pretty-format@29.7.0 AND INFORMATION -%% react-is@18.2.0 NOTICES AND INFORMATION BEGIN HERE +%% react-is@18.3.1 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -4063,7 +4085,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF react-is@18.2.0 AND INFORMATION +END OF react-is@18.3.1 AND INFORMATION %% readdirp@3.6.0 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -4304,6 +4326,32 @@ THE SOFTWARE. ========================================= END OF to-regex-range@5.0.1 AND INFORMATION +%% undici-types@6.19.8 NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Copyright (c) Matteo Collina and Undici contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +========================================= +END OF undici-types@6.19.8 AND INFORMATION + %% update-browserslist-db@1.0.13 NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -4351,6 +4399,6 @@ END OF yallist@3.1.1 AND INFORMATION SUMMARY BEGIN HERE ========================================= -Total Packages: 149 +Total Packages: 151 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright/bundles/expect/package-lock.json b/packages/playwright/bundles/expect/package-lock.json index 9a1707ff387fd..73375dd81b82c 100644 --- a/packages/playwright/bundles/expect/package-lock.json +++ b/packages/playwright/bundles/expect/package-lock.json @@ -8,37 +8,43 @@ "name": "expect-bundle", "version": "0.0.1", "dependencies": { - "expect": "29.5.0", - "jest-matcher-utils": "29.5.0" + "@jest/expect-utils": "29.7.0", + "jest-get-type": "29.6.3", + "jest-matcher-utils": "29.7.0", + "jest-message-util": "29.7.0", + "jest-mock": "29.7.0", + "jest-util": "29.7.0" } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -109,33 +115,33 @@ } }, "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -147,53 +153,56 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": { + "undici-types": "~6.19.2" + } }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, "node_modules/ansi-styles": { "version": "4.3.0", @@ -236,9 +245,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "funding": [ { "type": "github", @@ -266,9 +275,9 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -281,21 +290,6 @@ "node": ">=8" } }, - "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -329,53 +323,53 @@ } }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -383,12 +377,25 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -416,6 +423,11 @@ "node": ">=8.6" } }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -428,11 +440,11 @@ } }, "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -452,9 +464,9 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/slash": { "version": "3.0.0", @@ -496,30 +508,37 @@ "engines": { "node": ">=8.0" } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" } }, "dependencies": { "@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "requires": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" } }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==" }, "@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "requires": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { @@ -574,27 +593,27 @@ } }, "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "requires": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" } }, "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "requires": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" } }, "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -603,53 +622,56 @@ } }, "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" }, "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "requires": { "@types/istanbul-lib-coverage": "*" } }, "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "requires": { "@types/istanbul-lib-report": "*" } }, "@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "requires": { + "undici-types": "~6.19.2" + } }, "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" }, "@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, "ansi-styles": { "version": "4.3.0", @@ -677,9 +699,9 @@ } }, "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" }, "color-convert": { "version": "2.0.1", @@ -695,27 +717,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==" + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==" }, "escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" }, - "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "requires": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - } - }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -740,54 +750,64 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "requires": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, "jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==" + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==" }, "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -809,17 +829,22 @@ "picomatch": "^2.3.1" } }, + "picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -832,9 +857,9 @@ } }, "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "slash": { "version": "3.0.0", @@ -864,6 +889,11 @@ "requires": { "is-number": "^7.0.0" } + }, + "undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" } } } diff --git a/packages/playwright/bundles/expect/package.json b/packages/playwright/bundles/expect/package.json index 11ea4cc42ed10..d9f436755f1e2 100644 --- a/packages/playwright/bundles/expect/package.json +++ b/packages/playwright/bundles/expect/package.json @@ -9,7 +9,11 @@ "generate-license": "node ../../../../utils/generate_third_party_notice.js" }, "dependencies": { - "expect": "29.5.0", - "jest-matcher-utils": "29.5.0" + "@jest/expect-utils": "29.7.0", + "jest-get-type": "29.6.3", + "jest-matcher-utils": "29.7.0", + "jest-message-util": "29.7.0", + "jest-mock": "29.7.0", + "jest-util": "29.7.0" } } diff --git a/packages/playwright/bundles/expect/src/expectBundleImpl.ts b/packages/playwright/bundles/expect/src/expectBundleImpl.ts index 3eddff13232f4..dbfd169353d9b 100644 --- a/packages/playwright/bundles/expect/src/expectBundleImpl.ts +++ b/packages/playwright/bundles/expect/src/expectBundleImpl.ts @@ -14,8 +14,30 @@ * limitations under the License. */ -import expectLibrary from 'expect'; +import expectLibrary from '../third_party/index'; export const expect = expectLibrary; +export * as mock from 'jest-mock'; +import * as am from '../third_party/asymmetricMatchers'; +import * as mu from 'jest-matcher-utils'; + +export const asymmetricMatchers = { + any: am.any, + anything: am.anything, + arrayContaining: am.arrayContaining, + arrayNotContaining: am.arrayNotContaining, + closeTo: am.closeTo, + notCloseTo: am.notCloseTo, + objectContaining: am.objectContaining, + objectNotContaining: am.objectNotContaining, + stringContaining: am.stringContaining, + stringMatching: am.stringMatching, + stringNotContaining: am.stringNotContaining, + stringNotMatching: am.stringNotMatching, +}; + +export const matcherUtils = { + stringify: mu.stringify, +}; export { INVERTED_COLOR, diff --git a/packages/playwright/bundles/expect/third_party/LICENSE b/packages/playwright/bundles/expect/third_party/LICENSE new file mode 100644 index 0000000000000..b93be90515ccd --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Meta Platforms, Inc. and affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/playwright/bundles/expect/third_party/asymmetricMatchers.ts b/packages/playwright/bundles/expect/third_party/asymmetricMatchers.ts new file mode 100644 index 0000000000000..4e7a3402c90e6 --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/asymmetricMatchers.ts @@ -0,0 +1,362 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { + equals, + getObjectKeys, + isA, + iterableEquality, + subsetEquality, +} from '@jest/expect-utils'; +import * as matcherUtils from 'jest-matcher-utils'; +import { pluralize } from 'jest-util'; +import { getCustomEqualityTesters, getState } from './jestMatchersObject'; +import type { + AsymmetricMatcher as AsymmetricMatcherInterface, + MatcherContext, + MatcherState, +} from './types'; + +const functionToString = Function.prototype.toString; + +function fnNameFor(func: () => unknown) { + if (func.name) + return func.name; + + const matches = functionToString + .call(func) + .match(/^(?:async)?\s*function\s*\*?\s*([\w$]+)\s*\(/); + return matches ? matches[1] : ''; +} + +const utils = Object.freeze({ + ...matcherUtils, + iterableEquality, + subsetEquality, +}); + +function getPrototype(obj: object) { + if (Object.getPrototypeOf) + return Object.getPrototypeOf(obj); + + if (obj.constructor.prototype === obj) + return null; + + return obj.constructor.prototype; +} + +export function hasProperty( + obj: object | null, + property: string | symbol, +): boolean { + if (!obj) + return false; + + if (Object.prototype.hasOwnProperty.call(obj, property)) + return true; + + return hasProperty(getPrototype(obj), property); +} + +export abstract class AsymmetricMatcher +implements AsymmetricMatcherInterface { + $$typeof = Symbol.for('jest.asymmetricMatcher'); + + constructor(protected sample: T, protected inverse = false) { } + + protected getMatcherContext(): MatcherContext { + return { + customTesters: getCustomEqualityTesters(), + + dontThrow: () => { }, + ...getState(), + equals, + isNot: this.inverse, + utils, + }; + } + + abstract asymmetricMatch(other: unknown): boolean; + abstract toString(): string; + getExpectedType?(): string; + toAsymmetricMatcher?(): string; +} + +class Any extends AsymmetricMatcher { + constructor(sample: unknown) { + if (typeof sample === 'undefined') { + throw new TypeError( + 'any() expects to be passed a constructor function. ' + + 'Please pass one or use anything() to match any object.', + ); + } + super(sample); + } + + asymmetricMatch(other: unknown) { + if (this.sample === String) + return typeof other === 'string' || other instanceof String; + + if (this.sample === Number) + return typeof other === 'number' || other instanceof Number; + + if (this.sample === Function) + return typeof other === 'function' || other instanceof Function; + + if (this.sample === Boolean) + return typeof other === 'boolean' || other instanceof Boolean; + + if (this.sample === BigInt) + return typeof other === 'bigint' || other instanceof BigInt; + + if (this.sample === Symbol) + return typeof other === 'symbol' || other instanceof Symbol; + + if (this.sample === Object) + return typeof other === 'object'; + + return other instanceof this.sample; + } + + toString() { + return 'Any'; + } + + override getExpectedType() { + if (this.sample === String) + return 'string'; + + if (this.sample === Number) + return 'number'; + + if (this.sample === Function) + return 'function'; + + if (this.sample === Object) + return 'object'; + + if (this.sample === Boolean) + return 'boolean'; + + return fnNameFor(this.sample); + } + + override toAsymmetricMatcher() { + return `Any<${fnNameFor(this.sample)}>`; + } +} + +class Anything extends AsymmetricMatcher { + asymmetricMatch(other: unknown) { + // eslint-disable-next-line eqeqeq + return other != null; + } + + toString() { + return 'Anything'; + } + + // No getExpectedType method, because it matches either null or undefined. + + override toAsymmetricMatcher() { + return 'Anything'; + } +} + +class ArrayContaining extends AsymmetricMatcher> { + constructor(sample: Array, inverse = false) { + super(sample, inverse); + } + + asymmetricMatch(other: unknown) { + if (!Array.isArray(this.sample)) { + throw new Error( + `You must provide an array to ${this.toString()}, not '${typeof this + .sample}'.`, + ); + } + + const matcherContext = this.getMatcherContext(); + const result = + this.sample.length === 0 || + (Array.isArray(other) && + this.sample.every(item => + other.some(another => + equals(item, another, matcherContext.customTesters), + ), + )); + + return this.inverse ? !result : result; + } + + toString() { + return `Array${this.inverse ? 'Not' : ''}Containing`; + } + + override getExpectedType() { + return 'array'; + } +} + +class ObjectContaining extends AsymmetricMatcher< + Record +> { + constructor(sample: Record, inverse = false) { + super(sample, inverse); + } + + asymmetricMatch(other: any) { + if (typeof this.sample !== 'object') { + throw new Error( + `You must provide an object to ${this.toString()}, not '${typeof this + .sample}'.`, + ); + } + + let result = true; + + const matcherContext = this.getMatcherContext(); + const objectKeys = getObjectKeys(this.sample); + + for (const key of objectKeys) { + if ( + !hasProperty(other, key) || + !equals(this.sample[key], other[key], matcherContext.customTesters) + ) { + result = false; + break; + } + } + + return this.inverse ? !result : result; + } + + toString() { + return `Object${this.inverse ? 'Not' : ''}Containing`; + } + + override getExpectedType() { + return 'object'; + } +} + +class StringContaining extends AsymmetricMatcher { + constructor(sample: string, inverse = false) { + if (!isA('String', sample)) + throw new Error('Expected is not a string'); + super(sample, inverse); + } + + asymmetricMatch(other: unknown) { + const result = isA('String', other) && other.includes(this.sample); + + return this.inverse ? !result : result; + } + + toString() { + return `String${this.inverse ? 'Not' : ''}Containing`; + } + + override getExpectedType() { + return 'string'; + } +} + +class StringMatching extends AsymmetricMatcher { + constructor(sample: string | RegExp, inverse = false) { + if (!isA('String', sample) && !isA('RegExp', sample)) + throw new Error('Expected is not a String or a RegExp'); + super(new RegExp(sample), inverse); + } + + asymmetricMatch(other: unknown) { + const result = isA('String', other) && this.sample.test(other); + + return this.inverse ? !result : result; + } + + toString() { + return `String${this.inverse ? 'Not' : ''}Matching`; + } + + override getExpectedType() { + return 'string'; + } +} + +class CloseTo extends AsymmetricMatcher { + private readonly precision: number; + + constructor(sample: number, precision = 2, inverse = false) { + if (!isA('Number', sample)) + throw new Error('Expected is not a Number'); + + if (!isA('Number', precision)) + throw new Error('Precision is not a Number'); + + super(sample); + this.inverse = inverse; + this.precision = precision; + } + + asymmetricMatch(other: unknown) { + if (!isA('Number', other)) + return false; + let result = false; + if (other === Infinity && this.sample === Infinity) { + result = true; // Infinity - Infinity is NaN + } else if (other === -Infinity && this.sample === -Infinity) { + result = true; // -Infinity - -Infinity is NaN + } else { + result = + Math.abs(this.sample - other) < Math.pow(10, -this.precision) / 2; + } + return this.inverse ? !result : result; + } + + toString() { + return `Number${this.inverse ? 'Not' : ''}CloseTo`; + } + + override getExpectedType() { + return 'number'; + } + + override toAsymmetricMatcher(): string { + return [ + this.toString(), + this.sample, + `(${pluralize('digit', this.precision)})`, + ].join(' '); + } +} + +export const any = (expectedObject: unknown): Any => new Any(expectedObject); +export const anything = (): Anything => new Anything(); +export const arrayContaining = (sample: Array): ArrayContaining => + new ArrayContaining(sample); +export const arrayNotContaining = (sample: Array): ArrayContaining => + new ArrayContaining(sample, true); +export const objectContaining = ( + sample: Record, +): ObjectContaining => new ObjectContaining(sample); +export const objectNotContaining = ( + sample: Record, +): ObjectContaining => new ObjectContaining(sample, true); +export const stringContaining = (expected: string): StringContaining => + new StringContaining(expected); +export const stringNotContaining = (expected: string): StringContaining => + new StringContaining(expected, true); +export const stringMatching = (expected: string | RegExp): StringMatching => + new StringMatching(expected); +export const stringNotMatching = (expected: string | RegExp): StringMatching => + new StringMatching(expected, true); +export const closeTo = (expected: number, precision?: number): CloseTo => + new CloseTo(expected, precision); +export const notCloseTo = (expected: number, precision?: number): CloseTo => + new CloseTo(expected, precision, true); diff --git a/packages/playwright/bundles/expect/third_party/extractExpectedAssertionsErrors.ts b/packages/playwright/bundles/expect/third_party/extractExpectedAssertionsErrors.ts new file mode 100644 index 0000000000000..1be9b4dce921a --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/extractExpectedAssertionsErrors.ts @@ -0,0 +1,85 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { + EXPECTED_COLOR, + RECEIVED_COLOR, + matcherHint, + pluralize, +} from 'jest-matcher-utils'; +import { getState, setState } from './jestMatchersObject'; +import type { Expect, ExpectedAssertionsErrors } from './types'; + +const resetAssertionsLocalState = () => { + setState({ + assertionCalls: 0, + expectedAssertionsNumber: null, + isExpectingAssertions: false, + numPassingAsserts: 0, + }); +}; + +// Create and format all errors related to the mismatched number of `expect` +// calls and reset the matcher's state. +const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors'] = + () => { + const result: ExpectedAssertionsErrors = []; + const { + assertionCalls, + expectedAssertionsNumber, + expectedAssertionsNumberError, + isExpectingAssertions, + isExpectingAssertionsError, + } = getState(); + + resetAssertionsLocalState(); + + if ( + typeof expectedAssertionsNumber === 'number' && + assertionCalls !== expectedAssertionsNumber + ) { + const numOfAssertionsExpected = EXPECTED_COLOR( + pluralize('assertion', expectedAssertionsNumber), + ); + + expectedAssertionsNumberError!.message = + `${matcherHint('.assertions', '', expectedAssertionsNumber.toString(), { + isDirectExpectCall: true, + })}\n\n` + + `Expected ${numOfAssertionsExpected} to be called but received ${RECEIVED_COLOR( + pluralize('assertion call', assertionCalls || 0), + )}.`; + + result.push({ + actual: assertionCalls.toString(), + error: expectedAssertionsNumberError!, + expected: expectedAssertionsNumber.toString(), + }); + } + if (isExpectingAssertions && assertionCalls === 0) { + const expected = EXPECTED_COLOR('at least one assertion'); + const received = RECEIVED_COLOR('received none'); + + isExpectingAssertionsError!.message = `${matcherHint( + '.hasAssertions', + '', + '', + { isDirectExpectCall: true }, + )}\n\nExpected ${expected} to be called but ${received}.`; + + result.push({ + actual: 'none', + error: isExpectingAssertionsError!, + expected: 'at least one', + }); + } + + return result; + }; + +export default extractExpectedAssertionsErrors; diff --git a/packages/playwright/bundles/expect/third_party/index.ts b/packages/playwright/bundles/expect/third_party/index.ts new file mode 100644 index 0000000000000..3935ab71e1f50 --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/index.ts @@ -0,0 +1,463 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { equals, iterableEquality, subsetEquality } from '@jest/expect-utils'; +import * as matcherUtils from 'jest-matcher-utils'; +import { isPromise } from 'jest-util'; +import { + any, + anything, + arrayContaining, + arrayNotContaining, + closeTo, + notCloseTo, + objectContaining, + objectNotContaining, + stringContaining, + stringMatching, + stringNotContaining, + stringNotMatching, +} from './asymmetricMatchers'; +import extractExpectedAssertionsErrors from './extractExpectedAssertionsErrors'; +import { + INTERNAL_MATCHER_FLAG, + addCustomEqualityTesters, + getCustomEqualityTesters, + getMatchers, + getState, + setMatchers, + setState, +} from './jestMatchersObject'; +import matchers from './matchers'; +import spyMatchers from './spyMatchers'; +import toThrowMatchers, { + createMatcher as createThrowMatcher, +} from './toThrowMatchers'; +import type { + Expect, + ExpectationResult, + MatcherContext, + MatcherState, + MatcherUtils, + MatchersObject, + PromiseMatcherFn, + RawMatcherFn, + SyncExpectationResult, + ThrowingMatcherFn, +} from './types'; + +export type { Tester, TesterContext } from '@jest/expect-utils'; +export { AsymmetricMatcher } from './asymmetricMatchers'; +export type { + AsyncExpectationResult, + AsymmetricMatchers, + BaseExpect, + Expect, + ExpectationResult, + MatcherContext, + MatcherFunction, + MatcherFunctionWithContext, + MatcherState, + MatcherUtils, + Matchers, + SyncExpectationResult, +} from './types'; + +export class JestAssertionError extends Error { + matcherResult?: Omit & { message: string }; +} + +const createToThrowErrorMatchingSnapshotMatcher = function( + matcher: RawMatcherFn, +) { + return function( + this: MatcherContext, + received: any, + testNameOrInlineSnapshot?: string, + ) { + return matcher.apply(this, [received, testNameOrInlineSnapshot, true]); + }; +}; + +const getPromiseMatcher = (name: string, matcher: RawMatcherFn) => { + if (name === 'toThrow' || name === 'toThrowError') + return createThrowMatcher(name, true); + else if ( + name === 'toThrowErrorMatchingSnapshot' || + name === 'toThrowErrorMatchingInlineSnapshot' + ) + return createToThrowErrorMatchingSnapshotMatcher(matcher); + + + return null; +}; + +export const expect: Expect = (actual: any, ...rest: Array) => { + if (rest.length !== 0) + throw new Error('Expect takes at most one argument.'); + + + const allMatchers = getMatchers(); + const expectation: any = { + not: {}, + rejects: { not: {} }, + resolves: { not: {} }, + }; + + const err = new JestAssertionError(); + + Object.keys(allMatchers).forEach(name => { + const matcher = allMatchers[name]; + const promiseMatcher = getPromiseMatcher(name, matcher) || matcher; + expectation[name] = makeThrowingMatcher(matcher, false, '', actual); + expectation.not[name] = makeThrowingMatcher(matcher, true, '', actual); + + expectation.resolves[name] = makeResolveMatcher( + name, + promiseMatcher, + false, + actual, + err, + ); + expectation.resolves.not[name] = makeResolveMatcher( + name, + promiseMatcher, + true, + actual, + err, + ); + + expectation.rejects[name] = makeRejectMatcher( + name, + promiseMatcher, + false, + actual, + err, + ); + expectation.rejects.not[name] = makeRejectMatcher( + name, + promiseMatcher, + true, + actual, + err, + ); + }); + + return expectation; +}; + +const getMessage = (message?: () => string) => + (message && message()) || + matcherUtils.RECEIVED_COLOR('No message was specified for this matcher.'); + +const makeResolveMatcher = + ( + matcherName: string, + matcher: RawMatcherFn, + isNot: boolean, + actual: Promise, + outerErr: JestAssertionError, + ): PromiseMatcherFn => + (...args) => { + const options = { + isNot, + promise: 'resolves', + }; + + if (!isPromise(actual)) { + throw new JestAssertionError( + matcherUtils.matcherErrorMessage( + matcherUtils.matcherHint(matcherName, undefined, '', options), + `${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`, + matcherUtils.printWithType( + 'Received', + actual, + matcherUtils.printReceived, + ), + ), + ); + } + + const innerErr = new JestAssertionError(); + + return actual.then( + result => + makeThrowingMatcher(matcher, isNot, 'resolves', result, innerErr).apply( + null, + args, + ), + reason => { + outerErr.message = + `${matcherUtils.matcherHint( + matcherName, + undefined, + '', + options, + )}\n\n` + + 'Received promise rejected instead of resolved\n' + + `Rejected to value: ${matcherUtils.printReceived(reason)}`; + return Promise.reject(outerErr); + }, + ); + }; + +const makeRejectMatcher = + ( + matcherName: string, + matcher: RawMatcherFn, + isNot: boolean, + actual: Promise | (() => Promise), + outerErr: JestAssertionError, + ): PromiseMatcherFn => + (...args) => { + const options = { + isNot, + promise: 'rejects', + }; + + const actualWrapper: Promise = + typeof actual === 'function' ? actual() : actual; + + if (!isPromise(actualWrapper)) { + throw new JestAssertionError( + matcherUtils.matcherErrorMessage( + matcherUtils.matcherHint(matcherName, undefined, '', options), + `${matcherUtils.RECEIVED_COLOR( + 'received', + )} value must be a promise or a function returning a promise`, + matcherUtils.printWithType( + 'Received', + actual, + matcherUtils.printReceived, + ), + ), + ); + } + + const innerErr = new JestAssertionError(); + + return actualWrapper.then( + result => { + outerErr.message = + `${matcherUtils.matcherHint( + matcherName, + undefined, + '', + options, + )}\n\n` + + 'Received promise resolved instead of rejected\n' + + `Resolved to value: ${matcherUtils.printReceived(result)}`; + return Promise.reject(outerErr); + }, + reason => + makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply( + null, + args, + ), + ); + }; + +const makeThrowingMatcher = ( + matcher: RawMatcherFn, + isNot: boolean, + promise: string, + actual: any, + err?: JestAssertionError, +): ThrowingMatcherFn => + function throwingMatcher(...args): any { + let throws = true; + const utils: MatcherUtils['utils'] = { + ...matcherUtils, + iterableEquality, + subsetEquality, + }; + + const matcherUtilsThing: MatcherUtils = { + customTesters: getCustomEqualityTesters(), + // When throws is disabled, the matcher will not throw errors during test + // execution but instead add them to the global matcher state. If a + // matcher throws, test execution is normally stopped immediately. The + // snapshot matcher uses it because we want to log all snapshot + // failures in a test. + dontThrow: () => (throws = false), + equals, + utils, + }; + + const matcherContext: MatcherContext = { + ...getState(), + ...matcherUtilsThing, + error: err, + isNot, + promise, + }; + + const processResult = ( + result: SyncExpectationResult, + asyncError?: JestAssertionError, + ) => { + _validateResult(result); + + getState().assertionCalls++; + + if ((result.pass && isNot) || (!result.pass && !isNot)) { + // XOR + const message = getMessage(result.message); + let error; + + if (err) { + error = err; + error.message = message; + } else if (asyncError) { + error = asyncError; + error.message = message; + } else { + error = new JestAssertionError(message); + + // Try to remove this function from the stack trace frame. + // Guard for some environments (browsers) that do not support this feature. + if (Error.captureStackTrace) + Error.captureStackTrace(error, throwingMatcher); + + } + // Passing the result of the matcher with the error so that a custom + // reporter could access the actual and expected objects of the result + // for example in order to display a custom visual diff + error.matcherResult = { ...result, message }; + + if (throws) + throw error; + else + getState().suppressedErrors.push(error); + + } else { + getState().numPassingAsserts++; + } + }; + + const handleError = (error: Error) => { + if ( + matcher[INTERNAL_MATCHER_FLAG] === true && + !(error instanceof JestAssertionError) && + error.name !== 'PrettyFormatPluginError' && + // Guard for some environments (browsers) that do not support this feature. + Error.captureStackTrace + ) { + // Try to remove this and deeper functions from the stack trace frame. + Error.captureStackTrace(error, throwingMatcher); + } + throw error; + }; + + let potentialResult: ExpectationResult; + + try { + potentialResult = + matcher[INTERNAL_MATCHER_FLAG] === true + ? matcher.call(matcherContext, actual, ...args) + : // It's a trap specifically for inline snapshot to capture this name + // in the stack trace, so that it can correctly get the custom matcher + // function call. + (function __EXTERNAL_MATCHER_TRAP__() { + return matcher.call(matcherContext, actual, ...args); + })(); + + if (isPromise(potentialResult)) { + const asyncError = new JestAssertionError(); + if (Error.captureStackTrace) + Error.captureStackTrace(asyncError, throwingMatcher); + + + return potentialResult + .then(aResult => processResult(aResult, asyncError)) + .catch(handleError); + } else { + return processResult(potentialResult); + } + } catch (error: any) { + return handleError(error); + } + }; + +expect.extend = (matchers: MatchersObject) => + setMatchers(matchers, false, expect); + +expect.addEqualityTesters = customTesters => + addCustomEqualityTesters(customTesters); + +expect.anything = anything; +expect.any = any; + +expect.not = { + arrayContaining: arrayNotContaining, + closeTo: notCloseTo, + objectContaining: objectNotContaining, + stringContaining: stringNotContaining, + stringMatching: stringNotMatching, +}; + +expect.arrayContaining = arrayContaining; +expect.closeTo = closeTo; +expect.objectContaining = objectContaining; +expect.stringContaining = stringContaining; +expect.stringMatching = stringMatching; + +const _validateResult = (result: any) => { + if ( + typeof result !== 'object' || + typeof result.pass !== 'boolean' || + (result.message && + typeof result.message !== 'string' && + typeof result.message !== 'function') + ) { + throw new Error( + 'Unexpected return from a matcher function.\n' + + 'Matcher functions should ' + + 'return an object in the following format:\n' + + ' {message?: string | function, pass: boolean}\n' + + `'${matcherUtils.stringify(result)}' was returned`, + ); + } +}; + +function assertions(expected: number): void { + const error = new Error(); + if (Error.captureStackTrace) + Error.captureStackTrace(error, assertions); + + + setState({ + expectedAssertionsNumber: expected, + expectedAssertionsNumberError: error, + }); +} +function hasAssertions(...args: Array): void { + const error = new Error(); + if (Error.captureStackTrace) + Error.captureStackTrace(error, hasAssertions); + + + matcherUtils.ensureNoExpected(args[0], '.hasAssertions'); + setState({ + isExpectingAssertions: true, + isExpectingAssertionsError: error, + }); +} + +// add default jest matchers +setMatchers(matchers, true, expect); +setMatchers(spyMatchers, true, expect); +setMatchers(toThrowMatchers, true, expect); + +expect.assertions = assertions; +expect.hasAssertions = hasAssertions; +expect.getState = getState; +expect.setState = setState; +expect.extractExpectedAssertionsErrors = extractExpectedAssertionsErrors; + +export default expect; diff --git a/packages/playwright/bundles/expect/third_party/jestMatchersObject.ts b/packages/playwright/bundles/expect/third_party/jestMatchersObject.ts new file mode 100644 index 0000000000000..7a9a304b303dc --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/jestMatchersObject.ts @@ -0,0 +1,144 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import type { Tester } from '@jest/expect-utils'; +import { getType } from 'jest-get-type'; +import { AsymmetricMatcher } from './asymmetricMatchers'; +import type { + Expect, + MatcherState, + MatchersObject, + SyncExpectationResult, +} from './types'; + +// Global matchers object holds the list of available matchers and +// the state, that can hold matcher specific values that change over time. +const JEST_MATCHERS_OBJECT = Symbol.for('$$jest-matchers-object'); + +// Notes a built-in/internal Jest matcher. +// Jest may override the stack trace of Errors thrown by internal matchers. +export const INTERNAL_MATCHER_FLAG = Symbol.for('$$jest-internal-matcher'); + +if (!Object.prototype.hasOwnProperty.call(globalThis, JEST_MATCHERS_OBJECT)) { + const defaultState: MatcherState = { + assertionCalls: 0, + expectedAssertionsNumber: null, + isExpectingAssertions: false, + numPassingAsserts: 0, + suppressedErrors: [], // errors that are not thrown immediately. + }; + Object.defineProperty(globalThis, JEST_MATCHERS_OBJECT, { + value: { + customEqualityTesters: [], + matchers: Object.create(null), + state: defaultState, + }, + }); +} + +export const getState = (): State => + (globalThis as any)[JEST_MATCHERS_OBJECT].state; + +export const setState = ( + state: Partial, +): void => { + Object.assign((globalThis as any)[JEST_MATCHERS_OBJECT].state, state); +}; + +export const getMatchers = (): MatchersObject => + (globalThis as any)[JEST_MATCHERS_OBJECT].matchers; + +export const setMatchers = ( + matchers: MatchersObject, + isInternal: boolean, + expect: Expect, +): void => { + Object.keys(matchers).forEach(key => { + const matcher = matchers[key]; + + if (typeof matcher !== 'function') { + throw new TypeError( + `expect.extend: \`${key}\` is not a valid matcher. Must be a function, is "${getType( + matcher, + )}"`, + ); + } + + Object.defineProperty(matcher, INTERNAL_MATCHER_FLAG, { + value: isInternal, + }); + + if (!isInternal) { + // expect is defined + + class CustomMatcher extends AsymmetricMatcher< + [unknown, ...Array] + > { + constructor(inverse = false, ...sample: [unknown, ...Array]) { + super(sample, inverse); + } + + asymmetricMatch(other: unknown) { + const { pass } = matcher.call( + this.getMatcherContext(), + other, + ...this.sample, + ) as SyncExpectationResult; + + return this.inverse ? !pass : pass; + } + + toString() { + return `${this.inverse ? 'not.' : ''}${key}`; + } + + override getExpectedType() { + return 'any'; + } + + override toAsymmetricMatcher() { + return `${this.toString()}<${this.sample.map(String).join(', ')}>`; + } + } + + Object.defineProperty(expect, key, { + configurable: true, + enumerable: true, + value: (...sample: [unknown, ...Array]) => + new CustomMatcher(false, ...sample), + writable: true, + }); + Object.defineProperty(expect.not, key, { + configurable: true, + enumerable: true, + value: (...sample: [unknown, ...Array]) => + new CustomMatcher(true, ...sample), + writable: true, + }); + } + }); + + Object.assign((globalThis as any)[JEST_MATCHERS_OBJECT].matchers, matchers); +}; + +export const getCustomEqualityTesters = (): Array => + (globalThis as any)[JEST_MATCHERS_OBJECT].customEqualityTesters; + +export const addCustomEqualityTesters = (newTesters: Array): void => { + if (!Array.isArray(newTesters)) { + throw new TypeError( + `expect.customEqualityTesters: Must be set to an array of Testers. Was given "${getType( + newTesters, + )}"`, + ); + } + + (globalThis as any)[JEST_MATCHERS_OBJECT].customEqualityTesters.push( + ...newTesters, + ); +}; diff --git a/packages/playwright/bundles/expect/third_party/matchers.ts b/packages/playwright/bundles/expect/third_party/matchers.ts new file mode 100644 index 0000000000000..5102b50c3262c --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/matchers.ts @@ -0,0 +1,983 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +/* eslint-disable eqeqeq */ + +import { + arrayBufferEquality, + equals, + getObjectSubset, + getPath, + iterableEquality, + pathAsArray, + sparseArrayEquality, + subsetEquality, + typeEquality, +} from '@jest/expect-utils'; +import { getType, isPrimitive } from 'jest-get-type'; +import { + DIM_COLOR, + EXPECTED_COLOR, + type MatcherHintOptions, + RECEIVED_COLOR, + SUGGEST_TO_CONTAIN_EQUAL, + ensureExpectedIsNonNegativeInteger, + ensureNoExpected, + ensureNumbers, + getLabelPrinter, + matcherErrorMessage, + matcherHint, + printDiffOrStringify, + printExpected, + printReceived, + printWithType, + stringify, +} from 'jest-matcher-utils'; +import { + printCloseTo, + printExpectedConstructorName, + printExpectedConstructorNameNot, + printReceivedArrayContainExpectedItem, + printReceivedConstructorName, + printReceivedConstructorNameNot, + printReceivedStringContainExpectedResult, + printReceivedStringContainExpectedSubstring, +} from './print'; +import type { MatchersObject } from './types'; + +// Omit colon and one or more spaces, so can call getLabelPrinter. +const EXPECTED_LABEL = 'Expected'; +const RECEIVED_LABEL = 'Received'; +const EXPECTED_VALUE_LABEL = 'Expected value'; +const RECEIVED_VALUE_LABEL = 'Received value'; + +// The optional property of matcher context is true if undefined. +const isExpand = (expand?: boolean): boolean => expand !== false; + +const toStrictEqualTesters = [ + iterableEquality, + typeEquality, + sparseArrayEquality, + arrayBufferEquality, +]; + +type ContainIterable = + | Array + | Set + | NodeListOf + | DOMTokenList + | HTMLCollectionOf; + +const matchers: MatchersObject = { + toBe(received: unknown, expected: unknown) { + const matcherName = 'toBe'; + const options: MatcherHintOptions = { + comment: 'Object.is equality', + isNot: this.isNot, + promise: this.promise, + }; + + const pass = Object.is(received, expected); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}` + : () => { + const expectedType = getType(expected); + + let deepEqualityName = null; + if (expectedType !== 'map' && expectedType !== 'set') { + // If deep equality passes when referential identity fails, + // but exclude map and set until review of their equality logic. + if ( + equals( + received, + expected, + [...this.customTesters, ...toStrictEqualTesters], + true, + ) + ) + deepEqualityName = 'toStrictEqual'; + else if ( + equals(received, expected, [ + ...this.customTesters, + iterableEquality, + ]) + ) + deepEqualityName = 'toEqual'; + + } + + return ( + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + (deepEqualityName !== null + ? `${DIM_COLOR( + `If it should pass with deep equality, replace "${matcherName}" with "${deepEqualityName}"`, + )}\n\n` + : '') + + printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + isExpand(this.expand), + ) + ); + }; + + // Passing the actual and expected objects so that a custom reporter + // could access them, for example in order to display a custom visual diff, + // or create a different error message + return { actual: received, expected, message, name: matcherName, pass }; + }, + + toBeCloseTo(received: number, expected: number, precision = 2) { + const matcherName = 'toBeCloseTo'; + const secondArgument = arguments.length === 3 ? 'precision' : undefined; + const isNot = this.isNot; + const options: MatcherHintOptions = { + isNot, + promise: this.promise, + secondArgument, + secondArgumentColor: (arg: string) => arg, + }; + + if (typeof expected !== 'number') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${EXPECTED_COLOR('expected')} value must be a number`, + printWithType('Expected', expected, printExpected), + ), + ); + } + + if (typeof received !== 'number') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${RECEIVED_COLOR('received')} value must be a number`, + printWithType('Received', received, printReceived), + ), + ); + } + + let pass = false; + let expectedDiff = 0; + let receivedDiff = 0; + + if (received === Infinity && expected === Infinity) { + pass = true; // Infinity - Infinity is NaN + } else if (received === -Infinity && expected === -Infinity) { + pass = true; // -Infinity - -Infinity is NaN + } else { + expectedDiff = Math.pow(10, -precision) / 2; + receivedDiff = Math.abs(expected - received); + pass = receivedDiff < expectedDiff; + } + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}\n` + + (receivedDiff === 0 + ? '' + : `Received: ${printReceived(received)}\n` + + `\n${printCloseTo(receivedDiff, expectedDiff, precision, isNot)}`) + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected: ${printExpected(expected)}\n` + + `Received: ${printReceived(received)}\n` + + '\n' + + printCloseTo(receivedDiff, expectedDiff, precision, isNot); + + return { message, pass }; + }, + + toBeDefined(received: unknown, expected: void) { + const matcherName = 'toBeDefined'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + + const pass = received !== void 0; + + const message = () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + `Received: ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeFalsy(received: unknown, expected: void) { + const matcherName = 'toBeFalsy'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + + const pass = !received; + + const message = () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + `Received: ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeGreaterThan(received: number | bigint, expected: number | bigint) { + const matcherName = 'toBeGreaterThan'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + isNot, + promise: this.promise, + }; + ensureNumbers(received, expected, matcherName, options); + + const pass = received > expected; + + const message = () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected:${isNot ? ' not' : ''} > ${printExpected(expected)}\n` + + `Received:${isNot ? ' ' : ''} ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeGreaterThanOrEqual(received: number | bigint, expected: number | bigint) { + const matcherName = 'toBeGreaterThanOrEqual'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + isNot, + promise: this.promise, + }; + ensureNumbers(received, expected, matcherName, options); + + const pass = received >= expected; + + const message = () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected:${isNot ? ' not' : ''} >= ${printExpected(expected)}\n` + + `Received:${isNot ? ' ' : ''} ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeInstanceOf(received: any, expected: Function) { + const matcherName = 'toBeInstanceOf'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + + if (typeof expected !== 'function') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${EXPECTED_COLOR('expected')} value must be a function`, + printWithType('Expected', expected, printExpected), + ), + ); + } + + const pass = received instanceof expected; + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printExpectedConstructorNameNot('Expected constructor', expected) + + (typeof received.constructor === 'function' && + received.constructor !== expected + ? printReceivedConstructorNameNot( + 'Received constructor', + received.constructor, + expected, + ) + : '') + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printExpectedConstructorName('Expected constructor', expected) + + (isPrimitive(received) || Object.getPrototypeOf(received) === null + ? `\nReceived value has no prototype\nReceived value: ${printReceived( + received, + )}` + : typeof received.constructor !== 'function' + ? `\nReceived value: ${printReceived(received)}` + : printReceivedConstructorName( + 'Received constructor', + received.constructor, + )); + + return { message, pass }; + }, + + toBeLessThan(received: number | bigint, expected: number | bigint) { + const matcherName = 'toBeLessThan'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + isNot, + promise: this.promise, + }; + ensureNumbers(received, expected, matcherName, options); + + const pass = received < expected; + + const message = () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected:${isNot ? ' not' : ''} < ${printExpected(expected)}\n` + + `Received:${isNot ? ' ' : ''} ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeLessThanOrEqual(received: number | bigint, expected: number | bigint) { + const matcherName = 'toBeLessThanOrEqual'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + isNot, + promise: this.promise, + }; + ensureNumbers(received, expected, matcherName, options); + + const pass = received <= expected; + + const message = () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected:${isNot ? ' not' : ''} <= ${printExpected(expected)}\n` + + `Received:${isNot ? ' ' : ''} ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeNaN(received: any, expected: void) { + const matcherName = 'toBeNaN'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + + const pass = Number.isNaN(received); + + const message = () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + `Received: ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeNull(received: unknown, expected: void) { + const matcherName = 'toBeNull'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + + const pass = received === null; + + const message = () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + `Received: ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeTruthy(received: unknown, expected: void) { + const matcherName = 'toBeTruthy'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + + const pass = !!received; + + const message = () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + `Received: ${printReceived(received)}`; + + return { message, pass }; + }, + + toBeUndefined(received: unknown, expected: void) { + const matcherName = 'toBeUndefined'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + + const pass = received === void 0; + + const message = () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + `Received: ${printReceived(received)}`; + + return { message, pass }; + }, + + toContain(received: ContainIterable | string, expected: unknown) { + const matcherName = 'toContain'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + comment: 'indexOf', + isNot, + promise: this.promise, + }; + + if (received == null) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${RECEIVED_COLOR('received')} value must not be null nor undefined`, + printWithType('Received', received, printReceived), + ), + ); + } + + if (typeof received === 'string') { + const wrongTypeErrorMessage = `${EXPECTED_COLOR( + 'expected', + )} value must be a string if ${RECEIVED_COLOR( + 'received', + )} value is a string`; + + if (typeof expected !== 'string') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, received, String(expected), options), + wrongTypeErrorMessage, + + printWithType('Expected', expected, printExpected) + + '\n' + + printWithType('Received', received, printReceived), + ), + ); + } + + const index = received.indexOf(String(expected)); + const pass = index !== -1; + + const message = () => { + const labelExpected = `Expected ${typeof expected === 'string' ? 'substring' : 'value' + }`; + const labelReceived = 'Received string'; + const printLabel = getLabelPrinter(labelExpected, labelReceived); + + return ( + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `${printLabel(labelExpected)}${isNot ? 'not ' : ''}${printExpected( + expected, + )}\n` + + `${printLabel(labelReceived)}${isNot ? ' ' : ''}${isNot + ? printReceivedStringContainExpectedSubstring( + received, + index, + String(expected).length, + ) + : printReceived(received) + }` + ); + }; + + return { message, pass }; + } + + const indexable = Array.from(received); + const index = indexable.indexOf(expected); + const pass = index !== -1; + + const message = () => { + const labelExpected = 'Expected value'; + const labelReceived = `Received ${getType(received)}`; + const printLabel = getLabelPrinter(labelExpected, labelReceived); + + return ( + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `${printLabel(labelExpected)}${isNot ? 'not ' : ''}${printExpected( + expected, + )}\n` + + `${printLabel(labelReceived)}${isNot ? ' ' : ''}${isNot && Array.isArray(received) + ? printReceivedArrayContainExpectedItem(received, index) + : printReceived(received) + }` + + (!isNot && + indexable.findIndex(item => + equals(item, expected, [...this.customTesters, iterableEquality]), + ) !== -1 + ? `\n\n${SUGGEST_TO_CONTAIN_EQUAL}` + : '') + ); + }; + + return { message, pass }; + }, + + toContainEqual(received: ContainIterable, expected: unknown) { + const matcherName = 'toContainEqual'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + comment: 'deep equality', + isNot, + promise: this.promise, + }; + + if (received == null) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${RECEIVED_COLOR('received')} value must not be null nor undefined`, + printWithType('Received', received, printReceived), + ), + ); + } + + const index = Array.from(received).findIndex(item => + equals(item, expected, [...this.customTesters, iterableEquality]), + ); + const pass = index !== -1; + + const message = () => { + const labelExpected = 'Expected value'; + const labelReceived = `Received ${getType(received)}`; + const printLabel = getLabelPrinter(labelExpected, labelReceived); + + return ( + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `${printLabel(labelExpected)}${isNot ? 'not ' : ''}${printExpected( + expected, + )}\n` + + `${printLabel(labelReceived)}${isNot ? ' ' : ''}${isNot && Array.isArray(received) + ? printReceivedArrayContainExpectedItem(received, index) + : printReceived(received) + }` + ); + }; + + return { message, pass }; + }, + + toEqual(received: unknown, expected: unknown) { + const matcherName = 'toEqual'; + const options: MatcherHintOptions = { + comment: 'deep equality', + isNot: this.isNot, + promise: this.promise, + }; + + const pass = equals(received, expected, [ + ...this.customTesters, + iterableEquality, + ]); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}\n` + + (stringify(expected) !== stringify(received) + ? `Received: ${printReceived(received)}` + : '') + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + isExpand(this.expand), + ); + + // Passing the actual and expected objects so that a custom reporter + // could access them, for example in order to display a custom visual diff, + // or create a different error message + return { actual: received, expected, message, name: matcherName, pass }; + }, + + toHaveLength(received: any, expected: number) { + const matcherName = 'toHaveLength'; + const isNot = this.isNot; + const options: MatcherHintOptions = { + isNot, + promise: this.promise, + }; + + if (typeof received?.length !== 'number') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${RECEIVED_COLOR( + 'received', + )} value must have a length property whose value must be a number`, + printWithType('Received', received, printReceived), + ), + ); + } + + ensureExpectedIsNonNegativeInteger(expected, matcherName, options); + + const pass = received.length === expected; + + const message = () => { + const labelExpected = 'Expected length'; + const labelReceivedLength = 'Received length'; + const labelReceivedValue = `Received ${getType(received)}`; + const printLabel = getLabelPrinter( + labelExpected, + labelReceivedLength, + labelReceivedValue, + ); + + return ( + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `${printLabel(labelExpected)}${isNot ? 'not ' : ''}${printExpected( + expected, + )}\n` + + (isNot + ? '' + : `${printLabel(labelReceivedLength)}${printReceived( + received.length, + )}\n`) + + `${printLabel(labelReceivedValue)}${isNot ? ' ' : ''}${printReceived( + received, + )}` + ); + }; + + return { message, pass }; + }, + + toHaveProperty( + received: object, + expectedPath: string | Array, + expectedValue?: unknown, + ) { + const matcherName = 'toHaveProperty'; + const expectedArgument = 'path'; + const hasValue = arguments.length === 3; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + secondArgument: hasValue ? 'value' : '', + }; + + if (received === null || received === undefined) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${RECEIVED_COLOR('received')} value must not be null nor undefined`, + printWithType('Received', received, printReceived), + ), + ); + } + + const expectedPathType = getType(expectedPath); + + if (expectedPathType !== 'string' && expectedPathType !== 'array') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${EXPECTED_COLOR('expected')} path must be a string or array`, + printWithType('Expected', expectedPath, printExpected), + ), + ); + } + + const expectedPathLength = + typeof expectedPath === 'string' + ? pathAsArray(expectedPath).length + : expectedPath.length; + + if (expectedPathType === 'array' && expectedPathLength === 0) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${EXPECTED_COLOR('expected')} path must not be an empty array`, + printWithType('Expected', expectedPath, printExpected), + ), + ); + } + + const result = getPath(received, expectedPath); + const { lastTraversedObject, endPropIsDefined, hasEndProp, value } = result; + const receivedPath = result.traversedPath; + const hasCompletePath = receivedPath.length === expectedPathLength; + const receivedValue = hasCompletePath ? result.value : lastTraversedObject; + + const pass = + hasValue && endPropIsDefined + ? equals(value, expectedValue, [ + ...this.customTesters, + iterableEquality, + ]) + : Boolean(hasEndProp); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, expectedArgument, options) + + '\n\n' + + (hasValue + ? `Expected path: ${printExpected(expectedPath)}\n\n` + + `Expected value: not ${printExpected(expectedValue)}${stringify(expectedValue) !== stringify(receivedValue) + ? `\nReceived value: ${printReceived(receivedValue)}` + : '' + }` + : `Expected path: not ${printExpected(expectedPath)}\n\n` + + `Received value: ${printReceived(receivedValue)}`) + : () => + + matcherHint(matcherName, undefined, expectedArgument, options) + + '\n\n' + + `Expected path: ${printExpected(expectedPath)}\n` + + (hasCompletePath + ? `\n${printDiffOrStringify( + expectedValue, + receivedValue, + EXPECTED_VALUE_LABEL, + RECEIVED_VALUE_LABEL, + isExpand(this.expand), + )}` + : `Received path: ${printReceived( + expectedPathType === 'array' || receivedPath.length === 0 + ? receivedPath + : receivedPath.join('.'), + )}\n\n${hasValue + ? `Expected value: ${printExpected(expectedValue)}\n` + : '' + }Received value: ${printReceived(receivedValue)}`); + + return { message, pass }; + }, + + toMatch(received: string, expected: string | RegExp) { + const matcherName = 'toMatch'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + + if (typeof received !== 'string') { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${RECEIVED_COLOR('received')} value must be a string`, + printWithType('Received', received, printReceived), + ), + ); + } + + if ( + !(typeof expected === 'string') && + !(expected && typeof expected.test === 'function') + ) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${EXPECTED_COLOR( + 'expected', + )} value must be a string or regular expression`, + printWithType('Expected', expected, printExpected), + ), + ); + } + + const pass = + typeof expected === 'string' + ? received.includes(expected) + : new RegExp(expected).test(received); + + const message = pass + ? () => + typeof expected === 'string' + ? + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected substring: not ${printExpected(expected)}\n` + + `Received string: ${printReceivedStringContainExpectedSubstring( + received, + received.indexOf(expected), + expected.length, + )}` + : + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected pattern: not ${printExpected(expected)}\n` + + `Received string: ${printReceivedStringContainExpectedResult( + received, + typeof expected.exec === 'function' + ? expected.exec(received) + : null, + )}` + : () => { + const labelExpected = `Expected ${typeof expected === 'string' ? 'substring' : 'pattern' + }`; + const labelReceived = 'Received string'; + const printLabel = getLabelPrinter(labelExpected, labelReceived); + + return ( + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `${printLabel(labelExpected)}${printExpected(expected)}\n` + + `${printLabel(labelReceived)}${printReceived(received)}` + ); + }; + + return { message, pass }; + }, + + toMatchObject(received: object, expected: object) { + const matcherName = 'toMatchObject'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + + if (typeof received !== 'object' || received === null) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${RECEIVED_COLOR('received')} value must be a non-null object`, + printWithType('Received', received, printReceived), + ), + ); + } + + if (typeof expected !== 'object' || expected === null) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${EXPECTED_COLOR('expected')} value must be a non-null object`, + printWithType('Expected', expected, printExpected), + ), + ); + } + + const pass = equals(received, expected, [ + ...this.customTesters, + iterableEquality, + subsetEquality, + ]); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}` + + (stringify(expected) !== stringify(received) + ? `\nReceived: ${printReceived(received)}` + : '') + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printDiffOrStringify( + expected, + getObjectSubset(received, expected, this.customTesters), + EXPECTED_LABEL, + RECEIVED_LABEL, + isExpand(this.expand), + ); + + return { message, pass }; + }, + + toStrictEqual(received: unknown, expected: unknown) { + const matcherName = 'toStrictEqual'; + const options: MatcherHintOptions = { + comment: 'deep equality', + isNot: this.isNot, + promise: this.promise, + }; + + const pass = equals( + received, + expected, + [...this.customTesters, ...toStrictEqualTesters], + true, + ); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}\n` + + (stringify(expected) !== stringify(received) + ? `Received: ${printReceived(received)}` + : '') + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + isExpand(this.expand), + ); + + // Passing the actual and expected objects so that a custom reporter + // could access them, for example in order to display a custom visual diff, + // or create a different error message + return { actual: received, expected, message, name: matcherName, pass }; + }, +}; + +export default matchers; diff --git a/packages/playwright/bundles/expect/third_party/print.ts b/packages/playwright/bundles/expect/third_party/print.ts new file mode 100644 index 0000000000000..63cad0f91e6b0 --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/print.ts @@ -0,0 +1,134 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { + EXPECTED_COLOR, + INVERTED_COLOR, + RECEIVED_COLOR, + printReceived, + stringify, +} from 'jest-matcher-utils'; + +// Format substring but do not enclose in double quote marks. +// The replacement is compatible with pretty-format package. +const printSubstring = (val: string): string => val.replace(/"|\\/g, '\\$&'); + +export const printReceivedStringContainExpectedSubstring = ( + received: string, + start: number, + length: number, // not end +): string => + RECEIVED_COLOR( + `"${printSubstring(received.slice(0, start))}${INVERTED_COLOR( + printSubstring(received.slice(start, start + length)), + )}${printSubstring(received.slice(start + length))}"`, + ); + +export const printReceivedStringContainExpectedResult = ( + received: string, + result: RegExpExecArray | null, +): string => + result === null + ? printReceived(received) + : printReceivedStringContainExpectedSubstring( + received, + result.index, + result[0].length, + ); + +// The serialized array is compatible with pretty-format package min option. +// However, items have default stringify depth (instead of depth - 1) +// so expected item looks consistent by itself and enclosed in the array. +export const printReceivedArrayContainExpectedItem = ( + received: Array, + index: number, +): string => + RECEIVED_COLOR( + `[${received + .map((item, i) => { + const stringified = stringify(item); + return i === index ? INVERTED_COLOR(stringified) : stringified; + }) + .join(', ')}]`, + ); + +export const printCloseTo = ( + receivedDiff: number, + expectedDiff: number, + precision: number, + isNot: boolean | undefined, +): string => { + const receivedDiffString = stringify(receivedDiff); + const expectedDiffString = receivedDiffString.includes('e') + ? // toExponential arg is number of digits after the decimal point. + expectedDiff.toExponential(0) + : 0 <= precision && precision < 20 + ? // toFixed arg is number of digits after the decimal point. + // It may be a value between 0 and 20 inclusive. + // Implementations may optionally support a larger range of values. + expectedDiff.toFixed(precision + 1) + : stringify(expectedDiff); + + return ( + `Expected precision: ${isNot ? ' ' : ''} ${stringify(precision)}\n` + + `Expected difference: ${isNot ? 'not ' : ''}< ${EXPECTED_COLOR( + expectedDiffString, + )}\n` + + `Received difference: ${isNot ? ' ' : ''} ${RECEIVED_COLOR( + receivedDiffString, + )}` + ); +}; + +export const printExpectedConstructorName = ( + label: string, + expected: Function, +): string => `${printConstructorName(label, expected, false, true)}\n`; + +export const printExpectedConstructorNameNot = ( + label: string, + expected: Function, +): string => `${printConstructorName(label, expected, true, true)}\n`; + +export const printReceivedConstructorName = ( + label: string, + received: Function, +): string => `${printConstructorName(label, received, false, false)}\n`; + +// Do not call function if received is equal to expected. +export const printReceivedConstructorNameNot = ( + label: string, + received: Function, + expected: Function, +): string => + typeof expected.name === 'string' && + expected.name.length !== 0 && + typeof received.name === 'string' && + received.name.length !== 0 + ? `${printConstructorName(label, received, true, false)} ${ + Object.getPrototypeOf(received) === expected + ? 'extends' + : 'extends … extends' + } ${EXPECTED_COLOR(expected.name)}\n` + : `${printConstructorName(label, received, false, false)}\n`; + +const printConstructorName = ( + label: string, + constructor: Function, + isNot: boolean, + isExpected: boolean, +): string => + typeof constructor.name !== 'string' + ? `${label} name is not a string` + : constructor.name.length === 0 + ? `${label} name is an empty string` + : `${label}: ${!isNot ? '' : isExpected ? 'not ' : ' '}${ + isExpected + ? EXPECTED_COLOR(constructor.name) + : RECEIVED_COLOR(constructor.name) + }`; diff --git a/packages/playwright/bundles/expect/third_party/spyMatchers.ts b/packages/playwright/bundles/expect/third_party/spyMatchers.ts new file mode 100644 index 0000000000000..ac74fd8d914fc --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/spyMatchers.ts @@ -0,0 +1,1184 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { equals, iterableEquality } from '@jest/expect-utils'; +import { getType, isPrimitive } from 'jest-get-type'; +import { + DIM_COLOR, + EXPECTED_COLOR, + type MatcherHintOptions, + RECEIVED_COLOR, + diff, + ensureExpectedIsNonNegativeInteger, + ensureNoExpected, + matcherErrorMessage, + matcherHint, + printExpected, + printReceived, + printWithType, + stringify, +} from 'jest-matcher-utils'; +import { getCustomEqualityTesters } from './jestMatchersObject'; +import type { + MatcherFunction, + MatchersObject, + SyncExpectationResult, +} from './types'; + +/* eslint-disable eqeqeq */ + +// The optional property of matcher context is true if undefined. +const isExpand = (expand?: boolean): boolean => expand !== false; + +const PRINT_LIMIT = 3; + +const NO_ARGUMENTS = 'called with 0 arguments'; + +const printExpectedArgs = (expected: Array): string => + expected.length === 0 + ? NO_ARGUMENTS + : expected.map(arg => printExpected(arg)).join(', '); + +const printReceivedArgs = ( + received: Array, + expected?: Array, +): string => + received.length === 0 + ? NO_ARGUMENTS + : received + .map((arg, i) => + Array.isArray(expected) && + i < expected.length && + isEqualValue(expected[i], arg) + ? printCommon(arg) + : printReceived(arg), + ) + .join(', '); + +const printCommon = (val: unknown) => DIM_COLOR(stringify(val)); + +const isEqualValue = (expected: unknown, received: unknown): boolean => + equals(expected, received, [...getCustomEqualityTesters(), iterableEquality]); + +const isEqualCall = ( + expected: Array, + received: Array, +): boolean => + received.length === expected.length && isEqualValue(expected, received); + +const isEqualReturn = (expected: unknown, result: any): boolean => + result.type === 'return' && isEqualValue(expected, result.value); + +const countReturns = (results: Array): number => + results.reduce( + (n: number, result: any) => (result.type === 'return' ? n + 1 : n), + 0, + ); + +const printNumberOfReturns = ( + countReturns: number, + countCalls: number, +): string => + `\nNumber of returns: ${printReceived(countReturns)}${countCalls !== countReturns + ? `\nNumber of calls: ${printReceived(countCalls)}` + : '' + }`; + +type PrintLabel = (string: string, isExpectedCall: boolean) => string; + +// Given a label, return a function which given a string, +// right-aligns it preceding the colon in the label. +const getRightAlignedPrinter = (label: string): PrintLabel => { + // Assume that the label contains a colon. + const index = label.indexOf(':'); + const suffix = label.slice(index); + + return (string: string, isExpectedCall: boolean) => + (isExpectedCall + ? `->${' '.repeat(Math.max(0, index - 2 - string.length))}` + : ' '.repeat(Math.max(index - string.length))) + + string + + suffix; +}; + +type IndexedCall = [number, Array]; + +const printReceivedCallsNegative = ( + expected: Array, + indexedCalls: Array, + isOnlyCall: boolean, + iExpectedCall?: number, +) => { + if (indexedCalls.length === 0) + return ''; + + + const label = 'Received: '; + if (isOnlyCall) + return `${label + printReceivedArgs(indexedCalls[0], expected)}\n`; + + + const printAligned = getRightAlignedPrinter(label); + + return `Received\n${indexedCalls.reduce( + (printed: string, [i, args]: IndexedCall) => + `${printed + + printAligned(String(i + 1), i === iExpectedCall) + + printReceivedArgs(args, expected) + }\n`, + '', + )}`; +}; + +const printExpectedReceivedCallsPositive = ( + expected: Array, + indexedCalls: Array, + expand: boolean, + isOnlyCall: boolean, + iExpectedCall?: number, +) => { + const expectedLine = `Expected: ${printExpectedArgs(expected)}\n`; + if (indexedCalls.length === 0) + return expectedLine; + + + const label = 'Received: '; + if (isOnlyCall && (iExpectedCall === 0 || iExpectedCall === undefined)) { + const received = indexedCalls[0][1]; + + if (isLineDiffableCall(expected, received)) { + // Display diff without indentation. + const lines = [ + EXPECTED_COLOR('- Expected'), + RECEIVED_COLOR('+ Received'), + '', + ]; + + const length = Math.max(expected.length, received.length); + for (let i = 0; i < length; i += 1) { + if (i < expected.length && i < received.length) { + if (isEqualValue(expected[i], received[i])) { + lines.push(` ${printCommon(received[i])},`); + continue; + } + + if (isLineDiffableArg(expected[i], received[i])) { + const difference = diff(expected[i], received[i], { expand }); + if ( + typeof difference === 'string' && + difference.includes('- Expected') && + difference.includes('+ Received') + ) { + // Omit annotation in case multiple args have diff. + lines.push(`${difference.split('\n').slice(3).join('\n')},`); + continue; + } + } + } + + if (i < expected.length) + lines.push(`${EXPECTED_COLOR(`- ${stringify(expected[i])}`)},`); + + if (i < received.length) + lines.push(`${RECEIVED_COLOR(`+ ${stringify(received[i])}`)},`); + + } + + return `${lines.join('\n')}\n`; + } + + return `${expectedLine + label + printReceivedArgs(received, expected)}\n`; + } + + const printAligned = getRightAlignedPrinter(label); + + return ( + + expectedLine + + 'Received\n' + + indexedCalls.reduce((printed: string, [i, received]: IndexedCall) => { + const aligned = printAligned(String(i + 1), i === iExpectedCall); + return `${printed + + ((i === iExpectedCall || iExpectedCall === undefined) && + isLineDiffableCall(expected, received) + ? aligned.replace(': ', '\n') + + printDiffCall(expected, received, expand) + : aligned + printReceivedArgs(received, expected)) + }\n`; + }, '') + ); +}; + +const indentation = 'Received'.replace(/\w/g, ' '); + +const printDiffCall = ( + expected: Array, + received: Array, + expand: boolean, +) => + received + .map((arg, i) => { + if (i < expected.length) { + if (isEqualValue(expected[i], arg)) + return `${indentation} ${printCommon(arg)},`; + + + if (isLineDiffableArg(expected[i], arg)) { + const difference = diff(expected[i], arg, { expand }); + + if ( + typeof difference === 'string' && + difference.includes('- Expected') && + difference.includes('+ Received') + ) { + // Display diff with indentation. + // Omit annotation in case multiple args have diff. + return `${difference + .split('\n') + .slice(3) + .map(line => indentation + line) + .join('\n')},`; + } + } + } + + // Display + only if received arg has no corresponding expected arg. + return `${indentation + + (i < expected.length + ? ` ${printReceived(arg)}` + : RECEIVED_COLOR(`+ ${stringify(arg)}`)) + },`; + }) + .join('\n'); + +const isLineDiffableCall = ( + expected: Array, + received: Array, +): boolean => + expected.some( + (arg, i) => i < received.length && isLineDiffableArg(arg, received[i]), + ); + +// Almost redundant with function in jest-matcher-utils, +// except no line diff for any strings. +const isLineDiffableArg = (expected: unknown, received: unknown): boolean => { + const expectedType = getType(expected); + const receivedType = getType(received); + + if (expectedType !== receivedType) + return false; + + + if (isPrimitive(expected)) + return false; + + + if ( + expectedType === 'date' || + expectedType === 'function' || + expectedType === 'regexp' + ) + return false; + + + if (expected instanceof Error && received instanceof Error) + return false; + + + if ( + expectedType === 'object' && + typeof (expected as any).asymmetricMatch === 'function' + ) + return false; + + + if ( + receivedType === 'object' && + typeof (received as any).asymmetricMatch === 'function' + ) + return false; + + + return true; +}; + +const printResult = (result: any, expected: unknown) => + result.type === 'throw' + ? 'function call threw an error' + : result.type === 'incomplete' + ? 'function call has not returned yet' + : isEqualValue(expected, result.value) + ? printCommon(result.value) + : printReceived(result.value); + +type IndexedResult = [number, any]; + +// Return either empty string or one line per indexed result, +// so additional empty line can separate from `Number of returns` which follows. +const printReceivedResults = ( + label: string, + expected: unknown, + indexedResults: Array, + isOnlyCall: boolean, + iExpectedCall?: number, +) => { + if (indexedResults.length === 0) + return ''; + + + if (isOnlyCall && (iExpectedCall === 0 || iExpectedCall === undefined)) + return `${label + printResult(indexedResults[0][1], expected)}\n`; + + + const printAligned = getRightAlignedPrinter(label); + + return ( + + label.replace(':', '').trim() + + '\n' + + indexedResults.reduce( + (printed: string, [i, result]: IndexedResult) => + `${printed + + printAligned(String(i + 1), i === iExpectedCall) + + printResult(result, expected) + }\n`, + '', + ) + ); +}; + +const createToBeCalledMatcher = ( + matcherName: string, +): MatcherFunction<[unknown]> => + function(received: any, expected: unknown): SyncExpectationResult { + const expectedArgument = ''; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + ensureMockOrSpy(received, matcherName, expectedArgument, options); + + const receivedIsSpy = isSpy(received); + const receivedName = receivedIsSpy ? 'spy' : received.getMockName(); + const count = receivedIsSpy + ? received.calls.count() + : received.mock.calls.length; + const calls = receivedIsSpy + ? received.calls.all().map((x: any) => x.args) + : received.mock.calls; + const pass = count > 0; + const message = pass + ? () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of calls: ${printExpected(0)}\n` + + `Received number of calls: ${printReceived(count)}\n\n` + + calls + .reduce((lines: Array, args: any, i: number) => { + if (lines.length < PRINT_LIMIT) + lines.push(`${i + 1}: ${printReceivedArgs(args)}`); + + + return lines; + }, []) + .join('\n') + : () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of calls: >= ${printExpected(1)}\n` + + `Received number of calls: ${printReceived(count)}`; + + return { message, pass }; + }; + +const createToReturnMatcher = ( + matcherName: string, +): MatcherFunction<[unknown]> => + function(received: any, expected): SyncExpectationResult { + const expectedArgument = ''; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureNoExpected(expected, matcherName, options); + ensureMock(received, matcherName, expectedArgument, options); + + const receivedName = received.getMockName(); + + // Count return values that correspond only to calls that returned + const count = received.mock.results.reduce( + (n: number, result: any) => (result.type === 'return' ? n + 1 : n), + 0, + ); + + const pass = count > 0; + + const message = pass + ? () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of returns: ${printExpected(0)}\n` + + `Received number of returns: ${printReceived(count)}\n\n` + + received.mock.results + .reduce((lines: Array, result: any, i: number) => { + if (result.type === 'return' && lines.length < PRINT_LIMIT) + lines.push(`${i + 1}: ${printReceived(result.value)}`); + + + return lines; + }, []) + .join('\n') + + (received.mock.calls.length !== count + ? `\n\nReceived number of calls: ${printReceived( + received.mock.calls.length, + )}` + : '') + : () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of returns: >= ${printExpected(1)}\n` + + `Received number of returns: ${printReceived(count)}` + + (received.mock.calls.length !== count + ? `\nReceived number of calls: ${printReceived( + received.mock.calls.length, + )}` + : ''); + + return { message, pass }; + }; + +const createToBeCalledTimesMatcher = ( + matcherName: string, +): MatcherFunction<[number]> => + function(received: any, expected): SyncExpectationResult { + const expectedArgument = 'expected'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureExpectedIsNonNegativeInteger(expected, matcherName, options); + ensureMockOrSpy(received, matcherName, expectedArgument, options); + + const receivedIsSpy = isSpy(received); + const receivedName = receivedIsSpy ? 'spy' : received.getMockName(); + const count = receivedIsSpy + ? received.calls.count() + : received.mock.calls.length; + + const pass = count === expected; + + const message = pass + ? () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of calls: not ${printExpected(expected)}` + : () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of calls: ${printExpected(expected)}\n` + + `Received number of calls: ${printReceived(count)}`; + + return { message, pass }; + }; + +const createToReturnTimesMatcher = ( + matcherName: string, +): MatcherFunction<[number]> => + function(received: any, expected): SyncExpectationResult { + const expectedArgument = 'expected'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureExpectedIsNonNegativeInteger(expected, matcherName, options); + ensureMock(received, matcherName, expectedArgument, options); + + const receivedName = received.getMockName(); + + // Count return values that correspond only to calls that returned + const count = received.mock.results.reduce( + (n: number, result: any) => (result.type === 'return' ? n + 1 : n), + 0, + ); + + const pass = count === expected; + + const message = pass + ? () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of returns: not ${printExpected(expected)}` + + (received.mock.calls.length !== count + ? `\n\nReceived number of calls: ${printReceived( + received.mock.calls.length, + )}` + : '') + : () => + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected number of returns: ${printExpected(expected)}\n` + + `Received number of returns: ${printReceived(count)}` + + (received.mock.calls.length !== count + ? `\nReceived number of calls: ${printReceived( + received.mock.calls.length, + )}` + : ''); + + return { message, pass }; + }; + +const createToBeCalledWithMatcher = ( + matcherName: string, +): MatcherFunction> => + function(received: any, ...expected): SyncExpectationResult { + const expectedArgument = '...expected'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureMockOrSpy(received, matcherName, expectedArgument, options); + + const receivedIsSpy = isSpy(received); + const receivedName = receivedIsSpy ? 'spy' : received.getMockName(); + + const calls = receivedIsSpy + ? received.calls.all().map((x: any) => x.args) + : received.mock.calls; + + const pass = calls.some((call: any) => isEqualCall(expected, call)); + + const message = pass + ? () => { + // Some examples of calls that are equal to expected value. + const indexedCalls: Array = []; + let i = 0; + while (i < calls.length && indexedCalls.length < PRINT_LIMIT) { + if (isEqualCall(expected, calls[i])) + indexedCalls.push([i, calls[i]]); + + i += 1; + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected: not ${printExpectedArgs(expected)}\n` + + (calls.length === 1 && stringify(calls[0]) === stringify(expected) + ? '' + : printReceivedCallsNegative( + expected, + indexedCalls, + calls.length === 1, + )) + + `\nNumber of calls: ${printReceived(calls.length)}` + ); + } + : () => { + // Some examples of calls that are not equal to expected value. + const indexedCalls: Array = []; + let i = 0; + while (i < calls.length && indexedCalls.length < PRINT_LIMIT) { + indexedCalls.push([i, calls[i]]); + i += 1; + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + printExpectedReceivedCallsPositive( + expected, + indexedCalls, + isExpand(this.expand), + calls.length === 1, + ) + + `\nNumber of calls: ${printReceived(calls.length)}` + ); + }; + + return { message, pass }; + }; + +const createToReturnWithMatcher = ( + matcherName: string, +): MatcherFunction<[unknown]> => + function(received: any, expected): SyncExpectationResult { + const expectedArgument = 'expected'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureMock(received, matcherName, expectedArgument, options); + + const receivedName = received.getMockName(); + const { calls, results } = received.mock; + + const pass = results.some((result: any) => isEqualReturn(expected, result)); + + const message = pass + ? () => { + // Some examples of results that are equal to expected value. + const indexedResults: Array = []; + let i = 0; + while (i < results.length && indexedResults.length < PRINT_LIMIT) { + if (isEqualReturn(expected, results[i])) + indexedResults.push([i, results[i]]); + + i += 1; + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}\n` + + (results.length === 1 && + results[0].type === 'return' && + stringify(results[0].value) === stringify(expected) + ? '' + : printReceivedResults( + 'Received: ', + expected, + indexedResults, + results.length === 1, + )) + + printNumberOfReturns(countReturns(results), calls.length) + ); + } + : () => { + // Some examples of results that are not equal to expected value. + const indexedResults: Array = []; + let i = 0; + while (i < results.length && indexedResults.length < PRINT_LIMIT) { + indexedResults.push([i, results[i]]); + i += 1; + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected: ${printExpected(expected)}\n` + + printReceivedResults( + 'Received: ', + expected, + indexedResults, + results.length === 1, + ) + + printNumberOfReturns(countReturns(results), calls.length) + ); + }; + + return { message, pass }; + }; + +const createLastCalledWithMatcher = ( + matcherName: string, +): MatcherFunction> => + function(received: any, ...expected): SyncExpectationResult { + const expectedArgument = '...expected'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureMockOrSpy(received, matcherName, expectedArgument, options); + + const receivedIsSpy = isSpy(received); + const receivedName = receivedIsSpy ? 'spy' : received.getMockName(); + + const calls = receivedIsSpy + ? received.calls.all().map((x: any) => x.args) + : received.mock.calls; + const iLast = calls.length - 1; + + const pass = iLast >= 0 && isEqualCall(expected, calls[iLast]); + + const message = pass + ? () => { + const indexedCalls: Array = []; + if (iLast > 0) { + // Display preceding call as context. + indexedCalls.push([iLast - 1, calls[iLast - 1]]); + } + indexedCalls.push([iLast, calls[iLast]]); + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected: not ${printExpectedArgs(expected)}\n` + + (calls.length === 1 && stringify(calls[0]) === stringify(expected) + ? '' + : printReceivedCallsNegative( + expected, + indexedCalls, + calls.length === 1, + iLast, + )) + + `\nNumber of calls: ${printReceived(calls.length)}` + ); + } + : () => { + const indexedCalls: Array = []; + if (iLast >= 0) { + if (iLast > 0) { + let i = iLast - 1; + // Is there a preceding call that is equal to expected args? + while (i >= 0 && !isEqualCall(expected, calls[i])) + i -= 1; + + if (i < 0) + i = iLast - 1; // otherwise, preceding call + + + indexedCalls.push([i, calls[i]]); + } + + indexedCalls.push([iLast, calls[iLast]]); + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + printExpectedReceivedCallsPositive( + expected, + indexedCalls, + isExpand(this.expand), + calls.length === 1, + iLast, + ) + + `\nNumber of calls: ${printReceived(calls.length)}` + ); + }; + + return { message, pass }; + }; + +const createLastReturnedMatcher = ( + matcherName: string, +): MatcherFunction<[unknown]> => + function(received: any, expected): SyncExpectationResult { + const expectedArgument = 'expected'; + const options: MatcherHintOptions = { + isNot: this.isNot, + promise: this.promise, + }; + ensureMock(received, matcherName, expectedArgument, options); + + const receivedName = received.getMockName(); + + const { calls, results } = received.mock; + const iLast = results.length - 1; + + const pass = iLast >= 0 && isEqualReturn(expected, results[iLast]); + + const message = pass + ? () => { + const indexedResults: Array = []; + if (iLast > 0) { + // Display preceding result as context. + indexedResults.push([iLast - 1, results[iLast - 1]]); + } + indexedResults.push([iLast, results[iLast]]); + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected: not ${printExpected(expected)}\n` + + (results.length === 1 && + results[0].type === 'return' && + stringify(results[0].value) === stringify(expected) + ? '' + : printReceivedResults( + 'Received: ', + expected, + indexedResults, + results.length === 1, + iLast, + )) + + printNumberOfReturns(countReturns(results), calls.length) + ); + } + : () => { + const indexedResults: Array = []; + if (iLast >= 0) { + if (iLast > 0) { + let i = iLast - 1; + // Is there a preceding result that is equal to expected value? + while (i >= 0 && !isEqualReturn(expected, results[i])) + i -= 1; + + if (i < 0) + i = iLast - 1; // otherwise, preceding result + + + indexedResults.push([i, results[i]]); + } + + indexedResults.push([iLast, results[iLast]]); + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `Expected: ${printExpected(expected)}\n` + + printReceivedResults( + 'Received: ', + expected, + indexedResults, + results.length === 1, + iLast, + ) + + printNumberOfReturns(countReturns(results), calls.length) + ); + }; + + return { message, pass }; + }; + +const createNthCalledWithMatcher = ( + matcherName: string, +): MatcherFunction<[number, ...Array]> => + function(received: any, nth, ...expected): SyncExpectationResult { + const expectedArgument = 'n'; + const options: MatcherHintOptions = { + expectedColor: (arg: string) => arg, + isNot: this.isNot, + promise: this.promise, + secondArgument: '...expected', + }; + ensureMockOrSpy(received, matcherName, expectedArgument, options); + + if (!Number.isSafeInteger(nth) || nth < 1) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${expectedArgument} must be a positive integer`, + printWithType(expectedArgument, nth, stringify), + ), + ); + } + + const receivedIsSpy = isSpy(received); + const receivedName = receivedIsSpy ? 'spy' : received.getMockName(); + + const calls = receivedIsSpy + ? received.calls.all().map((x: any) => x.args) + : received.mock.calls; + const length = calls.length; + const iNth = nth - 1; + + const pass = iNth < length && isEqualCall(expected, calls[iNth]); + + const message = pass + ? () => { + // Display preceding and following calls, + // in case assertions fails because index is off by one. + const indexedCalls: Array = []; + if (iNth - 1 >= 0) + indexedCalls.push([iNth - 1, calls[iNth - 1]]); + + indexedCalls.push([iNth, calls[iNth]]); + if (iNth + 1 < length) + indexedCalls.push([iNth + 1, calls[iNth + 1]]); + + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `n: ${nth}\n` + + `Expected: not ${printExpectedArgs(expected)}\n` + + (calls.length === 1 && stringify(calls[0]) === stringify(expected) + ? '' + : printReceivedCallsNegative( + expected, + indexedCalls, + calls.length === 1, + iNth, + )) + + `\nNumber of calls: ${printReceived(calls.length)}` + ); + } + : () => { + // Display preceding and following calls: + // * nearest call that is equal to expected args + // * otherwise, adjacent call + // in case assertions fails because of index, especially off by one. + const indexedCalls: Array = []; + if (iNth < length) { + if (iNth - 1 >= 0) { + let i = iNth - 1; + // Is there a preceding call that is equal to expected args? + while (i >= 0 && !isEqualCall(expected, calls[i])) + i -= 1; + + if (i < 0) + i = iNth - 1; // otherwise, adjacent call + + + indexedCalls.push([i, calls[i]]); + } + indexedCalls.push([iNth, calls[iNth]]); + if (iNth + 1 < length) { + let i = iNth + 1; + // Is there a following call that is equal to expected args? + while (i < length && !isEqualCall(expected, calls[i])) + i += 1; + + if (i >= length) + i = iNth + 1; // otherwise, adjacent call + + + indexedCalls.push([i, calls[i]]); + } + } else if (length > 0) { + // The number of received calls is fewer than the expected number. + let i = length - 1; + // Is there a call that is equal to expected args? + while (i >= 0 && !isEqualCall(expected, calls[i])) + i -= 1; + + if (i < 0) + i = length - 1; // otherwise, last call + + + indexedCalls.push([i, calls[i]]); + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `n: ${nth}\n` + + printExpectedReceivedCallsPositive( + expected, + indexedCalls, + isExpand(this.expand), + calls.length === 1, + iNth, + ) + + `\nNumber of calls: ${printReceived(calls.length)}` + ); + }; + + return { message, pass }; + }; + +const createNthReturnedWithMatcher = ( + matcherName: string, +): MatcherFunction<[number, unknown]> => + function(received: any, nth, expected): SyncExpectationResult { + const expectedArgument = 'n'; + const options: MatcherHintOptions = { + expectedColor: (arg: string) => arg, + isNot: this.isNot, + promise: this.promise, + secondArgument: 'expected', + }; + ensureMock(received, matcherName, expectedArgument, options); + + if (!Number.isSafeInteger(nth) || nth < 1) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${expectedArgument} must be a positive integer`, + printWithType(expectedArgument, nth, stringify), + ), + ); + } + + const receivedName = received.getMockName(); + const { calls, results } = received.mock; + const length = results.length; + const iNth = nth - 1; + + const pass = iNth < length && isEqualReturn(expected, results[iNth]); + + const message = pass + ? () => { + // Display preceding and following results, + // in case assertions fails because index is off by one. + const indexedResults: Array = []; + if (iNth - 1 >= 0) + indexedResults.push([iNth - 1, results[iNth - 1]]); + + indexedResults.push([iNth, results[iNth]]); + if (iNth + 1 < length) + indexedResults.push([iNth + 1, results[iNth + 1]]); + + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `n: ${nth}\n` + + `Expected: not ${printExpected(expected)}\n` + + (results.length === 1 && + results[0].type === 'return' && + stringify(results[0].value) === stringify(expected) + ? '' + : printReceivedResults( + 'Received: ', + expected, + indexedResults, + results.length === 1, + iNth, + )) + + printNumberOfReturns(countReturns(results), calls.length) + ); + } + : () => { + // Display preceding and following results: + // * nearest result that is equal to expected value + // * otherwise, adjacent result + // in case assertions fails because of index, especially off by one. + const indexedResults: Array = []; + if (iNth < length) { + if (iNth - 1 >= 0) { + let i = iNth - 1; + // Is there a preceding result that is equal to expected value? + while (i >= 0 && !isEqualReturn(expected, results[i])) + i -= 1; + + if (i < 0) + i = iNth - 1; // otherwise, adjacent result + + + indexedResults.push([i, results[i]]); + } + indexedResults.push([iNth, results[iNth]]); + if (iNth + 1 < length) { + let i = iNth + 1; + // Is there a following result that is equal to expected value? + while (i < length && !isEqualReturn(expected, results[i])) + i += 1; + + if (i >= length) + i = iNth + 1; // otherwise, adjacent result + + + indexedResults.push([i, results[i]]); + } + } else if (length > 0) { + // The number of received calls is fewer than the expected number. + let i = length - 1; + // Is there a result that is equal to expected value? + while (i >= 0 && !isEqualReturn(expected, results[i])) + i -= 1; + + if (i < 0) + i = length - 1; // otherwise, last result + + + indexedResults.push([i, results[i]]); + } + + return ( + + matcherHint(matcherName, receivedName, expectedArgument, options) + + '\n\n' + + `n: ${nth}\n` + + `Expected: ${printExpected(expected)}\n` + + printReceivedResults( + 'Received: ', + expected, + indexedResults, + results.length === 1, + iNth, + ) + + printNumberOfReturns(countReturns(results), calls.length) + ); + }; + + return { message, pass }; + }; + +const spyMatchers: MatchersObject = { + lastCalledWith: createLastCalledWithMatcher('lastCalledWith'), + lastReturnedWith: createLastReturnedMatcher('lastReturnedWith'), + nthCalledWith: createNthCalledWithMatcher('nthCalledWith'), + nthReturnedWith: createNthReturnedWithMatcher('nthReturnedWith'), + toBeCalled: createToBeCalledMatcher('toBeCalled'), + toBeCalledTimes: createToBeCalledTimesMatcher('toBeCalledTimes'), + toBeCalledWith: createToBeCalledWithMatcher('toBeCalledWith'), + toHaveBeenCalled: createToBeCalledMatcher('toHaveBeenCalled'), + toHaveBeenCalledTimes: createToBeCalledTimesMatcher('toHaveBeenCalledTimes'), + toHaveBeenCalledWith: createToBeCalledWithMatcher('toHaveBeenCalledWith'), + toHaveBeenLastCalledWith: createLastCalledWithMatcher( + 'toHaveBeenLastCalledWith', + ), + toHaveBeenNthCalledWith: createNthCalledWithMatcher( + 'toHaveBeenNthCalledWith', + ), + toHaveLastReturnedWith: createLastReturnedMatcher('toHaveLastReturnedWith'), + toHaveNthReturnedWith: createNthReturnedWithMatcher('toHaveNthReturnedWith'), + toHaveReturned: createToReturnMatcher('toHaveReturned'), + toHaveReturnedTimes: createToReturnTimesMatcher('toHaveReturnedTimes'), + toHaveReturnedWith: createToReturnWithMatcher('toHaveReturnedWith'), + toReturn: createToReturnMatcher('toReturn'), + toReturnTimes: createToReturnTimesMatcher('toReturnTimes'), + toReturnWith: createToReturnWithMatcher('toReturnWith'), +}; + +const isMock = (received: any) => + received != null && received._isMockFunction === true; + +const isSpy = (received: any) => + received != null && + received.calls != null && + typeof received.calls.all === 'function' && + typeof received.calls.count === 'function'; + +const ensureMockOrSpy = ( + received: any, + matcherName: string, + expectedArgument: string, + options: MatcherHintOptions, +) => { + if (!isMock(received) && !isSpy(received)) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${RECEIVED_COLOR('received')} value must be a mock or spy function`, + printWithType('Received', received, printReceived), + ), + ); + } +}; + +const ensureMock = ( + received: any, + matcherName: string, + expectedArgument: string, + options: MatcherHintOptions, +) => { + if (!isMock(received)) { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, expectedArgument, options), + `${RECEIVED_COLOR('received')} value must be a mock function`, + printWithType('Received', received, printReceived), + ), + ); + } +}; + +export default spyMatchers; diff --git a/packages/playwright/bundles/expect/third_party/toThrowMatchers.ts b/packages/playwright/bundles/expect/third_party/toThrowMatchers.ts new file mode 100644 index 0000000000000..5a2bb9dcad2f0 --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/toThrowMatchers.ts @@ -0,0 +1,481 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { isError } from '@jest/expect-utils'; +import { + EXPECTED_COLOR, + type MatcherHintOptions, + RECEIVED_COLOR, + matcherErrorMessage, + matcherHint, + printDiffOrStringify, + printExpected, + printReceived, + printWithType, +} from 'jest-matcher-utils'; +import { formatStackTrace, separateMessageFromStack } from 'jest-message-util'; +import { + printExpectedConstructorName, + printExpectedConstructorNameNot, + printReceivedConstructorName, + printReceivedConstructorNameNot, + printReceivedStringContainExpectedResult, + printReceivedStringContainExpectedSubstring, +} from './print'; +import type { + ExpectationResult, + MatcherFunction, + MatchersObject, + SyncExpectationResult, +} from './types'; + +/* eslint-disable eqeqeq */ + +const DID_NOT_THROW = 'Received function did not throw'; + +type Thrown = + | { + hasMessage: true; + isError: true; + message: string; + value: Error; + } + | { + hasMessage: boolean; + isError: false; + message: string; + value: any; + }; + +const getThrown = (e: any): Thrown => { + const hasMessage = + e !== null && e !== undefined && typeof e.message === 'string'; + + if (hasMessage && typeof e.name === 'string' && typeof e.stack === 'string') { + return { + hasMessage, + isError: true, + message: e.message, + value: e, + }; + } + + return { + hasMessage, + isError: false, + message: hasMessage ? e.message : String(e), + value: e, + }; +}; + +export const createMatcher = ( + matcherName: string, + fromPromise?: boolean, +): MatcherFunction<[any]> => + function(received, expected): ExpectationResult { + const options = { + isNot: this.isNot, + promise: this.promise, + }; + + let thrown = null; + + if (fromPromise && isError(received)) { + thrown = getThrown(received); + } else { + if (typeof received !== 'function') { + if (!fromPromise) { + const placeholder = expected === undefined ? '' : 'expected'; + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, placeholder, options), + `${RECEIVED_COLOR('received')} value must be a function`, + printWithType('Received', received, printReceived), + ), + ); + } + } else { + try { + received(); + } catch (e) { + thrown = getThrown(e); + } + } + } + + if (expected === undefined) { + return toThrow(matcherName, options, thrown); + } else if (typeof expected === 'function') { + return toThrowExpectedClass(matcherName, options, thrown, expected); + } else if (typeof expected === 'string') { + return toThrowExpectedString(matcherName, options, thrown, expected); + } else if (expected !== null && typeof expected.test === 'function') { + return toThrowExpectedRegExp(matcherName, options, thrown, expected); + } else if ( + expected !== null && + typeof expected.asymmetricMatch === 'function' + ) { + return toThrowExpectedAsymmetric(matcherName, options, thrown, expected); + } else if (expected !== null && typeof expected === 'object') { + return toThrowExpectedObject(matcherName, options, thrown, expected); + } else { + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, undefined, options), + `${EXPECTED_COLOR( + 'expected', + )} value must be a string or regular expression or class or error`, + printWithType('Expected', expected, printExpected), + ), + ); + } + }; + +const matchers: MatchersObject = { + toThrow: createMatcher('toThrow'), + toThrowError: createMatcher('toThrowError'), +}; + +const toThrowExpectedRegExp = ( + matcherName: string, + options: MatcherHintOptions, + thrown: Thrown | null, + expected: RegExp, +): SyncExpectationResult => { + const pass = thrown !== null && expected.test(thrown.message); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected('Expected pattern: not ', expected) + + (thrown !== null && thrown.hasMessage + ? formatReceived( + 'Received message: ', + thrown, + 'message', + expected, + ) + formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value')) + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected('Expected pattern: ', expected) + + (thrown === null + ? `\n${DID_NOT_THROW}` + : thrown.hasMessage + ? formatReceived('Received message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value')); + + return { message, pass }; +}; + +type AsymmetricMatcher = { + asymmetricMatch: (received: unknown) => boolean; +}; + +const toThrowExpectedAsymmetric = ( + matcherName: string, + options: MatcherHintOptions, + thrown: Thrown | null, + expected: AsymmetricMatcher, +): SyncExpectationResult => { + const pass = thrown !== null && expected.asymmetricMatch(thrown.value); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected('Expected asymmetric matcher: not ', expected) + + '\n' + + (thrown !== null && thrown.hasMessage + ? formatReceived('Received name: ', thrown, 'name') + + formatReceived('Received message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Thrown value: ', thrown, 'value')) + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected('Expected asymmetric matcher: ', expected) + + '\n' + + (thrown === null + ? DID_NOT_THROW + : thrown.hasMessage + ? formatReceived('Received name: ', thrown, 'name') + + formatReceived('Received message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Thrown value: ', thrown, 'value')); + + return { message, pass }; +}; + +const toThrowExpectedObject = ( + matcherName: string, + options: MatcherHintOptions, + thrown: Thrown | null, + expected: Error, +): SyncExpectationResult => { + const expectedMessageAndCause = createMessageAndCause(expected); + const thrownMessageAndCause = + thrown !== null ? createMessageAndCause(thrown.value) : null; + const pass = + thrown !== null && + thrown.message === expected.message && + thrownMessageAndCause === expectedMessageAndCause; + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected( + `Expected ${messageAndCause(expected)}: not `, + expectedMessageAndCause, + ) + + (thrown !== null && thrown.hasMessage + ? formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value')) + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + (thrown === null + ? + formatExpected( + `Expected ${messageAndCause(expected)}: `, + expectedMessageAndCause, + ) + + '\n' + + DID_NOT_THROW + : thrown.hasMessage + ? + printDiffOrStringify( + expectedMessageAndCause, + thrownMessageAndCause, + `Expected ${messageAndCause(expected)}`, + `Received ${messageAndCause(thrown.value)}`, + true, + ) + + '\n' + + formatStack(thrown) + : formatExpected( + `Expected ${messageAndCause(expected)}: `, + expectedMessageAndCause, + ) + formatReceived('Received value: ', thrown, 'value')); + + return { message, pass }; +}; + +const toThrowExpectedClass = ( + matcherName: string, + options: MatcherHintOptions, + thrown: Thrown | null, + expected: Function, +): SyncExpectationResult => { + const pass = thrown !== null && thrown.value instanceof expected; + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printExpectedConstructorNameNot('Expected constructor', expected) + + (thrown !== null && + thrown.value != null && + typeof thrown.value.constructor === 'function' && + thrown.value.constructor !== expected + ? printReceivedConstructorNameNot( + 'Received constructor', + thrown.value.constructor, + expected, + ) + : '') + + '\n' + + (thrown !== null && thrown.hasMessage + ? formatReceived('Received message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value')) + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + printExpectedConstructorName('Expected constructor', expected) + + (thrown === null + ? `\n${DID_NOT_THROW}` + : `${thrown.value != null && + typeof thrown.value.constructor === 'function' + ? printReceivedConstructorName( + 'Received constructor', + thrown.value.constructor, + ) + : '' + }\n${thrown.hasMessage + ? formatReceived('Received message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value') + }`); + + return { message, pass }; +}; + +const toThrowExpectedString = ( + matcherName: string, + options: MatcherHintOptions, + thrown: Thrown | null, + expected: string, +): SyncExpectationResult => { + const pass = thrown !== null && thrown.message.includes(expected); + + const message = pass + ? () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected('Expected substring: not ', expected) + + (thrown !== null && thrown.hasMessage + ? formatReceived( + 'Received message: ', + thrown, + 'message', + expected, + ) + formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value')) + : () => + + matcherHint(matcherName, undefined, undefined, options) + + '\n\n' + + formatExpected('Expected substring: ', expected) + + (thrown === null + ? `\n${DID_NOT_THROW}` + : thrown.hasMessage + ? formatReceived('Received message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Received value: ', thrown, 'value')); + + return { message, pass }; +}; + +const toThrow = ( + matcherName: string, + options: MatcherHintOptions, + thrown: Thrown | null, +): SyncExpectationResult => { + const pass = thrown !== null; + + const message = pass + ? () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + (thrown !== null && thrown.hasMessage + ? formatReceived('Error name: ', thrown, 'name') + + formatReceived('Error message: ', thrown, 'message') + + formatStack(thrown) + : formatReceived('Thrown value: ', thrown, 'value')) + : () => + + matcherHint(matcherName, undefined, '', options) + + '\n\n' + + DID_NOT_THROW; + + return { message, pass }; +}; + +const formatExpected = (label: string, expected: unknown) => + `${label + printExpected(expected)}\n`; + +const formatReceived = ( + label: string, + thrown: Thrown | null, + key: string, + expected?: string | RegExp, +) => { + if (thrown === null) + return ''; + + + if (key === 'message') { + const message = thrown.message; + + if (typeof expected === 'string') { + const index = message.indexOf(expected); + if (index !== -1) { + return `${label + + printReceivedStringContainExpectedSubstring( + message, + index, + expected.length, + ) + }\n`; + } + } else if (expected instanceof RegExp) { + return `${label + + printReceivedStringContainExpectedResult( + message, + typeof expected.exec === 'function' ? expected.exec(message) : null, + ) + }\n`; + } + + return `${label + printReceived(message)}\n`; + } + + if (key === 'name') { + return thrown.isError + ? `${label + printReceived(thrown.value.name)}\n` + : ''; + } + + if (key === 'value') + return thrown.isError ? '' : `${label + printReceived(thrown.value)}\n`; + + + return ''; +}; + +const formatStack = (thrown: Thrown | null) => + thrown === null || !thrown.isError + ? '' + : formatStackTrace( + separateMessageFromStack(thrown.value.stack!).stack, + { + rootDir: process.cwd(), + testMatch: [], + }, + { + noStackTrace: false, + }, + ); + +function createMessageAndCauseMessage(error: Error): string { + if (error.cause instanceof Error) { + return `{ message: ${error.message}, cause: ${createMessageAndCauseMessage( + error.cause, + )}}`; + } + + return `{ message: ${error.message} }`; +} + +function createMessageAndCause(error: Error) { + if (error.cause instanceof Error) + return createMessageAndCauseMessage(error); + + return error.message; +} + +function messageAndCause(error: Error) { + return error.cause === undefined ? 'message' : 'message and cause'; +} + +export default matchers; diff --git a/packages/playwright/bundles/expect/third_party/types.ts b/packages/playwright/bundles/expect/third_party/types.ts new file mode 100644 index 0000000000000..abaa3a3b69472 --- /dev/null +++ b/packages/playwright/bundles/expect/third_party/types.ts @@ -0,0 +1,353 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import type { EqualsFunction, Tester } from '@jest/expect-utils'; +import type * as jestMatcherUtils from 'jest-matcher-utils'; +import type { INTERNAL_MATCHER_FLAG } from './jestMatchersObject'; + +export type SyncExpectationResult = { + pass: boolean; + message(): string; +}; + +export type AsyncExpectationResult = Promise; + +export type ExpectationResult = SyncExpectationResult | AsyncExpectationResult; + +export type MatcherFunctionWithContext< + Context extends MatcherContext = MatcherContext, + Expected extends Array = [] /** TODO should be: extends Array = [] */, +> = ( + this: Context, + actual: unknown, + ...expected: Expected +) => ExpectationResult; + +export type MatcherFunction = []> = + MatcherFunctionWithContext; + +// TODO should be replaced with `MatcherFunctionWithContext` +export type RawMatcherFn = { + (this: Context, actual: any, ...expected: Array): ExpectationResult; + /** @internal */ + [INTERNAL_MATCHER_FLAG]?: boolean; +}; + +export type MatchersObject = { + [name: string]: RawMatcherFn; +}; + +export type ThrowingMatcherFn = (actual: any) => void; +export type PromiseMatcherFn = (actual: any) => Promise; + +export interface MatcherUtils { + customTesters: Array; + dontThrow(): void; + equals: EqualsFunction; + utils: typeof jestMatcherUtils & { + iterableEquality: Tester; + subsetEquality: Tester; + }; +} + +export interface MatcherState { + assertionCalls: number; + currentConcurrentTestName?: () => string | undefined; + currentTestName?: string; + error?: Error; + expand?: boolean; + expectedAssertionsNumber: number | null; + expectedAssertionsNumberError?: Error; + isExpectingAssertions: boolean; + isExpectingAssertionsError?: Error; + isNot?: boolean; + numPassingAsserts: number; + promise?: string; + suppressedErrors: Array; + testPath?: string; +} + +export type MatcherContext = MatcherUtils & Readonly; + +export type AsymmetricMatcher = { + asymmetricMatch(other: unknown): boolean; + toString(): string; + getExpectedType?(): string; + toAsymmetricMatcher?(): string; +}; + +export type ExpectedAssertionsErrors = Array<{ + actual: string | number; + error: Error; + expected: string; +}>; + +export interface BaseExpect { + assertions(numberOfAssertions: number): void; + addEqualityTesters(testers: Array): void; + extend(matchers: MatchersObject): void; + extractExpectedAssertionsErrors(): ExpectedAssertionsErrors; + getState(): MatcherState; + hasAssertions(): void; + setState(state: Partial): void; +} + +export type Expect = { + (actual: T): Matchers & + Inverse> & + PromiseMatchers; +} & BaseExpect & + AsymmetricMatchers & + Inverse>; + +type Inverse = { + /** + * Inverse next matcher. If you know how to test something, `.not` lets you test its opposite. + */ + not: Matchers; +}; + +export interface AsymmetricMatchers { + any(sample: unknown): AsymmetricMatcher; + anything(): AsymmetricMatcher; + arrayContaining(sample: Array): AsymmetricMatcher; + closeTo(sample: number, precision?: number): AsymmetricMatcher; + objectContaining(sample: Record): AsymmetricMatcher; + stringContaining(sample: string): AsymmetricMatcher; + stringMatching(sample: string | RegExp): AsymmetricMatcher; +} + +type PromiseMatchers = { + /** + * Unwraps the reason of a rejected promise so any other matcher can be chained. + * If the promise is fulfilled the assertion fails. + */ + rejects: Matchers, T> & Inverse, T>>; + /** + * Unwraps the value of a fulfilled promise so any other matcher can be chained. + * If the promise is rejected the assertion fails. + */ + resolves: Matchers, T> & Inverse, T>>; +}; + +export interface Matchers, T = unknown> { + /** + * T is a type param for the benefit of users who extend Matchers. It's + * intentionally unused and needs to be named T, not _T, for those users. + * This makes sure TypeScript agrees. + * + * @internal + */ + _unusedT(expected: T): R; + /** + * Ensures the last call to a mock function was provided specific args. + */ + lastCalledWith(...expected: Array): R; + /** + * Ensure that the last call to a mock function has returned a specified value. + */ + lastReturnedWith(expected?: unknown): R; + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + */ + nthCalledWith(nth: number, ...expected: Array): R; + /** + * Ensure that the nth call to a mock function has returned a specified value. + */ + nthReturnedWith(nth: number, expected?: unknown): R; + /** + * Checks that a value is what you expect. It calls `Object.is` to compare values. + * Don't use `toBe` with floating-point numbers. + */ + toBe(expected: unknown): R; + /** + * Ensures that a mock function is called. + */ + toBeCalled(): R; + /** + * Ensures that a mock function is called an exact number of times. + */ + toBeCalledTimes(expected: number): R; + /** + * Ensure that a mock function is called with specific arguments. + */ + toBeCalledWith(...expected: Array): R; + /** + * Using exact equality with floating point numbers is a bad idea. + * Rounding means that intuitive things fail. + * The default for `precision` is 2. + */ + toBeCloseTo(expected: number, precision?: number): R; + /** + * Ensure that a variable is not undefined. + */ + toBeDefined(): R; + /** + * When you don't care what a value is, you just want to + * ensure a value is false in a boolean context. + */ + toBeFalsy(): R; + /** + * For comparing floating point numbers. + */ + toBeGreaterThan(expected: number | bigint): R; + /** + * For comparing floating point numbers. + */ + toBeGreaterThanOrEqual(expected: number | bigint): R; + /** + * Ensure that an object is an instance of a class. + * This matcher uses `instanceof` underneath. + */ + toBeInstanceOf(expected: unknown): R; + /** + * For comparing floating point numbers. + */ + toBeLessThan(expected: number | bigint): R; + /** + * For comparing floating point numbers. + */ + toBeLessThanOrEqual(expected: number | bigint): R; + /** + * Used to check that a variable is NaN. + */ + toBeNaN(): R; + /** + * This is the same as `.toBe(null)` but the error messages are a bit nicer. + * So use `.toBeNull()` when you want to check that something is null. + */ + toBeNull(): R; + /** + * Use when you don't care what a value is, you just want to ensure a value + * is true in a boolean context. In JavaScript, there are six falsy values: + * `false`, `0`, `''`, `null`, `undefined`, and `NaN`. Everything else is truthy. + */ + toBeTruthy(): R; + /** + * Used to check that a variable is undefined. + */ + toBeUndefined(): R; + /** + * Used when you want to check that an item is in a list. + * For testing the items in the list, this uses `===`, a strict equality check. + */ + toContain(expected: unknown): R; + /** + * Used when you want to check that an item is in a list. + * For testing the items in the list, this matcher recursively checks the + * equality of all fields, rather than checking for object identity. + */ + toContainEqual(expected: unknown): R; + /** + * Used when you want to check that two objects have the same value. + * This matcher recursively checks the equality of all fields, rather than checking for object identity. + */ + toEqual(expected: unknown): R; + /** + * Ensures that a mock function is called. + */ + toHaveBeenCalled(): R; + /** + * Ensures that a mock function is called an exact number of times. + */ + toHaveBeenCalledTimes(expected: number): R; + /** + * Ensure that a mock function is called with specific arguments. + */ + toHaveBeenCalledWith(...expected: Array): R; + /** + * Ensure that a mock function is called with specific arguments on an Nth call. + */ + toHaveBeenNthCalledWith(nth: number, ...expected: Array): R; + /** + * If you have a mock function, you can use `.toHaveBeenLastCalledWith` + * to test what arguments it was last called with. + */ + toHaveBeenLastCalledWith(...expected: Array): R; + /** + * Use to test the specific value that a mock function last returned. + * If the last call to the mock function threw an error, then this matcher will fail + * no matter what value you provided as the expected return value. + */ + toHaveLastReturnedWith(expected?: unknown): R; + /** + * Used to check that an object has a `.length` property + * and it is set to a certain numeric value. + */ + toHaveLength(expected: number): R; + /** + * Use to test the specific value that a mock function returned for the nth call. + * If the nth call to the mock function threw an error, then this matcher will fail + * no matter what value you provided as the expected return value. + */ + toHaveNthReturnedWith(nth: number, expected?: unknown): R; + /** + * Use to check if property at provided reference keyPath exists for an object. + * For checking deeply nested properties in an object you may use dot notation or an array containing + * the keyPath for deep references. + * + * Optionally, you can provide a value to check if it's equal to the value present at keyPath + * on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks + * the equality of all fields. + * + * @example + * + * expect(houseForSale).toHaveProperty('kitchen.area', 20); + */ + toHaveProperty( + expectedPath: string | Array, + expectedValue?: unknown, + ): R; + /** + * Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time + */ + toHaveReturned(): R; + /** + * Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times. + * Any calls to the mock function that throw an error are not counted toward the number of times the function returned. + */ + toHaveReturnedTimes(expected: number): R; + /** + * Use to ensure that a mock function returned a specific value. + */ + toHaveReturnedWith(expected?: unknown): R; + /** + * Check that a string matches a regular expression. + */ + toMatch(expected: string | RegExp): R; + /** + * Used to check that a JavaScript object matches a subset of the properties of an object + */ + toMatchObject( + expected: Record | Array>, + ): R; + /** + * Ensure that a mock function has returned (as opposed to thrown) at least once. + */ + toReturn(): R; + /** + * Ensure that a mock function has returned (as opposed to thrown) a specified number of times. + */ + toReturnTimes(expected: number): R; + /** + * Ensure that a mock function has returned a specified value at least once. + */ + toReturnWith(expected?: unknown): R; + /** + * Use to test that objects have the same types as well as structure. + */ + toStrictEqual(expected: unknown): R; + /** + * Used to test that a function throws when it is called. + */ + toThrow(expected?: unknown): R; + /** + * If you want to test that a specific error is thrown inside a function. + */ + toThrowError(expected?: unknown): R; +} diff --git a/packages/playwright/src/common/expectBundle.ts b/packages/playwright/src/common/expectBundle.ts index 3322c36277db5..4b601b77aeb9c 100644 --- a/packages/playwright/src/common/expectBundle.ts +++ b/packages/playwright/src/common/expectBundle.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export const expect: typeof import('../../bundles/expect/node_modules/expect/build').expect = require('./expectBundleImpl').expect; +export const expect: typeof import('../../bundles/expect/third_party/index').expect = require('./expectBundleImpl').expect; +export const mock: typeof import('../../bundles/expect/node_modules/jest-mock') = require('./expectBundleImpl').mock; +export const asymmetricMatchers = require('./expectBundleImpl').asymmetricMatchers; +export const matcherUtils = require('./expectBundleImpl').matcherUtils; export const EXPECTED_COLOR: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').EXPECTED_COLOR = require('./expectBundleImpl').EXPECTED_COLOR; export const INVERTED_COLOR: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').INVERTED_COLOR = require('./expectBundleImpl').INVERTED_COLOR; export const RECEIVED_COLOR: typeof import('../../bundles/expect/node_modules/jest-matcher-utils/build').RECEIVED_COLOR = require('./expectBundleImpl').RECEIVED_COLOR; diff --git a/packages/web/src/ansi2html.ts b/packages/web/src/ansi2html.ts index 210d1210bc6fb..e1d80ed073e85 100644 --- a/packages/web/src/ansi2html.ts +++ b/packages/web/src/ansi2html.ts @@ -26,12 +26,13 @@ export function ansi2html(text: string): string { switch (code) { case 0: style = {}; break; case 1: style['font-weight'] = 'bold'; break; + case 2: style['opacity'] = '0.8'; break; case 3: style['font-style'] = 'italic'; break; case 4: style['text-decoration'] = 'underline'; break; case 8: style.display = 'none'; break; case 9: style['text-decoration'] = 'line-through'; break; - case 22: style = { ...style, 'font-weight': undefined, 'font-style': undefined, 'text-decoration': undefined }; break; - case 23: style = { ...style, 'font-weight': undefined, 'font-style': undefined }; break; + case 22: style = { ...style, 'font-weight': undefined, 'font-style': undefined, 'opacity': undefined, 'text-decoration': undefined }; break; + case 23: style = { ...style, 'font-weight': undefined, 'font-style': undefined, 'opacity': undefined }; break; case 24: style = { ...style, 'text-decoration': undefined }; break; case 30: case 31: diff --git a/tests/config/utils.ts b/tests/config/utils.ts index 88cff686b3375..d01d40771f003 100644 --- a/tests/config/utils.ts +++ b/tests/config/utils.ts @@ -23,6 +23,7 @@ import { TraceModel } from '../../packages/trace-viewer/src/traceModel'; import type { ActionTreeItem } from '../../packages/trace-viewer/src/ui/modelUtil'; import { buildActionTree, MultiTraceModel } from '../../packages/trace-viewer/src/ui/modelUtil'; import type { ActionTraceEvent, ConsoleMessageTraceEvent, EventTraceEvent, TraceEvent } from '@trace/trace'; +import style from 'ansi-styles'; export async function attachFrame(page: Page, frameId: string, url: string): Promise { const handle = await page.evaluateHandle(async ({ frameId, url }) => { @@ -207,6 +208,40 @@ export function stripAnsi(str: string): string { return str.replace(ansiRegex, ''); } +export function ansi2Markup(text: string): string { + return text.replace(ansiRegex, match => { + switch (match) { + case style.inverse.open: + return ''; + case style.inverse.close: + return ''; + + case style.bold.open: + return ''; + case style.dim.open: + return ''; + case style.green.open: + return ''; + case style.red.open: + return ''; + case style.yellow.open: + return ''; + case style.bgYellow.open: + return ''; + + case style.bold.close: + case style.dim.close: + case style.green.close: + case style.red.close: + case style.yellow.close: + case style.bgYellow.close: + return ''; + + default: + return match; // unexpected escape sequence + } + }); +} class TraceBackend implements TraceModelBackend { private _fileName: string; diff --git a/tests/expect/assertionCounts.test.ts b/tests/expect/assertionCounts.test.ts new file mode 100644 index 0000000000000..ebaae506c9b44 --- /dev/null +++ b/tests/expect/assertionCounts.test.ts @@ -0,0 +1,78 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +test.describe('.assertions()', () => { + test('does not throw', () => { + expectUnderTest.assertions(2); + expectUnderTest('a').not.toBe('b'); + expectUnderTest('a').toBe('a'); + }); + + test('redeclares different assertion count', () => { + expectUnderTest.assertions(3); + expectUnderTest('a').not.toBe('b'); + expectUnderTest('a').toBe('a'); + expectUnderTest.assertions(2); + }); + test('expects no assertions', () => { + expectUnderTest.assertions(0); + }); +}); + +test.describe('.hasAssertions()', () => { + test('does not throw if there is an assertion', () => { + expectUnderTest.hasAssertions(); + expectUnderTest('a').toBe('a'); + }); + + test('throws if expected is not undefined', () => { + expect(() => + (expectUnderTest as any).hasAssertions(2) + ).toThrowErrorMatchingSnapshot(`expect(received)[.not].hasAssertions() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 2`); + }); +}); + +test.describe('numPassingAsserts', () => { + test.skip('verify the default value of numPassingAsserts', () => { + const { numPassingAsserts } = expectUnderTest.getState(); + expect(numPassingAsserts).toBe(0); + }); + + test('verify the resetting of numPassingAsserts after a test', () => { + expect('a').toBe('a'); + expect('a').toBe('a'); + // reset state + expectUnderTest.extractExpectedAssertionsErrors(); + const { numPassingAsserts } = expectUnderTest.getState(); + expect(numPassingAsserts).toBe(0); + }); + + test.skip('verify the correctness of numPassingAsserts count for passing test', () => { + expect('a').toBe('a'); + expect('a').toBe('a'); + const { numPassingAsserts } = expectUnderTest.getState(); + expect(numPassingAsserts).toBe(2); + }); + + test.skip('verify the correctness of numPassingAsserts count for failing test', () => { + expect('a').toBe('a'); + try { + expect('a').toBe('b'); + } catch (error) { } + const { numPassingAsserts } = expectUnderTest.getState(); + expect(numPassingAsserts).toBe(1); + }); +}); diff --git a/tests/expect/asymmetricMatchers.test.ts b/tests/expect/asymmetricMatchers.test.ts new file mode 100644 index 0000000000000..ec0c40dbecbc7 --- /dev/null +++ b/tests/expect/asymmetricMatchers.test.ts @@ -0,0 +1,519 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test } from '../playwright-test/stable-test-runner'; +import { expect as expectUnderTest, asymmetricMatchers } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +const { + any, + anything, + arrayContaining, + arrayNotContaining, + closeTo, + notCloseTo, + objectContaining, + objectNotContaining, + stringContaining, + stringMatching, + stringNotContaining, + stringNotMatching, +} = asymmetricMatchers; + +test('Any.asymmetricMatch()', () => { + class Thing {} + + [ + any(String).asymmetricMatch('jest'), + any(Number).asymmetricMatch(1), + any(Function).asymmetricMatch(() => {}), + any(Boolean).asymmetricMatch(true), + any(BigInt).asymmetricMatch(1n), + any(Symbol).asymmetricMatch(Symbol()), + any(Object).asymmetricMatch({}), + any(Object).asymmetricMatch(null), + any(Array).asymmetricMatch([]), + any(Thing).asymmetricMatch(new Thing()), + ].forEach(test => { + expectUnderTest(test).toBe(true); + }); +}); + +test('Any.asymmetricMatch() on primitive wrapper classes', () => { + [ + + any(String).asymmetricMatch(new String('jest')), + + any(Number).asymmetricMatch(new Number(1)), + + any(Function).asymmetricMatch(new Function('() => {}')), + + any(Boolean).asymmetricMatch(new Boolean(true)), + any(BigInt).asymmetricMatch(Object(1n)), + any(Symbol).asymmetricMatch(Object(Symbol())), + ].forEach(test => { + expectUnderTest(test).toBe(true); + }); +}); + +test('Any.toAsymmetricMatcher()', () => { + expectUnderTest(any(Number).toAsymmetricMatcher()).toBe('Any'); +}); + +test('Any.toAsymmetricMatcher() with function name', () => { + [ + ['someFunc', function someFunc() {}], + ['$someFunc', function $someFunc() {}], + [ + '$someFunc2', + (function() { + function $someFunc2() {} + Object.defineProperty($someFunc2, 'name', { value: '' }); + return $someFunc2; + })(), + ], + [ + '$someAsyncFunc', + (function() { + async function $someAsyncFunc() {} + Object.defineProperty($someAsyncFunc, 'name', { value: '' }); + return $someAsyncFunc; + })(), + ], + [ + '$someGeneratorFunc', + (function() { + function* $someGeneratorFunc() {} + Object.defineProperty($someGeneratorFunc, 'name', { value: '' }); + return $someGeneratorFunc; + })(), + ], + [ + '$someFuncWithFakeToString', + (function() { + function $someFuncWithFakeToString() {} + $someFuncWithFakeToString.toString = () => 'Fake to string'; + return $someFuncWithFakeToString; + })(), + ], + ].forEach(([name, fn]) => { + expectUnderTest(any(fn).toAsymmetricMatcher()).toBe(`Any<${name}>`); + }); +}); + +test('Any throws when called with empty constructor', () => { + // @ts-expect-error: Testing runtime error + expectUnderTest(() => any()).toThrow( + 'any() expects to be passed a constructor function. Please pass one or use anything() to match any object.', + ); +}); + +test('Anything matches any type', () => { + [ + anything().asymmetricMatch('jest'), + anything().asymmetricMatch(1), + anything().asymmetricMatch(() => {}), + anything().asymmetricMatch(true), + anything().asymmetricMatch({}), + anything().asymmetricMatch([]), + ].forEach(test => { + expectUnderTest(test).toBe(true); + }); +}); + +test('Anything does not match null and undefined', () => { + [ + anything().asymmetricMatch(null), + anything().asymmetricMatch(undefined), + ].forEach(test => { + expectUnderTest(test).toBe(false); + }); +}); + +test('Anything.toAsymmetricMatcher()', () => { + expectUnderTest(anything().toAsymmetricMatcher()).toBe('Anything'); +}); + +test('ArrayContaining matches', () => { + [ + arrayContaining([]).asymmetricMatch('jest'), + arrayContaining(['foo']).asymmetricMatch(['foo']), + arrayContaining(['foo']).asymmetricMatch(['foo', 'bar']), + arrayContaining([]).asymmetricMatch({}), + ].forEach(test => { + expectUnderTest(test).toEqual(true); + }); +}); + +test('ArrayContaining does not match', () => { + expectUnderTest(arrayContaining(['foo']).asymmetricMatch(['bar'])).toBe(false); +}); + +test('ArrayContaining throws for non-arrays', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + arrayContaining('foo').asymmetricMatch([]); + }).toThrow("You must provide an array to ArrayContaining, not 'string'."); +}); + +test('ArrayNotContaining matches', () => { + expectUnderTest(arrayNotContaining(['foo']).asymmetricMatch(['bar'])).toBe(true); +}); + +test('ArrayNotContaining does not match', () => { + [ + arrayNotContaining([]).asymmetricMatch('jest'), + arrayNotContaining(['foo']).asymmetricMatch(['foo']), + arrayNotContaining(['foo']).asymmetricMatch(['foo', 'bar']), + arrayNotContaining([]).asymmetricMatch({}), + ].forEach(test => { + expectUnderTest(test).toEqual(false); + }); +}); + +test('ArrayNotContaining throws for non-arrays', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + arrayNotContaining('foo').asymmetricMatch([]); + }).toThrow("You must provide an array to ArrayNotContaining, not 'string'."); +}); + +test('ObjectContaining matches', () => { + const foo = Symbol('foo'); + [ + objectContaining({}).asymmetricMatch('jest'), + objectContaining({ foo: 'foo' }).asymmetricMatch({ foo: 'foo', jest: 'jest' }), + objectContaining({ foo: undefined }).asymmetricMatch({ foo: undefined }), + objectContaining({ first: objectContaining({ second: {} }) }).asymmetricMatch({ + first: { second: {} }, + }), + objectContaining({ foo: Buffer.from('foo') }).asymmetricMatch({ + foo: Buffer.from('foo'), + jest: 'jest', + }), + objectContaining({ [foo]: 'foo' }).asymmetricMatch({ [foo]: 'foo' }), + ].forEach(test => { + expectUnderTest(test).toEqual(true); + }); +}); + +test('ObjectContaining does not match', () => { + const foo = Symbol('foo'); + const bar = Symbol('bar'); + [ + objectContaining({ foo: 'foo' }).asymmetricMatch({ bar: 'bar' }), + objectContaining({ foo: 'foo' }).asymmetricMatch({ foo: 'foox' }), + objectContaining({ foo: undefined }).asymmetricMatch({}), + objectContaining({ + answer: 42, + foo: { bar: 'baz', foobar: 'qux' }, + }).asymmetricMatch({ foo: { bar: 'baz' } }), + objectContaining({ [foo]: 'foo' }).asymmetricMatch({ [bar]: 'bar' }), + ].forEach(test => { + expectUnderTest(test).toEqual(false); + }); +}); + +test('ObjectContaining matches defined properties', () => { + const definedPropertyObject = {}; + Object.defineProperty(definedPropertyObject, 'foo', { get: () => 'bar' }); + expectUnderTest( + objectContaining({ foo: 'bar' }).asymmetricMatch(definedPropertyObject), + ).toBe(true); +}); + +test('ObjectContaining matches prototype properties', () => { + const prototypeObject = { foo: 'bar' }; + let obj; + + if (Object.create) { + obj = Object.create(prototypeObject); + } else { + function Foo() {} + Foo.prototype = prototypeObject; + Foo.prototype.constructor = Foo; + obj = new (Foo as any)(); + } + expectUnderTest(objectContaining({ foo: 'bar' }).asymmetricMatch(obj)).toBe(true); +}); + +test('ObjectContaining throws for non-objects', () => { + // @ts-expect-error: Testing runtime error + expectUnderTest(() => objectContaining(1337).asymmetricMatch()).toThrow( + "You must provide an object to ObjectContaining, not 'number'.", + ); +}); + +test('ObjectContaining does not mutate the sample', () => { + const sample = { foo: { bar: {} } }; + const sample_json = JSON.stringify(sample); + expectUnderTest({ foo: { bar: {} } }).toEqual(expectUnderTest.objectContaining(sample)); + + expectUnderTest(JSON.stringify(sample)).toEqual(sample_json); +}); + +test('ObjectNotContaining matches', () => { + const foo = Symbol('foo'); + const bar = Symbol('bar'); + [ + objectContaining({}).asymmetricMatch(null), + objectContaining({}).asymmetricMatch(undefined), + objectNotContaining({ [foo]: 'foo' }).asymmetricMatch({ [bar]: 'bar' }), + objectNotContaining({ foo: 'foo' }).asymmetricMatch({ bar: 'bar' }), + objectNotContaining({ foo: 'foo' }).asymmetricMatch({ foo: 'foox' }), + objectNotContaining({ foo: undefined }).asymmetricMatch({}), + objectNotContaining({ + first: objectNotContaining({ second: {} }), + }).asymmetricMatch({ first: { second: {} } }), + objectNotContaining({ first: { second: {}, third: {} } }).asymmetricMatch({ + first: { second: {} }, + }), + objectNotContaining({ first: { second: {} } }).asymmetricMatch({ + first: { second: {}, third: {} }, + }), + objectNotContaining({ foo: 'foo', jest: 'jest' }).asymmetricMatch({ + foo: 'foo', + }), + ].forEach(test => { + expectUnderTest(test).toEqual(true); + }); +}); + +test('ObjectNotContaining does not match', () => { + [ + objectNotContaining({}).asymmetricMatch('jest'), + objectNotContaining({ foo: 'foo' }).asymmetricMatch({ + foo: 'foo', + jest: 'jest', + }), + objectNotContaining({ foo: undefined }).asymmetricMatch({ foo: undefined }), + objectNotContaining({ first: { second: {} } }).asymmetricMatch({ + first: { second: {} }, + }), + objectNotContaining({ + first: objectContaining({ second: {} }), + }).asymmetricMatch({ first: { second: {} } }), + objectNotContaining({}).asymmetricMatch(null), + objectNotContaining({}).asymmetricMatch(undefined), + objectNotContaining({}).asymmetricMatch({}), + ].forEach(test => { + expectUnderTest(test).toEqual(false); + }); +}); + +test('ObjectNotContaining inverts ObjectContaining', () => { + ( + [ + [{}, null], + [{ foo: 'foo' }, { foo: 'foo', jest: 'jest' }], + [{ foo: 'foo', jest: 'jest' }, { foo: 'foo' }], + [{ foo: undefined }, { foo: undefined }], + [{ foo: undefined }, {}], + [{ first: { second: {} } }, { first: { second: {} } }], + [{ first: objectContaining({ second: {} }) }, { first: { second: {} } }], + [{ first: objectNotContaining({ second: {} }) }, { first: { second: {} } }], + [{}, { foo: undefined }], + ] as const + ).forEach(([sample, received]) => { + expectUnderTest(objectNotContaining(sample).asymmetricMatch(received)).toEqual( + !objectContaining(sample).asymmetricMatch(received), + ); + }); +}); + +test('ObjectNotContaining throws for non-objects', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + objectNotContaining(1337).asymmetricMatch(); + }).toThrow( + "You must provide an object to ObjectNotContaining, not 'number'.", + ); +}); + +test('StringContaining matches string against string', () => { + expectUnderTest(stringContaining('en*').asymmetricMatch('queen*')).toBe(true); + expectUnderTest(stringContaining('en').asymmetricMatch('queue')).toBe(false); +}); + +test('StringContaining throws if expected value is not string', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + stringContaining([1]).asymmetricMatch('queen'); + }).toThrow('Expected is not a string'); +}); + +test('StringContaining returns false if received value is not string', () => { + expectUnderTest(stringContaining('en*').asymmetricMatch(1)).toBe(false); +}); + +test('StringNotContaining matches string against string', () => { + expectUnderTest(stringNotContaining('en*').asymmetricMatch('queen*')).toBe(false); + expectUnderTest(stringNotContaining('en').asymmetricMatch('queue')).toBe(true); +}); + +test('StringNotContaining throws if expected value is not string', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + stringNotContaining([1]).asymmetricMatch('queen'); + }).toThrow('Expected is not a string'); +}); + +test('StringNotContaining returns true if received value is not string', () => { + expectUnderTest(stringNotContaining('en*').asymmetricMatch(1)).toBe(true); +}); + +test('StringMatching matches string against regexp', () => { + expectUnderTest(stringMatching(/en/).asymmetricMatch('queen')).toBe(true); + expectUnderTest(stringMatching(/en/).asymmetricMatch('queue')).toBe(false); +}); + +test('StringMatching matches string against string', () => { + expectUnderTest(stringMatching('en').asymmetricMatch('queen')).toBe(true); + expectUnderTest(stringMatching('en').asymmetricMatch('queue')).toBe(false); +}); + +test('StringMatching throws if expected value is neither string nor regexp', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + stringMatching([1]).asymmetricMatch('queen'); + }).toThrow('Expected is not a String or a RegExp'); +}); + +test('StringMatching returns false if received value is not string', () => { + expectUnderTest(stringMatching('en').asymmetricMatch(1)).toBe(false); +}); + +test('StringMatching returns false even if coerced non-string received value matches pattern', () => { + expectUnderTest(stringMatching('null').asymmetricMatch(null)).toBe(false); +}); + +test('StringNotMatching matches string against regexp', () => { + expectUnderTest(stringNotMatching(/en/).asymmetricMatch('queen')).toBe(false); + expectUnderTest(stringNotMatching(/en/).asymmetricMatch('queue')).toBe(true); +}); + +test('StringNotMatching matches string against string', () => { + expectUnderTest(stringNotMatching('en').asymmetricMatch('queen')).toBe(false); + expectUnderTest(stringNotMatching('en').asymmetricMatch('queue')).toBe(true); +}); + +test('StringNotMatching throws if expected value is neither string nor regexp', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + stringNotMatching([1]).asymmetricMatch('queen'); + }).toThrow('Expected is not a String or a RegExp'); +}); + +test('StringNotMatching returns true if received value is not string', () => { + expectUnderTest(stringNotMatching('en').asymmetricMatch(1)).toBe(true); +}); + +test.describe('closeTo', () => { + [ + [0, 0], + [0, 0.001], + [1.23, 1.229], + [1.23, 1.226], + [1.23, 1.225], + [1.23, 1.234], + [Infinity, Infinity], + [-Infinity, -Infinity], + ].forEach(([expected, received]) => { + test(`${expected} closeTo ${received} return true`, () => { + expectUnderTest(closeTo(expected).asymmetricMatch(received)).toBe(true); + }); + test(`${expected} notCloseTo ${received} return false`, () => { + expectUnderTest(notCloseTo(expected).asymmetricMatch(received)).toBe(false); + }); + }); + + [ + [0, 0.01], + [1, 1.23], + [1.23, 1.2249999], + [Infinity, -Infinity], + [Infinity, 1.23], + [-Infinity, -1.23], + ].forEach(([expected, received]) => { + test(`${expected} closeTo ${received} return false`, () => { + expectUnderTest(closeTo(expected).asymmetricMatch(received)).toBe(false); + }); + test(`${expected} notCloseTo ${received} return true`, () => { + expectUnderTest(notCloseTo(expected).asymmetricMatch(received)).toBe(true); + }); + }); + + [ + [0, 0.1, 0], + [0, 0.0001, 3], + [0, 0.000004, 5], + [2.0000002, 2, 5], + ].forEach(([expected, received, precision]) => { + test(`${expected} closeTo ${received} with precision ${precision} return true`, () => { + expectUnderTest(closeTo(expected, precision).asymmetricMatch(received)).toBe( + true, + ); + }); + test(`${expected} notCloseTo ${received} with precision ${precision} return false`, () => { + expectUnderTest( + notCloseTo(expected, precision).asymmetricMatch(received), + ).toBe(false); + }); + }); + + [ + [3.141592e-7, 3e-7, 8], + [56789, 51234, -4], + ].forEach(([expected, received, precision]) => { + test(`${expected} closeTo ${received} with precision ${precision} return false`, () => { + expectUnderTest(closeTo(expected, precision).asymmetricMatch(received)).toBe( + false, + ); + }); + test(`${expected} notCloseTo ${received} with precision ${precision} return true`, () => { + expectUnderTest( + notCloseTo(expected, precision).asymmetricMatch(received), + ).toBe(true); + }); + }); + + test('closeTo throw if expected is not number', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + closeTo('a'); + }).toThrow('Expected is not a Number'); + }); + + test('notCloseTo throw if expected is not number', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + notCloseTo('a'); + }).toThrow('Expected is not a Number'); + }); + + test('closeTo throw if precision is not number', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + closeTo(1, 'a'); + }).toThrow('Precision is not a Number'); + }); + + test('notCloseTo throw if precision is not number', () => { + expectUnderTest(() => { + // @ts-expect-error: Testing runtime error + notCloseTo(1, 'a'); + }).toThrow('Precision is not a Number'); + }); + + test('closeTo return false if received is not number', () => { + expectUnderTest(closeTo(1).asymmetricMatch('a')).toBe(false); + }); + + test('notCloseTo return false if received is not number', () => { + expectUnderTest(notCloseTo(1).asymmetricMatch('a')).toBe(false); + }); +}); diff --git a/tests/expect/customEqualityTesters.test.ts b/tests/expect/customEqualityTesters.test.ts new file mode 100644 index 0000000000000..2909c1091e874 --- /dev/null +++ b/tests/expect/customEqualityTesters.test.ts @@ -0,0 +1,197 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest, mock } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +class Volume { + public amount: number; + public unit: 'L' | 'mL'; + + constructor(amount: number, unit: 'L' | 'mL') { + this.amount = amount; + this.unit = unit; + } + + toString(): string { + return `[Volume ${this.amount}${this.unit}]`; + } + + equals(other: Volume): boolean { + if (this.unit === other.unit) + return this.amount === other.amount; + else if (this.unit === 'L' && other.unit === 'mL') + return this.amount * 1000 === other.amount; + else + return this.amount === other.amount * 1000; + + } +} + +function createVolume(amount: number, unit: 'L' | 'mL' = 'L') { + return new Volume(amount, unit); +} + +function isVolume(a: unknown): a is Volume { + return a instanceof Volume; +} + +const areVolumesEqual = ( + a: unknown, + b: unknown, +): boolean | undefined => { + const isAVolume = isVolume(a); + const isBVolume = isVolume(b); + + if (isAVolume && isBVolume) + return a.equals(b); + else if (isAVolume !== isBVolume) + return false; + else + return undefined; + +}; + +function* toIterator(array: Array): Iterator { + for (const obj of array) + yield obj; + +} + +expectUnderTest.extend({ + toEqualVolume(expected: Volume, actual: Volume) { + const result = this.equals(expected, actual, this.customTesters); + + return { + message: () => + `Expected Volume object: ${expected.toString()}. Actual Volume object: ${actual.toString()}`, + pass: result, + }; + }, +}); + +// Create Volumes with different specifications but the same value for use in +// tests. Without the custom tester, these volumes would not be equal because +// their properties have different values. However, with our custom tester they +// are equal. +const volume1 = createVolume(1, 'L'); +const volume2 = createVolume(1000, 'mL'); + +const volumeArg1 = createVolume(1, 'L'); +const volumeArg2 = createVolume(1000, 'mL'); +const volumeArg3 = createVolume(2, 'L'); +const volumeArg4 = createVolume(2000, 'mL'); + +const volumeReturn1 = createVolume(2, 'L'); +const volumeReturn2 = createVolume(2000, 'mL'); + +const testArgs = [volumeArg1, volumeArg2, [volumeArg3, volumeArg4]]; +// Swap the order of args to assert custom tester sees these volumes as equal +const expectedArgs = [volumeArg2, volumeArg1, [volumeArg4, volumeArg3]]; + +expectUnderTest.addEqualityTesters([areVolumesEqual]); + +test.describe('with custom equality testers', () => { + test('basic matchers customTesters do not apply to still do not pass different Volume objects', () => { + expectUnderTest(volume1).not.toBe(volume2); + expectUnderTest([volume1]).not.toContain(volume2); + }); + + test('basic matchers pass different Volume objects', () => { + expectUnderTest(volume1).toEqual(volume1); + expectUnderTest(volume1).toEqual(volume2); + expectUnderTest([volume1, volume2]).toEqual([volume2, volume1]); + expectUnderTest(new Map([['key', volume1]])).toEqual(new Map([['key', volume2]])); + expectUnderTest(new Set([volume1])).toEqual(new Set([volume2])); + expectUnderTest(toIterator([volume1, volume2])).toEqual( + toIterator([volume2, volume1]), + ); + expectUnderTest([volume1]).toContainEqual(volume2); + expectUnderTest({ a: volume1 }).toHaveProperty('a', volume2); + expectUnderTest({ a: volume1, b: undefined }).toStrictEqual({ + a: volume2, + b: undefined, + }); + expectUnderTest({ a: 1, b: { c: volume1 } }).toMatchObject({ + a: 1, + b: { c: volume2 }, + }); + }); + + test('asymmetric matchers pass different Volume objects', () => { + expectUnderTest([volume1]).toEqual(expectUnderTest.arrayContaining([volume2])); + expectUnderTest({ a: 1, b: { c: volume1 } }).toEqual( + expectUnderTest.objectContaining({ b: { c: volume2 } }), + ); + }); + + test('spy matchers pass different Volume objects', () => { + const mockFn = mock.fn<(...args: Array) => unknown>( + () => volumeReturn1, + ); + mockFn(...testArgs); + + expectUnderTest(mockFn).toHaveBeenCalledWith(...expectedArgs); + expectUnderTest(mockFn).toHaveBeenLastCalledWith(...expectedArgs); + expectUnderTest(mockFn).toHaveBeenNthCalledWith(1, ...expectedArgs); + + expectUnderTest(mockFn).toHaveReturnedWith(volumeReturn2); + expectUnderTest(mockFn).toHaveLastReturnedWith(volumeReturn2); + expectUnderTest(mockFn).toHaveNthReturnedWith(1, volumeReturn2); + }); + + test('custom matchers pass different Volume objects', () => { + (expectUnderTest as any)(volume1).toEqualVolume(volume2); + }); + + test('toBe recommends toStrictEqual even with different Volume objects', () => { + expectUnderTest(() => expectUnderTest(volume1).toBe(volume2)).toThrow('toStrictEqual'); + }); + + test('toBe recommends toEqual even with different Volume objects', () => { + expectUnderTest(() => expectUnderTest({ a: undefined, b: volume1 }).toBe({ b: volume2 })).toThrow( + 'toEqual', + ); + }); + + test('toContains recommends toContainEquals even with different Volume objects', () => { + expectUnderTest(() => expectUnderTest([volume1]).toContain(volume2)).toThrow( + 'toContainEqual', + ); + }); + + test('toMatchObject error shows Volume objects as equal', () => { + expect(() => + expectUnderTest({ a: 1, b: volume1 }).toMatchObject({ a: 2, b: volume2 }) + ).toThrowErrorMatchingSnapshot(`expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": 2, ++ "a": 1, + "b": Volume { + "amount": 1000, + "unit": "mL", + }, + }`); + }); + + test('iterableEquality still properly detects cycles', () => { + const a = new Set(); + a.add(volume1); + a.add(a); + + const b = new Set(); + b.add(volume2); + b.add(b); + + expectUnderTest(a).toEqual(b); + }); +}); diff --git a/tests/expect/customEqualityTestersRecursive.test.ts b/tests/expect/customEqualityTestersRecursive.test.ts new file mode 100644 index 0000000000000..34c5813a8dc2e --- /dev/null +++ b/tests/expect/customEqualityTestersRecursive.test.ts @@ -0,0 +1,246 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest, mock } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +// Test test file demonstrates and tests the capability of recursive custom +// testers that call `equals` within their tester logic. These testers should +// receive the array of custom testers and be able to pass it into equals + +const CONNECTION_PROP = '__connection'; +type DbConnection = number; +let DbConnectionId = 0; + +class Author { + public name: string; + public [CONNECTION_PROP]: DbConnection; + + constructor(name: string) { + this.name = name; + this[CONNECTION_PROP] = DbConnectionId++; + } +} + +class Book { + public name: string; + public authors: Array; + public [CONNECTION_PROP]: DbConnection; + + constructor(name: string, authors: Array) { + this.name = name; + this.authors = authors; + this[CONNECTION_PROP] = DbConnectionId++; + } +} + +const areAuthorsEqual = (a: unknown, b: unknown) => { + const isAAuthor = a instanceof Author; + const isBAuthor = b instanceof Author; + + if (isAAuthor && isBAuthor) + return a.name === b.name; + else if (isAAuthor !== isBAuthor) + return false; + else + return undefined; + +}; + +const areBooksEqual = function( + a: unknown, + b: unknown, + customTesters: [], +) { + const isABook = a instanceof Book; + const isBBook = b instanceof Book; + + if (isABook && isBBook) { + return ( + a.name === b.name && this.equals(a.authors, b.authors, customTesters) + ); + } else if (isABook !== isBBook) { + return false; + } else { + return undefined; + } +}; + +function* toIterator(array: Array): Iterator { + for (const obj of array) + yield obj; + +} + +expectUnderTest.extend({ + toEqualBook(expected: Book, actual: Book) { + const result = this.equals(expected, actual, this.customTesters); + + return { + message: () => + `Expected Book object: ${expected.name}. Actual Book object: ${actual.name}`, + pass: result, + }; + }, +}); + +// Create books with the same name and authors for use in tests. Without the +// custom tester, these books would not be equal because their DbConnections +// would have different values. However, with our custom tester they are equal. +const book1 = new Book('Book 1', [ + new Author('Author 1'), + new Author('Author 2'), +]); +const book1b = new Book('Book 1', [ + new Author('Author 1'), + new Author('Author 2'), +]); + +const bookArg1a = new Book('Book Arg 1', [ + new Author('Author Arg 1'), + new Author('Author Arg 2'), +]); +const bookArg1b = new Book('Book Arg 1', [ + new Author('Author Arg 1'), + new Author('Author Arg 2'), +]); +const bookArg2a = new Book('Book Arg 2', [ + new Author('Author Arg 3'), + new Author('Author Arg 4'), +]); +const bookArg2b = new Book('Book Arg 2', [ + new Author('Author Arg 3'), + new Author('Author Arg 4'), +]); + +const bookReturn1a = new Book('Book Return 1', [ + new Author('Author Return 1'), + new Author('Author Return 2'), +]); +const bookReturn1b = new Book('Book Return 1', [ + new Author('Author Return 1'), + new Author('Author Return 2'), +]); + +const testArgs = [bookArg1a, bookArg1b, [bookArg2a, bookArg2b]]; +// Swap the order of args to assert custom tester works correctly and ignores +// DbConnection differences +const expectedArgs = [bookArg1b, bookArg1a, [bookArg2b, bookArg2a]]; + +expectUnderTest.addEqualityTesters([areAuthorsEqual, areBooksEqual]); + +test.describe('with custom equality testers', () => { + test('exposes an equality function to custom testers', () => { + const runTestSymbol = Symbol('run this test'); + + expectUnderTest.addEqualityTesters([ + function dummyTester() { + return undefined; + }, + ]); + + expectUnderTest(() => + expectUnderTest(runTestSymbol).toEqual(runTestSymbol), + ).not.toThrow(); + }); + + test('basic matchers customTesters do not apply to still do not pass different Book objects', () => { + expectUnderTest(book1).not.toBe(book1b); + expectUnderTest([book1]).not.toContain(book1b); + }); + + test('basic matchers pass different Book objects', () => { + expectUnderTest(book1).toEqual(book1); + expectUnderTest(book1).toEqual(book1b); + expectUnderTest([book1, book1b]).toEqual([book1b, book1]); + expectUnderTest(new Map([['key', book1]])).toEqual(new Map([['key', book1b]])); + expectUnderTest(new Set([book1])).toEqual(new Set([book1b])); + expectUnderTest(toIterator([book1, book1b])).toEqual(toIterator([book1b, book1])); + expectUnderTest([book1]).toContainEqual(book1b); + expectUnderTest({ a: book1 }).toHaveProperty('a', book1b); + expectUnderTest({ a: book1, b: undefined }).toStrictEqual({ + a: book1b, + b: undefined, + }); + expectUnderTest({ a: 1, b: { c: book1 } }).toMatchObject({ + a: 1, + b: { c: book1b }, + }); + }); + + test('asymmetric matchers pass different Book objects', () => { + expectUnderTest([book1]).toEqual(expect.arrayContaining([book1b])); + expectUnderTest({ a: 1, b: { c: book1 } }).toEqual( + expect.objectContaining({ b: { c: book1b } }), + ); + }); + + test('spy matchers pass different Book objects', () => { + const mockFn = mock.fn<(...args: Array) => unknown>( + () => bookReturn1a, + ); + mockFn(...testArgs); + + expectUnderTest(mockFn).toHaveBeenCalledWith(...expectedArgs); + expectUnderTest(mockFn).toHaveBeenLastCalledWith(...expectedArgs); + expectUnderTest(mockFn).toHaveBeenNthCalledWith(1, ...expectedArgs); + + expectUnderTest(mockFn).toHaveReturnedWith(bookReturn1b); + expectUnderTest(mockFn).toHaveLastReturnedWith(bookReturn1b); + expectUnderTest(mockFn).toHaveNthReturnedWith(1, bookReturn1b); + }); + + test('custom matchers pass different Book objects', () => { + (expectUnderTest as any)(book1).toEqualBook(book1b); + }); + + test('toBe recommends toStrictEqual even with different Book objects', () => { + expectUnderTest(() => expectUnderTest(book1).toBe(book1b)).toThrow('toStrictEqual'); + }); + + test('toBe recommends toEqual even with different Book objects', () => { + expectUnderTest(() => expectUnderTest({ a: undefined, b: book1 }).toBe({ b: book1b })).toThrow( + 'toEqual', + ); + }); + + test('toContains recommends toContainEquals even with different Book objects', () => { + expectUnderTest(() => expectUnderTest([book1]).toContain(book1b)).toThrow('toContainEqual'); + }); + + test('toMatchObject error shows Book objects as equal', () => { + expect(() => + expectUnderTest({ a: 1, b: book1 }).toMatchObject({ a: 2, b: book1b }) + ).toThrowErrorMatchingSnapshot(`expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + +@@ -1,7 +1,7 @@ + Object { +- "a": 2, ++ "a": 1, + "b": Book { + "__connection": 5, + "authors": Array [ + Author { + "__connection": 3,`); + }); + + test('iterableEquality still properly detects cycles', () => { + const a = new Set(); + a.add(book1); + a.add(a); + + const b = new Set(); + b.add(book1b); + b.add(b); + + expectUnderTest(a).toEqual(b); + }); +}); diff --git a/tests/expect/extend.test.ts b/tests/expect/extend.test.ts new file mode 100644 index 0000000000000..94b879bb4010c --- /dev/null +++ b/tests/expect/extend.test.ts @@ -0,0 +1,247 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +expectUnderTest.extend({ + toBeDivisibleBy(actual: number, expected: number) { + const pass = actual % expected === 0; + const message: () => string = pass + ? () => + `expected ${this.utils.printReceived( + actual, + )} not to be divisible by ${expected}` + : () => + `expected ${this.utils.printReceived( + actual, + )} to be divisible by ${expected}`; + + return { message, pass }; + }, + toBeSymbol(actual: symbol, expected: symbol) { + const pass = actual === expected; + const message = () => + `expected ${actual.toString()} to be Symbol ${expected.toString()}`; + + return { message, pass }; + }, + toBeWithinRange(actual: number, floor: number, ceiling: number) { + const pass = actual >= floor && actual <= ceiling; + const message = pass + ? () => + `expected ${this.utils.printReceived( + actual, + )} not to be within range ${floor} - ${ceiling}` + : () => + `expected ${this.utils.printReceived( + actual, + )} to be within range ${floor} - ${ceiling}`; + + return { message, pass }; + }, +}); + +const expectUnderTestAsAny = expectUnderTest as any; + +test('is available globally when matcher is unary', () => { + expectUnderTestAsAny(15).toBeDivisibleBy(5); + expectUnderTestAsAny(15).toBeDivisibleBy(3); + expectUnderTestAsAny(15).not.toBeDivisibleBy(6); + + expect(() => + expectUnderTestAsAny(15).toBeDivisibleBy(2), + ).toThrowErrorMatchingSnapshot(`expected 15 to be divisible by 2`); +}); + +test('is available globally when matcher is variadic', () => { + expectUnderTestAsAny(15).toBeWithinRange(10, 20); + expectUnderTestAsAny(15).not.toBeWithinRange(6, 10); + + expect(() => + expectUnderTestAsAny(15).toBeWithinRange(1, 3), + ).toThrowErrorMatchingSnapshot(`expected 15 to be within range 1 - 3`); +}); + +test.skip('exposes matcherUtils in context', () => { + // expectUnderTest.extend({ + // shouldNotError(_actual: unknown) { + // const pass: boolean = this.equals( + // this.utils, + // Object.assign(matcherUtils, { + // iterableEquality, + // subsetEquality, + // }), + // ); + // const message = pass + // ? () => 'expected this.utils to be defined in an extend call' + // : () => 'expected this.utils not to be defined in an extend call'; + + // return { message, pass }; + // }, + // }); + + // expectUnderTestAsAny('test').shouldNotError(); +}); + +test('is ok if there is no message specified', () => { + expectUnderTest.extend({ + toFailWithoutMessage(_expected: unknown) { + return { message: () => '', pass: false }; + }, + }); + + expect(() => + expectUnderTestAsAny(true).toFailWithoutMessage(), + ).toThrowErrorMatchingSnapshot(`No message was specified for this matcher.`); +}); + +test('exposes an equality function to custom matchers', () => { + expectUnderTest.extend({ + toBeOne(_expected: unknown) { + return { message: () => '', pass: !!this.equals(1, 1) }; + }, + }); + + expect(() => expectUnderTestAsAny('test').toBeOne()).not.toThrow(); +}); + +test('defines asymmetric unary matchers', () => { + expect(() => + expectUnderTest({ value: 2 }).toEqual({ value: expectUnderTestAsAny.toBeDivisibleBy(2) }), + ).not.toThrow(); + expect(() => + expectUnderTest({ value: 3 }).toEqual({ value: expectUnderTestAsAny.toBeDivisibleBy(2) }), + ).toThrowErrorMatchingSnapshot(`expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "value": toBeDivisibleBy<2>, ++ "value": 3, + }`); +}); + +test('defines asymmetric unary matchers that can be prefixed by not', () => { + expect(() => + expectUnderTest({ value: 2 }).toEqual({ value: expectUnderTestAsAny.not.toBeDivisibleBy(2) }), + ).toThrowErrorMatchingSnapshot(`expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "value": not.toBeDivisibleBy<2>, ++ "value": 2, + }`); + expect(() => + expectUnderTest({ value: 3 }).toEqual({ value: expectUnderTestAsAny.not.toBeDivisibleBy(2) }), + ).not.toThrow(); +}); + +test('defines asymmetric variadic matchers', () => { + expect(() => + expectUnderTest({ value: 2 }).toEqual({ value: expectUnderTestAsAny.toBeWithinRange(1, 3) }), + ).not.toThrow(); + expect(() => + expectUnderTest({ value: 3 }).toEqual({ value: expectUnderTestAsAny.toBeWithinRange(4, 11) }), + ).toThrowErrorMatchingSnapshot(`expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "value": toBeWithinRange<4, 11>, ++ "value": 3, + }`); +}); + +test('defines asymmetric variadic matchers that can be prefixed by not', () => { + expect(() => + expectUnderTest({ value: 2 }).toEqual({ + value: expectUnderTestAsAny.not.toBeWithinRange(1, 3), + }), + ).toThrowErrorMatchingSnapshot(`expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "value": not.toBeWithinRange<1, 3>, ++ "value": 2, + }`); + expect(() => + expectUnderTest({ value: 3 }).toEqual({ + value: expectUnderTestAsAny.not.toBeWithinRange(5, 7), + }), + ).not.toThrow(); +}); + +test('prints the Symbol into the error message', () => { + const foo = Symbol('foo'); + const bar = Symbol('bar'); + + expect(() => + expectUnderTest({ a: foo }).toEqual({ + a: expectUnderTestAsAny.toBeSymbol(bar), + }), + ).toThrowErrorMatchingSnapshot(`expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "a": toBeSymbol, ++ "a": Symbol(foo), + }`); +}); + +test('allows overriding existing extension', () => { + expectUnderTest.extend({ + toAllowOverridingExistingMatcher(_expected: unknown) { + return { message: () => '', pass: _expected === 'bar' }; + }, + }); + + expectUnderTestAsAny('foo').not.toAllowOverridingExistingMatcher(); + + expectUnderTest.extend({ + toAllowOverridingExistingMatcher(_expected: unknown) { + return { message: () => '', pass: _expected === 'foo' }; + }, + }); + + expectUnderTestAsAny('foo').toAllowOverridingExistingMatcher(); +}); + +test('throws descriptive errors for invalid matchers', () => { + expect(() => + expectUnderTest.extend({ + default: undefined, + }), + ).toThrow( + 'expect.extend: `default` is not a valid matcher. Must be a function, is "undefined"', + ); + expect(() => + expectUnderTest.extend({ + // @ts-expect-error: Testing runtime error + default: 42, + }), + ).toThrow( + 'expect.extend: `default` is not a valid matcher. Must be a function, is "number"', + ); + expect(() => + expectUnderTest.extend({ + // @ts-expect-error: Testing runtime error + default: 'foobar', + }), + ).toThrow( + 'expect.extend: `default` is not a valid matcher. Must be a function, is "string"', + ); +}); diff --git a/tests/expect/fixtures.ts b/tests/expect/fixtures.ts new file mode 100644 index 0000000000000..502f9571b01e2 --- /dev/null +++ b/tests/expect/fixtures.ts @@ -0,0 +1,108 @@ +/* + Copyright (c) Microsoft Corporation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import fs from 'fs'; +import { ansi2Markup } from 'tests/config/utils'; +import { expect as baseExpect } from '../playwright-test/stable-test-runner'; +import { test } from '../playwright-test/stable-test-runner'; +export { test } from '../playwright-test/stable-test-runner'; + +const ordinals = new Map(); +const snapshotFiles = new Set(); + +function checkExpectation(unformatted: string, inlineExpected?: string) { + const actual = ansi2Markup(unformatted); + const file = test.info().file.replace('.test.ts', '.snapshots.js'); + const fullKey = test.info().titlePath.join('|'); + const ordinal = ordinals.get(fullKey) || 0; + ordinals.set(fullKey, ordinal + 1); + + const key = test.info().titlePath.slice(1).join(' ') + (ordinal ? ` #${ordinal}` : ''); + + if (!inlineExpected && test.info().config.updateSnapshots === 'all') { + if (!snapshotFiles.has(file)) { + fs.writeFileSync(file, ''); + snapshotFiles.add(file); + } + const line = `module.exports[${JSON.stringify(key)}] = \`${actual.replace(/\\/g, '\\\\').replace(/`/g, '\\`')}\`;\n\n`; + fs.appendFileSync(file, line); + return { message: () => '', pass: true }; + } + + let expected: string; + if (inlineExpected) { + expected = inlineExpected; + } else { + const data = require(file); + expected = data[key]; + } + + let pass: boolean; + let matcherResult: any; + try { + baseExpect(actual).toBe(expected); + pass = true; + } catch (e: any) { + matcherResult = e.matcherResult; + pass = false; + } + + const expectOptions = { + isNot: this.isNot, + }; + + const message = pass + ? () => this.utils.matcherHint('toBe', actual, expected, expectOptions) + + '\n\n' + + `Expected: ${this.isNot ? 'not' : ''}${this.utils.printExpected(expected)}\n` + + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : '') + : () => this.utils.matcherHint('toBe', actual, expected, expectOptions) + + '\n\n' + + `Expected: ${this.utils.printExpected(expected)}\n` + + (matcherResult ? `Received: ${this.utils.printReceived(matcherResult.actual)}` : ''); + + return { + name: 'toThrowErrorMatching', + expected, + message, + pass, + actual: matcherResult?.actual, + }; +} + +export const expect = baseExpect.extend({ + toMatchSnapshot(message: string, expected?: string) { + return checkExpectation.call(this, message, expected); + }, + + toThrowErrorMatchingSnapshot(callback: () => any, expected?: string) { + try { + callback(); + } catch (e) { + return checkExpectation.call(this, e.message, expected); + } + throw new Error('Expected function to throw, but it did not'); + }, + + async toThrowErrorMatchingSnapshotAsync(callback: () => Promise, expected?: string) { + try { + await callback(); + } catch (e) { + return checkExpectation.call(this, e.message, expected); + } + throw new Error('Expected function to throw, but it did not'); + } +}); diff --git a/tests/expect/matchers.snapshots.js b/tests/expect/matchers.snapshots.js new file mode 100644 index 0000000000000..0f8a5a5030d63 --- /dev/null +++ b/tests/expect/matchers.snapshots.js @@ -0,0 +1,3614 @@ +module.exports[".rejects fails non-promise value \"a\""] = `expect(received).rejects.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has type: string +Received has value: "a"`; + +module.exports[".rejects fails non-promise value [1]"] = `expect(received).rejects.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has type: array +Received has value: [1]`; + +module.exports[".rejects fails non-promise value [Function anonymous]"] = `expect(received).rejects.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has type: function +Received has value: [Function anonymous]`; + +module.exports[".rejects fails non-promise value {\"a\": 1}"] = `expect(received).rejects.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has type: object +Received has value: {"a": 1}`; + +module.exports[".rejects fails non-promise value 4"] = `expect(received).rejects.not.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has type: number +Received has value: 4`; + +module.exports[".rejects fails non-promise value null"] = `expect(received).rejects.not.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has value: null`; + +module.exports[".rejects fails non-promise value true"] = `expect(received).rejects.not.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has type: boolean +Received has value: true`; + +module.exports[".rejects fails non-promise value undefined"] = `expect(received).rejects.not.toBeDefined() + +Matcher error: received value must be a promise or a function returning a promise + +Received has value: undefined`; + +module.exports[".rejects fails for promise that resolves"] = `expect(received).rejects.toBe() + +Received promise resolved instead of rejected +Resolved to value: 4`; + +module.exports[".resolves fails non-promise value \"a\" synchronously"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: string +Received has value: "a"`; + +module.exports[".resolves fails non-promise value \"a\""] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: string +Received has value: "a"`; + +module.exports[".resolves fails non-promise value [1] synchronously"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: array +Received has value: [1]`; + +module.exports[".resolves fails non-promise value [1]"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: array +Received has value: [1]`; + +module.exports[".resolves fails non-promise value [Function anonymous] synchronously"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: function +Received has value: [Function anonymous]`; + +module.exports[".resolves fails non-promise value [Function anonymous]"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: function +Received has value: [Function anonymous]`; + +module.exports[".resolves fails non-promise value {\"a\": 1} synchronously"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: object +Received has value: {"a": 1}`; + +module.exports[".resolves fails non-promise value {\"a\": 1}"] = `expect(received).resolves.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: object +Received has value: {"a": 1}`; + +module.exports[".resolves fails non-promise value 4 synchronously"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: number +Received has value: 4`; + +module.exports[".resolves fails non-promise value 4"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: number +Received has value: 4`; + +module.exports[".resolves fails non-promise value null synchronously"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has value: null`; + +module.exports[".resolves fails non-promise value null"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has value: null`; + +module.exports[".resolves fails non-promise value true synchronously"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: boolean +Received has value: true`; + +module.exports[".resolves fails non-promise value true"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has type: boolean +Received has value: true`; + +module.exports[".resolves fails non-promise value undefined synchronously"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has value: undefined`; + +module.exports[".resolves fails non-promise value undefined"] = `expect(received).resolves.not.toBeDefined() + +Matcher error: received value must be a promise + +Received has value: undefined`; + +module.exports[".resolves fails for promise that rejects"] = `expect(received).resolves.toBe() + +Received promise rejected instead of resolved +Rejected to value: 4`; + +module.exports[".toBe() fails for: 1 and 2 (0)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: 2 +Received: 1`; + +module.exports[".toBe() fails for: true and false (1)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: false +Received: true`; + +module.exports[".toBe() fails for: [Function anonymous] and [Function anonymous] (2)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: [Function anonymous] +Received: serializes to the same string`; + +module.exports[".toBe() fails for: {} and {} (3)"] = `expect(received).toBe(expected) // Object.is equality + +If it should pass with deep equality, replace "toBe" with "toStrictEqual" + +Expected: {} +Received: serializes to the same string`; + +module.exports[".toBe() fails for: {\"a\": 1} and {\"a\": 1} (4)"] = `expect(received).toBe(expected) // Object.is equality + +If it should pass with deep equality, replace "toBe" with "toStrictEqual" + +Expected: {"a": 1} +Received: serializes to the same string`; + +module.exports[".toBe() fails for: {\"a\": 1} and {\"a\": 5} (5)"] = `expect(received).toBe(expected) // Object.is equality + +- Expected - 1 ++ Received + 1 + + Object { +- "a": 5, ++ "a": 1, + }`; + +module.exports[".toBe() fails for: {\"a\": [Function a], \"b\": 2} and {\"a\": Any, \"b\": 2} (6)"] = `expect(received).toBe(expected) // Object.is equality + +If it should pass with deep equality, replace "toBe" with "toStrictEqual" + +Expected: {"a": Any, "b": 2} +Received: {"a": [Function a], "b": 2}`; + +module.exports[".toBe() fails for: {\"a\": undefined, \"b\": 2} and {\"b\": 2} (7)"] = `expect(received).toBe(expected) // Object.is equality + +If it should pass with deep equality, replace "toBe" with "toEqual" + +- Expected - 0 ++ Received + 1 + + Object { ++ "a": undefined, + "b": 2, + }`; + +module.exports[".toBe() fails for: 2020-02-20T00:00:00.000Z and 2020-02-20T00:00:00.000Z (8)"] = `expect(received).toBe(expected) // Object.is equality + +If it should pass with deep equality, replace "toBe" with "toStrictEqual" + +Expected: 2020-02-20T00:00:00.000Z +Received: serializes to the same string`; + +module.exports[".toBe() fails for: 2020-02-21T00:00:00.000Z and 2020-02-20T00:00:00.000Z (9)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: 2020-02-20T00:00:00.000Z +Received: 2020-02-21T00:00:00.000Z`; + +module.exports[".toBe() fails for: /received/ and /expected/ (10)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: /expected/ +Received: /received/`; + +module.exports[".toBe() fails for: Symbol(received) and Symbol(expected) (11)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: Symbol(expected) +Received: Symbol(received)`; + +module.exports[".toBe() fails for: [Error: received] and [Error: expected] (12)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: [Error: expected] +Received: [Error: received]`; + +module.exports[".toBe() fails for: \"abc\" and \"cde\" (13)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: "cde" +Received: "abc"`; + +module.exports[".toBe() fails for: \"painless JavaScript testing\" and \"delightful JavaScript testing\" (14)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: "delightful JavaScript testing" +Received: "painless JavaScript testing"`; + +module.exports[".toBe() fails for: \"\" and \"compare one-line string to empty string\" (15)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: "compare one-line string to empty string" +Received: ""`; + +module.exports[".toBe() fails for: \"with \ntrailing space\" and \"without trailing space\" (16)"] = `expect(received).toBe(expected) // Object.is equality + +- Expected - 1 ++ Received + 2 + +- without trailing space ++ with ++ trailing space`; + +module.exports[".toBe() fails for: \"four\n4\nline\nstring\" and \"3\nline\nstring\" (17)"] = `expect(received).toBe(expected) // Object.is equality + +- Expected - 1 ++ Received + 2 + +- 3 ++ four ++ 4 + line + string`; + +module.exports[".toBe() fails for: [] and [] (18)"] = `expect(received).toBe(expected) // Object.is equality + +If it should pass with deep equality, replace "toBe" with "toStrictEqual" + +Expected: [] +Received: serializes to the same string`; + +module.exports[".toBe() fails for: null and undefined (19)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: undefined +Received: null`; + +module.exports[".toBe() fails for: -0 and 0 (20)"] = `expect(received).toBe(expected) // Object.is equality + +Expected: 0 +Received: -0`; + +module.exports[".toBe() fails for 'false' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not false`; + +module.exports[".toBe() fails for '1' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not 1`; + +module.exports[".toBe() fails for '\"a\"' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not "a"`; + +module.exports[".toBe() fails for 'undefined' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not undefined`; + +module.exports[".toBe() fails for 'null' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not null`; + +module.exports[".toBe() fails for '{}' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not {}`; + +module.exports[".toBe() fails for '[]' with '.not'"] = `expect(received).not.toBe(expected) // Object.is equality + +Expected: not []`; + +module.exports[".toBe() does not crash on circular references"] = `expect(received).toBe(expected) // Object.is equality + +- Expected - 1 ++ Received + 3 + +- Object {} ++ Object { ++ "circular": [Circular], ++ }`; + +module.exports[".toStrictEqual() matches the expected snapshot when it fails"] = `expect(received).toStrictEqual(expected) // deep equality + +- Expected - 4 ++ Received + 1 + + Object { +- "test": TestClassA { +- "a": 1, +- "b": 2, +- }, ++ "test": 2, + }`; + +module.exports[".toStrictEqual() matches the expected snapshot when it fails #1"] = `expect(received).not.toStrictEqual(expected) // deep equality + +Expected: not {"test": {"a": 1, "b": 2}} +`; + +module.exports[".toStrictEqual() displays substring diff"] = `expect(received).toStrictEqual(expected) // deep equality + +Expected: "Another caveat is that Jest will not typecheck your tests." +Received: "Because TypeScript support in Babel is just transpilation, Jest will not type-check your tests as they run."`; + +module.exports[".toStrictEqual() displays substring diff for multiple lines"] = `expect(received).toStrictEqual(expected) // deep equality + +- Expected - 7 ++ Received + 7 + +- 69 | ++ 68 | +- 70 | test('assert.doesNotThrow', () => { ++ 69 | test('assert.doesNotThrow', () => { +- > 71 | assert.doesNotThrow(() => { ++ > 70 | assert.doesNotThrow(() => { + | ^ +- 72 | throw Error('err!'); ++ 71 | throw Error('err!'); +- 73 | }); ++ 72 | }); +- 74 | }); ++ 73 | }); +- at Object.doesNotThrow (__tests__/assertionError.test.js:71:10) ++ at Object.doesNotThrow (__tests__/assertionError.test.js:70:10)`; + +module.exports[".toEqual() {pass: false} expect(true).toEqual(false (0))"] = `expect(received).toEqual(expected) // deep equality + +Expected: false +Received: true`; + +module.exports[".toEqual() {pass: false} expect(1).toEqual(2 (1))"] = `expect(received).toEqual(expected) // deep equality + +Expected: 2 +Received: 1`; + +module.exports[".toEqual() {pass: false} expect(0).toEqual(-0 (2))"] = `expect(received).toEqual(expected) // deep equality + +Expected: -0 +Received: 0`; + +module.exports[".toEqual() {pass: false} expect(0).toEqual(5e-324 (3))"] = `expect(received).toEqual(expected) // deep equality + +Expected: 5e-324 +Received: 0`; + +module.exports[".toEqual() {pass: false} expect(5e-324).toEqual(0 (4))"] = `expect(received).toEqual(expected) // deep equality + +Expected: 0 +Received: 5e-324`; + +module.exports[".toEqual() {pass: false} expect(0).toEqual({} (5))"] = `expect(received).toEqual(expected) // deep equality + +Expected: {} +Received: 0`; + +module.exports[".toEqual() {pass: false} expect({}).toEqual(0 (6))"] = `expect(received).toEqual(expected) // deep equality + +Expected: 0 +Received: {}`; + +module.exports[".toEqual() {pass: false} expect({}).toEqual({} (7))"] = `expect(received).toEqual(expected) // deep equality + +Expected: {} +Received: serializes to the same string`; + +module.exports[".toEqual() {pass: false} expect(\"abc\").toEqual({\"0\": \"a\", \"1\": \"b\", \"2\": \"c\"} (8))"] = `expect(received).toEqual(expected) // deep equality + +Expected: {"0": "a", "1": "b", "2": "c"} +Received: "abc"`; + +module.exports[".toEqual() {pass: false} expect({\"0\": \"a\", \"1\": \"b\", \"2\": \"c\"}).toEqual(\"abc\" (9))"] = `expect(received).toEqual(expected) // deep equality + +Expected: "abc" +Received: {"0": "a", "1": "b", "2": "c"}`; + +module.exports[".toEqual() {pass: false} expect(/abc/gsy).toEqual(/abc/g (10))"] = `expect(received).toEqual(expected) // deep equality + +Expected: /abc/g +Received: /abc/gsy`; + +module.exports[".toEqual() {pass: false} expect({\"a\": 1}).toEqual({\"a\": 2} (11))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "a": 2, ++ "a": 1, + }`; + +module.exports[".toEqual() {pass: false} expect({\"a\": 5}).toEqual({\"b\": 6} (12))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "b": 6, ++ "a": 5, + }`; + +module.exports[".toEqual() {pass: false} expect({\"foo\": {\"bar\": 1}}).toEqual({\"foo\": {}} (13))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 3 + + Object { +- "foo": Object {}, ++ "foo": Object { ++ "bar": 1, ++ }, + }`; + +module.exports[".toEqual() {pass: false} expect({\"getterAndSetter\": {}}).toEqual({\"getterAndSetter\": {\"foo\": \"bar\"}} (14))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + + Object { +- "getterAndSetter": Object { +- "foo": "bar", +- }, ++ "getterAndSetter": Object {}, + }`; + +module.exports[".toEqual() {pass: false} expect({\"frozenGetterAndSetter\": {}}).toEqual({\"frozenGetterAndSetter\": {\"foo\": \"bar\"}} (15))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + + Object { +- "frozenGetterAndSetter": Object { +- "foo": "bar", +- }, ++ "frozenGetterAndSetter": Object {}, + }`; + +module.exports[".toEqual() {pass: false} expect({\"getter\": {}}).toEqual({\"getter\": {\"foo\": \"bar\"}} (16))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + + Object { +- "getter": Object { +- "foo": "bar", +- }, ++ "getter": Object {}, + }`; + +module.exports[".toEqual() {pass: false} expect({\"frozenGetter\": {}}).toEqual({\"frozenGetter\": {\"foo\": \"bar\"}} (17))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + + Object { +- "frozenGetter": Object { +- "foo": "bar", +- }, ++ "frozenGetter": Object {}, + }`; + +module.exports[".toEqual() {pass: false} expect({\"setter\": undefined}).toEqual({\"setter\": {\"foo\": \"bar\"}} (18))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + + Object { +- "setter": Object { +- "foo": "bar", +- }, ++ "setter": undefined, + }`; + +module.exports[".toEqual() {pass: false} expect({\"frozenSetter\": undefined}).toEqual({\"frozenSetter\": {\"foo\": \"bar\"}} (19))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + + Object { +- "frozenSetter": Object { +- "foo": "bar", +- }, ++ "frozenSetter": undefined, + }`; + +module.exports[".toEqual() {pass: false} expect(\"banana\").toEqual(\"apple\" (20))"] = `expect(received).toEqual(expected) // deep equality + +Expected: "apple" +Received: "banana"`; + +module.exports[".toEqual() {pass: false} expect(\"1 234,57 $\").toEqual(\"1 234,57 $\" (21))"] = `expect(received).toEqual(expected) // deep equality + +Expected: "1 234,57 $" +Received: "1 234,57 $"`; + +module.exports[".toEqual() {pass: false} expect(\"type TypeName = T extends Function ? \\\"function\\\" : \\\"object\\\";\").toEqual(\"type TypeName = T extends Function\n? \\\"function\\\"\n: \\\"object\\\";\" (22))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + +- type TypeName = T extends Function +- ? "function" +- : "object"; ++ type TypeName = T extends Function ? "function" : "object";`; + +module.exports[".toEqual() {pass: false} expect(null).toEqual(undefined (23))"] = `expect(received).toEqual(expected) // deep equality + +Expected: undefined +Received: null`; + +module.exports[".toEqual() {pass: false} expect([1]).toEqual([2] (24))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Array [ +- 2, ++ 1, + ]`; + +module.exports[".toEqual() {pass: false} expect([1, 2]).toEqual([2, 1] (25))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Array [ +- 2, + 1, ++ 2, + ]`; + +module.exports[".toEqual() {pass: false} expect(Immutable.List [1]).toEqual(Immutable.List [2] (26))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.List [ +- 2, ++ 1, + ]`; + +module.exports[".toEqual() {pass: false} expect(Immutable.List [1, 2]).toEqual(Immutable.List [2, 1] (27))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.List [ +- 2, + 1, ++ 2, + ]`; + +module.exports[".toEqual() {pass: false} expect(Map {}).toEqual(Set {} (28))"] = `expect(received).toEqual(expected) // deep equality + +Expected: Set {} +Received: Map {}`; + +module.exports[".toEqual() {pass: false} expect(Set {1, 2}).toEqual(Set {} (29))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 4 + +- Set {} ++ Set { ++ 1, ++ 2, ++ }`; + +module.exports[".toEqual() {pass: false} expect(Set {1, 2}).toEqual(Set {1, 2, 3} (30))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 0 + + Set { + 1, + 2, +- 3, + }`; + +module.exports[".toEqual() {pass: false} expect(Set {[1], [2]}).toEqual(Set {[1], [2], [3]} (31))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 0 + +@@ -3,9 +3,6 @@ + 1, + ], + Array [ + 2, + ], +- Array [ +- 3, +- ], + }`; + +module.exports[".toEqual() {pass: false} expect(Set {[1], [2]}).toEqual(Set {[1], [2], [2]} (32))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 0 + +@@ -3,9 +3,6 @@ + 1, + ], + Array [ + 2, + ], +- Array [ +- 2, +- ], + }`; + +module.exports[".toEqual() {pass: false} expect(Set {Set {1}, Set {2}}).toEqual(Set {Set {1}, Set {3}} (33))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Set { + Set { + 1, + }, + Set { +- 3, ++ 2, + }, + }`; + +module.exports[".toEqual() {pass: false} expect(Immutable.Set [1, 2]).toEqual(Immutable.Set [] (34))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 4 + +- Immutable.Set [] ++ Immutable.Set [ ++ 1, ++ 2, ++ ]`; + +module.exports[".toEqual() {pass: false} expect(Immutable.Set [1, 2]).toEqual(Immutable.Set [1, 2, 3] (35))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 0 + + Immutable.Set [ + 1, + 2, +- 3, + ]`; + +module.exports[".toEqual() {pass: false} expect(Immutable.OrderedSet [1, 2]).toEqual(Immutable.OrderedSet [2, 1] (36))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.OrderedSet [ +- 2, + 1, ++ 2, + ]`; + +module.exports[".toEqual() {pass: false} expect(Map {1 => \"one\", 2 => \"two\"}).toEqual(Map {1 => \"one\"} (37))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 0 ++ Received + 1 + + Map { + 1 => "one", ++ 2 => "two", + }`; + +module.exports[".toEqual() {pass: false} expect(Map {\"a\" => 0}).toEqual(Map {\"b\" => 0} (38))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Map { +- "b" => 0, ++ "a" => 0, + }`; + +module.exports[".toEqual() {pass: false} expect(Map {\"v\" => 1}).toEqual(Map {\"v\" => 2} (39))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Map { +- "v" => 2, ++ "v" => 1, + }`; + +module.exports[".toEqual() {pass: false} expect(Map {[\"v\"] => 1}).toEqual(Map {[\"v\"] => 2} (40))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Map { + Array [ + "v", +- ] => 2, ++ ] => 1, + }`; + +module.exports[".toEqual() {pass: false} expect(Map {[1] => Map {[1] => \"one\"}}).toEqual(Map {[1] => Map {[1] => \"two\"}} (41))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + +@@ -2,8 +2,8 @@ + Array [ + 1, + ] => Map { + Array [ + 1, +- ] => "two", ++ ] => "one", + }, + }`; + +module.exports[".toEqual() {pass: false} expect(Immutable.Map {\"a\": 0}).toEqual(Immutable.Map {\"b\": 0} (42))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.Map { +- "b": 0, ++ "a": 0, + }`; + +module.exports[".toEqual() {pass: false} expect(Immutable.Map {\"v\": 1}).toEqual(Immutable.Map {\"v\": 2} (43))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.Map { +- "v": 2, ++ "v": 1, + }`; + +module.exports[".toEqual() {pass: false} expect(Immutable.OrderedMap {1: \"one\", 2: \"two\"}).toEqual(Immutable.OrderedMap {2: \"two\", 1: \"one\"} (44))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.OrderedMap { +- 2: "two", + 1: "one", ++ 2: "two", + }`; + +module.exports[".toEqual() {pass: false} expect(Immutable.Map {\"1\": Immutable.Map {\"2\": {\"a\": 99}}}).toEqual(Immutable.Map {\"1\": Immutable.Map {\"2\": {\"a\": 11}}} (45))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Immutable.Map { + "1": Immutable.Map { + "2": Object { +- "a": 11, ++ "a": 99, + }, + }, + }`; + +module.exports[".toEqual() {pass: false} expect([97, 98, 99]).toEqual([97, 98, 100] (46))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Uint8Array [ + 97, + 98, +- 100, ++ 99, + ]`; + +module.exports[".toEqual() {pass: false} expect({\"a\": 1, \"b\": 2}).toEqual(ObjectContaining {\"a\": 2} (47))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 2 ++ Received + 3 + +- ObjectContaining { +- "a": 2, ++ Object { ++ "a": 1, ++ "b": 2, + }`; + +module.exports[".toEqual() {pass: false} expect(false).toEqual(ObjectContaining {\"a\": 2} (48))"] = `expect(received).toEqual(expected) // deep equality + +Expected: ObjectContaining {"a": 2} +Received: false`; + +module.exports[".toEqual() {pass: false} expect([1, 3]).toEqual(ArrayContaining [1, 2] (49))"] = `expect(received).toEqual(expected) // deep equality + +Expected: ArrayContaining [1, 2] +Received: [1, 3]`; + +module.exports[".toEqual() {pass: false} expect(1).toEqual(ArrayContaining [1, 2] (50))"] = `expect(received).toEqual(expected) // deep equality + +Expected: ArrayContaining [1, 2] +Received: 1`; + +module.exports[".toEqual() {pass: false} expect(\"abd\").toEqual(StringContaining \"bc\" (51))"] = `expect(received).toEqual(expected) // deep equality + +Expected: StringContaining "bc" +Received: "abd"`; + +module.exports[".toEqual() {pass: false} expect(\"abd\").toEqual(StringMatching /bc/i (52))"] = `expect(received).toEqual(expected) // deep equality + +Expected: StringMatching /bc/i +Received: "abd"`; + +module.exports[".toEqual() {pass: false} expect(undefined).toEqual(Anything (53))"] = `expect(received).toEqual(expected) // deep equality + +Expected: Anything +Received: undefined`; + +module.exports[".toEqual() {pass: false} expect(undefined).toEqual(Any (54))"] = `expect(received).toEqual(expected) // deep equality + +Expected: Any +Received: undefined`; + +module.exports[".toEqual() {pass: false} expect(\"Eve\").toEqual({\"asymmetricMatch\": [Function asymmetricMatch]} (55))"] = `expect(received).toEqual(expected) // deep equality + +Expected: {"asymmetricMatch": [Function asymmetricMatch]} +Received: "Eve"`; + +module.exports[".toEqual() {pass: false} expect({\"target\": {\"nodeType\": 1, \"value\": \"a\"}}).toEqual({\"target\": {\"nodeType\": 1, \"value\": \"b\"}} (56))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { + "target": Object { + "nodeType": 1, +- "value": "b", ++ "value": "a", + }, + }`; + +module.exports[".toEqual() {pass: false} expect({\"nodeName\": \"div\", \"nodeType\": 1}).toEqual({\"nodeName\": \"p\", \"nodeType\": 1} (57))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "nodeName": "p", ++ "nodeName": "div", + "nodeType": 1, + }`; + +module.exports[".toEqual() {pass: false} expect({Symbol(foo): 1, Symbol(bar): 2}).toEqual({Symbol(foo): Any, Symbol(bar): 1} (58))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { + Symbol(foo): Any, +- Symbol(bar): 1, ++ Symbol(bar): 2, + }`; + +module.exports[".toEqual() {pass: false} expect([, , 1, ]).toEqual([, , 2, ] (59))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Array [ + undefined, + undefined, +- 2, ++ 1, + undefined, + ]`; + +module.exports[".toEqual() {pass: false} expect([]).toEqual([] (60))"] = `expect(received).toEqual(expected) // deep equality + +Expected: [] +Received: serializes to the same string`; + +module.exports[".toEqual() {pass: false} expect([]).toEqual([1] (61))"] = `expect(received).toEqual(expected) // deep equality + +- Expected - 3 ++ Received + 1 + +- Array [ +- 1, +- ] ++ Array []`; + +module.exports[".toEqual() {pass: false} expect([]).toEqual([] (62))"] = `expect(received).toEqual(expected) // deep equality + +Expected: [] +Received: serializes to the same string`; + +module.exports[".toEqual() {pass: false} expect([]).toEqual([] (63))"] = `expect(received).toEqual(expected) // deep equality + +Expected: [] +Received: serializes to the same string`; + +module.exports[".toEqual() {pass: true} expect(true).not.toEqual(true) (0)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not true +`; + +module.exports[".toEqual() {pass: true} expect(1).not.toEqual(1) (1)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not 1 +`; + +module.exports[".toEqual() {pass: true} expect(NaN).not.toEqual(NaN) (2)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not NaN +`; + +module.exports[".toEqual() {pass: true} expect(0).not.toEqual(0) (3)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not 0 +`; + +module.exports[".toEqual() {pass: true} expect(0).not.toEqual(0) (4)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not 0 +`; + +module.exports[".toEqual() {pass: true} expect({}).not.toEqual({}) (5)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {} +`; + +module.exports[".toEqual() {pass: true} expect(\"abc\").not.toEqual(\"abc\") (6)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not "abc" +`; + +module.exports[".toEqual() {pass: true} expect(\"abc\").not.toEqual(\"abc\") (7)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not "abc" +`; + +module.exports[".toEqual() {pass: true} expect(\"abc\").not.toEqual(\"abc\") (8)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not "abc" +`; + +module.exports[".toEqual() {pass: true} expect([1]).not.toEqual([1]) (9)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1] +`; + +module.exports[".toEqual() {pass: true} expect([1, 2]).not.toEqual([1, 2]) (10)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1, 2] +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.List [1]).not.toEqual(Immutable.List [1]) (11)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.List [1] +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.List [1, 2]).not.toEqual(Immutable.List [1, 2]) (12)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.List [1, 2] +`; + +module.exports[".toEqual() {pass: true} expect({}).not.toEqual({}) (13)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {} +`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 99}).not.toEqual({\"a\": 99}) (14)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 99} +`; + +module.exports[".toEqual() {pass: true} expect(Set {}).not.toEqual(Set {}) (15)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {} +`; + +module.exports[".toEqual() {pass: true} expect(Set {1, 2}).not.toEqual(Set {1, 2}) (16)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {1, 2} +`; + +module.exports[".toEqual() {pass: true} expect(Set {1, 2}).not.toEqual(Set {2, 1}) (17)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {2, 1} +Received: Set {1, 2}`; + +module.exports[".toEqual() {pass: true} expect(Set {[1], [2]}).not.toEqual(Set {[2], [1]}) (18)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {[2], [1]} +Received: Set {[1], [2]}`; + +module.exports[".toEqual() {pass: true} expect(Set {Set {[1]}, Set {[2]}}).not.toEqual(Set {Set {[2]}, Set {[1]}}) (19)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {Set {[2]}, Set {[1]}} +Received: Set {Set {[1]}, Set {[2]}}`; + +module.exports[".toEqual() {pass: true} expect(Set {[1], [2], [3], [3]}).not.toEqual(Set {[3], [3], [2], [1]}) (20)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {[3], [3], [2], [1]} +Received: Set {[1], [2], [3], [3]}`; + +module.exports[".toEqual() {pass: true} expect(Set {{\"a\": 1}, {\"b\": 2}}).not.toEqual(Set {{\"b\": 2}, {\"a\": 1}}) (21)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Set {{"b": 2}, {"a": 1}} +Received: Set {{"a": 1}, {"b": 2}}`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Set []).not.toEqual(Immutable.Set []) (22)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Set [] +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Set [1, 2]).not.toEqual(Immutable.Set [1, 2]) (23)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Set [1, 2] +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Set [1, 2]).not.toEqual(Immutable.Set [2, 1]) (24)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Set [2, 1] +Received: Immutable.Set [1, 2]`; + +module.exports[".toEqual() {pass: true} expect(Immutable.OrderedSet []).not.toEqual(Immutable.OrderedSet []) (25)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.OrderedSet [] +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.OrderedSet [1, 2]).not.toEqual(Immutable.OrderedSet [1, 2]) (26)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.OrderedSet [1, 2] +`; + +module.exports[".toEqual() {pass: true} expect(Map {}).not.toEqual(Map {}) (27)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {} +`; + +module.exports[".toEqual() {pass: true} expect(Map {1 => \"one\", 2 => \"two\"}).not.toEqual(Map {1 => \"one\", 2 => \"two\"}) (28)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {1 => "one", 2 => "two"} +`; + +module.exports[".toEqual() {pass: true} expect(Map {1 => \"one\", 2 => \"two\"}).not.toEqual(Map {2 => \"two\", 1 => \"one\"}) (29)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {2 => "two", 1 => "one"} +Received: Map {1 => "one", 2 => "two"}`; + +module.exports[".toEqual() {pass: true} expect(Map {[1] => \"one\", [2] => \"two\", [3] => \"three\", [3] => \"four\"}).not.toEqual(Map {[3] => \"three\", [3] => \"four\", [2] => \"two\", [1] => \"one\"}) (30)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {[3] => "three", [3] => "four", [2] => "two", [1] => "one"} +Received: Map {[1] => "one", [2] => "two", [3] => "three", [3] => "four"}`; + +module.exports[".toEqual() {pass: true} expect(Map {[1] => Map {[1] => \"one\"}, [2] => Map {[2] => \"two\"}}).not.toEqual(Map {[2] => Map {[2] => \"two\"}, [1] => Map {[1] => \"one\"}}) (31)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {[2] => Map {[2] => "two"}, [1] => Map {[1] => "one"}} +Received: Map {[1] => Map {[1] => "one"}, [2] => Map {[2] => "two"}}`; + +module.exports[".toEqual() {pass: true} expect(Map {[1] => \"one\", [2] => \"two\"}).not.toEqual(Map {[2] => \"two\", [1] => \"one\"}) (32)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {[2] => "two", [1] => "one"} +Received: Map {[1] => "one", [2] => "two"}`; + +module.exports[".toEqual() {pass: true} expect(Map {{\"a\": 1} => \"one\", {\"b\": 2} => \"two\"}).not.toEqual(Map {{\"b\": 2} => \"two\", {\"a\": 1} => \"one\"}) (33)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {{"b": 2} => "two", {"a": 1} => "one"} +Received: Map {{"a": 1} => "one", {"b": 2} => "two"}`; + +module.exports[".toEqual() {pass: true} expect(Map {1 => [\"one\"], 2 => [\"two\"]}).not.toEqual(Map {2 => [\"two\"], 1 => [\"one\"]}) (34)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Map {2 => ["two"], 1 => ["one"]} +Received: Map {1 => ["one"], 2 => ["two"]}`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Map {}).not.toEqual(Immutable.Map {}) (35)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Map {} +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Map {1: \"one\", 2: \"two\"}).not.toEqual(Immutable.Map {1: \"one\", 2: \"two\"}) (36)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Map {1: "one", 2: "two"} +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Map {1: \"one\", 2: \"two\"}).not.toEqual(Immutable.Map {2: \"two\", 1: \"one\"}) (37)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Map {2: "two", 1: "one"} +Received: Immutable.Map {1: "one", 2: "two"}`; + +module.exports[".toEqual() {pass: true} expect(Immutable.OrderedMap {1: \"one\", 2: \"two\"}).not.toEqual(Immutable.OrderedMap {1: \"one\", 2: \"two\"}) (38)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.OrderedMap {1: "one", 2: "two"} +`; + +module.exports[".toEqual() {pass: true} expect(Immutable.Map {\"1\": Immutable.Map {\"2\": {\"a\": 99}}}).not.toEqual(Immutable.Map {\"1\": Immutable.Map {\"2\": {\"a\": 99}}}) (39)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Immutable.Map {"1": Immutable.Map {"2": {"a": 99}}} +`; + +module.exports[".toEqual() {pass: true} expect([97, 98, 99]).not.toEqual([97, 98, 99]) (40)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [97, 98, 99] +`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": 2}).not.toEqual(ObjectContaining {\"a\": 1}) (41)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not ObjectContaining {"a": 1} +Received: {"a": 1, "b": 2}`; + +module.exports[".toEqual() {pass: true} expect([1, 2, 3]).not.toEqual(ArrayContaining [2, 3]) (42)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not ArrayContaining [2, 3] +Received: [1, 2, 3]`; + +module.exports[".toEqual() {pass: true} expect(\"abcd\").not.toEqual(StringContaining \"bc\") (43)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not StringContaining "bc" +Received: "abcd"`; + +module.exports[".toEqual() {pass: true} expect(\"abcd\").not.toEqual(StringMatching /bc/) (44)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not StringMatching /bc/ +Received: "abcd"`; + +module.exports[".toEqual() {pass: true} expect(true).not.toEqual(Anything) (45)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Anything +Received: true`; + +module.exports[".toEqual() {pass: true} expect([Function anonymous]).not.toEqual(Any) (46)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not Any +Received: [Function anonymous]`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": [Function b], \"c\": true}).not.toEqual({\"a\": 1, \"b\": Any, \"c\": Anything}) (47)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1, "b": Any, "c": Anything} +Received: {"a": 1, "b": [Function b], "c": true}`; + +module.exports[".toEqual() {pass: true} expect(\"Alice\").not.toEqual({\"asymmetricMatch\": [Function asymmetricMatch]}) (48)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"asymmetricMatch": [Function asymmetricMatch]} +Received: "Alice"`; + +module.exports[".toEqual() {pass: true} expect({\"nodeName\": \"div\", \"nodeType\": 1}).not.toEqual({\"nodeName\": \"div\", \"nodeType\": 1}) (49)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"nodeName": "div", "nodeType": 1} +`; + +module.exports[".toEqual() {pass: true} expect({Symbol(foo): 1, Symbol(bar): 2}).not.toEqual({Symbol(foo): Any, Symbol(bar): 2}) (50)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {Symbol(foo): Any, Symbol(bar): 2} +Received: {Symbol(foo): 1, Symbol(bar): 2}`; + +module.exports[".toEqual() {pass: true} expect([, , 1, ]).not.toEqual([, , 1, ]) (51)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [, , 1, ] +`; + +module.exports[".toEqual() {pass: true} expect([, , 1, , ]).not.toEqual([, , 1, undefined, ]) (52)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [, , 1, undefined, ] +Received: [, , 1, , ]`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": [Function b]}).not.toEqual({\"a\": 1, \"b\": optionalFn<>}) (53)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1, "b": optionalFn<>} +Received: {"a": 1, "b": [Function b]}`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": optionalFn<>}).not.toEqual({\"a\": 1, \"b\": [Function b]}) (54)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1, "b": [Function b]} +Received: {"a": 1, "b": optionalFn<>}`; + +module.exports[".toEqual() {pass: true} expect([1, [Function anonymous]]).not.toEqual([1, optionalFn<>]) (55)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1, optionalFn<>] +Received: [1, [Function anonymous]]`; + +module.exports[".toEqual() {pass: true} expect([1, optionalFn<>]).not.toEqual([1, [Function anonymous]]) (56)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1, [Function anonymous]] +Received: [1, optionalFn<>]`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": undefined}).not.toEqual({\"a\": 1, \"b\": optionalFn<>}) (57)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1, "b": optionalFn<>} +Received: {"a": 1, "b": undefined}`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": optionalFn<>}).not.toEqual({\"a\": 1, \"b\": undefined}) (58)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1, "b": undefined} +Received: {"a": 1, "b": optionalFn<>}`; + +module.exports[".toEqual() {pass: true} expect([1, undefined]).not.toEqual([1, optionalFn<>]) (59)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1, optionalFn<>] +Received: [1, undefined]`; + +module.exports[".toEqual() {pass: true} expect([1, optionalFn<>]).not.toEqual([1, undefined]) (60)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1, undefined] +Received: [1, optionalFn<>]`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1}).not.toEqual({\"a\": 1, \"b\": optionalFn<>}) (61)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1, "b": optionalFn<>} +Received: {"a": 1}`; + +module.exports[".toEqual() {pass: true} expect({\"a\": 1, \"b\": optionalFn<>}).not.toEqual({\"a\": 1}) (62)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not {"a": 1} +Received: {"a": 1, "b": optionalFn<>}`; + +module.exports[".toEqual() {pass: true} expect([1]).not.toEqual([1, optionalFn<>]) (63)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1, optionalFn<>] +Received: [1]`; + +module.exports[".toEqual() {pass: true} expect([1, optionalFn<>]).not.toEqual([1]) (64)"] = `expect(received).not.toEqual(expected) // deep equality + +Expected: not [1] +Received: [1, optionalFn<>]`; + +module.exports[".toBeInstanceOf() passing Map {} and [Function Map] (0)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor: not Map +`; + +module.exports[".toBeInstanceOf() passing [] and [Function Array] (1)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor: not Array +`; + +module.exports[".toBeInstanceOf() passing {} and [Function A] (2)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor: not A +`; + +module.exports[".toBeInstanceOf() passing {} and [Function B] (3)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor: not B +Received constructor: C extends B +`; + +module.exports[".toBeInstanceOf() passing {} and [Function B] (4)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor: not B +Received constructor: E extends … extends B +`; + +module.exports[".toBeInstanceOf() passing {} and [Function anonymous] (5)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor name is an empty string +Received constructor: SubHasNameProp +`; + +module.exports[".toBeInstanceOf() passing {} and [Function B] (6)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor: not B +Received constructor name is not a string +`; + +module.exports[".toBeInstanceOf() passing {} and [Function name() {}] (7)"] = `expect(received).not.toBeInstanceOf(expected) + +Expected constructor name is not a string +`; + +module.exports[".toBeInstanceOf() failing \"a\" and [Function String] (0)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: String + +Received value has no prototype +Received value: "a"`; + +module.exports[".toBeInstanceOf() failing 1 and [Function Number] (1)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: Number + +Received value has no prototype +Received value: 1`; + +module.exports[".toBeInstanceOf() failing true and [Function Boolean] (2)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: Boolean + +Received value has no prototype +Received value: true`; + +module.exports[".toBeInstanceOf() failing {} and [Function B] (3)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: B +Received constructor: A +`; + +module.exports[".toBeInstanceOf() failing {} and [Function A] (4)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: A + +Received value has no prototype +Received value: {}`; + +module.exports[".toBeInstanceOf() failing undefined and [Function String] (5)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: String + +Received value has no prototype +Received value: undefined`; + +module.exports[".toBeInstanceOf() failing null and [Function String] (6)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: String + +Received value has no prototype +Received value: null`; + +module.exports[".toBeInstanceOf() failing /\\w+/ and [Function anonymous] (7)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor name is an empty string +Received constructor: RegExp +`; + +module.exports[".toBeInstanceOf() failing {} and [Function RegExp] (8)"] = `expect(received).toBeInstanceOf(expected) + +Expected constructor: RegExp +Received constructor name is an empty string +`; + +module.exports[".toBeInstanceOf() throws if constructor is not a function"] = `expect(received).toBeInstanceOf(expected) + +Matcher error: expected value must be a function + +Expected has type: number +Expected has value: 4`; + +module.exports[".toBeTruthy(), .toBeFalsy() does not accept arguments"] = `expect(received).toBeTruthy() + +Matcher error: this matcher must not have an expected argument + +Expected has value: null`; + +module.exports[".toBeTruthy(), .toBeFalsy() does not accept arguments #1"] = `expect(received).not.toBeFalsy() + +Matcher error: this matcher must not have an expected argument + +Expected has value: null`; + +module.exports[".toBeTruthy(), .toBeFalsy() '{}' is truthy"] = `expect(received).not.toBeTruthy() + +Received: {}`; + +module.exports[".toBeTruthy(), .toBeFalsy() '{}' is truthy #1"] = `expect(received).toBeFalsy() + +Received: {}`; + +module.exports[".toBeTruthy(), .toBeFalsy() '[]' is truthy"] = `expect(received).not.toBeTruthy() + +Received: []`; + +module.exports[".toBeTruthy(), .toBeFalsy() '[]' is truthy #1"] = `expect(received).toBeFalsy() + +Received: []`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'true' is truthy"] = `expect(received).not.toBeTruthy() + +Received: true`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'true' is truthy #1"] = `expect(received).toBeFalsy() + +Received: true`; + +module.exports[".toBeTruthy(), .toBeFalsy() '1' is truthy"] = `expect(received).not.toBeTruthy() + +Received: 1`; + +module.exports[".toBeTruthy(), .toBeFalsy() '1' is truthy #1"] = `expect(received).toBeFalsy() + +Received: 1`; + +module.exports[".toBeTruthy(), .toBeFalsy() '\"a\"' is truthy"] = `expect(received).not.toBeTruthy() + +Received: "a"`; + +module.exports[".toBeTruthy(), .toBeFalsy() '\"a\"' is truthy #1"] = `expect(received).toBeFalsy() + +Received: "a"`; + +module.exports[".toBeTruthy(), .toBeFalsy() '0.5' is truthy"] = `expect(received).not.toBeTruthy() + +Received: 0.5`; + +module.exports[".toBeTruthy(), .toBeFalsy() '0.5' is truthy #1"] = `expect(received).toBeFalsy() + +Received: 0.5`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'Map {}' is truthy"] = `expect(received).not.toBeTruthy() + +Received: Map {}`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'Map {}' is truthy #1"] = `expect(received).toBeFalsy() + +Received: Map {}`; + +module.exports[".toBeTruthy(), .toBeFalsy() '[Function anonymous]' is truthy"] = `expect(received).not.toBeTruthy() + +Received: [Function anonymous]`; + +module.exports[".toBeTruthy(), .toBeFalsy() '[Function anonymous]' is truthy #1"] = `expect(received).toBeFalsy() + +Received: [Function anonymous]`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'Infinity' is truthy"] = `expect(received).not.toBeTruthy() + +Received: Infinity`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'Infinity' is truthy #1"] = `expect(received).toBeFalsy() + +Received: Infinity`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'false' is falsy"] = `expect(received).toBeTruthy() + +Received: false`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'false' is falsy #1"] = `expect(received).not.toBeFalsy() + +Received: false`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'null' is falsy"] = `expect(received).toBeTruthy() + +Received: null`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'null' is falsy #1"] = `expect(received).not.toBeFalsy() + +Received: null`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'NaN' is falsy"] = `expect(received).toBeTruthy() + +Received: NaN`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'NaN' is falsy #1"] = `expect(received).not.toBeFalsy() + +Received: NaN`; + +module.exports[".toBeTruthy(), .toBeFalsy() '0' is falsy"] = `expect(received).toBeTruthy() + +Received: 0`; + +module.exports[".toBeTruthy(), .toBeFalsy() '0' is falsy #1"] = `expect(received).not.toBeFalsy() + +Received: 0`; + +module.exports[".toBeTruthy(), .toBeFalsy() '\"\"' is falsy"] = `expect(received).toBeTruthy() + +Received: ""`; + +module.exports[".toBeTruthy(), .toBeFalsy() '\"\"' is falsy #1"] = `expect(received).not.toBeFalsy() + +Received: ""`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'undefined' is falsy"] = `expect(received).toBeTruthy() + +Received: undefined`; + +module.exports[".toBeTruthy(), .toBeFalsy() 'undefined' is falsy #1"] = `expect(received).not.toBeFalsy() + +Received: undefined`; + +module.exports[".toBeNaN() {pass: true} expect(NaN).toBeNaN()"] = `expect(received).not.toBeNaN() + +Received: NaN`; + +module.exports[".toBeNaN() {pass: true} expect(NaN).toBeNaN() #1"] = `expect(received).not.toBeNaN() + +Received: NaN`; + +module.exports[".toBeNaN() {pass: true} expect(NaN).toBeNaN() #2"] = `expect(received).not.toBeNaN() + +Received: NaN`; + +module.exports[".toBeNaN() {pass: true} expect(NaN).toBeNaN() #3"] = `expect(received).not.toBeNaN() + +Received: NaN`; + +module.exports[".toBeNaN() throws"] = `expect(received).toBeNaN() + +Received: 1`; + +module.exports[".toBeNaN() throws #1"] = `expect(received).toBeNaN() + +Received: ""`; + +module.exports[".toBeNaN() throws #2"] = `expect(received).toBeNaN() + +Received: null`; + +module.exports[".toBeNaN() throws #3"] = `expect(received).toBeNaN() + +Received: undefined`; + +module.exports[".toBeNaN() throws #4"] = `expect(received).toBeNaN() + +Received: {}`; + +module.exports[".toBeNaN() throws #5"] = `expect(received).toBeNaN() + +Received: []`; + +module.exports[".toBeNaN() throws #6"] = `expect(received).toBeNaN() + +Received: 0.2`; + +module.exports[".toBeNaN() throws #7"] = `expect(received).toBeNaN() + +Received: 0`; + +module.exports[".toBeNaN() throws #8"] = `expect(received).toBeNaN() + +Received: Infinity`; + +module.exports[".toBeNaN() throws #9"] = `expect(received).toBeNaN() + +Received: -Infinity`; + +module.exports[".toBeNull() fails for '{}'"] = `expect(received).toBeNull() + +Received: {}`; + +module.exports[".toBeNull() fails for '[]'"] = `expect(received).toBeNull() + +Received: []`; + +module.exports[".toBeNull() fails for 'true'"] = `expect(received).toBeNull() + +Received: true`; + +module.exports[".toBeNull() fails for '1'"] = `expect(received).toBeNull() + +Received: 1`; + +module.exports[".toBeNull() fails for '\"a\"'"] = `expect(received).toBeNull() + +Received: "a"`; + +module.exports[".toBeNull() fails for '0.5'"] = `expect(received).toBeNull() + +Received: 0.5`; + +module.exports[".toBeNull() fails for 'Map {}'"] = `expect(received).toBeNull() + +Received: Map {}`; + +module.exports[".toBeNull() fails for '[Function anonymous]'"] = `expect(received).toBeNull() + +Received: [Function anonymous]`; + +module.exports[".toBeNull() fails for 'Infinity'"] = `expect(received).toBeNull() + +Received: Infinity`; + +module.exports[".toBeNull() fails for null with .not"] = `expect(received).not.toBeNull() + +Received: null`; + +module.exports[".toBeDefined(), .toBeUndefined() '{}' is defined"] = `expect(received).not.toBeDefined() + +Received: {}`; + +module.exports[".toBeDefined(), .toBeUndefined() '{}' is defined #1"] = `expect(received).toBeUndefined() + +Received: {}`; + +module.exports[".toBeDefined(), .toBeUndefined() '[]' is defined"] = `expect(received).not.toBeDefined() + +Received: []`; + +module.exports[".toBeDefined(), .toBeUndefined() '[]' is defined #1"] = `expect(received).toBeUndefined() + +Received: []`; + +module.exports[".toBeDefined(), .toBeUndefined() 'true' is defined"] = `expect(received).not.toBeDefined() + +Received: true`; + +module.exports[".toBeDefined(), .toBeUndefined() 'true' is defined #1"] = `expect(received).toBeUndefined() + +Received: true`; + +module.exports[".toBeDefined(), .toBeUndefined() '1' is defined"] = `expect(received).not.toBeDefined() + +Received: 1`; + +module.exports[".toBeDefined(), .toBeUndefined() '1' is defined #1"] = `expect(received).toBeUndefined() + +Received: 1`; + +module.exports[".toBeDefined(), .toBeUndefined() '\"a\"' is defined"] = `expect(received).not.toBeDefined() + +Received: "a"`; + +module.exports[".toBeDefined(), .toBeUndefined() '\"a\"' is defined #1"] = `expect(received).toBeUndefined() + +Received: "a"`; + +module.exports[".toBeDefined(), .toBeUndefined() '0.5' is defined"] = `expect(received).not.toBeDefined() + +Received: 0.5`; + +module.exports[".toBeDefined(), .toBeUndefined() '0.5' is defined #1"] = `expect(received).toBeUndefined() + +Received: 0.5`; + +module.exports[".toBeDefined(), .toBeUndefined() 'Map {}' is defined"] = `expect(received).not.toBeDefined() + +Received: Map {}`; + +module.exports[".toBeDefined(), .toBeUndefined() 'Map {}' is defined #1"] = `expect(received).toBeUndefined() + +Received: Map {}`; + +module.exports[".toBeDefined(), .toBeUndefined() '[Function anonymous]' is defined"] = `expect(received).not.toBeDefined() + +Received: [Function anonymous]`; + +module.exports[".toBeDefined(), .toBeUndefined() '[Function anonymous]' is defined #1"] = `expect(received).toBeUndefined() + +Received: [Function anonymous]`; + +module.exports[".toBeDefined(), .toBeUndefined() 'Infinity' is defined"] = `expect(received).not.toBeDefined() + +Received: Infinity`; + +module.exports[".toBeDefined(), .toBeUndefined() 'Infinity' is defined #1"] = `expect(received).toBeUndefined() + +Received: Infinity`; + +module.exports[".toBeDefined(), .toBeUndefined() undefined is undefined"] = `expect(received).toBeDefined() + +Received: undefined`; + +module.exports[".toBeDefined(), .toBeUndefined() undefined is undefined #1"] = `expect(received).not.toBeUndefined() + +Received: undefined`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > 2 +Received: 1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < 2 +Received: 1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > 1 +Received: 2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < 1 +Received: 2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= 2 +Received: 1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 2 +Received: 1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 1 +Received: 2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [1, 2] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= 1 +Received: 2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > Infinity +Received: -Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < Infinity +Received: -Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > -Infinity +Received: Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < -Infinity +Received: Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= Infinity +Received: -Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= Infinity +Received: -Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= -Infinity +Received: Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [-Infinity, Infinity] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= -Infinity +Received: Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > 1.7976931348623157e+308 +Received: 5e-324`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < 1.7976931348623157e+308 +Received: 5e-324`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > 5e-324 +Received: 1.7976931348623157e+308`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < 5e-324 +Received: 1.7976931348623157e+308`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= 1.7976931348623157e+308 +Received: 5e-324`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 1.7976931348623157e+308 +Received: 5e-324`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 5e-324 +Received: 1.7976931348623157e+308`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [5e-324, 1.7976931348623157e+308] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= 5e-324 +Received: 1.7976931348623157e+308`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > 34 +Received: 17`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < 34 +Received: 17`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > 17 +Received: 34`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < 17 +Received: 34`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= 34 +Received: 17`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 34 +Received: 17`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 17 +Received: 34`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [17, 34] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= 17 +Received: 34`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > 7 +Received: 3`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < 7 +Received: 3`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > 3 +Received: 7`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < 3 +Received: 7`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= 7 +Received: 3`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 7 +Received: 3`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 3 +Received: 7`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [3, 7] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= 3 +Received: 7`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > 18 +Received: 9`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < 18 +Received: 9`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > 9 +Received: 18`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < 9 +Received: 18`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= 18 +Received: 9`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 18 +Received: 9`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 9 +Received: 18`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [9, 18] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= 9 +Received: 18`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2]"] = `expect(received).toBeGreaterThan(expected) + +Expected: > 0.2 +Received: 0.1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #1"] = `expect(received).not.toBeLessThan(expected) + +Expected: not < 0.2 +Received: 0.1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #2"] = `expect(received).not.toBeGreaterThan(expected) + +Expected: not > 0.1 +Received: 0.2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #3"] = `expect(received).toBeLessThan(expected) + +Expected: < 0.1 +Received: 0.2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #4"] = `expect(received).toBeGreaterThanOrEqual(expected) + +Expected: >= 0.2 +Received: 0.1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #5"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 0.2 +Received: 0.1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #6"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 0.1 +Received: 0.2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() throws: [0.1, 0.2] #7"] = `expect(received).toBeLessThanOrEqual(expected) + +Expected: <= 0.1 +Received: 0.2`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [1, 1]"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 1 +Received: 1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [1, 1] #1"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 1 +Received: 1`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [5e-324, 5e-324]"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 5e-324 +Received: 5e-324`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [5e-324, 5e-324] #1"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 5e-324 +Received: 5e-324`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [1.7976931348623157e+308, 1.7976931348623157e+308]"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= 1.7976931348623157e+308 +Received: 1.7976931348623157e+308`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [1.7976931348623157e+308, 1.7976931348623157e+308] #1"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= 1.7976931348623157e+308 +Received: 1.7976931348623157e+308`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [Infinity, Infinity]"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= Infinity +Received: Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [Infinity, Infinity] #1"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= Infinity +Received: Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [-Infinity, -Infinity]"] = `expect(received).not.toBeGreaterThanOrEqual(expected) + +Expected: not >= -Infinity +Received: -Infinity`; + +module.exports[".toBeGreaterThan(), .toBeLessThan(), .toBeGreaterThanOrEqual(), .toBeLessThanOrEqual() equal numbers: [-Infinity, -Infinity] #1"] = `expect(received).not.toBeLessThanOrEqual(expected) + +Expected: not <= -Infinity +Received: -Infinity`; + +module.exports[".toContain(), .toContainEqual() '[1, 2, 3, 4]' contains '1'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not 1 +Received array: [1, 2, 3, 4]`; + +module.exports[".toContain(), .toContainEqual() '[\"a\", \"b\", \"c\", \"d\"]' contains '\"a\"'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not "a" +Received array: ["a", "b", "c", "d"]`; + +module.exports[".toContain(), .toContainEqual() '[undefined, null]' contains 'null'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not null +Received array: [undefined, null]`; + +module.exports[".toContain(), .toContainEqual() '[undefined, null]' contains 'undefined'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not undefined +Received array: [undefined, null]`; + +module.exports[".toContain(), .toContainEqual() '[Symbol(a)]' contains 'Symbol(a)'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not Symbol(a) +Received array: [Symbol(a)]`; + +module.exports[".toContain(), .toContainEqual() '\"abcdef\"' contains '\"abc\"'"] = `expect(received).not.toContain(expected) // indexOf + +Expected substring: not "abc" +Received string: "abcdef"`; + +module.exports[".toContain(), .toContainEqual() '\"11112111\"' contains '\"2\"'"] = `expect(received).not.toContain(expected) // indexOf + +Expected substring: not "2" +Received string: "11112111"`; + +module.exports[".toContain(), .toContainEqual() 'Set {\"abc\", \"def\"}' contains '\"abc\"'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not "abc" +Received set: Set {"abc", "def"}`; + +module.exports[".toContain(), .toContainEqual() '[0, 1]' contains '1'"] = `expect(received).not.toContain(expected) // indexOf + +Expected value: not 1 +Received object: [0, 1]`; + +module.exports[".toContain(), .toContainEqual() '[1, 2, 3]' does not contain '4'"] = `expect(received).toContain(expected) // indexOf + +Expected value: 4 +Received array: [1, 2, 3]`; + +module.exports[".toContain(), .toContainEqual() '[null, undefined]' does not contain '1'"] = `expect(received).toContain(expected) // indexOf + +Expected value: 1 +Received array: [null, undefined]`; + +module.exports[".toContain(), .toContainEqual() '[{}, []]' does not contain '[]'"] = `expect(received).toContain(expected) // indexOf + +Expected value: [] +Received array: [{}, []] + +Looks like you wanted to test for object/array equality with the stricter \`toContain\` matcher. You probably need to use \`toContainEqual\` instead.`; + +module.exports[".toContain(), .toContainEqual() '[{}, []]' does not contain '{}'"] = `expect(received).toContain(expected) // indexOf + +Expected value: {} +Received array: [{}, []] + +Looks like you wanted to test for object/array equality with the stricter \`toContain\` matcher. You probably need to use \`toContainEqual\` instead.`; + +module.exports[".toContain(), .toContainEqual() error cases"] = `expect(received).toContain(expected) // indexOf + +Matcher error: received value must not be null nor undefined + +Received has value: null`; + +module.exports[".toContain(), .toContainEqual() error cases #1"] = `expect(-0).toContain(0) // indexOf + +Matcher error: expected value must be a string if received value is a string + +Expected has type: number +Expected has value: -0 +Received has type: string +Received has value: "-0"`; + +module.exports[".toContain(), .toContainEqual() error cases #2"] = `expect(null).toContain(null) // indexOf + +Matcher error: expected value must be a string if received value is a string + +Expected has value: null +Received has type: string +Received has value: "null"`; + +module.exports[".toContain(), .toContainEqual() error cases #3"] = `expect(undefined).toContain(undefined) // indexOf + +Matcher error: expected value must be a string if received value is a string + +Expected has value: undefined +Received has type: string +Received has value: "undefined"`; + +module.exports[".toContain(), .toContainEqual() error cases #4"] = `expect(false).toContain(false) // indexOf + +Matcher error: expected value must be a string if received value is a string + +Expected has type: boolean +Expected has value: false +Received has type: string +Received has value: "false"`; + +module.exports[".toContain(), .toContainEqual() '[1, 2, 3, 4]' contains a value equal to '1'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not 1 +Received array: [1, 2, 3, 4]`; + +module.exports[".toContain(), .toContainEqual() '[\"a\", \"b\", \"c\", \"d\"]' contains a value equal to '\"a\"'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not "a" +Received array: ["a", "b", "c", "d"]`; + +module.exports[".toContain(), .toContainEqual() '[undefined, null]' contains a value equal to 'null'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not null +Received array: [undefined, null]`; + +module.exports[".toContain(), .toContainEqual() '[undefined, null]' contains a value equal to 'undefined'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not undefined +Received array: [undefined, null]`; + +module.exports[".toContain(), .toContainEqual() '[Symbol(a)]' contains a value equal to 'Symbol(a)'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not Symbol(a) +Received array: [Symbol(a)]`; + +module.exports[".toContain(), .toContainEqual() '[{\"a\": \"b\"}, {\"a\": \"c\"}]' contains a value equal to '{\"a\": \"b\"}'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not {"a": "b"} +Received array: [{"a": "b"}, {"a": "c"}]`; + +module.exports[".toContain(), .toContainEqual() 'Set {1, 2, 3, 4}' contains a value equal to '1'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not 1 +Received set: Set {1, 2, 3, 4}`; + +module.exports[".toContain(), .toContainEqual() '[0, 1]' contains a value equal to '1'"] = `expect(received).not.toContainEqual(expected) // deep equality + +Expected value: not 1 +Received object: [0, 1]`; + +module.exports[".toContain(), .toContainEqual() '[{\"a\": \"b\"}, {\"a\": \"c\"}]' does not contain a value equal to'{\"a\": \"d\"}'"] = `expect(received).toContainEqual(expected) // deep equality + +Expected value: {"a": "d"} +Received array: [{"a": "b"}, {"a": "c"}]`; + +module.exports[".toContain(), .toContainEqual() error cases for toContainEqual"] = `expect(received).toContainEqual(expected) // deep equality + +Matcher error: received value must not be null nor undefined + +Received has value: null`; + +module.exports[".toBeCloseTo {pass: true} expect(0).toBeCloseTo(0)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not 0 +`; + +module.exports[".toBeCloseTo {pass: true} expect(0).toBeCloseTo(0.001)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not 0.001 +Received: 0 + +Expected precision: 2 +Expected difference: not < 0.005 +Received difference: 0.001`; + +module.exports[".toBeCloseTo {pass: true} expect(1.23).toBeCloseTo(1.229)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not 1.229 +Received: 1.23 + +Expected precision: 2 +Expected difference: not < 0.005 +Received difference: 0.0009999999999998899`; + +module.exports[".toBeCloseTo {pass: true} expect(1.23).toBeCloseTo(1.226)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not 1.226 +Received: 1.23 + +Expected precision: 2 +Expected difference: not < 0.005 +Received difference: 0.0040000000000000036`; + +module.exports[".toBeCloseTo {pass: true} expect(1.23).toBeCloseTo(1.225)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not 1.225 +Received: 1.23 + +Expected precision: 2 +Expected difference: not < 0.005 +Received difference: 0.004999999999999893`; + +module.exports[".toBeCloseTo {pass: true} expect(1.23).toBeCloseTo(1.234)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not 1.234 +Received: 1.23 + +Expected precision: 2 +Expected difference: not < 0.005 +Received difference: 0.0040000000000000036`; + +module.exports[".toBeCloseTo {pass: true} expect(Infinity).toBeCloseTo(Infinity)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not Infinity +`; + +module.exports[".toBeCloseTo {pass: true} expect(-Infinity).toBeCloseTo(-Infinity)"] = `expect(received).not.toBeCloseTo(expected) + +Expected: not -Infinity +`; + +module.exports[".toBeCloseTo {pass: false} expect(0).toBeCloseTo(0.01)"] = `expect(received).toBeCloseTo(expected) + +Expected: 0.01 +Received: 0 + +Expected precision: 2 +Expected difference: < 0.005 +Received difference: 0.01`; + +module.exports[".toBeCloseTo {pass: false} expect(1).toBeCloseTo(1.23)"] = `expect(received).toBeCloseTo(expected) + +Expected: 1.23 +Received: 1 + +Expected precision: 2 +Expected difference: < 0.005 +Received difference: 0.22999999999999998`; + +module.exports[".toBeCloseTo {pass: false} expect(1.23).toBeCloseTo(1.2249999)"] = `expect(received).toBeCloseTo(expected) + +Expected: 1.2249999 +Received: 1.23 + +Expected precision: 2 +Expected difference: < 0.005 +Received difference: 0.005000099999999952`; + +module.exports[".toBeCloseTo {pass: false} expect(Infinity).toBeCloseTo(-Infinity)"] = `expect(received).toBeCloseTo(expected) + +Expected: -Infinity +Received: Infinity + +Expected precision: 2 +Expected difference: < 0.005 +Received difference: Infinity`; + +module.exports[".toBeCloseTo {pass: false} expect(Infinity).toBeCloseTo(1.23)"] = `expect(received).toBeCloseTo(expected) + +Expected: 1.23 +Received: Infinity + +Expected precision: 2 +Expected difference: < 0.005 +Received difference: Infinity`; + +module.exports[".toBeCloseTo {pass: false} expect(-Infinity).toBeCloseTo(-1.23)"] = `expect(received).toBeCloseTo(expected) + +Expected: -1.23 +Received: -Infinity + +Expected precision: 2 +Expected difference: < 0.005 +Received difference: Infinity`; + +module.exports[".toBeCloseTo {pass: false} expect(3.141592e-7).toBeCloseTo(3e-7, 8)"] = `expect(received).toBeCloseTo(expected, precision) + +Expected: 3e-7 +Received: 3.141592e-7 + +Expected precision: 8 +Expected difference: < 5e-9 +Received difference: 1.4159200000000025e-8`; + +module.exports[".toBeCloseTo {pass: false} expect(56789).toBeCloseTo(51234, -4)"] = `expect(received).toBeCloseTo(expected, precision) + +Expected: 51234 +Received: 56789 + +Expected precision: -4 +Expected difference: < 5000 +Received difference: 5555`; + +module.exports[".toBeCloseTo {pass: true} expect(0).toBeCloseTo(0.1, 0)"] = `expect(received).not.toBeCloseTo(expected, precision) + +Expected: not 0.1 +Received: 0 + +Expected precision: 0 +Expected difference: not < 0.5 +Received difference: 0.1`; + +module.exports[".toBeCloseTo {pass: true} expect(0).toBeCloseTo(0.0001, 3)"] = `expect(received).not.toBeCloseTo(expected, precision) + +Expected: not 0.0001 +Received: 0 + +Expected precision: 3 +Expected difference: not < 0.0005 +Received difference: 0.0001`; + +module.exports[".toBeCloseTo {pass: true} expect(0).toBeCloseTo(0.000004, 5)"] = `expect(received).not.toBeCloseTo(expected, precision) + +Expected: not 0.000004 +Received: 0 + +Expected precision: 5 +Expected difference: not < 0.000005 +Received difference: 0.000004`; + +module.exports[".toBeCloseTo {pass: true} expect(2.0000002).toBeCloseTo(2, 5)"] = `expect(received).not.toBeCloseTo(expected, precision) + +Expected: not 2 +Received: 2.0000002 + +Expected precision: 5 +Expected difference: not < 5e-6 +Received difference: 2.0000000011677344e-7`; + +module.exports[".toBeCloseTo throws: Matcher error promise empty isNot false received"] = `expect(received).toBeCloseTo(expected, precision) + +Matcher error: received value must be a number + +Received has type: string +Received has value: ""`; + +module.exports[".toBeCloseTo throws: Matcher error promise empty isNot true expected"] = `expect(received).not.toBeCloseTo(expected) + +Matcher error: expected value must be a number + +Expected has value: undefined`; + +module.exports[".toBeCloseTo throws: Matcher error promise rejects isNot false expected"] = `callback is not a function`; + +module.exports[".toBeCloseTo throws: Matcher error promise rejects isNot true received"] = `callback is not a function`; + +module.exports[".toBeCloseTo throws: Matcher error promise resolves isNot false received"] = `callback is not a function`; + +module.exports[".toBeCloseTo throws: Matcher error promise resolves isNot true expected"] = `callback is not a function`; + +module.exports[".toMatch() {pass: true} expect(foo).toMatch(foo)"] = `expect(received).not.toMatch(expected) + +Expected substring: not "foo" +Received string: "foo"`; + +module.exports[".toMatch() {pass: true} expect(Foo bar).toMatch(/^foo/i)"] = `expect(received).not.toMatch(expected) + +Expected pattern: not /^foo/i +Received string: "Foo bar"`; + +module.exports[".toMatch() throws: [bar, foo]"] = `expect(received).toMatch(expected) + +Expected substring: "foo" +Received string: "bar"`; + +module.exports[".toMatch() throws: [bar, /foo/]"] = `expect(received).toMatch(expected) + +Expected pattern: /foo/ +Received string: "bar"`; + +module.exports[".toMatch() throws if non String actual value passed: [1, \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has type: number +Received has value: 1`; + +module.exports[".toMatch() throws if non String actual value passed: [{}, \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has type: object +Received has value: {}`; + +module.exports[".toMatch() throws if non String actual value passed: [[], \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has type: array +Received has value: []`; + +module.exports[".toMatch() throws if non String actual value passed: [true, \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has type: boolean +Received has value: true`; + +module.exports[".toMatch() throws if non String actual value passed: [/foo/i, \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has type: regexp +Received has value: /foo/i`; + +module.exports[".toMatch() throws if non String actual value passed: [[Function anonymous], \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has type: function +Received has value: [Function anonymous]`; + +module.exports[".toMatch() throws if non String actual value passed: [undefined, \"foo\"]"] = `expect(received).toMatch(expected) + +Matcher error: received value must be a string + +Received has value: undefined`; + +module.exports[".toMatch() throws if non String/RegExp expected value passed: [\"foo\", 1]"] = `expect(received).toMatch(expected) + +Matcher error: expected value must be a string or regular expression + +Expected has type: number +Expected has value: 1`; + +module.exports[".toMatch() throws if non String/RegExp expected value passed: [\"foo\", {}]"] = `expect(received).toMatch(expected) + +Matcher error: expected value must be a string or regular expression + +Expected has type: object +Expected has value: {}`; + +module.exports[".toMatch() throws if non String/RegExp expected value passed: [\"foo\", []]"] = `expect(received).toMatch(expected) + +Matcher error: expected value must be a string or regular expression + +Expected has type: array +Expected has value: []`; + +module.exports[".toMatch() throws if non String/RegExp expected value passed: [\"foo\", true]"] = `expect(received).toMatch(expected) + +Matcher error: expected value must be a string or regular expression + +Expected has type: boolean +Expected has value: true`; + +module.exports[".toMatch() throws if non String/RegExp expected value passed: [\"foo\", [Function anonymous]]"] = `expect(received).toMatch(expected) + +Matcher error: expected value must be a string or regular expression + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports[".toMatch() throws if non String/RegExp expected value passed: [\"foo\", undefined]"] = `expect(received).toMatch(expected) + +Matcher error: expected value must be a string or regular expression + +Expected has value: undefined`; + +module.exports[".toHaveLength {pass: true} expect([1, 2]).toHaveLength(2)"] = `expect(received).not.toHaveLength(expected) + +Expected length: not 2 +Received array: [1, 2]`; + +module.exports[".toHaveLength {pass: true} expect([]).toHaveLength(0)"] = `expect(received).not.toHaveLength(expected) + +Expected length: not 0 +Received array: []`; + +module.exports[".toHaveLength {pass: true} expect([\"a\", \"b\"]).toHaveLength(2)"] = `expect(received).not.toHaveLength(expected) + +Expected length: not 2 +Received array: ["a", "b"]`; + +module.exports[".toHaveLength {pass: true} expect(\"abc\").toHaveLength(3)"] = `expect(received).not.toHaveLength(expected) + +Expected length: not 3 +Received string: "abc"`; + +module.exports[".toHaveLength {pass: true} expect(\"\").toHaveLength(0)"] = `expect(received).not.toHaveLength(expected) + +Expected length: not 0 +Received string: ""`; + +module.exports[".toHaveLength {pass: true} expect([Function anonymous]).toHaveLength(0)"] = `expect(received).not.toHaveLength(expected) + +Expected length: not 0 +Received function: [Function anonymous]`; + +module.exports[".toHaveLength {pass: false} expect([1, 2]).toHaveLength(3)"] = `expect(received).toHaveLength(expected) + +Expected length: 3 +Received length: 2 +Received array: [1, 2]`; + +module.exports[".toHaveLength {pass: false} expect([]).toHaveLength(1)"] = `expect(received).toHaveLength(expected) + +Expected length: 1 +Received length: 0 +Received array: []`; + +module.exports[".toHaveLength {pass: false} expect([\"a\", \"b\"]).toHaveLength(99)"] = `expect(received).toHaveLength(expected) + +Expected length: 99 +Received length: 2 +Received array: ["a", "b"]`; + +module.exports[".toHaveLength {pass: false} expect(\"abc\").toHaveLength(66)"] = `expect(received).toHaveLength(expected) + +Expected length: 66 +Received length: 3 +Received string: "abc"`; + +module.exports[".toHaveLength {pass: false} expect(\"\").toHaveLength(1)"] = `expect(received).toHaveLength(expected) + +Expected length: 1 +Received length: 0 +Received string: ""`; + +module.exports[".toHaveLength error cases"] = `expect(received).toHaveLength(expected) + +Matcher error: received value must have a length property whose value must be a number + +Received has type: object +Received has value: {"a": 9}`; + +module.exports[".toHaveLength error cases #1"] = `expect(received).toHaveLength(expected) + +Matcher error: received value must have a length property whose value must be a number + +Received has type: number +Received has value: 0`; + +module.exports[".toHaveLength error cases #2"] = `expect(received).not.toHaveLength(expected) + +Matcher error: received value must have a length property whose value must be a number + +Received has value: undefined`; + +module.exports[".toHaveLength matcher error expected length not number"] = `expect(received).not.toHaveLength(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "3"`; + +module.exports[".toHaveLength matcher error expected length number Infinity"] = `callback is not a function`; + +module.exports[".toHaveLength matcher error expected length number NaN"] = `callback is not a function`; + +module.exports[".toHaveLength matcher error expected length number float"] = `callback is not a function`; + +module.exports[".toHaveLength matcher error expected length number negative integer"] = `callback is not a function`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a.b.c.d', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a.b.c.d" + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a,b,c,d', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: ["a", "b", "c", "d"] + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a.b.c.d\": 1}).toHaveProperty('a.b.c.d', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: ["a.b.c.d"] + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": [1, 2, 3]}}).toHaveProperty('a,b,1', 2)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: ["a", "b", 1] + +Expected value: not 2`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": [1, 2, 3]}}).toHaveProperty('a,b,1', Any)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: ["a", "b", 1] + +Expected value: not Any +Received value: 2`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": 0}).toHaveProperty('a', 0)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a" + +Expected value: not 0`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": undefined}}).toHaveProperty('a.b', undefined)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a.b" + +Expected value: not undefined`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": {\"c\": 5}}}).toHaveProperty('a.b', {\"c\": 5})"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a.b" + +Expected value: not {"c": 5}`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": [{\"c\": [{\"d\": 1}]}]}}).toHaveProperty('a.b[0].c[0].d', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a.b[0].c[0].d" + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": [{\"c\": {\"d\": [{\"e\": 1}, {\"f\": 2}]}}]}}).toHaveProperty('a.b[0].c.d[1].f', 2)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a.b[0].c.d[1].f" + +Expected value: not 2`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": [[{\"c\": [{\"d\": 1}]}]]}}).toHaveProperty('a.b[0][0].c[0].d', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a.b[0][0].c[0].d" + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"property\": 1}).toHaveProperty('property', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "property" + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"val\": undefined}).toHaveProperty('a', undefined)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a" + +Expected value: not undefined`; + +module.exports[".toHaveProperty() {pass: true} expect({\"val\": undefined}).toHaveProperty('b', \"b\")"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "b" + +Expected value: not "b"`; + +module.exports[".toHaveProperty() {pass: true} expect({\"val\": undefined}).toHaveProperty('setter', undefined)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "setter" + +Expected value: not undefined`; + +module.exports[".toHaveProperty() {pass: true} expect({\"val\": true}).toHaveProperty('a', undefined)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "a" + +Expected value: not undefined`; + +module.exports[".toHaveProperty() {pass: true} expect({\"val\": true}).toHaveProperty('c', \"c\")"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "c" + +Expected value: not "c"`; + +module.exports[".toHaveProperty() {pass: true} expect({\"val\": true}).toHaveProperty('val', true)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "val" + +Expected value: not true`; + +module.exports[".toHaveProperty() {pass: true} expect({\"nodeName\": \"DIV\"}).toHaveProperty('nodeType', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "nodeType" + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: true} expect(\"\").toHaveProperty('length', 0)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "length" + +Expected value: not 0`; + +module.exports[".toHaveProperty() {pass: true} expect([Function memoized]).toHaveProperty('memo', [])"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "memo" + +Expected value: not []`; + +module.exports[".toHaveProperty() {pass: true} expect({\"\": 1}).toHaveProperty('', 1)"] = `expect(received).not.toHaveProperty(path, value) + +Expected path: "" + +Expected value: not 1`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a.b.ttt.d', 1) (0)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.ttt.d" +Received path: "a.b" + +Expected value: 1 +Received value: {"c": {"d": 1}}`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a.b.c.d', 2) (1)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.c.d" + +Expected value: 2 +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a.b.c.d\": 1}).toHaveProperty('a.b.c.d', 2) (2)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.c.d" +Received path: [] + +Expected value: 2 +Received value: {"a.b.c.d": 1}`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a.b.c.d\": 1}).toHaveProperty('a.b.c.d', 2) (3)"] = `expect(received).toHaveProperty(path, value) + +Expected path: ["a.b.c.d"] + +Expected value: 2 +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect({\"children\": [\"\\\"That cartoon\\\"\"], \"props\": null, \"type\": \"p\"}).toHaveProperty('children,0', \"\\\"That cat cartoon\\\"\") (4)"] = `expect(received).toHaveProperty(path, value) + +Expected path: ["children", 0] + +Expected value: "\\"That cat cartoon\\"" +Received value: "\\"That cartoon\\""`; + +module.exports[".toHaveProperty() {pass: false} expect({\"children\": [\"Roses are red.\nViolets are blue.\nTesting with Jest is good for you.\"], \"props\": null, \"type\": \"pre\"}).toHaveProperty('children,0', \"Roses are red, violets are blue.\nTesting with Jest\nIs good for you.\") (5)"] = `expect(received).toHaveProperty(path, value) + +Expected path: ["children", 0] + +- Expected value - 3 ++ Received value + 3 + +- Roses are red, violets are blue. ++ Roses are red. ++ Violets are blue. +- Testing with Jest +- Is good for you. ++ Testing with Jest is good for you.`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a,b,c,d', 2) (6)"] = `expect(received).toHaveProperty(path, value) + +Expected path: ["a", "b", "c", "d"] + +Expected value: 2 +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": {}}}}).toHaveProperty('a.b.c.d', 1) (7)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.c.d" +Received path: "a.b.c" + +Expected value: 1 +Received value: {}`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": 1}).toHaveProperty('a.b.c.d', 5) (8)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.c.d" +Received path: "a" + +Expected value: 5 +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect({}).toHaveProperty('a', \"test\") (9)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a" +Received path: [] + +Expected value: "test" +Received value: {}`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": 3}}).toHaveProperty('a.b', undefined) (10)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b" + +Expected value: undefined +Received value: 3`; + +module.exports[".toHaveProperty() {pass: false} expect(1).toHaveProperty('a.b.c', \"test\") (11)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.c" +Received path: [] + +Expected value: "test" +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect(\"abc\").toHaveProperty('a.b.c', {\"a\": 5}) (12)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b.c" +Received path: [] + +Expected value: {"a": 5} +Received value: "abc"`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": 5}}}).toHaveProperty('a.b', {\"c\": 4}) (13)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b" + +- Expected value - 1 ++ Received value + 1 + + Object { +- "c": 4, ++ "c": 5, + }`; + +module.exports[".toHaveProperty() {pass: false} expect({\"val\": undefined}).toHaveProperty('a', \"a\") (14)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a" + +Expected value: "a" +Received value: undefined`; + +module.exports[".toHaveProperty() {pass: false} expect({\"val\": undefined}).toHaveProperty('b', undefined) (15)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "b" + +Expected value: undefined +Received value: "b"`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {}}).toHaveProperty('a.b', undefined) (16)"] = `expect(received).toHaveProperty(path, value) + +Expected path: "a.b" +Received path: "a" + +Expected value: undefined +Received value: {}`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a.b.c.d')"] = `expect(received).not.toHaveProperty(path) + +Expected path: not "a.b.c.d" + +Received value: 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": {\"c\": {\"d\": 1}}}}).toHaveProperty('a,b,c,d')"] = `expect(received).not.toHaveProperty(path) + +Expected path: not ["a", "b", "c", "d"] + +Received value: 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a.b.c.d\": 1}).toHaveProperty('a.b.c.d')"] = `expect(received).not.toHaveProperty(path) + +Expected path: not ["a.b.c.d"] + +Received value: 1`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": [1, 2, 3]}}).toHaveProperty('a,b,1')"] = `expect(received).not.toHaveProperty(path) + +Expected path: not ["a", "b", 1] + +Received value: 2`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": 0}).toHaveProperty('a')"] = `expect(received).not.toHaveProperty(path) + +Expected path: not "a" + +Received value: 0`; + +module.exports[".toHaveProperty() {pass: true} expect({\"a\": {\"b\": undefined}}).toHaveProperty('a.b')"] = `expect(received).not.toHaveProperty(path) + +Expected path: not "a.b" + +Received value: undefined`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": {}}}}).toHaveProperty('a.b.c.d')"] = `expect(received).toHaveProperty(path) + +Expected path: "a.b.c.d" +Received path: "a.b.c" + +Received value: {}`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": {\"b\": {\"c\": {}}}}).toHaveProperty('.a.b.c')"] = `expect(received).toHaveProperty(path) + +Expected path: ".a.b.c" +Received path: [] + +Received value: {"a": {"b": {"c": {}}}}`; + +module.exports[".toHaveProperty() {pass: false} expect({\"a\": 1}).toHaveProperty('a.b.c.d')"] = `expect(received).toHaveProperty(path) + +Expected path: "a.b.c.d" +Received path: "a" + +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect({}).toHaveProperty('a')"] = `expect(received).toHaveProperty(path) + +Expected path: "a" +Received path: [] + +Received value: {}`; + +module.exports[".toHaveProperty() {pass: false} expect(1).toHaveProperty('a.b.c')"] = `expect(received).toHaveProperty(path) + +Expected path: "a.b.c" +Received path: [] + +Received value: 1`; + +module.exports[".toHaveProperty() {pass: false} expect(\"abc\").toHaveProperty('a.b.c')"] = `expect(received).toHaveProperty(path) + +Expected path: "a.b.c" +Received path: [] + +Received value: "abc"`; + +module.exports[".toHaveProperty() {pass: false} expect(false).toHaveProperty('key')"] = `expect(received).toHaveProperty(path) + +Expected path: "key" +Received path: [] + +Received value: false`; + +module.exports[".toHaveProperty() {pass: false} expect(0).toHaveProperty('key')"] = `expect(received).toHaveProperty(path) + +Expected path: "key" +Received path: [] + +Received value: 0`; + +module.exports[".toHaveProperty() {pass: false} expect(\"\").toHaveProperty('key')"] = `expect(received).toHaveProperty(path) + +Expected path: "key" +Received path: [] + +Received value: ""`; + +module.exports[".toHaveProperty() {pass: false} expect(Symbol()).toHaveProperty('key')"] = `expect(received).toHaveProperty(path) + +Expected path: "key" +Received path: [] + +Received value: Symbol()`; + +module.exports[".toHaveProperty() {pass: false} expect({\"key\": 1}).toHaveProperty('not')"] = `expect(received).toHaveProperty(path) + +Expected path: "not" +Received path: [] + +Received value: {"key": 1}`; + +module.exports[".toHaveProperty() {error} expect(null).toHaveProperty('a.b')"] = `expect(received).toHaveProperty(path) + +Matcher error: received value must not be null nor undefined + +Received has value: null`; + +module.exports[".toHaveProperty() {error} expect(undefined).toHaveProperty('a')"] = `expect(received).toHaveProperty(path) + +Matcher error: received value must not be null nor undefined + +Received has value: undefined`; + +module.exports[".toHaveProperty() {error} expect({\"a\": {\"b\": {}}}).toHaveProperty('undefined')"] = `expect(received).toHaveProperty(path) + +Matcher error: expected path must be a string or array + +Expected has value: undefined`; + +module.exports[".toHaveProperty() {error} expect({\"a\": {\"b\": {}}}).toHaveProperty('null')"] = `expect(received).toHaveProperty(path) + +Matcher error: expected path must be a string or array + +Expected has value: null`; + +module.exports[".toHaveProperty() {error} expect({\"a\": {\"b\": {}}}).toHaveProperty('1')"] = `expect(received).toHaveProperty(path) + +Matcher error: expected path must be a string or array + +Expected has type: number +Expected has value: 1`; + +module.exports[".toHaveProperty() {error} expect({}).toHaveProperty('')"] = `expect(received).toHaveProperty(path) + +Matcher error: expected path must not be an empty array + +Expected has type: array +Expected has value: []`; + +module.exports["toMatchObject() circular references simple circular references {pass: true} expect({\"a\": \"hello\", \"ref\": [Circular]}).toMatchObject({})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {} +Received: {"a": "hello", "ref": [Circular]}`; + +module.exports["toMatchObject() circular references simple circular references {pass: true} expect({\"a\": \"hello\", \"ref\": [Circular]}).toMatchObject({\"a\": \"hello\", \"ref\": [Circular]})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "hello", "ref": [Circular]}`; + +module.exports["toMatchObject() circular references simple circular references {pass: false} expect({}).toMatchObject({\"a\": \"hello\", \"ref\": [Circular]})"] = `expect(received).toMatchObject(expected) + +- Expected - 4 ++ Received + 1 + +- Object { +- "a": "hello", +- "ref": [Circular], +- } ++ Object {}`; + +module.exports["toMatchObject() circular references simple circular references {pass: false} expect({\"a\": \"hello\", \"ref\": [Circular]}).toMatchObject({\"a\": \"world\", \"ref\": [Circular]})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": "world", ++ "a": "hello", + "ref": [Circular], + }`; + +module.exports["toMatchObject() circular references simple circular references {pass: false} expect({\"ref\": \"not a ref\"}).toMatchObject({\"a\": \"hello\", \"ref\": [Circular]})"] = `expect(received).toMatchObject(expected) + +- Expected - 2 ++ Received + 1 + + Object { +- "a": "hello", +- "ref": [Circular], ++ "ref": "not a ref", + }`; + +module.exports["toMatchObject() circular references transitive circular references {pass: true} expect({\"a\": \"hello\", \"nestedObj\": {\"parentObj\": [Circular]}}).toMatchObject({})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {} +Received: {"a": "hello", "nestedObj": {"parentObj": [Circular]}}`; + +module.exports["toMatchObject() circular references transitive circular references {pass: true} expect({\"a\": \"hello\", \"nestedObj\": {\"parentObj\": [Circular]}}).toMatchObject({\"a\": \"hello\", \"nestedObj\": {\"parentObj\": [Circular]}})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "hello", "nestedObj": {"parentObj": [Circular]}}`; + +module.exports["toMatchObject() circular references transitive circular references {pass: false} expect({}).toMatchObject({\"a\": \"hello\", \"nestedObj\": {\"parentObj\": [Circular]}})"] = `expect(received).toMatchObject(expected) + +- Expected - 6 ++ Received + 1 + +- Object { +- "a": "hello", +- "nestedObj": Object { +- "parentObj": [Circular], +- }, +- } ++ Object {}`; + +module.exports["toMatchObject() circular references transitive circular references {pass: false} expect({\"a\": \"world\", \"nestedObj\": {\"parentObj\": [Circular]}}).toMatchObject({\"a\": \"hello\", \"nestedObj\": {\"parentObj\": [Circular]}})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": "hello", ++ "a": "world", + "nestedObj": Object { + "parentObj": [Circular], + }, + }`; + +module.exports["toMatchObject() circular references transitive circular references {pass: false} expect({\"nestedObj\": {\"parentObj\": \"not the parent ref\"}}).toMatchObject({\"a\": \"hello\", \"nestedObj\": {\"parentObj\": [Circular]}})"] = `expect(received).toMatchObject(expected) + +- Expected - 2 ++ Received + 1 + + Object { +- "a": "hello", + "nestedObj": Object { +- "parentObj": [Circular], ++ "parentObj": "not the parent ref", + }, + }`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"c\": \"d\"}).toMatchObject({\"a\": \"b\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "b"} +Received: {"a": "b", "c": "d"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"c\": \"d\"}).toMatchObject({\"a\": \"b\", \"c\": \"d\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "b", "c": "d"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"t\": {\"x\": {\"r\": \"r\"}, \"z\": \"z\"}}).toMatchObject({\"a\": \"b\", \"t\": {\"z\": \"z\"}})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "b", "t": {"z": "z"}} +Received: {"a": "b", "t": {"x": {"r": "r"}, "z": "z"}}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"t\": {\"x\": {\"r\": \"r\"}, \"z\": \"z\"}}).toMatchObject({\"t\": {\"x\": {\"r\": \"r\"}}})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"t": {"x": {"r": "r"}}} +Received: {"a": "b", "t": {"x": {"r": "r"}, "z": "z"}}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": [3, 4, 5], \"b\": \"b\"}).toMatchObject({\"a\": [3, 4, 5]})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": [3, 4, 5]} +Received: {"a": [3, 4, 5], "b": "b"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": [3, 4, 5, \"v\"], \"b\": \"b\"}).toMatchObject({\"a\": [3, 4, 5, \"v\"]})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": [3, 4, 5, "v"]} +Received: {"a": [3, 4, 5, "v"], "b": "b"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": 1, \"c\": 2}).toMatchObject({\"a\": Any})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": Any} +Received: {"a": 1, "c": 2}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": {\"x\": \"x\", \"y\": \"y\"}}).toMatchObject({\"a\": {\"x\": Any}})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": {"x": Any}} +Received: {"a": {"x": "x", "y": "y"}}`; + +module.exports["toMatchObject() {pass: true} expect(Set {1, 2}).toMatchObject(Set {1, 2})"] = `expect(received).not.toMatchObject(expected) + +Expected: not Set {1, 2}`; + +module.exports["toMatchObject() {pass: true} expect(Set {1, 2}).toMatchObject(Set {2, 1})"] = `expect(received).not.toMatchObject(expected) + +Expected: not Set {2, 1} +Received: Set {1, 2}`; + +module.exports["toMatchObject() {pass: true} expect(2015-11-30T00:00:00.000Z).toMatchObject(2015-11-30T00:00:00.000Z)"] = `expect(received).not.toMatchObject(expected) + +Expected: not 2015-11-30T00:00:00.000Z`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": 2015-11-30T00:00:00.000Z, \"b\": \"b\"}).toMatchObject({\"a\": 2015-11-30T00:00:00.000Z})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": 2015-11-30T00:00:00.000Z} +Received: {"a": 2015-11-30T00:00:00.000Z, "b": "b"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": null, \"b\": \"b\"}).toMatchObject({\"a\": null})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": null} +Received: {"a": null, "b": "b"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": undefined, \"b\": \"b\"}).toMatchObject({\"a\": undefined})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": undefined} +Received: {"a": undefined, "b": "b"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": [{\"a\": \"a\", \"b\": \"b\"}]}).toMatchObject({\"a\": [{\"a\": \"a\"}]})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": [{"a": "a"}]} +Received: {"a": [{"a": "a", "b": "b"}]}`; + +module.exports["toMatchObject() {pass: true} expect([1, 2]).toMatchObject([1, 2])"] = `expect(received).not.toMatchObject(expected) + +Expected: not [1, 2]`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": undefined}).toMatchObject({\"a\": undefined})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": undefined}`; + +module.exports["toMatchObject() {pass: true} expect([]).toMatchObject([])"] = `expect(received).not.toMatchObject(expected) + +Expected: not []`; + +module.exports["toMatchObject() {pass: true} expect([Error: foo]).toMatchObject([Error: foo])"] = `expect(received).not.toMatchObject(expected) + +Expected: not [Error: foo]`; + +module.exports["toMatchObject() {pass: true} expect([Error: bar]).toMatchObject({\"message\": \"bar\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"message": "bar"} +Received: [Error: bar]`; + +module.exports["toMatchObject() {pass: true} expect({}).toMatchObject({\"a\": undefined, \"b\": \"b\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": undefined, "b": "b"} +Received: {}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\"}).toMatchObject({\"a\": \"b\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "b"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"c\": \"d\", Symbol(jest): \"jest\"}).toMatchObject({\"a\": \"b\", Symbol(jest): \"jest\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "b", Symbol(jest): "jest"} +Received: {"a": "b", "c": "d", Symbol(jest): "jest"}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"c\": \"d\", Symbol(jest): \"jest\"}).toMatchObject({\"a\": \"b\", \"c\": \"d\", Symbol(jest): \"jest\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": "b", "c": "d", Symbol(jest): "jest"}`; + +module.exports["toMatchObject() {pass: true} expect({}).toMatchObject({\"a\": undefined, \"b\": \"b\", \"c\": \"c\"})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"a": undefined, "b": "b", "c": "c"} +Received: {}`; + +module.exports["toMatchObject() {pass: true} expect({}).toMatchObject({\"d\": 4})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"d": 4} +Received: {}`; + +module.exports["toMatchObject() {pass: true} expect({\"a\": \"b\", \"toString\": [Function toString]}).toMatchObject({\"toString\": Any})"] = `expect(received).not.toMatchObject(expected) + +Expected: not {"toString": Any} +Received: {"a": "b", "toString": [Function toString]}`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\", \"c\": \"d\"}).toMatchObject({\"e\": \"b\"})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 2 + + Object { +- "e": "b", ++ "a": "b", ++ "c": "d", + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\", \"c\": \"d\"}).toMatchObject({\"a\": \"b!\", \"c\": \"d\"})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": "b!", ++ "a": "b", + "c": "d", + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"a\", \"c\": \"d\"}).toMatchObject({\"a\": Any})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": Any, ++ "a": "a", + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\", \"t\": {\"x\": {\"r\": \"r\"}, \"z\": \"z\"}}).toMatchObject({\"a\": \"b\", \"t\": {\"z\": [3]}})"] = `expect(received).toMatchObject(expected) + +- Expected - 3 ++ Received + 1 + + Object { + "a": "b", + "t": Object { +- "z": Array [ +- 3, +- ], ++ "z": "z", + }, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\", \"t\": {\"x\": {\"r\": \"r\"}, \"z\": \"z\"}}).toMatchObject({\"t\": {\"l\": {\"r\": \"r\"}}})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 2 + + Object { + "t": Object { +- "l": Object { ++ "x": Object { + "r": "r", + }, ++ "z": "z", + }, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": [3, 4, 5], \"b\": \"b\"}).toMatchObject({\"a\": [3, 4, 5, 6]})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 0 + + Object { + "a": Array [ + 3, + 4, + 5, +- 6, + ], + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": [3, 4, 5], \"b\": \"b\"}).toMatchObject({\"a\": [3, 4]})"] = `expect(received).toMatchObject(expected) + +- Expected - 0 ++ Received + 1 + + Object { + "a": Array [ + 3, + 4, ++ 5, + ], + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": [3, 4, \"v\"], \"b\": \"b\"}).toMatchObject({\"a\": [\"v\"]})"] = `expect(received).toMatchObject(expected) + +- Expected - 0 ++ Received + 2 + + Object { + "a": Array [ ++ 3, ++ 4, + "v", + ], + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": [3, 4, 5], \"b\": \"b\"}).toMatchObject({\"a\": {\"b\": 4}})"] = `expect(received).toMatchObject(expected) + +- Expected - 3 ++ Received + 5 + + Object { +- "a": Object { +- "b": 4, +- }, ++ "a": Array [ ++ 3, ++ 4, ++ 5, ++ ], + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": [3, 4, 5], \"b\": \"b\"}).toMatchObject({\"a\": {\"b\": Any}})"] = `expect(received).toMatchObject(expected) + +- Expected - 3 ++ Received + 5 + + Object { +- "a": Object { +- "b": Any, +- }, ++ "a": Array [ ++ 3, ++ 4, ++ 5, ++ ], + }`; + +module.exports["toMatchObject() {pass: false} expect([1, 2]).toMatchObject([1, 3])"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Array [ + 1, +- 3, ++ 2, + ]`; + +module.exports["toMatchObject() {pass: false} expect([0]).toMatchObject([-0])"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Array [ +- -0, ++ 0, + ]`; + +module.exports["toMatchObject() {pass: false} expect(Set {1, 2}).toMatchObject(Set {2})"] = `expect(received).toMatchObject(expected) + +- Expected - 0 ++ Received + 1 + + Set { ++ 1, + 2, + }`; + +module.exports["toMatchObject() {pass: false} expect(2015-11-30T00:00:00.000Z).toMatchObject(2015-10-10T00:00:00.000Z)"] = `expect(received).toMatchObject(expected) + +Expected: 2015-10-10T00:00:00.000Z +Received: 2015-11-30T00:00:00.000Z`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": 2015-11-30T00:00:00.000Z, \"b\": \"b\"}).toMatchObject({\"a\": 2015-10-10T00:00:00.000Z})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": 2015-10-10T00:00:00.000Z, ++ "a": 2015-11-30T00:00:00.000Z, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": null, \"b\": \"b\"}).toMatchObject({\"a\": \"4\"})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": "4", ++ "a": null, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": null, \"b\": \"b\"}).toMatchObject({\"a\": undefined})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": undefined, ++ "a": null, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": undefined}).toMatchObject({\"a\": null})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": null, ++ "a": undefined, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": [{\"a\": \"a\", \"b\": \"b\"}]}).toMatchObject({\"a\": [{\"a\": \"c\"}]})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { + "a": Array [ + Object { +- "a": "c", ++ "a": "a", + }, + ], + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": 1, \"b\": 1, \"c\": 1, \"d\": {\"e\": {\"f\": 555}}}).toMatchObject({\"d\": {\"e\": {\"f\": 222}}})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { + "d": Object { + "e": Object { +- "f": 222, ++ "f": 555, + }, + }, + }`; + +module.exports["toMatchObject() {pass: false} expect({}).toMatchObject({\"a\": undefined})"] = `expect(received).toMatchObject(expected) + +- Expected - 3 ++ Received + 1 + +- Object { +- "a": undefined, +- } ++ Object {}`; + +module.exports["toMatchObject() {pass: false} expect([1, 2, 3]).toMatchObject([2, 3, 1])"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Array [ ++ 1, + 2, + 3, +- 1, + ]`; + +module.exports["toMatchObject() {pass: false} expect([1, 2, 3]).toMatchObject([1, 2, 2])"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Array [ + 1, + 2, +- 2, ++ 3, + ]`; + +module.exports["toMatchObject() {pass: false} expect([Error: foo]).toMatchObject([Error: bar])"] = `expect(received).toMatchObject(expected) + +Expected: [Error: bar] +Received: [Error: foo]`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\"}).toMatchObject({\"c\": \"d\"})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "c": "d", ++ "a": "b", + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\", \"c\": \"d\", Symbol(jest): \"jest\"}).toMatchObject({\"a\": \"c\", Symbol(jest): Any})"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 1 + + Object { +- "a": "c", ++ "a": "b", + Symbol(jest): Any, + }`; + +module.exports["toMatchObject() {pass: false} expect({\"a\": \"b\"}).toMatchObject({\"toString\": Any})"] = `expect(received).toMatchObject(expected) + +- Expected - 0 ++ Received + 1 + + Object { ++ "a": "b", + "toString": Any, + }`; + +module.exports["toMatchObject() throws expect(null).toMatchObject({})"] = `expect(received).toMatchObject(expected) + +Matcher error: received value must be a non-null object + +Received has value: null`; + +module.exports["toMatchObject() throws expect(4).toMatchObject({})"] = `expect(received).toMatchObject(expected) + +Matcher error: received value must be a non-null object + +Received has type: number +Received has value: 4`; + +module.exports["toMatchObject() throws expect(\"44\").toMatchObject({})"] = `expect(received).toMatchObject(expected) + +Matcher error: received value must be a non-null object + +Received has type: string +Received has value: "44"`; + +module.exports["toMatchObject() throws expect(true).toMatchObject({})"] = `expect(received).toMatchObject(expected) + +Matcher error: received value must be a non-null object + +Received has type: boolean +Received has value: true`; + +module.exports["toMatchObject() throws expect(undefined).toMatchObject({})"] = `expect(received).toMatchObject(expected) + +Matcher error: received value must be a non-null object + +Received has value: undefined`; + +module.exports["toMatchObject() throws expect({}).toMatchObject(null)"] = `expect(received).toMatchObject(expected) + +Matcher error: expected value must be a non-null object + +Expected has value: null`; + +module.exports["toMatchObject() throws expect({}).toMatchObject(4)"] = `expect(received).toMatchObject(expected) + +Matcher error: expected value must be a non-null object + +Expected has type: number +Expected has value: 4`; + +module.exports["toMatchObject() throws expect({}).toMatchObject(\"some string\")"] = `expect(received).toMatchObject(expected) + +Matcher error: expected value must be a non-null object + +Expected has type: string +Expected has value: "some string"`; + +module.exports["toMatchObject() throws expect({}).toMatchObject(true)"] = `expect(received).toMatchObject(expected) + +Matcher error: expected value must be a non-null object + +Expected has type: boolean +Expected has value: true`; + +module.exports["toMatchObject() throws expect({}).toMatchObject(undefined)"] = `expect(received).toMatchObject(expected) + +Matcher error: expected value must be a non-null object + +Expected has value: undefined`; + +module.exports["toMatchObject() does not match properties up in the prototype chain"] = `expect(received).toMatchObject(expected) + +- Expected - 1 ++ Received + 0 + + Object { + "other": "child", +- "ref": [Circular], + }`; + diff --git a/tests/expect/matchers.test.ts b/tests/expect/matchers.test.ts new file mode 100644 index 0000000000000..8824039bab7fa --- /dev/null +++ b/tests/expect/matchers.test.ts @@ -0,0 +1,2338 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest, matcherUtils } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; +import Immutable from 'immutable'; + +const { stringify } = matcherUtils; + +const expectUnderTestAsAny = expectUnderTest as any; + +expectUnderTest.extend({ + optionalFn(fn) { + const pass = fn === undefined || typeof fn === 'function'; + return { message: () => 'expect either a function or undefined', pass }; + }, +}); + +test('should throw if passed two arguments', () => { + expect(() => expectUnderTestAsAny('foo', 'bar')).toThrow( + new Error('Expect takes at most one argument.'), + ); +}); + +test.describe('.rejects', () => { + test('should reject', async () => { + await expectUnderTest(Promise.reject(4)).rejects.toBe(4); + await expectUnderTest(Promise.reject(4)).rejects.not.toBe(5); + await expectUnderTest(Promise.reject(4.2)).rejects.toBeCloseTo(4.2, 5); + await expectUnderTest(Promise.reject(3)).rejects.not.toBeCloseTo(4.2, 5); + await expectUnderTest(Promise.reject({ a: 1, b: 2 })).rejects.toMatchObject({ + a: 1, + }); + await expectUnderTest(Promise.reject({ a: 1, b: 2 })).rejects.not.toMatchObject({ + c: 1, + }); + await expectUnderTest( + Promise.reject(new Error('rejectMessage')), + ).rejects.toMatchObject({ message: 'rejectMessage' }); + await expectUnderTest(Promise.reject(new Error())).rejects.toThrow(); + }); + + test('should reject with toThrow', async () => { + async function fn() { + throw new Error('some error'); + } + await expectUnderTest(fn()).rejects.toThrow('some error'); + }); + + test('should reject async function to toThrow', async () => { + await expectUnderTest(async () => { + throw new Error('Test'); + }).rejects.toThrow('Test'); + }); + + ['a', [1], () => { }, { a: 1 }].forEach(value => { + test(`fails non-promise value ${stringify(value)} synchronously`, () => { + let error; + try { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + expectUnderTest(value).rejects.toBe(111); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + }); + + test(`fails non-promise value ${stringify(value)}`, async () => { + let error; + try { + await expectUnderTest(value).rejects.toBeDefined(); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); + }); + + [4, null, true, undefined].forEach(value => { + test(`fails non-promise value ${stringify(value)} synchronously`, () => { + let error; + try { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + expectUnderTest(value).rejects.not.toBe(111); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + }); + + test(`fails non-promise value ${stringify(value)}`, async () => { + let error; + try { + await expectUnderTest(value).rejects.not.toBeDefined(); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); + }); + + test('fails for promise that resolves', async () => { + let error; + try { + await expectUnderTest(Promise.resolve(4)).rejects.toBe(4); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); +}); + +test.describe('.resolves', () => { + test('should resolve', async () => { + await expectUnderTest(Promise.resolve(4)).resolves.toBe(4); + await expectUnderTest(Promise.resolve(4)).resolves.not.toBe(5); + await expectUnderTest(Promise.resolve(4.2)).resolves.toBeCloseTo(4.2, 5); + await expectUnderTest(Promise.resolve(3)).resolves.not.toBeCloseTo(4.2, 5); + await expectUnderTest(Promise.resolve({ a: 1, b: 2 })).resolves.toMatchObject({ + a: 1, + }); + await expectUnderTest(Promise.resolve({ a: 1, b: 2 })).resolves.not.toMatchObject({ + c: 1, + }); + await expectUnderTest( + Promise.resolve(() => { + throw new Error(); + }), + ).resolves.toThrow(); + }); + + ['a', [1], () => { }, { a: 1 }].forEach(value => { + test(`fails non-promise value ${stringify(value)} synchronously`, () => { + let error; + try { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + expectUnderTest(value).resolves.toBeDefined(); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); + + test(`fails non-promise value ${stringify(value)}`, async () => { + let error; + try { + await expectUnderTest(value).resolves.toBeDefined(); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); + }); + + [4, null, true, undefined].forEach(value => { + test(`fails non-promise value ${stringify(value)} synchronously`, () => { + let error; + try { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + expectUnderTest(value).resolves.not.toBeDefined(); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); + + test(`fails non-promise value ${stringify(value)}`, async () => { + let error; + try { + await expectUnderTest(value).resolves.not.toBeDefined(); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); + }); + + test('fails for promise that rejects', async () => { + let error; + try { + await expectUnderTest(Promise.reject(4)).resolves.toBe(4); + } catch (e) { + error = e; + } + expect(error).toBeDefined(); + expect(error.message).toMatchSnapshot(); + }); +}); + +test.describe('.toBe()', () => { + test('does not throw', () => { + expectUnderTest('a').not.toBe('b'); + expectUnderTest('a').toBe('a'); + expectUnderTest(1).not.toBe(2); + expectUnderTest(1).toBe(1); + expectUnderTest(null).not.toBe(undefined); + expectUnderTest(null).toBe(null); + expectUnderTest(undefined).toBe(undefined); + expectUnderTest(NaN).toBe(NaN); + expectUnderTest(BigInt(1)).not.toBe(BigInt(2)); + expectUnderTest(BigInt(1)).not.toBe(1); + expectUnderTest(BigInt(1)).toBe(BigInt(1)); + }); + + [ + [1, 2], + [true, false], + [() => { }, () => { }], + [{}, {}], + [{ a: 1 }, { a: 1 }], + [{ a: 1 }, { a: 5 }], + [ + { a: () => { }, b: 2 }, + { a: expect.any(Function), b: 2 }, + ], + [{ a: undefined, b: 2 }, { b: 2 }], + [new Date('2020-02-20'), new Date('2020-02-20')], + [new Date('2020-02-21'), new Date('2020-02-20')], + [/received/, /expected/], + [Symbol('received'), Symbol('expected')], + [new Error('received'), new Error('expected')], + ['abc', 'cde'], + ['painless JavaScript testing', 'delightful JavaScript testing'], + ['', 'compare one-line string to empty string'], + ['with \ntrailing space', 'without trailing space'], + ['four\n4\nline\nstring', '3\nline\nstring'], + [[], []], + [null, undefined], + [-0, +0], + ].forEach(([a, b]: [a: any, b: any], index) => { + test(`fails for: ${stringify(a)} and ${stringify(b)} (${index})`, () => { + expect(() => expectUnderTest(a).toBe(b)).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [BigInt(1), BigInt(2)], + [{ a: BigInt(1) }, { a: BigInt(1) }], + ].forEach(([a, b]) => { + test(`fails for: ${stringify(a)} and ${stringify(b)}`, () => { + expect(() => expectUnderTest(a).toBe(b)).toThrow('toBe'); + }); + }); + + [false, 1, 'a', undefined, null, {}, []].forEach(v => { + test(`fails for '${stringify(v)}' with '.not'`, () => { + expect(() => expectUnderTest(v).not.toBe(v)).toThrowErrorMatchingSnapshot(); + }); + }); + + [BigInt(1), BigInt('1')].forEach((v, index) => { + test(`fails for '${stringify(v)}' with '.not' (${index})}`, () => { + expect(() => expectUnderTest(v).not.toBe(v)).toThrow('toBe'); + }); + }); + + test('does not crash on circular references', () => { + const obj: any = {}; + obj.circular = obj; + + expect(() => expectUnderTest(obj).toBe({})).toThrowErrorMatchingSnapshot(); + }); + + test('assertion error matcherResult property contains matcher name, expected and actual values', () => { + const actual = { a: 1 }; + const expected = { a: 2 }; + try { + expectUnderTest(actual).toBe(expected); + } catch (error) { + expect(error.matcherResult).toEqual( + expect.objectContaining({ + actual, + expected, + name: 'toBe', + }), + ); + } + }); +}); + +test.describe('.toStrictEqual()', () => { + class TestClassA { + constructor(public a, public b) { } + } + + class TestClassB { + constructor(public a, public b) { } + } + + const TestClassC = class Child extends TestClassA { + constructor(a, b) { + super(a, b); + } + }; + + const TestClassD = class Child extends TestClassB { + constructor(a, b) { + super(a, b); + } + }; + + test('does not ignore keys with undefined values', () => { + expect({ + a: undefined, + b: 2, + }).not.toStrictEqual({ b: 2 }); + }); + + test('does not ignore keys with undefined values inside an array', () => { + expect([{ a: undefined }]).not.toStrictEqual([{}]); + }); + + test('does not ignore keys with undefined values deep inside an object', () => { + expect([{ a: [{ a: undefined }] }]).not.toStrictEqual([{ a: [{}] }]); + }); + + test('does not consider holes as undefined in sparse arrays', () => { + + expect([, , , 1, , ,]).not.toStrictEqual([, , , 1, undefined, ,]); + }); + + test('passes when comparing same type', () => { + expect({ + test: new TestClassA(1, 2), + }).toStrictEqual({ test: new TestClassA(1, 2) }); + }); + + test('matches the expected snapshot when it fails', () => { + expect(() => + expectUnderTest({ + test: 2, + }).toStrictEqual({ test: new TestClassA(1, 2) }), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest({ + test: new TestClassA(1, 2), + }).not.toStrictEqual({ test: new TestClassA(1, 2) }), + ).toThrowErrorMatchingSnapshot(); + }); + + test('displays substring diff', () => { + const expected = + 'Another caveat is that Jest will not typecheck your tests.'; + const received = + 'Because TypeScript support in Babel is just transpilation, Jest will not type-check your tests as they run.'; + expect(() => + expectUnderTest(received).toStrictEqual(expected), + ).toThrowErrorMatchingSnapshot(); + }); + + test('displays substring diff for multiple lines', () => { + const expected = [ + ' 69 | ', + " 70 | test('assert.doesNotThrow', () => {", + ' > 71 | assert.doesNotThrow(() => {', + ' | ^', + " 72 | throw Error('err!');", + ' 73 | });', + ' 74 | });', + ' at Object.doesNotThrow (__tests__/assertionError.test.js:71:10)', + ].join('\n'); + const received = [ + ' 68 | ', + " 69 | test('assert.doesNotThrow', () => {", + ' > 70 | assert.doesNotThrow(() => {', + ' | ^', + " 71 | throw Error('err!');", + ' 72 | });', + ' 73 | });', + ' at Object.doesNotThrow (__tests__/assertionError.test.js:70:10)', + ].join('\n'); + expect(() => + expectUnderTest(received).toStrictEqual(expected), + ).toThrowErrorMatchingSnapshot(); + }); + + test('does not pass for different types', () => { + expect({ + test: new TestClassA(1, 2), + }).not.toStrictEqual({ test: new TestClassB(1, 2) }); + }); + + test('does not simply compare constructor names', () => { + const c = new TestClassC(1, 2); + const d = new TestClassD(1, 2); + expect(c.constructor.name).toEqual(d.constructor.name); + expect({ test: c }).not.toStrictEqual({ test: d }); + }); + + + test('passes for matching sparse arrays', () => { + expect([, 1]).toStrictEqual([, 1]); + }); + + test('does not pass when sparseness of arrays do not match', () => { + expect([, 1]).not.toStrictEqual([undefined, 1]); + expect([undefined, 1]).not.toStrictEqual([, 1]); + expect([, , , 1]).not.toStrictEqual([, 1]); + }); + + test('does not pass when equally sparse arrays have different values', () => { + expect([, 1]).not.toStrictEqual([, 2]); + }); + + test('does not pass when ArrayBuffers are not equal', () => { + expect(Uint8Array.from([1, 2]).buffer).not.toStrictEqual( + Uint8Array.from([0, 0]).buffer, + ); + expect(Uint8Array.from([2, 1]).buffer).not.toStrictEqual( + Uint8Array.from([2, 2]).buffer, + ); + expect(Uint8Array.from([]).buffer).not.toStrictEqual( + Uint8Array.from([1]).buffer, + ); + }); + + test('passes for matching buffers', () => { + expect(Uint8Array.from([1]).buffer).toStrictEqual( + Uint8Array.from([1]).buffer, + ); + expect(Uint8Array.from([]).buffer).toStrictEqual( + Uint8Array.from([]).buffer, + ); + expect(Uint8Array.from([9, 3]).buffer).toStrictEqual( + Uint8Array.from([9, 3]).buffer, + ); + }); + + test('fails for missing keys even if backed by an asymmetric matcher accepting them', () => { + // issue 12463 + expect({ a: 1 }).not.toStrictEqual({ a: 1, b: expectUnderTestAsAny.optionalFn() }); + expect({ a: 1, b: expectUnderTestAsAny.optionalFn() }).not.toStrictEqual({ a: 1 }); + expect([1]).not.toStrictEqual([1, expectUnderTestAsAny.optionalFn()]); + expect([1, expectUnderTestAsAny.optionalFn()]).not.toStrictEqual([1]); + }); + + test('passes if keys are present and asymmetric matcher accept them', () => { + // issue 12463 + // with a proper function + expect({ a: 1, b: () => { } }).toStrictEqual({ + a: 1, + b: expectUnderTestAsAny.optionalFn(), + }); + expect({ a: 1, b: expectUnderTestAsAny.optionalFn() }).toStrictEqual({ + a: 1, + b: () => { }, + }); + expect([1, () => { }]).toStrictEqual([1, expectUnderTestAsAny.optionalFn()]); + expect([1, expectUnderTestAsAny.optionalFn()]).toStrictEqual([1, () => { }]); + // with undefined + expect({ a: 1, b: undefined }).toStrictEqual({ + a: 1, + b: expectUnderTestAsAny.optionalFn(), + }); + expect({ a: 1, b: expectUnderTestAsAny.optionalFn() }).toStrictEqual({ + a: 1, + b: undefined, + }); + expect([1, undefined]).toStrictEqual([1, expectUnderTestAsAny.optionalFn()]); + expect([1, expectUnderTestAsAny.optionalFn()]).toStrictEqual([1, undefined]); + }); + +}); + +test.describe('.toEqual()', () => { + + [ + [true, false], + [1, 2], + [0, -0], + [0, Number.MIN_VALUE], // issues/7941 + [Number.MIN_VALUE, 0], + [0, new Number(0)], + [new Number(0), 0], + [new Number(0), new Number(1)], + ['abc', new String('abc')], + [new String('abc'), 'abc'], + // @ts-ignore + [/abc/gsy, /abc/g], + [{ a: 1 }, { a: 2 }], + [{ a: 5 }, { b: 6 }], + [Object.freeze({ foo: { bar: 1 } }), { foo: {} }], + [ + { + get getterAndSetter() { + return {}; + }, + set getterAndSetter(value) { + throw new Error('noo'); + }, + }, + { getterAndSetter: { foo: 'bar' } }, + ], + [ + Object.freeze({ + get frozenGetterAndSetter() { + return {}; + }, + set frozenGetterAndSetter(value) { + throw new Error('noo'); + }, + }), + { frozenGetterAndSetter: { foo: 'bar' } }, + ], + [ + { + get getter() { + return {}; + }, + }, + { getter: { foo: 'bar' } }, + ], + [ + Object.freeze({ + get frozenGetter() { + return {}; + }, + }), + { frozenGetter: { foo: 'bar' } }, + ], + [ + { + + set setter(value) { + throw new Error('noo'); + }, + }, + { setter: { foo: 'bar' } }, + ], + [ + Object.freeze({ + + set frozenSetter(value) { + throw new Error('noo'); + }, + }), + { frozenSetter: { foo: 'bar' } }, + ], + ['banana', 'apple'], + ['1\u{00A0}234,57\u{00A0}$', '1 234,57 $'], // issues/6881 + [ + 'type TypeName = T extends Function ? "function" : "object";', + 'type TypeName = T extends Function\n? "function"\n: "object";', + ], + [null, undefined], + [[1], [2]], + [ + [1, 2], + [2, 1], + ], + [Immutable.List([1]), Immutable.List([2])], + [Immutable.List([1, 2]), Immutable.List([2, 1])], + [new Map(), new Set()], + [new Set([1, 2]), new Set()], + [new Set([1, 2]), new Set([1, 2, 3])], + [new Set([[1], [2]]), new Set([[1], [2], [3]])], + [new Set([[1], [2]]), new Set([[1], [2], [2]])], + [ + new Set([new Set([1]), new Set([2])]), + new Set([new Set([1]), new Set([3])]), + ], + [Immutable.Set([1, 2]), Immutable.Set()], + [Immutable.Set([1, 2]), Immutable.Set([1, 2, 3])], + [Immutable.OrderedSet([1, 2]), Immutable.OrderedSet([2, 1])], + [ + new Map([ + [1, 'one'], + [2, 'two'], + ]), + new Map([[1, 'one']]), + ], + [new Map([['a', 0]]), new Map([['b', 0]])], + [new Map([['v', 1]]), new Map([['v', 2]])], + [new Map([[['v'], 1]]), new Map([[['v'], 2]])], + [ + new Map([[[1], new Map([[[1], 'one']])]]), + new Map([[[1], new Map([[[1], 'two']])]]), + ], + [Immutable.Map({ a: 0 }), Immutable.Map({ b: 0 })], + [Immutable.Map({ v: 1 }), Immutable.Map({ v: 2 })], + [ + Immutable.OrderedMap().set(1, 'one').set(2, 'two'), + Immutable.OrderedMap().set(2, 'two').set(1, 'one'), + ], + [ + Immutable.Map({ 1: Immutable.Map({ 2: { a: 99 } }) }), + Immutable.Map({ 1: Immutable.Map({ 2: { a: 11 } }) }), + ], + [new Uint8Array([97, 98, 99]), new Uint8Array([97, 98, 100])], + [{ a: 1, b: 2 }, expectUnderTest.objectContaining({ a: 2 })], + [false, expectUnderTest.objectContaining({ a: 2 })], + [[1, 3], expectUnderTest.arrayContaining([1, 2])], + [1, expectUnderTest.arrayContaining([1, 2])], + ['abd', expectUnderTest.stringContaining('bc')], + ['abd', expectUnderTest.stringMatching(/bc/i)], + [undefined, expectUnderTest.anything()], + [undefined, expectUnderTest.any(Function)], + [ + 'Eve', + { + asymmetricMatch: function asymmetricMatch(who) { + return who === 'Alice' || who === 'Bob'; + }, + }, + ], + [ + { + target: { + nodeType: 1, + value: 'a', + }, + }, + { + target: { + nodeType: 1, + value: 'b', + }, + }, + ], + [ + { + nodeName: 'div', + nodeType: 1, + }, + { + nodeName: 'p', + nodeType: 1, + }, + ], + [ + { + [Symbol.for('foo')]: 1, + [Symbol.for('bar')]: 2, + }, + { + [Symbol.for('foo')]: expectUnderTest.any(Number), + [Symbol.for('bar')]: 1, + }, + ], + [ + + [, , 1, ,], + + [, , 2, ,], + ], + [ + Object.assign([], { 4294967295: 1 }), + Object.assign([], { 4294967295: 2 }), // issue 11056 + ], + [ + + Object.assign([], { ['-0']: 1 }), + + Object.assign([], { ['0']: 1 }), // issue 11056: also check (-0, 0) + ], + [ + Object.assign([], { a: 1 }), + Object.assign([], { b: 1 }), // issue 11056: also check strings + ], + [ + Object.assign([], { [Symbol()]: 1 }), + Object.assign([], { [Symbol()]: 1 }), // issue 11056: also check symbols + ], + ].forEach(([a, b], index) => { + test(`{pass: false} expect(${stringify(a)}).toEqual(${stringify( + b, + )} (${index}))`, () => { + expect(() => expectUnderTest(a).toEqual(b)).toThrowErrorMatchingSnapshot(); + expectUnderTest(a).not.toEqual(b); + }); + }); + + [ + [BigInt(1), BigInt(2)], + [BigInt(1), 1], + ].forEach(([a, b]) => { + test(`{pass: false} expect(${stringify(a)}).toEqual(${stringify( + b, + )})`, () => { + expect(() => expectUnderTest(a).toEqual(b)).toThrow('toEqual'); + expectUnderTest(a).not.toEqual(b); + }); + }); + + [ + [true, true], + [1, 1], + [NaN, NaN], + [0, Number(0)], + [Number(0), 0], + [new Number(0), new Number(0)], + ['abc', 'abc'], + [String('abc'), 'abc'], + ['abc', String('abc')], + [[1], [1]], + [ + [1, 2], + [1, 2], + ], + [Immutable.List([1]), Immutable.List([1])], + [Immutable.List([1, 2]), Immutable.List([1, 2])], + [{}, {}], + [{ a: 99 }, { a: 99 }], + [new Set(), new Set()], + [new Set([1, 2]), new Set([1, 2])], + [new Set([1, 2]), new Set([2, 1])], + [new Set([[1], [2]]), new Set([[2], [1]])], + [ + new Set([new Set([[1]]), new Set([[2]])]), + new Set([new Set([[2]]), new Set([[1]])]), + ], + [new Set([[1], [2], [3], [3]]), new Set([[3], [3], [2], [1]])], + [new Set([{ a: 1 }, { b: 2 }]), new Set([{ b: 2 }, { a: 1 }])], + [Immutable.Set(), Immutable.Set()], + [Immutable.Set([1, 2]), Immutable.Set([1, 2])], + [Immutable.Set([1, 2]), Immutable.Set([2, 1])], + [Immutable.OrderedSet(), Immutable.OrderedSet()], + [Immutable.OrderedSet([1, 2]), Immutable.OrderedSet([1, 2])], + [new Map(), new Map()], + [ + new Map([ + [1, 'one'], + [2, 'two'], + ]), + new Map([ + [1, 'one'], + [2, 'two'], + ]), + ], + [ + new Map([ + [1, 'one'], + [2, 'two'], + ]), + new Map([ + [2, 'two'], + [1, 'one'], + ]), + ], + [ + new Map([ + [[1], 'one'], + [[2], 'two'], + [[3], 'three'], + [[3], 'four'], + ]), + new Map([ + [[3], 'three'], + [[3], 'four'], + [[2], 'two'], + [[1], 'one'], + ]), + ], + [ + new Map([ + [[1], new Map([[[1], 'one']])], + [[2], new Map([[[2], 'two']])], + ]), + new Map([ + [[2], new Map([[[2], 'two']])], + [[1], new Map([[[1], 'one']])], + ]), + ], + [ + new Map([ + [[1], 'one'], + [[2], 'two'], + ]), + new Map([ + [[2], 'two'], + [[1], 'one'], + ]), + ], + [ + new Map([ + [{ a: 1 }, 'one'], + [{ b: 2 }, 'two'], + ]), + new Map([ + [{ b: 2 }, 'two'], + [{ a: 1 }, 'one'], + ]), + ], + [ + new Map([ + [1, ['one']], + [2, ['two']], + ]), + new Map([ + [2, ['two']], + [1, ['one']], + ]), + ], + [Immutable.Map(), Immutable.Map()], + [ + Immutable.Map().set(1, 'one').set(2, 'two'), + Immutable.Map().set(1, 'one').set(2, 'two'), + ], + [ + Immutable.Map().set(1, 'one').set(2, 'two'), + Immutable.Map().set(2, 'two').set(1, 'one'), + ], + [ + Immutable.OrderedMap().set(1, 'one').set(2, 'two'), + Immutable.OrderedMap().set(1, 'one').set(2, 'two'), + ], + [ + Immutable.Map({ 1: Immutable.Map({ 2: { a: 99 } }) }), + Immutable.Map({ 1: Immutable.Map({ 2: { a: 99 } }) }), + ], + [new Uint8Array([97, 98, 99]), new Uint8Array([97, 98, 99])], + [{ a: 1, b: 2 }, expectUnderTest.objectContaining({ a: 1 })], + [[1, 2, 3], expectUnderTest.arrayContaining([2, 3])], + ['abcd', expectUnderTest.stringContaining('bc')], + ['abcd', expectUnderTest.stringMatching('bc')], + [true, expectUnderTest.anything()], + [() => { }, expectUnderTest.any(Function)], + [ + { + a: 1, + b: function b() { }, + c: true, + }, + { + a: 1, + b: expectUnderTest.any(Function), + c: expectUnderTest.anything(), + }, + ], + [ + 'Alice', + { + asymmetricMatch: function asymmetricMatch(who) { + return who === 'Alice' || who === 'Bob'; + }, + }, + ], + [ + { + nodeName: 'div', + nodeType: 1, + }, + { + nodeName: 'div', + nodeType: 1, + }, + ], + [ + { + [Symbol.for('foo')]: 1, + [Symbol.for('bar')]: 2, + }, + { + [Symbol.for('foo')]: expectUnderTest.any(Number), + [Symbol.for('bar')]: 2, + }, + ], + [ + + [, , 1, ,], + + [, , 1, ,], + ], + [ + + [, , 1, , ,], + + [, , 1, undefined, ,], // same length but hole replaced by undefined + ], + // issue 12463 - "matcher" vs "proper function" + [ + { a: 1, b: () => { } }, + { a: 1, b: expectUnderTestAsAny.optionalFn() }, + ], + [ + { a: 1, b: expectUnderTestAsAny.optionalFn() }, + { a: 1, b: () => { } }, + ], + [ + [1, () => { }], + [1, expectUnderTestAsAny.optionalFn()], + ], + [ + [1, expectUnderTestAsAny.optionalFn()], + [1, () => { }], + ], + // issue 12463 - "matcher" vs "undefined" + [ + { a: 1, b: undefined }, + { a: 1, b: expectUnderTestAsAny.optionalFn() }, + ], + [ + { a: 1, b: expectUnderTestAsAny.optionalFn() }, + { a: 1, b: undefined }, + ], + [ + [1, undefined], + [1, expectUnderTestAsAny.optionalFn()], + ], + [ + [1, expectUnderTestAsAny.optionalFn()], + [1, undefined], + ], + // issue 12463 - "matcher" vs "missing" + [{ a: 1 }, { a: 1, b: expectUnderTestAsAny.optionalFn() }], + [{ a: 1, b: expectUnderTestAsAny.optionalFn() }, { a: 1 }], + [[1], [1, expectUnderTestAsAny.optionalFn()]], + [[1, expectUnderTestAsAny.optionalFn()], [1]], + ].forEach(([a, b], index) => { + test(`{pass: true} expect(${stringify(a)}).not.toEqual(${stringify( + b, + )}) (${index})`, () => { + expectUnderTest(a).toEqual(b); + expect(() => expectUnderTest(a).not.toEqual(b)).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [BigInt(1), BigInt(1)], + [BigInt(0), BigInt('0')], + [[BigInt(1)], [BigInt(1)]], + [ + [BigInt(1), 2], + [BigInt(1), 2], + ], + [Immutable.List([BigInt(1)]), Immutable.List([BigInt(1)])], + [{ a: BigInt(99) }, { a: BigInt(99) }], + [new Set([BigInt(1), BigInt(2)]), new Set([BigInt(1), BigInt(2)])], + ].forEach(([a, b]) => { + test(`{pass: true} expect(${stringify(a)}).not.toEqual(${stringify( + b, + )})`, () => { + expectUnderTest(a).toEqual(b); + expect(() => expectUnderTest(a).not.toEqual(b)).toThrow('toEqual'); + }); + }); + + test('assertion error matcherResult property contains matcher name, expected and actual values', () => { + const actual = { a: 1 }; + const expected = { a: 2 }; + try { + expectUnderTest(actual).toEqual(expected); + } catch (error) { + expect(error.matcherResult).toEqual( + expect.objectContaining({ + actual, + expected, + name: 'toEqual', + }), + ); + } + }); + + test('symbol based keys in arrays are processed correctly', () => { + const mySymbol = Symbol('test'); + const actual1 = []; + actual1[mySymbol] = 3; + const actual2 = []; + actual2[mySymbol] = 4; + const expected = []; + expected[mySymbol] = 3; + + expect(actual1).toEqual(expected); + expect(actual2).not.toEqual(expected); + }); + + test('non-enumerable members should be skipped during equal', () => { + const actual = { + x: 3, + }; + Object.defineProperty(actual, 'test', { + enumerable: false, + value: 5, + }); + expect(actual).toEqual({ x: 3 }); + }); + + test('non-enumerable symbolic members should be skipped during equal', () => { + const actual = { + x: 3, + }; + const mySymbol = Symbol('test'); + Object.defineProperty(actual, mySymbol, { + enumerable: false, + value: 5, + }); + expect(actual).toEqual({ x: 3 }); + }); + + test.describe('cyclic object equality', () => { + test('properties with the same circularity are equal', () => { + const a: any = {}; + a.x = a; + const b: any = {}; + b.x = b; + expect(a).toEqual(b); + expect(b).toEqual(a); + + const c: any = {}; + c.x = a; + const d: any = {}; + d.x = b; + expect(c).toEqual(d); + expect(d).toEqual(c); + }); + + test('properties with different circularity are not equal', () => { + const a: any = {}; + a.x = { y: a }; + const b: any = {}; + const bx: any = {}; + b.x = bx; + bx.y = bx; + expect(a).not.toEqual(b); + expect(b).not.toEqual(a); + + const c: any = {}; + c.x = a; + const d: any = {}; + d.x = b; + expect(c).not.toEqual(d); + expect(d).not.toEqual(c); + }); + + test('are not equal if circularity is not on the same property', () => { + const a: any = {}; + const b: any = {}; + a.a = a; + b.a = {}; + b.a.a = a; + expect(a).not.toEqual(b); + expect(b).not.toEqual(a); + + const c: any = {}; + c.x = { x: c }; + const d: any = {}; + d.x = d; + expect(c).not.toEqual(d); + expect(d).not.toEqual(c); + }); + }); + +}); + +test.describe('.toBeInstanceOf()', () => { + class A { } + class B { } + class C extends B { } + class D extends C { } + class E extends D { } + + class SubHasStaticNameMethod extends B { + constructor() { + super(); + } + static name() { } + } + + class HasStaticNameMethod { + constructor() { } + static name() { } + } + + function DefinesNameProp() { } + Object.defineProperty(DefinesNameProp, 'name', { + configurable: true, + enumerable: false, + value: '', + writable: true, + }); + // @ts-ignore + class SubHasNameProp extends DefinesNameProp { } + + [ + [new Map(), Map], + [[], Array], + [new A(), A], + [new C(), B], // C extends B + [new E(), B], // E extends … extends B + [new SubHasNameProp(), DefinesNameProp], // omit extends + [new SubHasStaticNameMethod(), B], // Received + [new HasStaticNameMethod(), HasStaticNameMethod], // Expected + ].forEach(([a, b], index) => { + test(`passing ${stringify(a)} and ${stringify(b)} (${index})`, () => { + expect(() => + expectUnderTest(a).not.toBeInstanceOf(b), + ).toThrowErrorMatchingSnapshot(); + + expectUnderTest(a).toBeInstanceOf(b); + }); + }); + + [ + ['a', String], + [1, Number], + [true, Boolean], + [new A(), B], + [Object.create(null), A], + [undefined, String], + [null, String], + [/\w+/, function() { }], + [new DefinesNameProp(), RegExp], + ].forEach(([a, b], index) => { + test(`failing ${stringify(a)} and ${stringify(b)} (${index})`, () => { + expect(() => + expectUnderTest(a).toBeInstanceOf(b), + ).toThrowErrorMatchingSnapshot(); + + expectUnderTest(a).not.toBeInstanceOf(b); + }); + }); + + test('throws if constructor is not a function', () => { + expect(() => + expectUnderTest({}).toBeInstanceOf(4), + ).toThrowErrorMatchingSnapshot(); + }); +}); + +test.describe('.toBeTruthy(), .toBeFalsy()', () => { + test('does not accept arguments', () => { + expect(() => expectUnderTestAsAny(0).toBeTruthy(null)).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTestAsAny(0).not.toBeFalsy(null), + ).toThrowErrorMatchingSnapshot(); + }); + + [{}, [], true, 1, 'a', 0.5, new Map(), () => { }, Infinity].forEach(v => { + test(`'${stringify(v)}' is truthy`, () => { + expectUnderTest(v).toBeTruthy(); + expectUnderTest(v).not.toBeFalsy(); + + expect(() => + expectUnderTest(v).not.toBeTruthy(), + ).toThrowErrorMatchingSnapshot(); + + expect(() => expectUnderTest(v).toBeFalsy()).toThrowErrorMatchingSnapshot(); + }); + }); + + [BigInt(1)].forEach(v => { + test(`'${stringify(v)}' is truthy`, () => { + expectUnderTest(v).toBeTruthy(); + expectUnderTest(v).not.toBeFalsy(); + + expect(() => expectUnderTest(v).not.toBeTruthy()).toThrow('toBeTruthy'); + + expect(() => expectUnderTest(v).toBeFalsy()).toThrow('toBeFalsy'); + }); + }); + + [false, null, NaN, 0, '', undefined].forEach(v => { + test(`'${stringify(v)}' is falsy`, () => { + expectUnderTest(v).toBeFalsy(); + expectUnderTest(v).not.toBeTruthy(); + + expect(() => expectUnderTest(v).toBeTruthy()).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(v).not.toBeFalsy(), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [BigInt(0)].forEach(v => { + test(`'${stringify(v)}' is falsy`, () => { + expectUnderTest(v).toBeFalsy(); + expectUnderTest(v).not.toBeTruthy(); + + expect(() => expectUnderTest(v).toBeTruthy()).toThrow('toBeTruthy'); + + expect(() => expectUnderTest(v).not.toBeFalsy()).toThrow('toBeFalsy'); + }); + }); +}); + +test.describe('.toBeNaN()', () => { + test('{pass: true} expect(NaN).toBeNaN()', () => { + [NaN, Math.sqrt(-1), Infinity - Infinity, 0 / 0].forEach(v => { + expectUnderTest(v).toBeNaN(); + + expect(() => expectUnderTest(v).not.toBeNaN()).toThrowErrorMatchingSnapshot(); + }); + }); + + test('throws', () => { + [1, '', null, undefined, {}, [], 0.2, 0, Infinity, -Infinity].forEach(v => { + expect(() => expectUnderTest(v).toBeNaN()).toThrowErrorMatchingSnapshot(); + + expectUnderTest(v).not.toBeNaN(); + }); + }); +}); + +test.describe('.toBeNull()', () => { + [{}, [], true, 1, 'a', 0.5, new Map(), () => { }, Infinity].forEach(v => { + test(`fails for '${stringify(v)}'`, () => { + expectUnderTest(v).not.toBeNull(); + + expect(() => expectUnderTest(v).toBeNull()).toThrowErrorMatchingSnapshot(); + }); + }); + + test('fails for null with .not', () => { + expect(() => + expectUnderTest(null).not.toBeNull(), + ).toThrowErrorMatchingSnapshot(); + }); + + test('pass for null', () => { + expectUnderTest(null).toBeNull(); + }); +}); + +test.describe('.toBeDefined(), .toBeUndefined()', () => { + [{}, [], true, 1, 'a', 0.5, new Map(), () => { }, Infinity].forEach(v => { + test(`'${stringify(v)}' is defined`, () => { + expectUnderTest(v).toBeDefined(); + expectUnderTest(v).not.toBeUndefined(); + + expect(() => + expectUnderTest(v).not.toBeDefined(), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(v).toBeUndefined(), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [BigInt(1)].forEach(v => { + test(`'${stringify(v)}' is defined`, () => { + expectUnderTest(v).toBeDefined(); + expectUnderTest(v).not.toBeUndefined(); + + expect(() => expectUnderTest(v).not.toBeDefined()).toThrow('toBeDefined'); + + expect(() => expectUnderTest(v).toBeUndefined()).toThrow('toBeUndefined'); + }); + }); + + test('undefined is undefined', () => { + expectUnderTest(undefined).toBeUndefined(); + expectUnderTest(undefined).not.toBeDefined(); + + expect(() => + expectUnderTest(undefined).toBeDefined(), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(undefined).not.toBeUndefined(), + ).toThrowErrorMatchingSnapshot(); + }); +}); + +test.describe( + '.toBeGreaterThan(), .toBeLessThan(), ' + + '.toBeGreaterThanOrEqual(), .toBeLessThanOrEqual()', + () => { + [ + [1, 2], + [-Infinity, Infinity], + [Number.MIN_VALUE, Number.MAX_VALUE], + [0x11, 0x22], + [0b11, 0b111], + [0o11, 0o22], + [0.1, 0.2], + ].forEach(([small, big]) => { + test(`{pass: true} expect(${small}).toBeLessThan(${big})`, () => { + expectUnderTest(small).toBeLessThan(big); + }); + + test(`{pass: false} expect(${big}).toBeLessThan(${small})`, () => { + expectUnderTest(big).not.toBeLessThan(small); + }); + + test(`{pass: true} expect(${big}).toBeGreaterThan(${small})`, () => { + expectUnderTest(big).toBeGreaterThan(small); + }); + + test(`{pass: false} expect(${small}).toBeGreaterThan(${big})`, () => { + expectUnderTest(small).not.toBeGreaterThan(big); + }); + + test(`{pass: true} expect(${small}).toBeLessThanOrEqual(${big})`, () => { + expectUnderTest(small).toBeLessThanOrEqual(big); + }); + + test(`{pass: false} expect(${big}).toBeLessThanOrEqual(${small})`, () => { + expectUnderTest(big).not.toBeLessThanOrEqual(small); + }); + + test(`{pass: true} expect(${big}).toBeGreaterThanOrEqual(${small})`, () => { + expectUnderTest(big).toBeGreaterThanOrEqual(small); + }); + + test(`{pass: false} expect(${small}).toBeGreaterThanOrEqual(${big})`, () => { + expectUnderTest(small).not.toBeGreaterThanOrEqual(big); + }); + + test(`throws: [${small}, ${big}]`, () => { + expect(() => + expectUnderTest(small).toBeGreaterThan(big), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(small).not.toBeLessThan(big), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(big).not.toBeGreaterThan(small), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(big).toBeLessThan(small), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(small).toBeGreaterThanOrEqual(big), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(small).not.toBeLessThanOrEqual(big), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(big).not.toBeGreaterThanOrEqual(small), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(big).toBeLessThanOrEqual(small), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('can compare BigInt to Numbers', () => { + const a = BigInt(2); + expectUnderTest(a).toBeGreaterThan(1); + expectUnderTest(a).toBeGreaterThanOrEqual(2); + expectUnderTest(2).toBeLessThanOrEqual(a); + expectUnderTest(a).toBeLessThan(3); + expectUnderTest(a).toBeLessThanOrEqual(2); + }); + [ + [BigInt(1), BigInt(2)], + [BigInt(0x11), BigInt(0x22)], + [-1, BigInt(2)], + ].forEach(([small, big]) => { + test(`{pass: true} expect(${stringify(small)}).toBeLessThan(${stringify( + big, + )})`, () => { + expectUnderTest(small).toBeLessThan(big); + }); + + test(`{pass: false} expect(${stringify(big)}).toBeLessThan(${stringify( + small, + )})`, () => { + expectUnderTest(big).not.toBeLessThan(small); + }); + + test(`{pass: true} expect(${stringify(big)}).toBeGreaterThan(${stringify( + small, + )})`, () => { + expectUnderTest(big).toBeGreaterThan(small); + }); + + test(`{pass: false} expect(${stringify(small)}).toBeGreaterThan(${stringify( + big, + )})`, () => { + expectUnderTest(small).not.toBeGreaterThan(big); + }); + + test(`{pass: true} expect(${stringify( + small, + )}).toBeLessThanOrEqual(${stringify(big)})`, () => { + expectUnderTest(small).toBeLessThanOrEqual(big); + }); + + test(`{pass: false} expect(${stringify( + big, + )}).toBeLessThanOrEqual(${stringify(small)})`, () => { + expectUnderTest(big).not.toBeLessThanOrEqual(small); + }); + + test(`{pass: true} expect(${stringify( + big, + )}).toBeGreaterThanOrEqual(${stringify(small)})`, () => { + expectUnderTest(big).toBeGreaterThanOrEqual(small); + }); + + test(`{pass: false} expect(${stringify( + small, + )}).toBeGreaterThanOrEqual(${stringify(big)})`, () => { + expectUnderTest(small).not.toBeGreaterThanOrEqual(big); + }); + + test(`throws: [${stringify(small)}, ${stringify(big)}]`, () => { + expect(() => expectUnderTest(small).toBeGreaterThan(big)).toThrow( + 'toBeGreaterThan', + ); + + expect(() => expectUnderTest(small).not.toBeLessThan(big)).toThrow( + 'toBeLessThan', + ); + + expect(() => expectUnderTest(big).not.toBeGreaterThan(small)).toThrow( + 'toBeGreaterThan', + ); + + expect(() => expectUnderTest(big).toBeLessThan(small)).toThrow( + 'toBeLessThan', + ); + + expect(() => expectUnderTest(small).toBeGreaterThanOrEqual(big)).toThrow( + 'toBeGreaterThanOrEqual', + ); + + expect(() => expectUnderTest(small).not.toBeLessThanOrEqual(big)).toThrow( + 'toBeLessThanOrEqual', + ); + + expect(() => expectUnderTest(big).not.toBeGreaterThanOrEqual(small)).toThrow( + 'toBeGreaterThanOrEqual', + ); + + expect(() => expectUnderTest(big).toBeLessThanOrEqual(small)).toThrow( + 'toBeLessThanOrEqual', + ); + }); + }); + + [ + [1, 1], + [Number.MIN_VALUE, Number.MIN_VALUE], + [Number.MAX_VALUE, Number.MAX_VALUE], + [Infinity, Infinity], + [-Infinity, -Infinity], + ].forEach(([n1, n2]) => { + test(`equal numbers: [${n1}, ${n2}]`, () => { + expectUnderTest(n1).toBeGreaterThanOrEqual(n2); + expectUnderTest(n1).toBeLessThanOrEqual(n2); + + expect(() => + expectUnderTest(n1).not.toBeGreaterThanOrEqual(n2), + ).toThrowErrorMatchingSnapshot(); + + expect(() => + expectUnderTest(n1).not.toBeLessThanOrEqual(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [BigInt(1), BigInt(1)], + [BigInt(Number.MAX_SAFE_INTEGER), BigInt(Number.MAX_SAFE_INTEGER)], + ].forEach(([n1, n2], index) => { + test(`equal numbers: [${n1}, ${n2}] (${index})`, () => { + expectUnderTest(n1).toBeGreaterThanOrEqual(n2); + expectUnderTest(n1).toBeLessThanOrEqual(n2); + + expect(() => expectUnderTest(n1).not.toBeGreaterThanOrEqual(n2)).toThrow( + 'toBeGreaterThanOrEqual', + ); + + expect(() => expectUnderTest(n1).not.toBeLessThanOrEqual(n2)).toThrow( + 'toBeLessThanOrEqual', + ); + }); + }); + }, +); + +test.describe('.toContain(), .toContainEqual()', () => { + const typedArray = new Int8Array(2); + typedArray[0] = 0; + typedArray[1] = 1; + + test('iterable', () => { + // different node versions print iterable differently, so we can't + // use snapshots here. + const iterable = { + *[Symbol.iterator]() { + yield 1; + yield 2; + yield 3; + }, + }; + + expectUnderTest(iterable).toContain(2); + expectUnderTest(iterable).toContainEqual(2); + expect(() => expectUnderTest(iterable).not.toContain(1)).toThrow('toContain'); + expect(() => expectUnderTest(iterable).not.toContainEqual(1)).toThrow( + 'toContainEqual', + ); + }); + + [ + [[1, 2, 3, 4], 1], + [['a', 'b', 'c', 'd'], 'a'], + [[undefined, null], null], + [[undefined, null], undefined], + [[Symbol.for('a')], Symbol.for('a')], + ['abcdef', 'abc'], + ['11112111', '2'], + [new Set(['abc', 'def']), 'abc'], + [typedArray, 1], + ].forEach(([list, v]) => { + test(`'${stringify(list)}' contains '${stringify(v)}'`, () => { + expectUnderTest(list).toContain(v); + + expect(() => + expectUnderTest(list).not.toContain(v), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [[BigInt(1), BigInt(2), BigInt(3), BigInt(4)], BigInt(1)], + [[1, 2, 3, BigInt(3), 4], BigInt(3)], + ].forEach(([list, v]) => { + test(`'${stringify(list)}' contains '${stringify(v)}'`, () => { + expectUnderTest(list).toContain(v); + + expect(() => expectUnderTest(list).not.toContain(v)).toThrow('toContain'); + }); + }); + + [ + [[1, 2, 3], 4], + [[null, undefined], 1], + [[{}, []], []], + [[{}, []], {}], + ].forEach(([list, v]) => { + test(`'${stringify(list)}' does not contain '${stringify(v)}'`, () => { + expectUnderTest(list).not.toContain(v); + + expect(() => + expectUnderTest(list).toContain(v), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [[[BigInt(1), BigInt(2), BigInt(3)], 3]].forEach(([list, v]) => { + test(`'${stringify(list)}' does not contain '${stringify(v)}'`, () => { + expectUnderTest(list).not.toContain(v); + + expect(() => expectUnderTest(list).toContain(v)).toThrow('toContain'); + }); + }); + + test('error cases', () => { + expect(() => expectUnderTest(null).toContain(1)).toThrowErrorMatchingSnapshot(); + expect(() => expectUnderTest('-0').toContain(-0)).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest('null').toContain(null), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest('undefined').toContain(undefined), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest('false').toContain(false), + ).toThrowErrorMatchingSnapshot(); + expect(() => expectUnderTest('1').toContain(BigInt(1))).toThrow('toContain'); + }); + + [ + [[1, 2, 3, 4], 1], + [['a', 'b', 'c', 'd'], 'a'], + [[undefined, null], null], + [[undefined, null], undefined], + [[Symbol.for('a')], Symbol.for('a')], + [[{ a: 'b' }, { a: 'c' }], { a: 'b' }], + [new Set([1, 2, 3, 4]), 1], + [typedArray, 1], + ].forEach(([list, v]) => { + test(`'${stringify(list)}' contains a value equal to '${stringify( + v, + )}'`, () => { + expectUnderTest(list).toContainEqual(v); + expect(() => + expectUnderTest(list).not.toContainEqual(v), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [[[{ a: 'b' }, { a: 'c' }], { a: 'd' }]].forEach(([list, v]) => { + test(`'${stringify(list)}' does not contain a value equal to'${stringify( + v, + )}'`, () => { + expectUnderTest(list).not.toContainEqual(v); + + expect(() => + expectUnderTest(list).toContainEqual(v), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('error cases for toContainEqual', () => { + expect(() => + expectUnderTest(null).toContainEqual(1), + ).toThrowErrorMatchingSnapshot(); + }); +}); + +test.describe('.toBeCloseTo', () => { + [ + [0, 0], + [0, 0.001], + [1.23, 1.229], + [1.23, 1.226], + [1.23, 1.225], + [1.23, 1.234], + [Infinity, Infinity], + [-Infinity, -Infinity], + ].forEach(([n1, n2]) => { + test(`{pass: true} expect(${n1}).toBeCloseTo(${n2})`, () => { + expectUnderTest(n1).toBeCloseTo(n2); + + expect(() => + expectUnderTest(n1).not.toBeCloseTo(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [0, 0.01], + [1, 1.23], + [1.23, 1.2249999], + [Infinity, -Infinity], + [Infinity, 1.23], + [-Infinity, -1.23], + ].forEach(([n1, n2]) => { + test(`{pass: false} expect(${n1}).toBeCloseTo(${n2})`, () => { + expectUnderTest(n1).not.toBeCloseTo(n2); + + expect(() => + expectUnderTest(n1).toBeCloseTo(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [3.141592e-7, 3e-7, 8], + [56789, 51234, -4], + ].forEach(([n1, n2, p]) => { + test(`{pass: false} expect(${n1}).toBeCloseTo(${n2}, ${p})`, () => { + expectUnderTest(n1).not.toBeCloseTo(n2, p); + + expect(() => + expectUnderTest(n1).toBeCloseTo(n2, p), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [0, 0.1, 0], + [0, 0.0001, 3], + [0, 0.000004, 5], + [2.0000002, 2, 5], + ].forEach(([n1, n2, p]) => { + test(`{pass: true} expect(${n1}).toBeCloseTo(${n2}, ${p})`, () => { + expectUnderTest(n1).toBeCloseTo(n2, p); + + expect(() => + expectUnderTest(n1).not.toBeCloseTo(n2, p), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test.describe('throws: Matcher error', () => { + test('promise empty isNot false received', () => { + const precision = 3; + const expected = 0; + const received = ''; + expect(() => { + expectUnderTest(received).toBeCloseTo(expected, precision); + }).toThrowErrorMatchingSnapshot(); + }); + + test('promise empty isNot true expected', () => { + const received = 0.1; + // expected is undefined + expect(() => { + expectUnderTestAsAny(received).not.toBeCloseTo(); + }).toThrowErrorMatchingSnapshot(); + }); + + test('promise rejects isNot false expected', () => { + const expected = '0'; + const received = Promise.reject(0.01); + return expect( + expectUnderTestAsAny(received).rejects.toBeCloseTo(expected), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + + test('promise rejects isNot true received', () => { + const expected = 0; + const received = Promise.reject(Symbol('0.1')); + return expect( + expectUnderTest(received).rejects.not.toBeCloseTo(expected), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + + test('promise resolves isNot false received', () => { + const precision = 3; + const expected = 0; + const received = Promise.resolve(false); + return expect( + expectUnderTest(received).resolves.toBeCloseTo(expected, precision), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + + test('promise resolves isNot true expected', () => { + const precision = 3; + const expected = null; + const received = Promise.resolve(0.1); + return expect( + expectUnderTest(received).resolves.not.toBeCloseTo(expected, precision), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + }); +}); + +test.describe('.toMatch()', () => { + [ + ['foo', 'foo'], + ['Foo bar', /^foo/i], + ].forEach(([n1, n2]) => { + test(`{pass: true} expect(${n1}).toMatch(${n2})`, () => { + expectUnderTest(n1).toMatch(n2); + + expect(() => + expectUnderTest(n1).not.toMatch(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + ['bar', 'foo'], + ['bar', /foo/], + ].forEach(([n1, n2]) => { + test(`throws: [${n1}, ${n2}]`, () => { + expect(() => expectUnderTest(n1).toMatch(n2)).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [1, 'foo'], + [{}, 'foo'], + [[], 'foo'], + [true, 'foo'], + [/foo/i, 'foo'], + [() => { }, 'foo'], + [undefined, 'foo'], + ].forEach(([n1, n2]) => { + test( + 'throws if non String actual value passed:' + + ` [${stringify(n1)}, ${stringify(n2)}]`, + () => { + // @ts-ignore + expect(() => expectUnderTest(n1).toMatch(n2)).toThrowErrorMatchingSnapshot(); + }, + ); + }); + + [ + ['foo', 1], + ['foo', {}], + ['foo', []], + ['foo', true], + ['foo', () => { }], + ['foo', undefined], + ].forEach(([n1, n2]) => { + test( + 'throws if non String/RegExp expected value passed:' + + ` [${stringify(n1)}, ${stringify(n2)}]`, + () => { + // @ts-ignore + expect(() => expectUnderTest(n1).toMatch(n2)).toThrowErrorMatchingSnapshot(); + }, + ); + }); + + test('escapes strings properly', () => { + expectUnderTest('this?: throws').toMatch('this?: throws'); + }); + + test('does not maintain RegExp state between calls', () => { + const regex = /[f]\d+/gi; + expectUnderTest('f123').toMatch(regex); + expectUnderTest('F456').toMatch(regex); + expectUnderTest(regex.lastIndex).toBe(0); + }); +}); + +test.describe('.toHaveLength', () => { + [ + [[1, 2], 2], + [[], 0], + [['a', 'b'], 2], + ['abc', 3], + ['', 0], + [() => { }, 0], + ].forEach(([received, length]) => { + test(`{pass: true} expect(${stringify( + received, + )}).toHaveLength(${length})`, () => { + expectUnderTestAsAny(received).toHaveLength(length); + expect(() => + expectUnderTestAsAny(received).not.toHaveLength(length), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [[1, 2], 3], + [[], 1], + [['a', 'b'], 99], + ['abc', 66], + ['', 1], + ].forEach(([received, length]) => { + test(`{pass: false} expect(${stringify( + received, + )}).toHaveLength(${length})`, () => { + expectUnderTestAsAny(received).not.toHaveLength(length); + expect(() => + expectUnderTestAsAny(received).toHaveLength(length), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('error cases', () => { + expect(() => + expectUnderTest({ a: 9 }).toHaveLength(1), + ).toThrowErrorMatchingSnapshot(); + expect(() => expectUnderTest(0).toHaveLength(1)).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(undefined).not.toHaveLength(1), + ).toThrowErrorMatchingSnapshot(); + }); + + test.describe('matcher error expected length', () => { + test('not number', () => { + const expected = '3'; + const received = 'abc'; + expect(() => { + expectUnderTestAsAny(received).not.toHaveLength(expected); + }).toThrowErrorMatchingSnapshot(); + }); + + test('number Infinity', () => { + const expected = Infinity; + const received = Promise.reject('abc'); + return expect( + expectUnderTest(received).rejects.toHaveLength(expected), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + + test('number NaN', () => { + const expected = NaN; + const received = Promise.reject('abc'); + return expect( + expectUnderTest(received).rejects.not.toHaveLength(expected), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + + test('number float', () => { + const expected = 0.5; + const received = Promise.resolve('abc'); + return expect( + expectUnderTest(received).resolves.toHaveLength(expected), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + + test('number negative integer', () => { + const expected = -3; + const received = Promise.resolve('abc'); + return expect( + expectUnderTest(received).resolves.not.toHaveLength(expected), + // @ts-ignore + ).rejects.toThrowErrorMatchingSnapshotAsync(); + }); + }); +}); + +test.describe('.toHaveProperty()', () => { + class Foo { + val: any; + get a() { + return undefined; + } + get b() { + return 'b'; + } + + set setter(val) { + this.val = val; + } + } + + class Foo2 extends Foo { + get c() { + return 'c'; + } + } + const foo2 = new Foo2(); + foo2.setter = true; + + function E(nodeName) { + this.nodeName = nodeName.toUpperCase(); + } + E.prototype.nodeType = 1; + + const memoized = function() { }; + memoized.memo = []; + + const pathDiff = ['children', 0]; + + const receivedDiffSingle = { + children: ['"That cartoon"'], + props: null, + type: 'p', + }; + const valueDiffSingle = '"That cat cartoon"'; + + const receivedDiffMultiple = { + children: [ + 'Roses are red.\nViolets are blue.\nTesting with Jest is good for you.', + ], + props: null, + type: 'pre', + }; + const valueDiffMultiple = + 'Roses are red, violets are blue.\nTesting with Jest\nIs good for you.'; + + [ + [{ a: { b: { c: { d: 1 } } } }, 'a.b.c.d', 1], + [{ a: { b: { c: { d: 1 } } } }, ['a', 'b', 'c', 'd'], 1], + [{ 'a.b.c.d': 1 }, ['a.b.c.d'], 1], + [{ a: { b: [1, 2, 3] } }, ['a', 'b', 1], 2], + [{ a: { b: [1, 2, 3] } }, ['a', 'b', 1], expect.any(Number)], + [{ a: 0 }, 'a', 0], + [{ a: { b: undefined } }, 'a.b', undefined], + [{ a: { b: { c: 5 } } }, 'a.b', { c: 5 }], + [{ a: { b: [{ c: [{ d: 1 }] }] } }, 'a.b[0].c[0].d', 1], + [{ a: { b: [{ c: { d: [{ e: 1 }, { f: 2 }] } }] } }, 'a.b[0].c.d[1].f', 2], + [{ a: { b: [[{ c: [{ d: 1 }] }]] } }, 'a.b[0][0].c[0].d', 1], + [Object.assign(Object.create(null), { property: 1 }), 'property', 1], + [new Foo(), 'a', undefined], + [new Foo(), 'b', 'b'], + [new Foo(), 'setter', undefined], + [foo2, 'a', undefined], + [foo2, 'c', 'c'], + [foo2, 'val', true], + [new E('div'), 'nodeType', 1], + ['', 'length', 0], + [memoized, 'memo', []], + [{ '': 1 }, '', 1], + ].forEach(([obj, keyPath, value]) => { + test(`{pass: true} expect(${stringify( + obj, + )}).toHaveProperty('${keyPath}', ${stringify(value)})`, () => { + expectUnderTestAsAny(obj).toHaveProperty(keyPath, value); + expect(() => + expectUnderTestAsAny(obj).not.toHaveProperty(keyPath, value), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [{ a: { b: { c: { d: 1 } } } }, 'a.b.ttt.d', 1], + [{ a: { b: { c: { d: 1 } } } }, 'a.b.c.d', 2], + [{ 'a.b.c.d': 1 }, 'a.b.c.d', 2], + [{ 'a.b.c.d': 1 }, ['a.b.c.d'], 2], + [receivedDiffSingle, pathDiff, valueDiffSingle], + [receivedDiffMultiple, pathDiff, valueDiffMultiple], + [{ a: { b: { c: { d: 1 } } } }, ['a', 'b', 'c', 'd'], 2], + [{ a: { b: { c: {} } } }, 'a.b.c.d', 1], + [{ a: 1 }, 'a.b.c.d', 5], + [{}, 'a', 'test'], + [{ a: { b: 3 } }, 'a.b', undefined], + [1, 'a.b.c', 'test'], + ['abc', 'a.b.c', { a: 5 }], + [{ a: { b: { c: 5 } } }, 'a.b', { c: 4 }], + [new Foo(), 'a', 'a'], + [new Foo(), 'b', undefined], + [{ a: {} }, 'a.b', undefined], + ].forEach(([obj, keyPath, value], index) => { + test(`{pass: false} expect(${stringify( + obj, + )}).toHaveProperty('${keyPath}', ${stringify(value)}) (${index})`, () => { + expect(() => + expectUnderTestAsAny(obj).toHaveProperty(keyPath, value), + ).toThrowErrorMatchingSnapshot(); + expectUnderTestAsAny(obj).not.toHaveProperty(keyPath, value); + }); + }); + + [ + [{ a: { b: { c: { d: 1 } } } }, 'a.b.c.d'], + [{ a: { b: { c: { d: 1 } } } }, ['a', 'b', 'c', 'd']], + [{ 'a.b.c.d': 1 }, ['a.b.c.d']], + [{ a: { b: [1, 2, 3] } }, ['a', 'b', 1]], + [{ a: 0 }, 'a'], + [{ a: { b: undefined } }, 'a.b'], + ].forEach(([obj, keyPath]) => { + test(`{pass: true} expect(${stringify( + obj, + )}).toHaveProperty('${keyPath}')`, () => { + expectUnderTestAsAny(obj).toHaveProperty(keyPath); + expect(() => + expectUnderTestAsAny(obj).not.toHaveProperty(keyPath), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + [ + [{ a: { b: { c: {} } } }, 'a.b.c.d'], + [{ a: { b: { c: {} } } }, '.a.b.c'], + [{ a: 1 }, 'a.b.c.d'], + [{}, 'a'], + [1, 'a.b.c'], + ['abc', 'a.b.c'], + [false, 'key'], + [0, 'key'], + ['', 'key'], + [Symbol(), 'key'], + [Object.assign(Object.create(null), { key: 1 }), 'not'], + ].forEach(([obj, keyPath]) => { + test(`{pass: false} expect(${stringify( + obj, + )}).toHaveProperty('${keyPath}')`, () => { + expect(() => + expectUnderTest(obj).toHaveProperty(keyPath), + ).toThrowErrorMatchingSnapshot(); + expectUnderTest(obj).not.toHaveProperty(keyPath); + }); + }); + + [ + [null, 'a.b'], + [undefined, 'a'], + [{ a: { b: {} } }, undefined], + [{ a: { b: {} } }, null], + [{ a: { b: {} } }, 1], + [{}, []], // Residue: pass must be initialized + ].forEach(([obj, keyPath]) => { + test(`{error} expect(${stringify( + obj, + )}).toHaveProperty('${keyPath}')`, () => { + expect(() => + expectUnderTestAsAny(obj).toHaveProperty(keyPath), + ).toThrowErrorMatchingSnapshot(); + }); + }); +}); + +test.describe('toMatchObject()', () => { + class Foo { + get a() { + return undefined; + } + get b() { + return 'b'; + } + } + + class Sub extends Foo { + get c() { + return 'c'; + } + } + + const withDefineProperty = (obj, key, val) => { + Object.defineProperty(obj, key, { + get() { + return val; + }, + }); + + return obj; + }; + + const testNotToMatchSnapshots = tuples => { + tuples.forEach(([n1, n2]) => { + test(`{pass: true} expect(${stringify(n1)}).toMatchObject(${stringify( + n2, + )})`, () => { + expectUnderTest(n1).toMatchObject(n2); + expect(() => + expectUnderTest(n1).not.toMatchObject(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }; + + const testToMatchSnapshots = tuples => { + tuples.forEach(([n1, n2]) => { + test(`{pass: false} expect(${stringify(n1)}).toMatchObject(${stringify( + n2, + )})`, () => { + expectUnderTest(n1).not.toMatchObject(n2); + expect(() => + expectUnderTest(n1).toMatchObject(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }; + + test.describe('circular references', () => { + test.describe('simple circular references', () => { + const circularObjA1: any = { a: 'hello' }; + circularObjA1.ref = circularObjA1; + + const circularObjB: any = { a: 'world' }; + circularObjB.ref = circularObjB; + + const circularObjA2: any = { a: 'hello' }; + circularObjA2.ref = circularObjA2; + + const primitiveInsteadOfRef: any = {}; + primitiveInsteadOfRef.ref = 'not a ref'; + + testNotToMatchSnapshots([ + [circularObjA1, {}], + [circularObjA2, circularObjA1], + ]); + + testToMatchSnapshots([ + [{}, circularObjA1], + [circularObjA1, circularObjB], + [primitiveInsteadOfRef, circularObjA1], + ]); + }); + + test.describe('transitive circular references', () => { + const transitiveCircularObjA1: any = { a: 'hello' }; + transitiveCircularObjA1.nestedObj = { parentObj: transitiveCircularObjA1 }; + + const transitiveCircularObjA2: any = { a: 'hello' }; + transitiveCircularObjA2.nestedObj = { + parentObj: transitiveCircularObjA2, + }; + + const transitiveCircularObjB: any = { a: 'world' }; + transitiveCircularObjB.nestedObj = { + parentObj: transitiveCircularObjB, + }; + + const primitiveInsteadOfRef: any = {}; + primitiveInsteadOfRef.nestedObj = { + parentObj: 'not the parent ref', + }; + + testNotToMatchSnapshots([ + [transitiveCircularObjA1, {}], + [transitiveCircularObjA2, transitiveCircularObjA1], + ]); + + testToMatchSnapshots([ + [{}, transitiveCircularObjA1], + [transitiveCircularObjB, transitiveCircularObjA1], + [primitiveInsteadOfRef, transitiveCircularObjA1], + ]); + }); + }); + + testNotToMatchSnapshots([ + [{ a: 'b', c: 'd' }, { a: 'b' }], + [ + { a: 'b', c: 'd' }, + { a: 'b', c: 'd' }, + ], + [ + { a: 'b', t: { x: { r: 'r' }, z: 'z' } }, + { a: 'b', t: { z: 'z' } }, + ], + [{ a: 'b', t: { x: { r: 'r' }, z: 'z' } }, { t: { x: { r: 'r' } } }], + [{ a: [3, 4, 5], b: 'b' }, { a: [3, 4, 5] }], + [{ a: [3, 4, 5, 'v'], b: 'b' }, { a: [3, 4, 5, 'v'] }], + [{ a: 1, c: 2 }, { a: expectUnderTest.any(Number) }], + [{ a: { x: 'x', y: 'y' } }, { a: { x: expectUnderTest.any(String) } }], + [new Set([1, 2]), new Set([1, 2])], + [new Set([1, 2]), new Set([2, 1])], + [new Date('2015-11-30'), new Date('2015-11-30')], + [{ a: new Date('2015-11-30'), b: 'b' }, { a: new Date('2015-11-30') }], + [{ a: null, b: 'b' }, { a: null }], + [{ a: undefined, b: 'b' }, { a: undefined }], + [{ a: [{ a: 'a', b: 'b' }] }, { a: [{ a: 'a' }] }], + [ + [1, 2], + [1, 2], + ], + [{ a: undefined }, { a: undefined }], + [[], []], + [new Error('foo'), new Error('foo')], + [new Error('bar'), { message: 'bar' }], + [new Foo(), { a: undefined, b: 'b' }], + [Object.assign(Object.create(null), { a: 'b' }), { a: 'b' }], + [ + { a: 'b', c: 'd', [Symbol.for('jest')]: 'jest' }, + { a: 'b', [Symbol.for('jest')]: 'jest' }, + ], + [ + { a: 'b', c: 'd', [Symbol.for('jest')]: 'jest' }, + { a: 'b', c: 'd', [Symbol.for('jest')]: 'jest' }, + ], + // These snapshots will show {} as the object because the properties + // are not enumerable. We will need to somehow make the serialization of + // these keys a little smarter before reporting accurately. + [new Sub(), { a: undefined, b: 'b', c: 'c' }], + [withDefineProperty(new Sub(), 'd', 4), { d: 4 }], + [{ a: 'b', toString() { } }, { toString: expectUnderTest.any(Function) }], + ]); + + testToMatchSnapshots([ + [{ a: 'b', c: 'd' }, { e: 'b' }], + [ + { a: 'b', c: 'd' }, + { a: 'b!', c: 'd' }, + ], + [{ a: 'a', c: 'd' }, { a: expectUnderTest.any(Number) }], + [ + { a: 'b', t: { x: { r: 'r' }, z: 'z' } }, + { a: 'b', t: { z: [3] } }, + ], + [{ a: 'b', t: { x: { r: 'r' }, z: 'z' } }, { t: { l: { r: 'r' } } }], + [{ a: [3, 4, 5], b: 'b' }, { a: [3, 4, 5, 6] }], + [{ a: [3, 4, 5], b: 'b' }, { a: [3, 4] }], + [{ a: [3, 4, 'v'], b: 'b' }, { a: ['v'] }], + [{ a: [3, 4, 5], b: 'b' }, { a: { b: 4 } }], + [{ a: [3, 4, 5], b: 'b' }, { a: { b: expectUnderTest.any(String) } }], + [ + [1, 2], + [1, 3], + ], + [[0], [-0]], + [new Set([1, 2]), new Set([2])], + [new Date('2015-11-30'), new Date('2015-10-10')], + [{ a: new Date('2015-11-30'), b: 'b' }, { a: new Date('2015-10-10') }], + [{ a: null, b: 'b' }, { a: '4' }], + [{ a: null, b: 'b' }, { a: undefined }], + [{ a: undefined }, { a: null }], + [{ a: [{ a: 'a', b: 'b' }] }, { a: [{ a: 'c' }] }], + [{ a: 1, b: 1, c: 1, d: { e: { f: 555 } } }, { d: { e: { f: 222 } } }], + [{}, { a: undefined }], + [ + [1, 2, 3], + [2, 3, 1], + ], + [ + [1, 2, 3], + [1, 2, 2], + ], + [new Error('foo'), new Error('bar')], + [Object.assign(Object.create(null), { a: 'b' }), { c: 'd' }], + [ + { a: 'b', c: 'd', [Symbol.for('jest')]: 'jest' }, + { a: 'c', [Symbol.for('jest')]: expect.any(String) }, + ], + [{ a: 'b' }, { toString: expectUnderTest.any(Function) }], + ]); + + [ + [null, {}], + [4, {}], + ['44', {}], + [true, {}], + [undefined, {}], + [{}, null], + [{}, 4], + [{}, 'some string'], + [{}, true], + [{}, undefined], + ].forEach(([n1, n2]: [any, any, string]) => { + test(`throws expect(${stringify(n1)}).toMatchObject(${stringify( + n2, + )})`, () => { + expect(() => + expectUnderTest(n1).toMatchObject(n2), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('does not match properties up in the prototype chain', () => { + const a: any = {}; + a.ref = a; + + const b = Object.create(a); + b.other = 'child'; + + const matcher: any = { other: 'child' }; + matcher.ref = matcher; + + expectUnderTest(b).not.toMatchObject(matcher); + expect(() => + expectUnderTest(b).toMatchObject(matcher), + ).toThrowErrorMatchingSnapshot(); + }); + + test('toMatchObject ignores symbol key properties', () => { + // issue 13638 + const sym = Symbol('foo'); + const sym2 = Symbol('foo2'); + expectUnderTestAsAny({}).not.toMatchObject({ [sym]: true }); + expectUnderTestAsAny({ [sym]: true }).not.toMatchObject({ [sym2]: true }); + expectUnderTestAsAny({ [sym]: true }).not.toMatchObject({ [sym]: false }); + expectUnderTestAsAny({ example: 10, [sym]: true }).not.toMatchObject({ + example: 12, + [sym]: true, + }); + expectUnderTestAsAny({ [sym]: true }).toMatchObject({ [sym]: true }); + expectUnderTestAsAny({ example: 10, [sym]: true }).toMatchObject({ + example: 10, + [sym]: true, + }); + }); +}); diff --git a/tests/expect/spyMatchers.snapshots.js b/tests/expect/spyMatchers.snapshots.js new file mode 100644 index 0000000000000..720620fae6eaf --- /dev/null +++ b/tests/expect/spyMatchers.snapshots.js @@ -0,0 +1,2600 @@ +module.exports["toBeCalled works only on spies or mock.fn"] = `expect(received).toBeCalled() + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toBeCalled passes when called"] = `expect(jest.fn()).not.toBeCalled() + +Expected number of calls: 0 +Received number of calls: 1 + +1: "arg0", "arg1", "arg2"`; + +module.exports["toBeCalled .not passes when called"] = `expect(spy).toBeCalled() + +Expected number of calls: >= 1 +Received number of calls: 0`; + +module.exports["toBeCalled fails with any argument passed"] = `expect(received).toBeCalled() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toBeCalled .not fails with any argument passed"] = `expect(received).not.toBeCalled() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toBeCalled includes the custom mock name in the error message"] = `expect(named-mock).not.toBeCalled() + +Expected number of calls: 0 +Received number of calls: 1 + +1: called with 0 arguments`; + +module.exports["toHaveBeenCalled works only on spies or mock.fn"] = `expect(received).toHaveBeenCalled() + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveBeenCalled passes when called"] = `expect(jest.fn()).not.toHaveBeenCalled() + +Expected number of calls: 0 +Received number of calls: 1 + +1: "arg0", "arg1", "arg2"`; + +module.exports["toHaveBeenCalled .not passes when called"] = `expect(spy).toHaveBeenCalled() + +Expected number of calls: >= 1 +Received number of calls: 0`; + +module.exports["toHaveBeenCalled fails with any argument passed"] = `expect(received).toHaveBeenCalled() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toHaveBeenCalled .not fails with any argument passed"] = `expect(received).not.toHaveBeenCalled() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toHaveBeenCalled includes the custom mock name in the error message"] = `expect(named-mock).not.toHaveBeenCalled() + +Expected number of calls: 0 +Received number of calls: 1 + +1: called with 0 arguments`; + +module.exports["toBeCalledTimes .not works only on spies or mock.fn"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toBeCalledTimes only accepts a number argument"] = `expect(received).toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toBeCalledTimes only accepts a number argument #1"] = `expect(received).toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toBeCalledTimes only accepts a number argument #2"] = `expect(received).toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toBeCalledTimes only accepts a number argument #3"] = `expect(received).toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toBeCalledTimes only accepts a number argument #4"] = `expect(received).toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toBeCalledTimes only accepts a number argument #5"] = `expect(received).toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toBeCalledTimes .not only accepts a number argument"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toBeCalledTimes .not only accepts a number argument #1"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toBeCalledTimes .not only accepts a number argument #2"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toBeCalledTimes .not only accepts a number argument #3"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toBeCalledTimes .not only accepts a number argument #4"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toBeCalledTimes .not only accepts a number argument #5"] = `expect(received).not.toBeCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toBeCalledTimes passes if function called equal to expected times"] = `expect(spy).not.toBeCalledTimes(expected) + +Expected number of calls: not 2`; + +module.exports["toBeCalledTimes .not passes if function called more than expected times"] = `expect(jest.fn()).toBeCalledTimes(expected) + +Expected number of calls: 2 +Received number of calls: 3`; + +module.exports["toBeCalledTimes .not passes if function called less than expected times"] = `expect(jest.fn()).toBeCalledTimes(expected) + +Expected number of calls: 2 +Received number of calls: 1`; + +module.exports["toBeCalledTimes includes the custom mock name in the error message"] = `expect(named-mock).toBeCalledTimes(expected) + +Expected number of calls: 2 +Received number of calls: 1`; + +module.exports["toHaveBeenCalledTimes .not works only on spies or mock.fn"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveBeenCalledTimes only accepts a number argument"] = `expect(received).toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toHaveBeenCalledTimes only accepts a number argument #1"] = `expect(received).toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toHaveBeenCalledTimes only accepts a number argument #2"] = `expect(received).toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toHaveBeenCalledTimes only accepts a number argument #3"] = `expect(received).toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toHaveBeenCalledTimes only accepts a number argument #4"] = `expect(received).toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toHaveBeenCalledTimes only accepts a number argument #5"] = `expect(received).toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toHaveBeenCalledTimes .not only accepts a number argument"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toHaveBeenCalledTimes .not only accepts a number argument #1"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toHaveBeenCalledTimes .not only accepts a number argument #2"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toHaveBeenCalledTimes .not only accepts a number argument #3"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toHaveBeenCalledTimes .not only accepts a number argument #4"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toHaveBeenCalledTimes .not only accepts a number argument #5"] = `expect(received).not.toHaveBeenCalledTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toHaveBeenCalledTimes passes if function called equal to expected times"] = `expect(spy).not.toHaveBeenCalledTimes(expected) + +Expected number of calls: not 2`; + +module.exports["toHaveBeenCalledTimes .not passes if function called more than expected times"] = `expect(jest.fn()).toHaveBeenCalledTimes(expected) + +Expected number of calls: 2 +Received number of calls: 3`; + +module.exports["toHaveBeenCalledTimes .not passes if function called less than expected times"] = `expect(jest.fn()).toHaveBeenCalledTimes(expected) + +Expected number of calls: 2 +Received number of calls: 1`; + +module.exports["toHaveBeenCalledTimes includes the custom mock name in the error message"] = `expect(named-mock).toHaveBeenCalledTimes(expected) + +Expected number of calls: 2 +Received number of calls: 1`; + +module.exports["lastCalledWith works only on spies or mock.fn"] = `expect(received).lastCalledWith(...expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["lastCalledWith works when not called"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo", "bar" + +Number of calls: 0`; + +module.exports["lastCalledWith works with arguments that don't match"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar1" + +Number of calls: 1`; + +module.exports["lastCalledWith works with arguments that don't match in number of arguments"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar", "plop" + +Number of calls: 1`; + +module.exports["lastCalledWith works with arguments that don't match with matchers"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: Any, Any +Received: "foo", "bar" + +Number of calls: 1`; + +module.exports["lastCalledWith works with arguments that don't match with matchers even when argument is undefined"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo", Any +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["lastCalledWith works with arguments that don't match in size even if one is an optional matcher"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo", optionalFn<> +Received: "foo" + +Number of calls: 1`; + +module.exports["lastCalledWith works with arguments that match"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["lastCalledWith works with arguments that match with matchers"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not Any, Any +Received: 0, ["foo", "bar"] + +Number of calls: 1`; + +module.exports["lastCalledWith works with trailing undefined arguments"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo" +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["lastCalledWith works with trailing undefined arguments if requested by the match query"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not "foo", undefined + +Number of calls: 1`; + +module.exports["lastCalledWith works with trailing undefined arguments when explicitly requested as optional by matcher"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not "foo", optionalFn<> +Received: 0, ["foo", undefined] + +Number of calls: 1`; + +module.exports["lastCalledWith works with Map"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of calls: 1`; + +module.exports["lastCalledWith works with Map #1"] = `expect(jest.fn()).lastCalledWith(...expected) + +- Expected ++ Received + + Map { +- "a" => "b", +- "b" => "a", ++ 1 => 2, ++ 2 => 1, + }, + +Number of calls: 1`; + +module.exports["lastCalledWith works with Set"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not Set {1, 2} + +Number of calls: 1`; + +module.exports["lastCalledWith works with Set #1"] = `expect(jest.fn()).lastCalledWith(...expected) + +- Expected ++ Received + + Set { +- 3, +- 4, ++ 1, ++ 2, + }, + +Number of calls: 1`; + +module.exports["lastCalledWith works with Immutable.js objects"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not Immutable.Map {"a": {"b": "c"}}, Immutable.Map {"a": {"b": "c"}} + +Number of calls: 1`; + +module.exports["lastCalledWith works with many arguments"] = `expect(jest.fn()).not.lastCalledWith(...expected) + +Expected: not "foo", "bar" +Received + 2: "foo", "bar1" +-> 3: "foo", "bar" + +Number of calls: 3`; + +module.exports["lastCalledWith works with many arguments that don't match"] = `expect(jest.fn()).lastCalledWith(...expected) + +Expected: "foo", "bar" +Received + 2: "foo", "bar2" +-> 3: "foo", "bar3" + +Number of calls: 3`; + +module.exports["lastCalledWith includes the custom mock name in the error message"] = `expect(named-mock).not.lastCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works only on spies or mock.fn"] = `expect(received).toHaveBeenLastCalledWith(...expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveBeenLastCalledWith works when not called"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo", "bar" + +Number of calls: 0`; + +module.exports["toHaveBeenLastCalledWith works with arguments that don't match"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar1" + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with arguments that don't match in number of arguments"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar", "plop" + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with arguments that don't match with matchers"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: Any, Any +Received: "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with arguments that don't match with matchers even when argument is undefined"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo", Any +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with arguments that don't match in size even if one is an optional matcher"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo", optionalFn<> +Received: "foo" + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with arguments that match"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with arguments that match with matchers"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not Any, Any +Received: 0, ["foo", "bar"] + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with trailing undefined arguments"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo" +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with trailing undefined arguments if requested by the match query"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with trailing undefined arguments when explicitly requested as optional by matcher"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not "foo", optionalFn<> +Received: 0, ["foo", undefined] + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with Map"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with Map #1"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +- Expected ++ Received + + Map { +- "a" => "b", +- "b" => "a", ++ 1 => 2, ++ 2 => 1, + }, + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with Set"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not Set {1, 2} + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with Set #1"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +- Expected ++ Received + + Set { +- 3, +- 4, ++ 1, ++ 2, + }, + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with Immutable.js objects"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not Immutable.Map {"a": {"b": "c"}}, Immutable.Map {"a": {"b": "c"}} + +Number of calls: 1`; + +module.exports["toHaveBeenLastCalledWith works with many arguments"] = `expect(jest.fn()).not.toHaveBeenLastCalledWith(...expected) + +Expected: not "foo", "bar" +Received + 2: "foo", "bar1" +-> 3: "foo", "bar" + +Number of calls: 3`; + +module.exports["toHaveBeenLastCalledWith works with many arguments that don't match"] = `expect(jest.fn()).toHaveBeenLastCalledWith(...expected) + +Expected: "foo", "bar" +Received + 2: "foo", "bar2" +-> 3: "foo", "bar3" + +Number of calls: 3`; + +module.exports["toHaveBeenLastCalledWith includes the custom mock name in the error message"] = `expect(named-mock).not.toHaveBeenLastCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["nthCalledWith works only on spies or mock.fn"] = `expect(received).nthCalledWith(n, ...expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["nthCalledWith works when not called"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", "bar" + +Number of calls: 0`; + +module.exports["nthCalledWith works with arguments that don't match"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", "bar" +Received: "foo", "bar1" + +Number of calls: 1`; + +module.exports["nthCalledWith works with arguments that don't match in number of arguments"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", "bar" +Received: "foo", "bar", "plop" + +Number of calls: 1`; + +module.exports["nthCalledWith works with arguments that don't match with matchers"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: Any, Any +Received: "foo", "bar" + +Number of calls: 1`; + +module.exports["nthCalledWith works with arguments that don't match with matchers even when argument is undefined"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", Any +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["nthCalledWith works with arguments that don't match in size even if one is an optional matcher"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", optionalFn<> +Received: "foo" + +Number of calls: 1`; + +module.exports["nthCalledWith works with arguments that match"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["nthCalledWith works with arguments that match with matchers"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not Any, Any +Received: 0, ["foo", "bar"] + +Number of calls: 1`; + +module.exports["nthCalledWith works with trailing undefined arguments"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +Expected: "foo" +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["nthCalledWith works with trailing undefined arguments if requested by the match query"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", undefined + +Number of calls: 1`; + +module.exports["nthCalledWith works with trailing undefined arguments when explicitly requested as optional by matcher"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", optionalFn<> +Received: 0, ["foo", undefined] + +Number of calls: 1`; + +module.exports["nthCalledWith works with Map"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not Map {1 => 2, 2 => 1} + +Number of calls: 1`; + +module.exports["nthCalledWith works with Map #1"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +- Expected ++ Received + + Map { +- "a" => "b", +- "b" => "a", ++ 1 => 2, ++ 2 => 1, + }, + +Number of calls: 1`; + +module.exports["nthCalledWith works with Set"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not Set {1, 2} + +Number of calls: 1`; + +module.exports["nthCalledWith works with Set #1"] = `expect(jest.fn()).nthCalledWith(n, ...expected) + +n: 1 +- Expected ++ Received + + Set { +- 3, +- 4, ++ 1, ++ 2, + }, + +Number of calls: 1`; + +module.exports["nthCalledWith works with Immutable.js objects"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not Immutable.Map {"a": {"b": "c"}}, Immutable.Map {"a": {"b": "c"}} + +Number of calls: 1`; + +module.exports["nthCalledWith works with three calls"] = `expect(jest.fn()).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo1", "bar" +Received +-> 1: "foo1", "bar" + 2: "foo", "bar1" + +Number of calls: 3`; + +module.exports["nthCalledWith positive throw matcher error for n that is not positive integer"] = `expect(received).nthCalledWith(n, ...expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0`; + +module.exports["nthCalledWith positive throw matcher error for n that is not integer"] = `expect(received).nthCalledWith(n, ...expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0.1`; + +module.exports["nthCalledWith negative throw matcher error for n that is not integer"] = `expect(received).not.nthCalledWith(n, ...expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: Infinity`; + +module.exports["nthCalledWith includes the custom mock name in the error message"] = `expect(named-mock).not.nthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works only on spies or mock.fn"] = `expect(received).toHaveBeenNthCalledWith(n, ...expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveBeenNthCalledWith works when not called"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", "bar" + +Number of calls: 0`; + +module.exports["toHaveBeenNthCalledWith works with arguments that don't match"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", "bar" +Received: "foo", "bar1" + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with arguments that don't match in number of arguments"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", "bar" +Received: "foo", "bar", "plop" + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with arguments that don't match with matchers"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: Any, Any +Received: "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with arguments that don't match with matchers even when argument is undefined"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", Any +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with arguments that don't match in size even if one is an optional matcher"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: "foo", optionalFn<> +Received: "foo" + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with arguments that match"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with arguments that match with matchers"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not Any, Any +Received: 0, ["foo", "bar"] + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with trailing undefined arguments"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: "foo" +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with trailing undefined arguments if requested by the match query"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with trailing undefined arguments when explicitly requested as optional by matcher"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", optionalFn<> +Received: 0, ["foo", undefined] + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with Map"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not Map {1 => 2, 2 => 1} + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with Map #1"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +- Expected ++ Received + + Map { +- "a" => "b", +- "b" => "a", ++ 1 => 2, ++ 2 => 1, + }, + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with Set"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not Set {1, 2} + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with Set #1"] = `expect(jest.fn()).toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +- Expected ++ Received + + Set { +- 3, +- 4, ++ 1, ++ 2, + }, + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with Immutable.js objects"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not Immutable.Map {"a": {"b": "c"}}, Immutable.Map {"a": {"b": "c"}} + +Number of calls: 1`; + +module.exports["toHaveBeenNthCalledWith works with three calls"] = `expect(jest.fn()).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo1", "bar" +Received +-> 1: "foo1", "bar" + 2: "foo", "bar1" + +Number of calls: 3`; + +module.exports["toHaveBeenNthCalledWith positive throw matcher error for n that is not positive integer"] = `expect(received).toHaveBeenNthCalledWith(n, ...expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0`; + +module.exports["toHaveBeenNthCalledWith positive throw matcher error for n that is not integer"] = `expect(received).toHaveBeenNthCalledWith(n, ...expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0.1`; + +module.exports["toHaveBeenNthCalledWith negative throw matcher error for n that is not integer"] = `expect(received).not.toHaveBeenNthCalledWith(n, ...expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: Infinity`; + +module.exports["toHaveBeenNthCalledWith includes the custom mock name in the error message"] = `expect(named-mock).not.toHaveBeenNthCalledWith(n, ...expected) + +n: 1 +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toBeCalledWith works only on spies or mock.fn"] = `expect(received).toBeCalledWith(...expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toBeCalledWith works when not called"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo", "bar" + +Number of calls: 0`; + +module.exports["toBeCalledWith works with arguments that don't match"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar1" + +Number of calls: 1`; + +module.exports["toBeCalledWith works with arguments that don't match in number of arguments"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar", "plop" + +Number of calls: 1`; + +module.exports["toBeCalledWith works with arguments that don't match with matchers"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: Any, Any +Received: "foo", "bar" + +Number of calls: 1`; + +module.exports["toBeCalledWith works with arguments that don't match with matchers even when argument is undefined"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo", Any +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toBeCalledWith works with arguments that don't match in size even if one is an optional matcher"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo", optionalFn<> +Received: "foo" + +Number of calls: 1`; + +module.exports["toBeCalledWith works with arguments that match"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toBeCalledWith works with arguments that match with matchers"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not Any, Any +Received: 0, ["foo", "bar"] + +Number of calls: 1`; + +module.exports["toBeCalledWith works with trailing undefined arguments"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo" +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toBeCalledWith works with trailing undefined arguments if requested by the match query"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not "foo", undefined + +Number of calls: 1`; + +module.exports["toBeCalledWith works with trailing undefined arguments when explicitly requested as optional by matcher"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not "foo", optionalFn<> +Received: 0, ["foo", undefined] + +Number of calls: 1`; + +module.exports["toBeCalledWith works with Map"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of calls: 1`; + +module.exports["toBeCalledWith works with Map #1"] = `expect(jest.fn()).toBeCalledWith(...expected) + +- Expected ++ Received + + Map { +- "a" => "b", +- "b" => "a", ++ 1 => 2, ++ 2 => 1, + }, + +Number of calls: 1`; + +module.exports["toBeCalledWith works with Set"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not Set {1, 2} + +Number of calls: 1`; + +module.exports["toBeCalledWith works with Set #1"] = `expect(jest.fn()).toBeCalledWith(...expected) + +- Expected ++ Received + + Set { +- 3, +- 4, ++ 1, ++ 2, + }, + +Number of calls: 1`; + +module.exports["toBeCalledWith works with Immutable.js objects"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not Immutable.Map {"a": {"b": "c"}}, Immutable.Map {"a": {"b": "c"}} + +Number of calls: 1`; + +module.exports["toBeCalledWith works with many arguments"] = `expect(jest.fn()).not.toBeCalledWith(...expected) + +Expected: not "foo", "bar" +Received + 3: "foo", "bar" + +Number of calls: 3`; + +module.exports["toBeCalledWith works with many arguments that don't match"] = `expect(jest.fn()).toBeCalledWith(...expected) + +Expected: "foo", "bar" +Received + 1: "foo", "bar1" + 2: "foo", "bar2" + 3: "foo", "bar3" + +Number of calls: 3`; + +module.exports["toBeCalledWith includes the custom mock name in the error message"] = `expect(named-mock).not.toBeCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works only on spies or mock.fn"] = `expect(received).toHaveBeenCalledWith(...expected) + +Matcher error: received value must be a mock or spy function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveBeenCalledWith works when not called"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo", "bar" + +Number of calls: 0`; + +module.exports["toHaveBeenCalledWith works with arguments that don't match"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar1" + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with arguments that don't match in number of arguments"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo", "bar" +Received: "foo", "bar", "plop" + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with arguments that don't match with matchers"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: Any, Any +Received: "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with arguments that don't match with matchers even when argument is undefined"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo", Any +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with arguments that don't match in size even if one is an optional matcher"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo", optionalFn<> +Received: "foo" + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with arguments that match"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with arguments that match with matchers"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not Any, Any +Received: 0, ["foo", "bar"] + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with trailing undefined arguments"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo" +Received: "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with trailing undefined arguments if requested by the match query"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not "foo", undefined + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with trailing undefined arguments when explicitly requested as optional by matcher"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not "foo", optionalFn<> +Received: 0, ["foo", undefined] + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with Map"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with Map #1"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +- Expected ++ Received + + Map { +- "a" => "b", +- "b" => "a", ++ 1 => 2, ++ 2 => 1, + }, + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with Set"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not Set {1, 2} + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with Set #1"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +- Expected ++ Received + + Set { +- 3, +- 4, ++ 1, ++ 2, + }, + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with Immutable.js objects"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not Immutable.Map {"a": {"b": "c"}}, Immutable.Map {"a": {"b": "c"}} + +Number of calls: 1`; + +module.exports["toHaveBeenCalledWith works with many arguments"] = `expect(jest.fn()).not.toHaveBeenCalledWith(...expected) + +Expected: not "foo", "bar" +Received + 3: "foo", "bar" + +Number of calls: 3`; + +module.exports["toHaveBeenCalledWith works with many arguments that don't match"] = `expect(jest.fn()).toHaveBeenCalledWith(...expected) + +Expected: "foo", "bar" +Received + 1: "foo", "bar1" + 2: "foo", "bar2" + 3: "foo", "bar3" + +Number of calls: 3`; + +module.exports["toHaveBeenCalledWith includes the custom mock name in the error message"] = `expect(named-mock).not.toHaveBeenCalledWith(...expected) + +Expected: not "foo", "bar" + +Number of calls: 1`; + +module.exports["toReturn .not works only on mock.fn"] = `expect(received).not.toReturn() + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toReturn throw matcher error if received is spy"] = `expect(received).toReturn() + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function spy]`; + +module.exports["toReturn passes when returned"] = `expect(jest.fn()).not.toReturn() + +Expected number of returns: 0 +Received number of returns: 1 + +1: 42`; + +module.exports["toReturn passes when undefined is returned"] = `expect(jest.fn()).not.toReturn() + +Expected number of returns: 0 +Received number of returns: 1 + +1: undefined`; + +module.exports["toReturn passes when at least one call does not throw"] = `expect(jest.fn()).not.toReturn() + +Expected number of returns: 0 +Received number of returns: 2 + +1: 42 +3: 42 + +Received number of calls: 3`; + +module.exports["toReturn .not passes when not returned"] = `expect(jest.fn()).toReturn() + +Expected number of returns: >= 1 +Received number of returns: 0`; + +module.exports["toReturn .not passes when all calls throw"] = `expect(jest.fn()).toReturn() + +Expected number of returns: >= 1 +Received number of returns: 0 +Received number of calls: 2`; + +module.exports["toReturn .not passes when a call throws undefined"] = `expect(jest.fn()).toReturn() + +Expected number of returns: >= 1 +Received number of returns: 0 +Received number of calls: 1`; + +module.exports["toReturn fails with any argument passed"] = `expect(received).toReturn() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toReturn .not fails with any argument passed"] = `expect(received).not.toReturn() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toReturn includes the custom mock name in the error message"] = `expect(named-mock).not.toReturn() + +Expected number of returns: 0 +Received number of returns: 1 + +1: 42`; + +module.exports["toReturn incomplete recursive calls are handled properly"] = `expect(jest.fn()).toReturn() + +Expected number of returns: >= 1 +Received number of returns: 0 +Received number of calls: 4`; + +module.exports["toHaveReturned .not works only on mock.fn"] = `expect(received).not.toHaveReturned() + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveReturned throw matcher error if received is spy"] = `expect(received).toHaveReturned() + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function spy]`; + +module.exports["toHaveReturned passes when returned"] = `expect(jest.fn()).not.toHaveReturned() + +Expected number of returns: 0 +Received number of returns: 1 + +1: 42`; + +module.exports["toHaveReturned passes when undefined is returned"] = `expect(jest.fn()).not.toHaveReturned() + +Expected number of returns: 0 +Received number of returns: 1 + +1: undefined`; + +module.exports["toHaveReturned passes when at least one call does not throw"] = `expect(jest.fn()).not.toHaveReturned() + +Expected number of returns: 0 +Received number of returns: 2 + +1: 42 +3: 42 + +Received number of calls: 3`; + +module.exports["toHaveReturned .not passes when not returned"] = `expect(jest.fn()).toHaveReturned() + +Expected number of returns: >= 1 +Received number of returns: 0`; + +module.exports["toHaveReturned .not passes when all calls throw"] = `expect(jest.fn()).toHaveReturned() + +Expected number of returns: >= 1 +Received number of returns: 0 +Received number of calls: 2`; + +module.exports["toHaveReturned .not passes when a call throws undefined"] = `expect(jest.fn()).toHaveReturned() + +Expected number of returns: >= 1 +Received number of returns: 0 +Received number of calls: 1`; + +module.exports["toHaveReturned fails with any argument passed"] = `expect(received).toHaveReturned() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toHaveReturned .not fails with any argument passed"] = `expect(received).not.toHaveReturned() + +Matcher error: this matcher must not have an expected argument + +Expected has type: number +Expected has value: 555`; + +module.exports["toHaveReturned includes the custom mock name in the error message"] = `expect(named-mock).not.toHaveReturned() + +Expected number of returns: 0 +Received number of returns: 1 + +1: 42`; + +module.exports["toHaveReturned incomplete recursive calls are handled properly"] = `expect(jest.fn()).toHaveReturned() + +Expected number of returns: >= 1 +Received number of returns: 0 +Received number of calls: 4`; + +module.exports["toReturnTimes throw matcher error if received is spy"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function spy]`; + +module.exports["toReturnTimes only accepts a number argument"] = `expect(received).toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toReturnTimes only accepts a number argument #1"] = `expect(received).toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toReturnTimes only accepts a number argument #2"] = `expect(received).toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toReturnTimes only accepts a number argument #3"] = `expect(received).toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toReturnTimes only accepts a number argument #4"] = `expect(received).toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toReturnTimes only accepts a number argument #5"] = `expect(received).toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toReturnTimes .not only accepts a number argument"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toReturnTimes .not only accepts a number argument #1"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toReturnTimes .not only accepts a number argument #2"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toReturnTimes .not only accepts a number argument #3"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toReturnTimes .not only accepts a number argument #4"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toReturnTimes .not only accepts a number argument #5"] = `expect(received).not.toReturnTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toReturnTimes passes if function returned equal to expected times"] = `expect(jest.fn()).not.toReturnTimes(expected) + +Expected number of returns: not 2`; + +module.exports["toReturnTimes calls that return undefined are counted as returns"] = `expect(jest.fn()).not.toReturnTimes(expected) + +Expected number of returns: not 2`; + +module.exports["toReturnTimes .not passes if function returned more than expected times"] = `expect(jest.fn()).toReturnTimes(expected) + +Expected number of returns: 2 +Received number of returns: 3`; + +module.exports["toReturnTimes .not passes if function called less than expected times"] = `expect(jest.fn()).toReturnTimes(expected) + +Expected number of returns: 2 +Received number of returns: 1`; + +module.exports["toReturnTimes calls that throw are not counted"] = `expect(jest.fn()).toReturnTimes(expected) + +Expected number of returns: 3 +Received number of returns: 2 +Received number of calls: 3`; + +module.exports["toReturnTimes calls that throw undefined are not counted"] = `expect(jest.fn()).not.toReturnTimes(expected) + +Expected number of returns: not 2 + +Received number of calls: 3`; + +module.exports["toReturnTimes includes the custom mock name in the error message"] = `expect(named-mock).toReturnTimes(expected) + +Expected number of returns: 1 +Received number of returns: 2`; + +module.exports["toReturnTimes incomplete recursive calls are handled properly"] = `expect(jest.fn()).not.toReturnTimes(expected) + +Expected number of returns: not 2 + +Received number of calls: 4`; + +module.exports["toHaveReturnedTimes throw matcher error if received is spy"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function spy]`; + +module.exports["toHaveReturnedTimes only accepts a number argument"] = `expect(received).toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toHaveReturnedTimes only accepts a number argument #1"] = `expect(received).toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toHaveReturnedTimes only accepts a number argument #2"] = `expect(received).toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toHaveReturnedTimes only accepts a number argument #3"] = `expect(received).toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toHaveReturnedTimes only accepts a number argument #4"] = `expect(received).toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toHaveReturnedTimes only accepts a number argument #5"] = `expect(received).toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toHaveReturnedTimes .not only accepts a number argument"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: object +Expected has value: {}`; + +module.exports["toHaveReturnedTimes .not only accepts a number argument #1"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: array +Expected has value: []`; + +module.exports["toHaveReturnedTimes .not only accepts a number argument #2"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: boolean +Expected has value: true`; + +module.exports["toHaveReturnedTimes .not only accepts a number argument #3"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: string +Expected has value: "a"`; + +module.exports["toHaveReturnedTimes .not only accepts a number argument #4"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: map +Expected has value: Map {}`; + +module.exports["toHaveReturnedTimes .not only accepts a number argument #5"] = `expect(received).not.toHaveReturnedTimes(expected) + +Matcher error: expected value must be a non-negative integer + +Expected has type: function +Expected has value: [Function anonymous]`; + +module.exports["toHaveReturnedTimes passes if function returned equal to expected times"] = `expect(jest.fn()).not.toHaveReturnedTimes(expected) + +Expected number of returns: not 2`; + +module.exports["toHaveReturnedTimes calls that return undefined are counted as returns"] = `expect(jest.fn()).not.toHaveReturnedTimes(expected) + +Expected number of returns: not 2`; + +module.exports["toHaveReturnedTimes .not passes if function returned more than expected times"] = `expect(jest.fn()).toHaveReturnedTimes(expected) + +Expected number of returns: 2 +Received number of returns: 3`; + +module.exports["toHaveReturnedTimes .not passes if function called less than expected times"] = `expect(jest.fn()).toHaveReturnedTimes(expected) + +Expected number of returns: 2 +Received number of returns: 1`; + +module.exports["toHaveReturnedTimes calls that throw are not counted"] = `expect(jest.fn()).toHaveReturnedTimes(expected) + +Expected number of returns: 3 +Received number of returns: 2 +Received number of calls: 3`; + +module.exports["toHaveReturnedTimes calls that throw undefined are not counted"] = `expect(jest.fn()).not.toHaveReturnedTimes(expected) + +Expected number of returns: not 2 + +Received number of calls: 3`; + +module.exports["toHaveReturnedTimes includes the custom mock name in the error message"] = `expect(named-mock).toHaveReturnedTimes(expected) + +Expected number of returns: 1 +Received number of returns: 2`; + +module.exports["toHaveReturnedTimes incomplete recursive calls are handled properly"] = `expect(jest.fn()).not.toHaveReturnedTimes(expected) + +Expected number of returns: not 2 + +Received number of calls: 4`; + +module.exports["lastReturnedWith works only on spies or mock.fn"] = `expect(received).lastReturnedWith(expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["lastReturnedWith works when not called"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["lastReturnedWith works with argument that does not match"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: "bar" +Received: "foo" + +Number of returns: 1`; + +module.exports["lastReturnedWith works with argument that does match"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not "foo" + +Number of returns: 1`; + +module.exports["lastReturnedWith works with undefined"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not undefined + +Number of returns: 1`; + +module.exports["lastReturnedWith works with Map"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["lastReturnedWith works with Map #1"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: Map {"a" => "b", "b" => "a"} +Received: Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["lastReturnedWith works with Set"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not Set {1, 2} + +Number of returns: 1`; + +module.exports["lastReturnedWith works with Set #1"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: Set {3, 4} +Received: Set {1, 2} + +Number of returns: 1`; + +module.exports["lastReturnedWith works with Immutable.js objects directly created"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["lastReturnedWith works with Immutable.js objects indirectly created"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["lastReturnedWith a call that throws is not considered to have returned"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["lastReturnedWith a call that throws undefined is not considered to have returned"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["lastReturnedWith returnedWith works with more calls than the limit"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: "bar" +Received + 5: "foo5" +-> 6: "foo6" + +Number of returns: 6`; + +module.exports["lastReturnedWith returnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: undefined +Received + 3: function call has not returned yet +-> 4: function call has not returned yet + +Number of returns: 0 +Number of calls: 4`; + +module.exports["lastReturnedWith lastReturnedWith works with three calls"] = `expect(jest.fn()).not.lastReturnedWith(expected) + +Expected: not "foo3" +Received + 2: "foo2" +-> 3: "foo3" + +Number of returns: 3`; + +module.exports["lastReturnedWith lastReturnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).lastReturnedWith(expected) + +Expected: 0 +Received + 3: function call has not returned yet +-> 4: function call has not returned yet + +Number of returns: 0 +Number of calls: 4`; + +module.exports["lastReturnedWith includes the custom mock name in the error message"] = `expect(named-mock).lastReturnedWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["toHaveLastReturnedWith works only on spies or mock.fn"] = `expect(received).toHaveLastReturnedWith(expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveLastReturnedWith works when not called"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["toHaveLastReturnedWith works with argument that does not match"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: "bar" +Received: "foo" + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with argument that does match"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not "foo" + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with undefined"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not undefined + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with Map"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with Map #1"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: Map {"a" => "b", "b" => "a"} +Received: Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with Set"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not Set {1, 2} + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with Set #1"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: Set {3, 4} +Received: Set {1, 2} + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with Immutable.js objects directly created"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith works with Immutable.js objects indirectly created"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toHaveLastReturnedWith a call that throws is not considered to have returned"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toHaveLastReturnedWith a call that throws undefined is not considered to have returned"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toHaveLastReturnedWith returnedWith works with more calls than the limit"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: "bar" +Received + 5: "foo5" +-> 6: "foo6" + +Number of returns: 6`; + +module.exports["toHaveLastReturnedWith returnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: undefined +Received + 3: function call has not returned yet +-> 4: function call has not returned yet + +Number of returns: 0 +Number of calls: 4`; + +module.exports["toHaveLastReturnedWith lastReturnedWith works with three calls"] = `expect(jest.fn()).not.toHaveLastReturnedWith(expected) + +Expected: not "foo3" +Received + 2: "foo2" +-> 3: "foo3" + +Number of returns: 3`; + +module.exports["toHaveLastReturnedWith lastReturnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).toHaveLastReturnedWith(expected) + +Expected: 0 +Received + 3: function call has not returned yet +-> 4: function call has not returned yet + +Number of returns: 0 +Number of calls: 4`; + +module.exports["toHaveLastReturnedWith includes the custom mock name in the error message"] = `expect(named-mock).toHaveLastReturnedWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["nthReturnedWith works only on spies or mock.fn"] = `expect(received).nthReturnedWith(n, expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["nthReturnedWith works when not called"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: "foo" + +Number of returns: 0`; + +module.exports["nthReturnedWith works with argument that does not match"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: "bar" +Received: "foo" + +Number of returns: 1`; + +module.exports["nthReturnedWith works with argument that does match"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not "foo" + +Number of returns: 1`; + +module.exports["nthReturnedWith works with undefined"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not undefined + +Number of returns: 1`; + +module.exports["nthReturnedWith works with Map"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["nthReturnedWith works with Map #1"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: Map {"a" => "b", "b" => "a"} +Received: Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["nthReturnedWith works with Set"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not Set {1, 2} + +Number of returns: 1`; + +module.exports["nthReturnedWith works with Set #1"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: Set {3, 4} +Received: Set {1, 2} + +Number of returns: 1`; + +module.exports["nthReturnedWith works with Immutable.js objects directly created"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["nthReturnedWith works with Immutable.js objects indirectly created"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["nthReturnedWith a call that throws is not considered to have returned"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["nthReturnedWith a call that throws undefined is not considered to have returned"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["nthReturnedWith nthReturnedWith works with three calls"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not "foo1" +Received +-> 1: "foo1" + 2: "foo2" + +Number of returns: 3`; + +module.exports["nthReturnedWith nthReturnedWith should replace 1st, 2nd, 3rd with first, second, third"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: "bar1" +Received +-> 1: "foo1" + 2: "foo2" + +Number of returns: 3`; + +module.exports["nthReturnedWith nthReturnedWith should replace 1st, 2nd, 3rd with first, second, third #1"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 1 +Expected: not "foo1" +Received +-> 1: "foo1" + 2: "foo2" + +Number of returns: 3`; + +module.exports["nthReturnedWith nthReturnedWith positive throw matcher error for n that is not positive integer"] = `expect(received).nthReturnedWith(n, expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0`; + +module.exports["nthReturnedWith nthReturnedWith should reject nth value greater than number of calls"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 4 +Expected: "foo" +Received + 3: "foo" + +Number of returns: 3`; + +module.exports["nthReturnedWith nthReturnedWith positive throw matcher error for n that is not integer"] = `expect(received).nthReturnedWith(n, expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0.1`; + +module.exports["nthReturnedWith nthReturnedWith negative throw matcher error for n that is not number"] = `expect(received).not.nthReturnedWith(n, expected) + +Matcher error: n must be a positive integer + +n has value: undefined`; + +module.exports["nthReturnedWith nthReturnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 1 +Expected: 6 +Received +-> 1: function call has not returned yet + 2: function call has not returned yet + +Number of returns: 2 +Number of calls: 4`; + +module.exports["nthReturnedWith nthReturnedWith incomplete recursive calls are handled properly #1"] = `expect(jest.fn()).nthReturnedWith(n, expected) + +n: 2 +Expected: 3 +Received + 1: function call has not returned yet +-> 2: function call has not returned yet + 3: 1 + +Number of returns: 2 +Number of calls: 4`; + +module.exports["nthReturnedWith nthReturnedWith incomplete recursive calls are handled properly #2"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 3 +Expected: not 1 +Received + 2: function call has not returned yet +-> 3: 1 + 4: 0 + +Number of returns: 2 +Number of calls: 4`; + +module.exports["nthReturnedWith nthReturnedWith incomplete recursive calls are handled properly #3"] = `expect(jest.fn()).not.nthReturnedWith(n, expected) + +n: 4 +Expected: not 0 +Received + 3: 1 +-> 4: 0 + +Number of returns: 2 +Number of calls: 4`; + +module.exports["nthReturnedWith includes the custom mock name in the error message"] = `expect(named-mock).nthReturnedWith(n, expected) + +n: 1 +Expected: "foo" + +Number of returns: 0`; + +module.exports["toHaveNthReturnedWith works only on spies or mock.fn"] = `expect(received).toHaveNthReturnedWith(n, expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveNthReturnedWith works when not called"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: "foo" + +Number of returns: 0`; + +module.exports["toHaveNthReturnedWith works with argument that does not match"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: "bar" +Received: "foo" + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with argument that does match"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not "foo" + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with undefined"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not undefined + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with Map"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with Map #1"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: Map {"a" => "b", "b" => "a"} +Received: Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with Set"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not Set {1, 2} + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with Set #1"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: Set {3, 4} +Received: Set {1, 2} + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with Immutable.js objects directly created"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith works with Immutable.js objects indirectly created"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toHaveNthReturnedWith a call that throws is not considered to have returned"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toHaveNthReturnedWith a call that throws undefined is not considered to have returned"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toHaveNthReturnedWith nthReturnedWith works with three calls"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not "foo1" +Received +-> 1: "foo1" + 2: "foo2" + +Number of returns: 3`; + +module.exports["toHaveNthReturnedWith nthReturnedWith should replace 1st, 2nd, 3rd with first, second, third"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: "bar1" +Received +-> 1: "foo1" + 2: "foo2" + +Number of returns: 3`; + +module.exports["toHaveNthReturnedWith nthReturnedWith should replace 1st, 2nd, 3rd with first, second, third #1"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: not "foo1" +Received +-> 1: "foo1" + 2: "foo2" + +Number of returns: 3`; + +module.exports["toHaveNthReturnedWith nthReturnedWith positive throw matcher error for n that is not positive integer"] = `expect(received).toHaveNthReturnedWith(n, expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0`; + +module.exports["toHaveNthReturnedWith nthReturnedWith should reject nth value greater than number of calls"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 4 +Expected: "foo" +Received + 3: "foo" + +Number of returns: 3`; + +module.exports["toHaveNthReturnedWith nthReturnedWith positive throw matcher error for n that is not integer"] = `expect(received).toHaveNthReturnedWith(n, expected) + +Matcher error: n must be a positive integer + +n has type: number +n has value: 0.1`; + +module.exports["toHaveNthReturnedWith nthReturnedWith negative throw matcher error for n that is not number"] = `expect(received).not.toHaveNthReturnedWith(n, expected) + +Matcher error: n must be a positive integer + +n has value: undefined`; + +module.exports["toHaveNthReturnedWith nthReturnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: 6 +Received +-> 1: function call has not returned yet + 2: function call has not returned yet + +Number of returns: 2 +Number of calls: 4`; + +module.exports["toHaveNthReturnedWith nthReturnedWith incomplete recursive calls are handled properly #1"] = `expect(jest.fn()).toHaveNthReturnedWith(n, expected) + +n: 2 +Expected: 3 +Received + 1: function call has not returned yet +-> 2: function call has not returned yet + 3: 1 + +Number of returns: 2 +Number of calls: 4`; + +module.exports["toHaveNthReturnedWith nthReturnedWith incomplete recursive calls are handled properly #2"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 3 +Expected: not 1 +Received + 2: function call has not returned yet +-> 3: 1 + 4: 0 + +Number of returns: 2 +Number of calls: 4`; + +module.exports["toHaveNthReturnedWith nthReturnedWith incomplete recursive calls are handled properly #3"] = `expect(jest.fn()).not.toHaveNthReturnedWith(n, expected) + +n: 4 +Expected: not 0 +Received + 3: 1 +-> 4: 0 + +Number of returns: 2 +Number of calls: 4`; + +module.exports["toHaveNthReturnedWith includes the custom mock name in the error message"] = `expect(named-mock).toHaveNthReturnedWith(n, expected) + +n: 1 +Expected: "foo" + +Number of returns: 0`; + +module.exports["toReturnWith works only on spies or mock.fn"] = `expect(received).toReturnWith(expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toReturnWith works when not called"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["toReturnWith works with argument that does not match"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: "bar" +Received: "foo" + +Number of returns: 1`; + +module.exports["toReturnWith works with argument that does match"] = `expect(jest.fn()).not.toReturnWith(expected) + +Expected: not "foo" + +Number of returns: 1`; + +module.exports["toReturnWith works with undefined"] = `expect(jest.fn()).not.toReturnWith(expected) + +Expected: not undefined + +Number of returns: 1`; + +module.exports["toReturnWith works with Map"] = `expect(jest.fn()).not.toReturnWith(expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toReturnWith works with Map #1"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: Map {"a" => "b", "b" => "a"} +Received: Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toReturnWith works with Set"] = `expect(jest.fn()).not.toReturnWith(expected) + +Expected: not Set {1, 2} + +Number of returns: 1`; + +module.exports["toReturnWith works with Set #1"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: Set {3, 4} +Received: Set {1, 2} + +Number of returns: 1`; + +module.exports["toReturnWith works with Immutable.js objects directly created"] = `expect(jest.fn()).not.toReturnWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toReturnWith works with Immutable.js objects indirectly created"] = `expect(jest.fn()).not.toReturnWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toReturnWith a call that throws is not considered to have returned"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toReturnWith a call that throws undefined is not considered to have returned"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toReturnWith returnedWith works with more calls than the limit"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: "bar" +Received + 1: "foo1" + 2: "foo2" + 3: "foo3" + +Number of returns: 6`; + +module.exports["toReturnWith returnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).toReturnWith(expected) + +Expected: undefined +Received + 1: function call has not returned yet + 2: function call has not returned yet + 3: function call has not returned yet + +Number of returns: 0 +Number of calls: 4`; + +module.exports["toReturnWith includes the custom mock name in the error message"] = `expect(named-mock).toReturnWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["toHaveReturnedWith works only on spies or mock.fn"] = `expect(received).toHaveReturnedWith(expected) + +Matcher error: received value must be a mock function + +Received has type: function +Received has value: [Function fn]`; + +module.exports["toHaveReturnedWith works when not called"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: "foo" + +Number of returns: 0`; + +module.exports["toHaveReturnedWith works with argument that does not match"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: "bar" +Received: "foo" + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with argument that does match"] = `expect(jest.fn()).not.toHaveReturnedWith(expected) + +Expected: not "foo" + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with undefined"] = `expect(jest.fn()).not.toHaveReturnedWith(expected) + +Expected: not undefined + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with Map"] = `expect(jest.fn()).not.toHaveReturnedWith(expected) + +Expected: not Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with Map #1"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: Map {"a" => "b", "b" => "a"} +Received: Map {1 => 2, 2 => 1} + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with Set"] = `expect(jest.fn()).not.toHaveReturnedWith(expected) + +Expected: not Set {1, 2} + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with Set #1"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: Set {3, 4} +Received: Set {1, 2} + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with Immutable.js objects directly created"] = `expect(jest.fn()).not.toHaveReturnedWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toHaveReturnedWith works with Immutable.js objects indirectly created"] = `expect(jest.fn()).not.toHaveReturnedWith(expected) + +Expected: not Immutable.Map {"a": {"b": "c"}} + +Number of returns: 1`; + +module.exports["toHaveReturnedWith a call that throws is not considered to have returned"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toHaveReturnedWith a call that throws undefined is not considered to have returned"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: undefined +Received: function call threw an error + +Number of returns: 0 +Number of calls: 1`; + +module.exports["toHaveReturnedWith returnedWith works with more calls than the limit"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: "bar" +Received + 1: "foo1" + 2: "foo2" + 3: "foo3" + +Number of returns: 6`; + +module.exports["toHaveReturnedWith returnedWith incomplete recursive calls are handled properly"] = `expect(jest.fn()).toHaveReturnedWith(expected) + +Expected: undefined +Received + 1: function call has not returned yet + 2: function call has not returned yet + 3: function call has not returned yet + +Number of returns: 0 +Number of calls: 4`; + +module.exports["toHaveReturnedWith includes the custom mock name in the error message"] = `expect(named-mock).toHaveReturnedWith(expected) + +Expected: "foo" + +Number of returns: 0`; + diff --git a/tests/expect/spyMatchers.test.ts b/tests/expect/spyMatchers.test.ts new file mode 100644 index 0000000000000..bb3b58107b3bb --- /dev/null +++ b/tests/expect/spyMatchers.test.ts @@ -0,0 +1,1499 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest, mock } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; +import Immutable from 'immutable'; + +const expectUnderTestAsAny = expectUnderTest as any; + +expectUnderTest.extend({ + optionalFn(fn?: unknown) { + const pass = fn === undefined || typeof fn === 'function'; + return { message: () => 'expect either a function or undefined', pass }; + }, +}); + + +// Given a Jest mock function, return a minimal mock of a spy. +const createSpy = (fn: mock.Mock) => { + const spy = function() { }; + + spy.calls = { + all() { + return fn.mock.calls.map(args => ({ args })); + }, + count() { + return fn.mock.calls.length; + }, + }; + + return spy; +}; + +for (const called of ['toBeCalled', 'toHaveBeenCalled']) { + test.describe(called, () => { + test('works only on spies or mock.fn', () => { + const fn = function fn() { }; + + expect(() => expectUnderTest(fn)[called]()).toThrowErrorMatchingSnapshot(); + }); + + test('passes when called', () => { + const fn = mock.fn(); + fn('arg0', 'arg1', 'arg2'); + expectUnderTest(createSpy(fn))[called](); + expectUnderTest(fn)[called](); + expect(() => expectUnderTest(fn).not[called]()).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes when called', () => { + const fn = mock.fn(); + const spy = createSpy(fn); + + expectUnderTest(spy).not[called](); + expectUnderTest(fn).not[called](); + expect(() => expectUnderTest(spy)[called]()).toThrowErrorMatchingSnapshot(); + }); + + test('fails with any argument passed', () => { + const fn = mock.fn(); + + fn(); + expect(() => expectUnderTest(fn)[called](555)).toThrowErrorMatchingSnapshot(); + }); + + test('.not fails with any argument passed', () => { + const fn = mock.fn(); + + expect(() => + expectUnderTest(fn).not[called](555), + ).toThrowErrorMatchingSnapshot(); + }); + + test('includes the custom mock name in the error message', () => { + const fn = mock.fn().mockName('named-mock'); + + fn(); + expectUnderTest(fn)[called](); + expect(() => expectUnderTest(fn).not[called]()).toThrowErrorMatchingSnapshot(); + }); + }); +} + +for (const calledTimes of ['toBeCalledTimes', 'toHaveBeenCalledTimes']) { + test.describe(calledTimes, () => { + test('.not works only on spies or mock.fn', () => { + const fn = function fn() { }; + + expect(() => + expectUnderTest(fn).not[calledTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('only accepts a number argument', () => { + const fn = mock.fn(); + fn(); + expectUnderTest(fn)[calledTimes](1); + + [{}, [], true, 'a', new Map(), () => { }].forEach(value => { + expect(() => + expectUnderTest(fn)[calledTimes](value), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('.not only accepts a number argument', () => { + const fn = mock.fn(); + expectUnderTest(fn).not[calledTimes](1); + + [{}, [], true, 'a', new Map(), () => { }].forEach(value => { + expect(() => + expectUnderTest(fn).not[calledTimes](value), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('passes if function called equal to expected times', () => { + const fn = mock.fn(); + fn(); + fn(); + + const spy = createSpy(fn); + expectUnderTest(spy)[calledTimes](2); + expectUnderTest(fn)[calledTimes](2); + + expect(() => + expectUnderTest(spy).not[calledTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes if function called more than expected times', () => { + const fn = mock.fn(); + fn(); + fn(); + fn(); + + const spy = createSpy(fn); + expectUnderTest(spy)[calledTimes](3); + expectUnderTest(spy).not[calledTimes](2); + + expectUnderTest(fn)[calledTimes](3); + expectUnderTest(fn).not[calledTimes](2); + + expect(() => + expectUnderTest(fn)[calledTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes if function called less than expected times', () => { + const fn = mock.fn(); + fn(); + + const spy = createSpy(fn); + expectUnderTest(spy)[calledTimes](1); + expectUnderTest(spy).not[calledTimes](2); + + expectUnderTest(fn)[calledTimes](1); + expectUnderTest(fn).not[calledTimes](2); + + expect(() => + expectUnderTest(fn)[calledTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('includes the custom mock name in the error message', () => { + const fn = mock.fn().mockName('named-mock'); + fn(); + + expect(() => + expectUnderTest(fn)[calledTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + }); +} + +for (const calledWith of [ + 'lastCalledWith', + 'toHaveBeenLastCalledWith', + 'nthCalledWith', + 'toHaveBeenNthCalledWith', + 'toBeCalledWith', + 'toHaveBeenCalledWith', +]) { + test.describe(calledWith, () => { + function isToHaveNth( + calledWith: string, + ): calledWith is 'nthCalledWith' | 'toHaveBeenNthCalledWith' { + return ( + calledWith === 'nthCalledWith' || calledWith === 'toHaveBeenNthCalledWith' + ); + } + + test('works only on spies or mock.fn', () => { + const fn = function fn() { }; + + if (isToHaveNth(calledWith)) { + expect(() => + expectUnderTest(fn)[calledWith](3), + ).toThrowErrorMatchingSnapshot(); + } else { + expect(() => expectUnderTest(fn)[calledWith]()).toThrowErrorMatchingSnapshot(); + } + }); + + test('works when not called', () => { + const fn = mock.fn(); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn)).not[calledWith](1, 'foo', 'bar'); + expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith](1, 'foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn)).not[calledWith]('foo', 'bar'); + expectUnderTest(fn).not[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with no arguments', () => { + const fn = mock.fn(); + fn(); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn))[calledWith](1); + expectUnderTest(fn)[calledWith](1); + } else { + expectUnderTest(createSpy(fn))[calledWith](); + expectUnderTest(fn)[calledWith](); + } + }); + + test("works with arguments that don't match", () => { + const fn = mock.fn(); + fn('foo', 'bar1'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn)).not[calledWith](1, 'foo', 'bar'); + expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith](1, 'foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn)).not[calledWith]('foo', 'bar'); + expectUnderTest(fn).not[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test("works with arguments that don't match in number of arguments", () => { + const fn = mock.fn(); + fn('foo', 'bar', 'plop'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn)).not[calledWith](1, 'foo', 'bar'); + expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith](1, 'foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn)).not[calledWith]('foo', 'bar'); + expectUnderTest(fn).not[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test("works with arguments that don't match with matchers", () => { + const fn = mock.fn(); + fn('foo', 'bar'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn)).not[calledWith]( + 1, + expectUnderTest.any(String), + expectUnderTest.any(Number), + ); + expectUnderTest(fn).not[calledWith]( + 1, + expectUnderTest.any(String), + expectUnderTest.any(Number), + ); + + expect(() => + expectUnderTest(fn)[calledWith]( + 1, + expectUnderTest.any(String), + expectUnderTest.any(Number), + ), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn)).not[calledWith]( + expectUnderTest.any(String), + expectUnderTest.any(Number), + ); + expectUnderTest(fn).not[calledWith]( + expectUnderTest.any(String), + expectUnderTest.any(Number), + ); + + expect(() => + expectUnderTest(fn)[calledWith]( + expectUnderTest.any(String), + expectUnderTest.any(Number), + ), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test("works with arguments that don't match with matchers even when argument is undefined", () => { + const fn = mock.fn(); + fn('foo', undefined); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn)).not[calledWith]( + 1, + 'foo', + expectUnderTest.any(String), + ); + expectUnderTest(fn).not[calledWith](1, 'foo', expectUnderTest.any(String)); + + expect(() => + expectUnderTest(fn)[calledWith](1, 'foo', expectUnderTest.any(String)), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn)).not[calledWith]('foo', expectUnderTest.any(String)); + expectUnderTest(fn).not[calledWith]('foo', expectUnderTest.any(String)); + + expect(() => + expectUnderTest(fn)[calledWith]('foo', expectUnderTest.any(String)), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test("works with arguments that don't match in size even if one is an optional matcher", () => { + // issue 12463 + const fn = mock.fn(); + fn('foo'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn).not[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn()); + expect(() => + expectUnderTest(fn)[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn()), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn).not[calledWith]('foo', expectUnderTestAsAny.optionalFn()); + expect(() => + expectUnderTest(fn)[calledWith]('foo', expectUnderTestAsAny.optionalFn()), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with arguments that match', () => { + const fn = mock.fn(); + fn('foo', 'bar'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn))[calledWith](1, 'foo', 'bar'); + expectUnderTest(fn)[calledWith](1, 'foo', 'bar'); + + expect(() => + expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn))[calledWith]('foo', 'bar'); + expectUnderTest(fn)[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn).not[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with arguments that match with matchers', () => { + const fn = mock.fn(); + fn('foo', 'bar'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(createSpy(fn))[calledWith]( + 1, + expectUnderTest.any(String), + expectUnderTest.any(String), + ); + expectUnderTest(fn)[calledWith]( + 1, + expectUnderTest.any(String), + expectUnderTest.any(String), + ); + + expect(() => + expectUnderTest(fn).not[calledWith]( + 1, + expectUnderTest.any(String), + expectUnderTest.any(String), + ), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(createSpy(fn))[calledWith]( + expectUnderTest.any(String), + expectUnderTest.any(String), + ); + expectUnderTest(fn)[calledWith]( + expectUnderTest.any(String), + expectUnderTest.any(String), + ); + + expect(() => + expectUnderTest(fn).not[calledWith]( + expectUnderTest.any(String), + expectUnderTest.any(String), + ), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with trailing undefined arguments', () => { + const fn = mock.fn(); + fn('foo', undefined); + + if (isToHaveNth(calledWith)) { + expect(() => + expectUnderTest(fn)[calledWith](1, 'foo'), + ).toThrowErrorMatchingSnapshot(); + } else { + expect(() => + expectUnderTest(fn)[calledWith]('foo'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with trailing undefined arguments if requested by the match query', () => { + const fn = mock.fn(); + fn('foo', undefined); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn)[calledWith](1, 'foo', undefined); + expect(() => + expectUnderTest(fn).not[calledWith](1, 'foo', undefined), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[calledWith]('foo', undefined); + expect(() => + expectUnderTest(fn).not[calledWith]('foo', undefined), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with trailing undefined arguments when explicitly requested as optional by matcher', () => { + // issue 12463 + const fn = mock.fn(); + fn('foo', undefined); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn)[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn()); + expect(() => + expectUnderTest(fn).not[calledWith](1, 'foo', expectUnderTestAsAny.optionalFn()), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[calledWith]('foo', expectUnderTestAsAny.optionalFn()); + expect(() => + expectUnderTest(fn).not[calledWith]('foo', expectUnderTestAsAny.optionalFn()), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Map', () => { + const fn = mock.fn(); + + const m1 = new Map([ + [1, 2], + [2, 1], + ]); + const m2 = new Map([ + [1, 2], + [2, 1], + ]); + const m3 = new Map([ + ['a', 'b'], + ['b', 'a'], + ]); + + fn(m1); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn)[calledWith](1, m2); + expectUnderTest(fn).not[calledWith](1, m3); + + expect(() => + expectUnderTest(fn).not[calledWith](1, m2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[calledWith](1, m3), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[calledWith](m2); + expectUnderTest(fn).not[calledWith](m3); + + expect(() => + expectUnderTest(fn).not[calledWith](m2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[calledWith](m3), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Set', () => { + const fn = mock.fn(); + + const s1 = new Set([1, 2]); + const s2 = new Set([1, 2]); + const s3 = new Set([3, 4]); + + fn(s1); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn)[calledWith](1, s2); + expectUnderTest(fn).not[calledWith](1, s3); + + expect(() => + expectUnderTest(fn).not[calledWith](1, s2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[calledWith](1, s3), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[calledWith](s2); + expectUnderTest(fn).not[calledWith](s3); + + expect(() => + expectUnderTest(fn).not[calledWith](s2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[calledWith](s3), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Immutable.js objects', () => { + const fn = mock.fn(); + const directlyCreated = Immutable.Map([['a', { b: 'c' }]]); + const indirectlyCreated = Immutable.Map().set('a', { b: 'c' }); + fn(directlyCreated, indirectlyCreated); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn)[calledWith](1, indirectlyCreated, directlyCreated); + + expect(() => + expectUnderTest(fn).not[calledWith](1, indirectlyCreated, directlyCreated), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[calledWith](indirectlyCreated, directlyCreated); + + expect(() => + expectUnderTest(fn).not[calledWith](indirectlyCreated, directlyCreated), + ).toThrowErrorMatchingSnapshot(); + } + }); + + if (!isToHaveNth(calledWith)) { + test('works with many arguments', () => { + const fn = mock.fn(); + fn('foo1', 'bar'); + fn('foo', 'bar1'); + fn('foo', 'bar'); + + expectUnderTest(fn)[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn).not[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + }); + + test("works with many arguments that don't match", () => { + const fn = mock.fn(); + fn('foo', 'bar1'); + fn('foo', 'bar2'); + fn('foo', 'bar3'); + + expectUnderTest(fn).not[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn)[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + }); + } + + if (isToHaveNth(calledWith)) { + test('works with three calls', () => { + const fn = mock.fn(); + fn('foo1', 'bar'); + fn('foo', 'bar1'); + fn('foo', 'bar'); + + expectUnderTest(fn)[calledWith](1, 'foo1', 'bar'); + expectUnderTest(fn)[calledWith](2, 'foo', 'bar1'); + expectUnderTest(fn)[calledWith](3, 'foo', 'bar'); + + expect(() => { + expectUnderTest(fn).not[calledWith](1, 'foo1', 'bar'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('positive throw matcher error for n that is not positive integer', async () => { + const fn = mock.fn(); + fn('foo1', 'bar'); + + expect(() => { + expectUnderTest(fn)[calledWith](0, 'foo1', 'bar'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('positive throw matcher error for n that is not integer', async () => { + const fn = mock.fn(); + fn('foo1', 'bar'); + + expect(() => { + expectUnderTest(fn)[calledWith](0.1, 'foo1', 'bar'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('negative throw matcher error for n that is not integer', async () => { + const fn = mock.fn(); + fn('foo1', 'bar'); + + expect(() => { + expectUnderTest(fn).not[calledWith](Infinity, 'foo1', 'bar'); + }).toThrowErrorMatchingSnapshot(); + }); + } + + test('includes the custom mock name in the error message', () => { + const fn = mock.fn().mockName('named-mock'); + fn('foo', 'bar'); + + if (isToHaveNth(calledWith)) { + expectUnderTest(fn)[calledWith](1, 'foo', 'bar'); + + expect(() => + expectUnderTest(fn).not[calledWith](1, 'foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[calledWith]('foo', 'bar'); + + expect(() => + expectUnderTest(fn).not[calledWith]('foo', 'bar'), + ).toThrowErrorMatchingSnapshot(); + } + }); + }); +} + +for (const returned of ['toReturn', 'toHaveReturned']) { + test.describe(returned, () => { + test('.not works only on mock.fn', () => { + const fn = function fn() { }; + + expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('throw matcher error if received is spy', () => { + const spy = createSpy(mock.fn()); + + expect(() => expectUnderTest(spy)[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('passes when returned', () => { + const fn = mock.fn(() => 42); + fn(); + expectUnderTest(fn)[returned](); + expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('passes when undefined is returned', () => { + const fn = mock.fn(() => undefined); + fn(); + expectUnderTest(fn)[returned](); + expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('passes when at least one call does not throw', () => { + const fn = mock.fn((causeError: boolean) => { + if (causeError) + throw new Error('Error!'); + + + return 42; + }); + + fn(false); + + try { + fn(true); + } catch { + // ignore error + } + + fn(false); + + expectUnderTest(fn)[returned](); + expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes when not returned', () => { + const fn = mock.fn(); + + expectUnderTest(fn).not[returned](); + expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes when all calls throw', () => { + const fn = mock.fn(() => { + throw new Error('Error!'); + }); + + try { + fn(); + } catch { + // ignore error + } + + try { + fn(); + } catch { + // ignore error + } + + expectUnderTest(fn).not[returned](); + expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes when a call throws undefined', () => { + const fn = mock.fn(() => { + + throw undefined; + }); + + try { + fn(); + } catch { + // ignore error + } + + expectUnderTest(fn).not[returned](); + expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('fails with any argument passed', () => { + const fn = mock.fn(); + + fn(); + expect(() => expectUnderTest(fn)[returned](555)).toThrowErrorMatchingSnapshot(); + }); + + test('.not fails with any argument passed', () => { + const fn = mock.fn(); + + expect(() => + expectUnderTest(fn).not[returned](555), + ).toThrowErrorMatchingSnapshot(); + }); + + test('includes the custom mock name in the error message', () => { + const fn = mock.fn(() => 42).mockName('named-mock'); + fn(); + expectUnderTest(fn)[returned](); + expect(() => expectUnderTest(fn).not[returned]()).toThrowErrorMatchingSnapshot(); + }); + + test('incomplete recursive calls are handled properly', () => { + // sums up all integers from 0 -> value, using recursion + const fn: mock.Mock<(value: number) => number> = mock.fn(value => { + if (value === 0) { + // Before returning from the base case of recursion, none of the + // calls have returned yet. + expectUnderTest(fn).not[returned](); + expect(() => expectUnderTest(fn)[returned]()).toThrowErrorMatchingSnapshot(); + return 0; + } else { + return value + fn(value - 1); + } + }); + + fn(3); + }); + }); +} + +for (const returnedTimes of ['toReturnTimes', 'toHaveReturnedTimes']) { + test.describe(returnedTimes, () => { + test('throw matcher error if received is spy', () => { + const spy = createSpy(mock.fn()); + + expect(() => + expectUnderTest(spy).not[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('only accepts a number argument', () => { + const fn = mock.fn(() => 42); + fn(); + expectUnderTest(fn)[returnedTimes](1); + + [{}, [], true, 'a', new Map(), () => { }].forEach(value => { + expect(() => + expectUnderTest(fn)[returnedTimes](value), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('.not only accepts a number argument', () => { + const fn = mock.fn(() => 42); + expectUnderTest(fn).not[returnedTimes](2); + + [{}, [], true, 'a', new Map(), () => { }].forEach(value => { + expect(() => + expectUnderTest(fn).not[returnedTimes](value), + ).toThrowErrorMatchingSnapshot(); + }); + }); + + test('passes if function returned equal to expected times', () => { + const fn = mock.fn(() => 42); + fn(); + fn(); + + expectUnderTest(fn)[returnedTimes](2); + + expect(() => + expectUnderTest(fn).not[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('calls that return undefined are counted as returns', () => { + const fn = mock.fn(() => undefined); + fn(); + fn(); + + expectUnderTest(fn)[returnedTimes](2); + + expect(() => + expectUnderTest(fn).not[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes if function returned more than expected times', () => { + const fn = mock.fn(() => 42); + fn(); + fn(); + fn(); + + expectUnderTest(fn)[returnedTimes](3); + expectUnderTest(fn).not[returnedTimes](2); + + expect(() => + expectUnderTest(fn)[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('.not passes if function called less than expected times', () => { + const fn = mock.fn(() => 42); + fn(); + + expectUnderTest(fn)[returnedTimes](1); + expectUnderTest(fn).not[returnedTimes](2); + + expect(() => + expectUnderTest(fn)[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('calls that throw are not counted', () => { + const fn = mock.fn((causeError: boolean) => { + if (causeError) + throw new Error('Error!'); + + + return 42; + }); + + fn(false); + + try { + fn(true); + } catch { + // ignore error + } + + fn(false); + + expectUnderTest(fn).not[returnedTimes](3); + + expect(() => + expectUnderTest(fn)[returnedTimes](3), + ).toThrowErrorMatchingSnapshot(); + }); + + test('calls that throw undefined are not counted', () => { + const fn = mock.fn((causeError: boolean) => { + if (causeError) + + throw undefined; + + + return 42; + }); + + fn(false); + + try { + fn(true); + } catch { + // ignore error + } + + fn(false); + + expectUnderTest(fn)[returnedTimes](2); + + expect(() => + expectUnderTest(fn).not[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + }); + + test('includes the custom mock name in the error message', () => { + const fn = mock.fn(() => 42).mockName('named-mock'); + fn(); + fn(); + + expectUnderTest(fn)[returnedTimes](2); + + expect(() => + expectUnderTest(fn)[returnedTimes](1), + ).toThrowErrorMatchingSnapshot(); + }); + + test('incomplete recursive calls are handled properly', () => { + // sums up all integers from 0 -> value, using recursion + const fn: mock.Mock<(value: number) => number> = mock.fn(value => { + if (value === 0) { + return 0; + } else { + const recursiveResult = fn(value - 1); + + if (value === 2) { + // Only 2 of the recursive calls have returned at this point + expectUnderTest(fn)[returnedTimes](2); + expect(() => + expectUnderTest(fn).not[returnedTimes](2), + ).toThrowErrorMatchingSnapshot(); + } + + return value + recursiveResult; + } + }); + + fn(3); + }); + }); +} + +for (const returnedWith of [ + 'lastReturnedWith', + 'toHaveLastReturnedWith', + 'nthReturnedWith', + 'toHaveNthReturnedWith', + 'toReturnWith', + 'toHaveReturnedWith', +]) { + test.describe(returnedWith, () => { + function isToHaveNth( + returnedWith: string, + ): returnedWith is 'nthReturnedWith' | 'toHaveNthReturnedWith' { + return ( + returnedWith === 'nthReturnedWith' || + returnedWith === 'toHaveNthReturnedWith' + ); + } + + function isToHaveLast( + returnedWith: string, + ): returnedWith is 'lastReturnedWith' | 'toHaveLastReturnedWith' { + return ( + returnedWith === 'lastReturnedWith' || + returnedWith === 'toHaveLastReturnedWith' + ); + } + test('works only on spies or mock.fn', () => { + const fn = function fn() { }; + + expect(() => expectUnderTest(fn)[returnedWith]()).toThrowErrorMatchingSnapshot(); + }); + + test('works when not called', () => { + const fn = mock.fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn).not[returnedWith](1, 'foo'); + + expect(() => + expectUnderTest(fn)[returnedWith](1, 'foo'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn).not[returnedWith]('foo'); + + expect(() => + expectUnderTest(fn)[returnedWith]('foo'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with no arguments', () => { + const fn = mock.fn(); + fn(); + + if (isToHaveNth(returnedWith)) + expectUnderTest(fn)[returnedWith](1); + else + expectUnderTest(fn)[returnedWith](); + + }); + + test('works with argument that does not match', () => { + const fn = mock.fn(() => 'foo'); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn).not[returnedWith](1, 'bar'); + + expect(() => + expectUnderTest(fn)[returnedWith](1, 'bar'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn).not[returnedWith]('bar'); + + expect(() => + expectUnderTest(fn)[returnedWith]('bar'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with argument that does match', () => { + const fn = mock.fn(() => 'foo'); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn)[returnedWith](1, 'foo'); + + expect(() => + expectUnderTest(fn).not[returnedWith](1, 'foo'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[returnedWith]('foo'); + + expect(() => + expectUnderTest(fn).not[returnedWith]('foo'), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with undefined', () => { + const fn = mock.fn(() => undefined); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn)[returnedWith](1, undefined); + + expect(() => + expectUnderTest(fn).not[returnedWith](1, undefined), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[returnedWith](undefined); + + expect(() => + expectUnderTest(fn).not[returnedWith](undefined), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Map', () => { + const m1 = new Map([ + [1, 2], + [2, 1], + ]); + const m2 = new Map([ + [1, 2], + [2, 1], + ]); + const m3 = new Map([ + ['a', 'b'], + ['b', 'a'], + ]); + + const fn = mock.fn(() => m1); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn)[returnedWith](1, m2); + expectUnderTest(fn).not[returnedWith](1, m3); + + expect(() => + expectUnderTest(fn).not[returnedWith](1, m2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[returnedWith](1, m3), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[returnedWith](m2); + expectUnderTest(fn).not[returnedWith](m3); + + expect(() => + expectUnderTest(fn).not[returnedWith](m2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[returnedWith](m3), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Set', () => { + const s1 = new Set([1, 2]); + const s2 = new Set([1, 2]); + const s3 = new Set([3, 4]); + + const fn = mock.fn(() => s1); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn)[returnedWith](1, s2); + expectUnderTest(fn).not[returnedWith](1, s3); + + expect(() => + expectUnderTest(fn).not[returnedWith](1, s2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[returnedWith](1, s3), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[returnedWith](s2); + expectUnderTest(fn).not[returnedWith](s3); + + expect(() => + expectUnderTest(fn).not[returnedWith](s2), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[returnedWith](s3), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Immutable.js objects directly created', () => { + const directlyCreated = Immutable.Map([['a', { b: 'c' }]]); + const fn = mock.fn(() => directlyCreated); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn)[returnedWith](1, directlyCreated); + + expect(() => + expectUnderTest(fn).not[returnedWith](1, directlyCreated), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[returnedWith](directlyCreated); + + expect(() => + expectUnderTest(fn).not[returnedWith](directlyCreated), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('works with Immutable.js objects indirectly created', () => { + const indirectlyCreated = Immutable.Map().set('a', { b: 'c' }); + const fn = mock.fn(() => indirectlyCreated); + fn(); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn)[returnedWith](1, indirectlyCreated); + + expect(() => + expectUnderTest(fn).not[returnedWith](1, indirectlyCreated), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn)[returnedWith](indirectlyCreated); + + expect(() => + expectUnderTest(fn).not[returnedWith](indirectlyCreated), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('a call that throws is not considered to have returned', () => { + const fn = mock.fn(() => { + throw new Error('Error!'); + }); + + try { + fn(); + } catch { + // ignore error + } + + if (isToHaveNth(returnedWith)) { + // It doesn't matter what return value is tested if the call threw + expectUnderTest(fn).not[returnedWith](1, 'foo'); + expectUnderTest(fn).not[returnedWith](1, null); + expectUnderTest(fn).not[returnedWith](1, undefined); + + expect(() => + expectUnderTest(fn)[returnedWith](1, undefined), + ).toThrowErrorMatchingSnapshot(); + } else { + // It doesn't matter what return value is tested if the call threw + expectUnderTest(fn).not[returnedWith]('foo'); + expectUnderTest(fn).not[returnedWith](null); + expectUnderTest(fn).not[returnedWith](undefined); + + expect(() => + expectUnderTest(fn)[returnedWith](undefined), + ).toThrowErrorMatchingSnapshot(); + } + }); + + test('a call that throws undefined is not considered to have returned', () => { + const fn = mock.fn(() => { + + throw undefined; + }); + + try { + fn(); + } catch { + // ignore error + } + + if (isToHaveNth(returnedWith)) { + // It doesn't matter what return value is tested if the call threw + expectUnderTest(fn).not[returnedWith](1, 'foo'); + expectUnderTest(fn).not[returnedWith](1, null); + expectUnderTest(fn).not[returnedWith](1, undefined); + + expect(() => + expectUnderTest(fn)[returnedWith](1, undefined), + ).toThrowErrorMatchingSnapshot(); + } else { + // It doesn't matter what return value is tested if the call threw + expectUnderTest(fn).not[returnedWith]('foo'); + expectUnderTest(fn).not[returnedWith](null); + expectUnderTest(fn).not[returnedWith](undefined); + + expect(() => + expectUnderTest(fn)[returnedWith](undefined), + ).toThrowErrorMatchingSnapshot(); + } + }); + + if (!isToHaveNth(returnedWith)) { + test.describe('returnedWith', () => { + test('works with more calls than the limit', () => { + const fn = mock.fn<() => string>(); + fn.mockReturnValueOnce('foo1'); + fn.mockReturnValueOnce('foo2'); + fn.mockReturnValueOnce('foo3'); + fn.mockReturnValueOnce('foo4'); + fn.mockReturnValueOnce('foo5'); + fn.mockReturnValueOnce('foo6'); + + fn(); + fn(); + fn(); + fn(); + fn(); + fn(); + + expectUnderTest(fn).not[returnedWith]('bar'); + + expect(() => { + expectUnderTest(fn)[returnedWith]('bar'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('incomplete recursive calls are handled properly', () => { + // sums up all integers from 0 -> value, using recursion + const fn: mock.Mock<(value: number) => number> = mock.fn(value => { + if (value === 0) { + // Before returning from the base case of recursion, none of the + // calls have returned yet. + // This test ensures that the incomplete calls are not incorrectly + // interpreted as have returned undefined + expectUnderTest(fn).not[returnedWith](undefined); + expect(() => + expectUnderTest(fn)[returnedWith](undefined), + ).toThrowErrorMatchingSnapshot(); + + return 0; + } else { + return value + fn(value - 1); + } + }); + + fn(3); + }); + }); + } + + if (isToHaveNth(returnedWith)) { + test.describe('nthReturnedWith', () => { + test('works with three calls', () => { + const fn = mock.fn<() => string>(); + fn.mockReturnValueOnce('foo1'); + fn.mockReturnValueOnce('foo2'); + fn.mockReturnValueOnce('foo3'); + fn(); + fn(); + fn(); + + expectUnderTest(fn)[returnedWith](1, 'foo1'); + expectUnderTest(fn)[returnedWith](2, 'foo2'); + expectUnderTest(fn)[returnedWith](3, 'foo3'); + + expect(() => { + expectUnderTest(fn).not[returnedWith](1, 'foo1'); + expectUnderTest(fn).not[returnedWith](2, 'foo2'); + expectUnderTest(fn).not[returnedWith](3, 'foo3'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('should replace 1st, 2nd, 3rd with first, second, third', async () => { + const fn = mock.fn<() => string>(); + fn.mockReturnValueOnce('foo1'); + fn.mockReturnValueOnce('foo2'); + fn.mockReturnValueOnce('foo3'); + fn(); + fn(); + fn(); + + expect(() => { + expectUnderTest(fn)[returnedWith](1, 'bar1'); + expectUnderTest(fn)[returnedWith](2, 'bar2'); + expectUnderTest(fn)[returnedWith](3, 'bar3'); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + expectUnderTest(fn).not[returnedWith](1, 'foo1'); + expectUnderTest(fn).not[returnedWith](2, 'foo2'); + expectUnderTest(fn).not[returnedWith](3, 'foo3'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('positive throw matcher error for n that is not positive integer', async () => { + const fn = mock.fn(() => 'foo'); + fn(); + + expect(() => { + expectUnderTest(fn)[returnedWith](0, 'foo'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('should reject nth value greater than number of calls', async () => { + const fn = mock.fn(() => 'foo'); + fn(); + fn(); + fn(); + + expect(() => { + expectUnderTest(fn)[returnedWith](4, 'foo'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('positive throw matcher error for n that is not integer', async () => { + const fn = mock.fn<(a: string) => string>(() => 'foo'); + fn('foo'); + + expect(() => { + expectUnderTest(fn)[returnedWith](0.1, 'foo'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('negative throw matcher error for n that is not number', async () => { + const fn = mock.fn<(a: string) => string>(() => 'foo'); + fn('foo'); + + expect(() => { + // @ts-expect-error: Testing runtime error + expectUnderTest(fn).not[returnedWith](); + }).toThrowErrorMatchingSnapshot(); + }); + + test('incomplete recursive calls are handled properly', () => { + // sums up all integers from 0 -> value, using recursion + const fn: mock.Mock<(value: number) => number> = mock.fn(value => { + if (value === 0) { + return 0; + } else { + const recursiveResult = fn(value - 1); + + if (value === 2) { + // Only 2 of the recursive calls have returned at this point + expectUnderTest(fn).not[returnedWith](1, 6); + expectUnderTest(fn).not[returnedWith](2, 3); + expectUnderTest(fn)[returnedWith](3, 1); + expectUnderTest(fn)[returnedWith](4, 0); + + expect(() => + expectUnderTest(fn)[returnedWith](1, 6), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn)[returnedWith](2, 3), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn).not[returnedWith](3, 1), + ).toThrowErrorMatchingSnapshot(); + expect(() => + expectUnderTest(fn).not[returnedWith](4, 0), + ).toThrowErrorMatchingSnapshot(); + } + + return value + recursiveResult; + } + }); + + fn(3); + }); + }); + } + + if (isToHaveLast(returnedWith)) { + test.describe('lastReturnedWith', () => { + test('works with three calls', () => { + const fn = mock.fn<() => string>(); + fn.mockReturnValueOnce('foo1'); + fn.mockReturnValueOnce('foo2'); + fn.mockReturnValueOnce('foo3'); + fn(); + fn(); + fn(); + + expectUnderTest(fn)[returnedWith]('foo3'); + + expect(() => { + expectUnderTest(fn).not[returnedWith]('foo3'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('incomplete recursive calls are handled properly', () => { + // sums up all integers from 0 -> value, using recursion + const fn: mock.Mock<(value: number) => number> = mock.fn(value => { + if (value === 0) { + // Before returning from the base case of recursion, none of the + // calls have returned yet. + expectUnderTest(fn).not[returnedWith](0); + expect(() => + expectUnderTest(fn)[returnedWith](0), + ).toThrowErrorMatchingSnapshot(); + return 0; + } else { + return value + fn(value - 1); + } + }); + + fn(3); + }); + }); + } + + test('includes the custom mock name in the error message', () => { + const fn = mock.fn().mockName('named-mock'); + + if (isToHaveNth(returnedWith)) { + expectUnderTest(fn).not[returnedWith](1, 'foo'); + + expect(() => + expectUnderTest(fn)[returnedWith](1, 'foo'), + ).toThrowErrorMatchingSnapshot(); + } else { + expectUnderTest(fn).not[returnedWith]('foo'); + + expect(() => + expectUnderTest(fn)[returnedWith]('foo'), + ).toThrowErrorMatchingSnapshot(); + } + }); + }); +} diff --git a/tests/expect/stacktrace.test.ts b/tests/expect/stacktrace.test.ts new file mode 100644 index 0000000000000..6f5cf8bcc7c73 --- /dev/null +++ b/tests/expect/stacktrace.test.ts @@ -0,0 +1,71 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +const expectUnderTestAsAny = expectUnderTest as any; + +expectUnderTest.extend({ + toCustomMatch(callback: () => unknown, expected: unknown) { + const actual = callback(); + + if (actual !== expected) { + return { + message: () => `Expected "${expected}" but got "${actual}"`, + pass: false, + }; + } + + return { + message: () => '', + pass: true, + }; + }, + toMatchPredicate(received: unknown, expected: (a: unknown) => void) { + expected(received); + return { + message: () => '', + pass: true, + }; + }, +}); + +test('stack trace points to correct location when using matchers', () => { + try { + expectUnderTest(true).toBe(false); + } catch (error: any) { + expect(error.stack).toContain('stacktrace.test.ts:'); + } +}); + +test('stack trace points to correct location when using nested matchers', () => { + try { + expectUnderTestAsAny(true).toMatchPredicate((value: unknown) => { + expectUnderTest(value).toBe(false); + }); + } catch (error: any) { + expect(error.stack).toContain('stacktrace.test.ts:'); + } +}); + +test('stack trace points to correct location when throwing from a custom matcher', () => { + try { + expectUnderTestAsAny(() => { + const foo = () => bar(); + const bar = () => baz(); + const baz = () => { + throw new Error('Expected'); + }; + + foo(); + }).toCustomMatch('bar'); + } catch (error: any) { + expect(error.stack).toContain('stacktrace.test.ts:'); + } +}); diff --git a/tests/expect/symbolInObjects.test.ts b/tests/expect/symbolInObjects.test.ts new file mode 100644 index 0000000000000..011d87e72db10 --- /dev/null +++ b/tests/expect/symbolInObjects.test.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { test } from './fixtures'; +import { expect as expectUnderTest } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +test.describe('Symbol in objects', () => { + test('should compare objects with Symbol keys', () => { + const sym = Symbol('foo'); + const obj1 = { [sym]: 'one' }; + const obj2 = { [sym]: 'two' }; + const obj3 = { [sym]: 'one' }; + + expectUnderTest(obj1).toEqual(obj3); + expectUnderTest(obj1).not.toEqual(obj2); + }); + + test('should compare objects with mixed keys and Symbol', () => { + const sym = Symbol('foo2'); + const obj1 = { foo: 2, [sym]: 'one' }; + const obj2 = { foo: 2, [sym]: 'two' }; + const obj3 = { foo: 2, [sym]: 'one' }; + + expectUnderTest(obj1).toEqual(obj3); + expectUnderTest(obj1).not.toEqual(obj2); + }); + + test('should compare objects with different Symbol keys', () => { + const sym = Symbol('foo'); + const sym2 = Symbol('foo'); + const obj1 = { [sym]: 'one' }; + const obj2 = { [sym2]: 'one' }; + const obj3 = { [sym]: 'one' }; + + expectUnderTest(obj1).toEqual(obj3); + expectUnderTest(obj1).not.toEqual(obj2); + }); +}); diff --git a/tests/expect/toThrowMatchers.snapshots.js b/tests/expect/toThrowMatchers.snapshots.js new file mode 100644 index 0000000000000..c1243e0f0ba80 --- /dev/null +++ b/tests/expect/toThrowMatchers.snapshots.js @@ -0,0 +1,456 @@ +module.exports["toThrowError substring did not throw at all"] = `expect(received).toThrowError(expected) + +Expected substring: "apple" + +Received function did not throw`; + +module.exports["toThrowError substring threw, but message did not match (error)"] = `expect(received).toThrowError(expected) + +Expected substring: "banana" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError substring threw, but message did not match (non-error falsey)"] = `expect(received).toThrowError(expected) + +Expected substring: "Server Error" +Received value: "" +`; + +module.exports["toThrowError substring threw, but message should not match (error)"] = `expect(received).not.toThrowError(expected) + +Expected substring: not "array" +Received message: "Invalid array length" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError substring threw, but message should not match (non-error truthy)"] = `expect(received).not.toThrowError(expected) + +Expected substring: not "Server Error" +Received value: "Internal Server Error" +`; + +module.exports["toThrowError regexp did not throw at all"] = `expect(received).toThrowError(expected) + +Expected pattern: /apple/ + +Received function did not throw`; + +module.exports["toThrowError regexp threw, but message did not match (error)"] = `expect(received).toThrowError(expected) + +Expected pattern: /banana/ +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError regexp threw, but message did not match (non-error falsey)"] = `expect(received).toThrowError(expected) + +Expected pattern: /^[123456789]\\d*/ +Received value: 0 +`; + +module.exports["toThrowError regexp threw, but message should not match (error)"] = `expect(received).not.toThrowError(expected) + +Expected pattern: not / array / +Received message: "Invalid array length" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError regexp threw, but message should not match (non-error truthy)"] = `expect(received).not.toThrowError(expected) + +Expected pattern: not /^[123456789]\\d*/ +Received value: 404 +`; + +module.exports["toThrowError error class did not throw at all"] = `expect(received).toThrowError(expected) + +Expected constructor: Err + +Received function did not throw`; + +module.exports["toThrowError error class threw, but class did not match (error)"] = `expect(received).toThrowError(expected) + +Expected constructor: Err2 +Received constructor: Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError error class threw, but class did not match (non-error falsey)"] = `expect(received).toThrowError(expected) + +Expected constructor: Err2 + +Received value: undefined +`; + +module.exports["toThrowError error class threw, but class should not match (error)"] = `expect(received).not.toThrowError(expected) + +Expected constructor: not Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError error class threw, but class should not match (error subclass)"] = `expect(received).not.toThrowError(expected) + +Expected constructor: not Err +Received constructor: SubErr extends Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError error class threw, but class should not match (error subsubclass)"] = `expect(received).not.toThrowError(expected) + +Expected constructor: not Err +Received constructor: SubSubErr extends … extends Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError error-message fail isNot false"] = `expect(received).toThrowError(expected) + +Expected message: "apple" +Received message: "banana" +`; + +module.exports["toThrowError error-message fail isNot true"] = `expect(received).not.toThrowError(expected) + +Expected message: not "Invalid array length" +`; + +module.exports["toThrowError error-message fail multiline diff highlight incorrect expected space"] = `expect(received).toThrowError(expected) + +- Expected message - 1 ++ Received message + 1 + +- There is no route defined for key Settings. ++ There is no route defined for key Settings. + Must be one of: 'Home' +`; + +module.exports["toThrowError asymmetric any-Class fail isNot false"] = `expect(received).toThrowError(expected) + +Expected asymmetric matcher: Any + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError asymmetric any-Class fail isNot true"] = `expect(received).not.toThrowError(expected) + +Expected asymmetric matcher: not Any + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError asymmetric anything fail isNot false"] = `expect(received).toThrowError(expected) + +Expected asymmetric matcher: Anything + +Thrown value: null +`; + +module.exports["toThrowError asymmetric anything fail isNot true"] = `expect(received).not.toThrowError(expected) + +Expected asymmetric matcher: not Anything + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError asymmetric no-symbol fail isNot false"] = `expect(received).toThrowError(expected) + +Expected asymmetric matcher: {"asymmetricMatch": [Function asymmetricMatch]} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError asymmetric no-symbol fail isNot true"] = `expect(received).not.toThrowError(expected) + +Expected asymmetric matcher: not {"asymmetricMatch": [Function asymmetricMatch]} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError asymmetric objectContaining fail isNot false"] = `expect(received).toThrowError(expected) + +Expected asymmetric matcher: ObjectContaining {"name": "NotError"} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError asymmetric objectContaining fail isNot true"] = `expect(received).not.toThrowError(expected) + +Expected asymmetric matcher: not ObjectContaining {"name": "Error"} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrowError promise/async throws if Error-like object is returned did not throw at all"] = `callback is not a function`; + +module.exports["toThrowError promise/async throws if Error-like object is returned threw, but class did not match"] = `callback is not a function`; + +module.exports["toThrowError promise/async throws if Error-like object is returned threw, but should not have"] = `callback is not a function`; + +module.exports["toThrowError expected is undefined threw, but should not have (non-error falsey)"] = `expect(received).not.toThrowError() + +Thrown value: null +`; + +module.exports["toThrowError invalid arguments"] = `expect(received).not.toThrowError(expected) + +Matcher error: expected value must be a string or regular expression or class or error + +Expected has type: number +Expected has value: 111`; + +module.exports["toThrowError invalid actual"] = `expect(received).toThrowError() + +Matcher error: received value must be a function + +Received has type: string +Received has value: "a string"`; + +module.exports["toThrow substring did not throw at all"] = `expect(received).toThrow(expected) + +Expected substring: "apple" + +Received function did not throw`; + +module.exports["toThrow substring threw, but message did not match (error)"] = `expect(received).toThrow(expected) + +Expected substring: "banana" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow substring threw, but message did not match (non-error falsey)"] = `expect(received).toThrow(expected) + +Expected substring: "Server Error" +Received value: "" +`; + +module.exports["toThrow substring threw, but message should not match (error)"] = `expect(received).not.toThrow(expected) + +Expected substring: not "array" +Received message: "Invalid array length" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow substring threw, but message should not match (non-error truthy)"] = `expect(received).not.toThrow(expected) + +Expected substring: not "Server Error" +Received value: "Internal Server Error" +`; + +module.exports["toThrow regexp did not throw at all"] = `expect(received).toThrow(expected) + +Expected pattern: /apple/ + +Received function did not throw`; + +module.exports["toThrow regexp threw, but message did not match (error)"] = `expect(received).toThrow(expected) + +Expected pattern: /banana/ +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow regexp threw, but message did not match (non-error falsey)"] = `expect(received).toThrow(expected) + +Expected pattern: /^[123456789]\\d*/ +Received value: 0 +`; + +module.exports["toThrow regexp threw, but message should not match (error)"] = `expect(received).not.toThrow(expected) + +Expected pattern: not / array / +Received message: "Invalid array length" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow regexp threw, but message should not match (non-error truthy)"] = `expect(received).not.toThrow(expected) + +Expected pattern: not /^[123456789]\\d*/ +Received value: 404 +`; + +module.exports["toThrow error class did not throw at all"] = `expect(received).toThrow(expected) + +Expected constructor: Err + +Received function did not throw`; + +module.exports["toThrow error class threw, but class did not match (error)"] = `expect(received).toThrow(expected) + +Expected constructor: Err2 +Received constructor: Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow error class threw, but class did not match (non-error falsey)"] = `expect(received).toThrow(expected) + +Expected constructor: Err2 + +Received value: undefined +`; + +module.exports["toThrow error class threw, but class should not match (error)"] = `expect(received).not.toThrow(expected) + +Expected constructor: not Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow error class threw, but class should not match (error subclass)"] = `expect(received).not.toThrow(expected) + +Expected constructor: not Err +Received constructor: SubErr extends Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow error class threw, but class should not match (error subsubclass)"] = `expect(received).not.toThrow(expected) + +Expected constructor: not Err +Received constructor: SubSubErr extends … extends Err + +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow error-message fail isNot false"] = `expect(received).toThrow(expected) + +Expected message: "apple" +Received message: "banana" +`; + +module.exports["toThrow error-message fail isNot true"] = `expect(received).not.toThrow(expected) + +Expected message: not "Invalid array length" +`; + +module.exports["toThrow error-message fail multiline diff highlight incorrect expected space"] = `expect(received).toThrow(expected) + +- Expected message - 1 ++ Received message + 1 + +- There is no route defined for key Settings. ++ There is no route defined for key Settings. + Must be one of: 'Home' +`; + +module.exports["toThrow asymmetric any-Class fail isNot false"] = `expect(received).toThrow(expected) + +Expected asymmetric matcher: Any + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow asymmetric any-Class fail isNot true"] = `expect(received).not.toThrow(expected) + +Expected asymmetric matcher: not Any + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow asymmetric anything fail isNot false"] = `expect(received).toThrow(expected) + +Expected asymmetric matcher: Anything + +Thrown value: null +`; + +module.exports["toThrow asymmetric anything fail isNot true"] = `expect(received).not.toThrow(expected) + +Expected asymmetric matcher: not Anything + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow asymmetric no-symbol fail isNot false"] = `expect(received).toThrow(expected) + +Expected asymmetric matcher: {"asymmetricMatch": [Function asymmetricMatch]} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow asymmetric no-symbol fail isNot true"] = `expect(received).not.toThrow(expected) + +Expected asymmetric matcher: not {"asymmetricMatch": [Function asymmetricMatch]} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow asymmetric objectContaining fail isNot false"] = `expect(received).toThrow(expected) + +Expected asymmetric matcher: ObjectContaining {"name": "NotError"} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow asymmetric objectContaining fail isNot true"] = `expect(received).not.toThrow(expected) + +Expected asymmetric matcher: not ObjectContaining {"name": "Error"} + +Received name: "Error" +Received message: "apple" + + at expectUnderTest (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)`; + +module.exports["toThrow promise/async throws if Error-like object is returned did not throw at all"] = `callback is not a function`; + +module.exports["toThrow promise/async throws if Error-like object is returned threw, but class did not match"] = `callback is not a function`; + +module.exports["toThrow promise/async throws if Error-like object is returned threw, but should not have"] = `callback is not a function`; + +module.exports["toThrow expected is undefined threw, but should not have (non-error falsey)"] = `expect(received).not.toThrow() + +Thrown value: null +`; + +module.exports["toThrow invalid arguments"] = `expect(received).not.toThrow(expected) + +Matcher error: expected value must be a string or regular expression or class or error + +Expected has type: number +Expected has value: 111`; + +module.exports["toThrow invalid actual"] = `expect(received).toThrow() + +Matcher error: received value must be a function + +Received has type: string +Received has value: "a string"`; + diff --git a/tests/expect/toThrowMatchers.test.ts b/tests/expect/toThrowMatchers.test.ts new file mode 100644 index 0000000000000..a5d5e52ba828c --- /dev/null +++ b/tests/expect/toThrowMatchers.test.ts @@ -0,0 +1,591 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { test, expect } from './fixtures'; +import { expect as expectUnderTest } from '../../packages/playwright/bundles/expect/src/expectBundleImpl'; + +const expectUnderTestAsAny = expectUnderTest as any; + +// Custom Error class because node versions have different stack trace strings. +class CustomError extends Error { + constructor(message?: string) { + super(message); + this.name = 'Error'; + this.stack = + 'Error\n' + + ' at expectUnderTest' + + ' (packages/expect/src/__tests__/toThrowMatchers-test.js:24:74)'; + } +} + +for (const toThrow of ['toThrowError', 'toThrow'] as const) { + test.describe(toThrow, () => { + class Err extends CustomError {} + class Err2 extends CustomError {} + + test('to throw or not to throw', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](); + expectUnderTest(() => {}).not[toThrow](); + }); + + test.describe('substring', () => { + test('passes', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow]('apple'); + expectUnderTest(() => { + throw new CustomError('banana'); + }).not[toThrow]('apple'); + expectUnderTest(() => {}).not[toThrow]('apple'); + }); + + test('did not throw at all', () => { + expect(() => + expectUnderTest(() => {})[toThrow]('apple'), + ).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message did not match (error)', () => { + expect(() => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow]('banana'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message did not match (non-error falsey)', () => { + expect(() => { + expectUnderTest(() => { + + throw ''; + })[toThrow]('Server Error'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('properly escapes strings when matching against errors', () => { + expectUnderTest(() => { + throw new TypeError('"this"? throws.'); + })[toThrow]('"this"? throws.'); + }); + + test('threw, but message should not match (error)', () => { + expect(() => { + expectUnderTest(() => { + throw new CustomError('Invalid array length'); + }).not[toThrow]('array'); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message should not match (non-error truthy)', () => { + expect(() => { + expectUnderTest(() => { + + throw 'Internal Server Error'; + }).not[toThrow]('Server Error'); + }).toThrowErrorMatchingSnapshot(); + }); + }); + + test.describe('regexp', () => { + test('passes', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](/apple/); + expectUnderTest(() => { + throw new CustomError('banana'); + }).not[toThrow](/apple/); + expectUnderTest(() => {}).not[toThrow](/apple/); + }); + + test('did not throw at all', () => { + expect(() => + expectUnderTest(() => {})[toThrow](/apple/), + ).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message did not match (error)', () => { + expect(() => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](/banana/); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message did not match (non-error falsey)', () => { + expect(() => { + expectUnderTest(() => { + + throw 0; + })[toThrow](/^[123456789]\d*/); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message should not match (error)', () => { + expect(() => { + expectUnderTest(() => { + throw new CustomError('Invalid array length'); + }).not[toThrow](/ array /); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but message should not match (non-error truthy)', () => { + expect(() => { + expectUnderTest(() => { + + throw 404; + }).not[toThrow](/^[123456789]\d*/); + }).toThrowErrorMatchingSnapshot(); + }); + }); + + test.describe('error class', () => { + class SubErr extends Err { + constructor(message?: string) { + super(message); + // In a carefully written error subclass, + // name property is equal to constructor name. + this.name = this.constructor.name; + } + } + + class SubSubErr extends SubErr { + constructor(message?: string) { + super(message); + // In a carefully written error subclass, + // name property is equal to constructor name. + this.name = this.constructor.name; + } + } + + test('passes', () => { + expectUnderTest(() => { + throw new Err(); + })[toThrow](Err); + expectUnderTest(() => { + throw new Err(); + })[toThrow](CustomError); + expectUnderTest(() => { + throw new Err(); + }).not[toThrow](Err2); + expectUnderTest(() => {}).not[toThrow](Err); + }); + + test('did not throw at all', () => { + expect(() => + expect(() => {})[toThrow](Err), + ).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but class did not match (error)', () => { + expect(() => { + expectUnderTest(() => { + throw new Err('apple'); + })[toThrow](Err2); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but class did not match (non-error falsey)', () => { + expect(() => { + expectUnderTest(() => { + + throw undefined; + })[toThrow](Err2); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but class should not match (error)', () => { + expect(() => { + expectUnderTest(() => { + throw new Err('apple'); + }).not[toThrow](Err); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but class should not match (error subclass)', () => { + expect(() => { + expectUnderTest(() => { + throw new SubErr('apple'); + }).not[toThrow](Err); + }).toThrowErrorMatchingSnapshot(); + }); + + test('threw, but class should not match (error subsubclass)', () => { + expect(() => { + expectUnderTest(() => { + throw new SubSubErr('apple'); + }).not[toThrow](Err); + }).toThrowErrorMatchingSnapshot(); + }); + }); + + test.describe('error-message', () => { + // Received message in report if object has message property. + class ErrorMessage { + // not extending Error! + constructor(public message: string) {} + } + const expected = new ErrorMessage('apple'); + + test.describe('pass', () => { + test('isNot false', () => { + expectUnderTest(() => { + throw new ErrorMessage('apple'); + })[toThrow](expected); + }); + + test('isNot true', () => { + expectUnderTest(() => { + throw new ErrorMessage('banana'); + }).not[toThrow](expected); + }); + }); + + test.describe('fail', () => { + test('isNot false', () => { + expect(() => + expectUnderTest(() => { + throw new ErrorMessage('banana'); + })[toThrow](expected), + ).toThrowErrorMatchingSnapshot(); + }); + + test('isNot true', () => { + const message = 'Invalid array length'; + expect(() => + expectUnderTest(() => { + throw new ErrorMessage(message); + }).not[toThrow]({ message }), + ).toThrowErrorMatchingSnapshot(); + }); + + test('multiline diff highlight incorrect expected space', () => { + // jest/issues/2673 + const a = + "There is no route defined for key Settings. \nMust be one of: 'Home'"; + const b = + "There is no route defined for key Settings.\nMust be one of: 'Home'"; + expect(() => + expectUnderTest(() => { + throw new ErrorMessage(b); + })[toThrow]({ message: a }), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }); + + test.describe('error message and cause', () => { + const errorA = new Error('A'); + const errorB = new Error('B', { cause: errorA }); + const expected = new Error('good', { cause: errorB }); + + test.describe('pass', () => { + test('isNot false', () => { + expectUnderTest(() => { + throw new Error('good', { cause: errorB }); + })[toThrow](expected); + }); + + test('isNot true, incorrect message', () => { + expectUnderTest(() => { + throw new Error('bad', { cause: errorB }); + }).not[toThrow](expected); + }); + + test('isNot true, incorrect cause', () => { + expectUnderTest(() => { + throw new Error('good', { cause: errorA }); + }).not[toThrow](expected); + }); + }); + + test.describe('fail', () => { + test('isNot false, incorrect message', () => { + expect(() => + expectUnderTest(() => { + throw new Error('bad', { cause: errorB }); + })[toThrow](expected), + ).toThrow( + /^(?=.*Expected message and cause: ).*Received message and cause: /s, + ); + }); + + test('isNot true, incorrect cause', () => { + expect(() => + expectUnderTest(() => { + throw new Error('good', { cause: errorA }); + })[toThrow](expected), + ).toThrow( + /^(?=.*Expected message and cause: ).*Received message and cause: /s, + ); + }); + }); + }); + + test.describe('asymmetric', () => { + test.describe('any-Class', () => { + test.describe('pass', () => { + test('isNot false', () => { + expectUnderTest(() => { + throw new Err('apple'); + })[toThrow](expect.any(Err)); + }); + + test('isNot true', () => { + expectUnderTest(() => { + throw new Err('apple'); + }).not[toThrow](expect.any(Err2)); + }); + }); + + test.describe('fail', () => { + test('isNot false', () => { + expect(() => + expectUnderTest(() => { + throw new Err('apple'); + })[toThrow](expect.any(Err2)), + ).toThrowErrorMatchingSnapshot(); + }); + + test('isNot true', () => { + expect(() => + expectUnderTest(() => { + throw new Err('apple'); + }).not[toThrow](expect.any(Err)), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }); + + test.describe('anything', () => { + test.describe('pass', () => { + test('isNot false', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](expect.anything()); + }); + + test('isNot true', () => { + expectUnderTest(() => {}).not[toThrow](expect.anything()); + expectUnderTest(() => { + + throw null; + }).not[toThrow](expect.anything()); + }); + }); + + test.describe('fail', () => { + test('isNot false', () => { + expect(() => + expectUnderTest(() => { + + throw null; + })[toThrow](expect.anything()), + ).toThrowErrorMatchingSnapshot(); + }); + + test('isNot true', () => { + expect(() => + expectUnderTest(() => { + throw new CustomError('apple'); + }).not[toThrow](expect.anything()), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }); + + test.describe('no-symbol', () => { + // Test serialization of asymmetric matcher which has no property: + // this.$$typeof = Symbol.for('jest.asymmetricMatcher') + const matchError = { + asymmetricMatch(received: Error | null | undefined) { + return ( + received !== null && + received !== undefined && + received.name === 'Error' + ); + }, + }; + const matchNotError = { + asymmetricMatch(received: Error | null | undefined) { + return ( + received !== null && + received !== undefined && + received.name !== 'Error' + ); + }, + }; + + test.describe('pass', () => { + test('isNot false', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](matchError); + }); + + test('isNot true', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + }).not[toThrow](matchNotError); + }); + }); + + test.describe('fail', () => { + test('isNot false', () => { + expect(() => + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](matchNotError), + ).toThrowErrorMatchingSnapshot(); + }); + + test('isNot true', () => { + expect(() => + expectUnderTest(() => { + throw new CustomError('apple'); + }).not[toThrow](matchError), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }); + + test.describe('objectContaining', () => { + const matchError = expect.objectContaining({ + name: 'Error', + }); + const matchNotError = expect.objectContaining({ + name: 'NotError', + }); + + test.describe('pass', () => { + test('isNot false', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](matchError); + }); + + test('isNot true', () => { + expectUnderTest(() => { + throw new CustomError('apple'); + }).not[toThrow](matchNotError); + }); + }); + + test.describe('fail', () => { + test('isNot false', () => { + expect(() => + expectUnderTest(() => { + throw new CustomError('apple'); + })[toThrow](matchNotError), + ).toThrowErrorMatchingSnapshot(); + }); + + test('isNot true', () => { + expect(() => + expectUnderTest(() => { + throw new CustomError('apple'); + }).not[toThrow](matchError), + ).toThrowErrorMatchingSnapshot(); + }); + }); + }); + }); + + test.describe('promise/async throws if Error-like object is returned', () => { + const asyncFn = async (shouldThrow?: boolean, resolve?: boolean) => { + let err; + if (shouldThrow) + err = new Err('async apple'); + + if (resolve) + return Promise.resolve(err || 'apple'); + else + return Promise.reject(err || 'apple'); + }; + + test('passes', async () => { + await expectUnderTest(Promise.reject(new Error())).rejects[toThrow](); + + await expectUnderTest(asyncFn(true)).rejects[toThrow](); + await expectUnderTest(asyncFn(true)).rejects[toThrow](Err); + await expectUnderTest(asyncFn(true)).rejects[toThrow](Error); + await expectUnderTest(asyncFn(true)).rejects[toThrow]('apple'); + await expectUnderTest(asyncFn(true)).rejects[toThrow](/app/); + + await expectUnderTest(asyncFn(true)).rejects.not[toThrow](Err2); + await expectUnderTest(asyncFn(true)).rejects.not[toThrow]('banana'); + await expectUnderTest(asyncFn(true)).rejects.not[toThrow](/banana/); + + await expectUnderTest(asyncFn(true, true)).resolves[toThrow](); + + await expectUnderTest(asyncFn(false, true)).resolves.not[toThrow](); + await expectUnderTest(asyncFn(false, true)).resolves.not[toThrow](Error); + await expectUnderTest(asyncFn(false, true)).resolves.not[toThrow]('apple'); + await expectUnderTest(asyncFn(false, true)).resolves.not[toThrow](/apple/); + await expectUnderTest(asyncFn(false, true)).resolves.not[toThrow]('banana'); + await expectUnderTest(asyncFn(false, true)).resolves.not[toThrow](/banana/); + + await expectUnderTest(asyncFn()).rejects.not[toThrow](); + await expectUnderTest(asyncFn()).rejects.not[toThrow](Error); + await expectUnderTest(asyncFn()).rejects.not[toThrow]('apple'); + await expectUnderTest(asyncFn()).rejects.not[toThrow](/apple/); + await expectUnderTest(asyncFn()).rejects.not[toThrow]('banana'); + await expectUnderTest(asyncFn()).rejects.not[toThrow](/banana/); + + // Works with nested functions inside promises + await expectUnderTest( + Promise.reject(() => { + throw new Error(); + }), + ).rejects[toThrow](); + await expectUnderTest(Promise.reject(() => {})).rejects.not[toThrow](); + }); + + test('did not throw at all', async () => { + await expectUnderTestAsAny( + expectUnderTest(asyncFn()).rejects[toThrow](), + ).rejects.toThrowErrorMatchingSnapshot(); + }); + + test('threw, but class did not match', async () => { + await expectUnderTestAsAny( + expectUnderTest(asyncFn(true)).rejects[toThrow](Err2), + ).rejects.toThrowErrorMatchingSnapshot(); + }); + + test('threw, but should not have', async () => { + await expectUnderTestAsAny( + expectUnderTest(asyncFn(true)).rejects.not[toThrow](), + ).rejects.toThrowErrorMatchingSnapshot(); + }); + }); + + test.describe('expected is undefined', () => { + test('threw, but should not have (non-error falsey)', () => { + expect(() => { + expectUnderTest(() => { + + throw null; + }).not[toThrow](); + }).toThrowErrorMatchingSnapshot(); + }); + }); + + test('invalid arguments', () => { + expect(() => + expectUnderTest(() => {}).not[toThrow](111), + ).toThrowErrorMatchingSnapshot(); + }); + + test('invalid actual', () => { + expect(() => + expectUnderTest('a string')[toThrow](), + ).toThrowErrorMatchingSnapshot(); + }); + }); +} \ No newline at end of file diff --git a/tests/playwright-test/playwright.config.ts b/tests/playwright-test/playwright.config.ts index 34d4dc6d9f593..0d94a8197dd6f 100644 --- a/tests/playwright-test/playwright.config.ts +++ b/tests/playwright-test/playwright.config.ts @@ -47,6 +47,10 @@ export default defineConfig({ testDir: path.join(__dirname, '../image_tools'), testIgnore: [path.join(__dirname, '../fixtures/**')], }, + { + name: 'expect', + testDir: path.join(__dirname, '../expect'), + }, ], reporter: reporters(), metadata: { diff --git a/utils/check_deps.js b/utils/check_deps.js index 8943ca6800c0b..79eca03062885 100644 --- a/utils/check_deps.js +++ b/utils/check_deps.js @@ -79,7 +79,7 @@ async function innerCheckDeps(root) { }); const sourceFiles = program.getSourceFiles(); const errors = []; - sourceFiles.filter(x => !x.fileName.includes('node_modules')).map(x => visit(x, x.fileName, x.getFullText())); + sourceFiles.filter(x => !x.fileName.includes(path.sep + 'node_modules' + path.sep) && !x.fileName.includes(path.sep + 'bundles' + path.sep)).map(x => visit(x, x.fileName, x.getFullText())); if (errors.length) { for (const error of errors) @@ -244,7 +244,7 @@ async function innerCheckDeps(root) { function listAllFiles(dir) { const dirs = fs.readdirSync(dir, { withFileTypes: true }); const result = []; - dirs.map(d => { + dirs.forEach(d => { const res = path.resolve(dir, d.name); if (d.isDirectory()) result.push(...listAllFiles(res)); From e5d6ee5bd81327a26fff312ce055c7c82175483e Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 9 Sep 2024 22:28:08 +0200 Subject: [PATCH 034/805] chore: merge fetch params on server side (#32518) https://github.com/microsoft/playwright-python/pull/2546#discussion_r1750090592 --- packages/playwright-core/src/client/fetch.ts | 33 ++++--------------- .../playwright-core/src/protocol/validator.ts | 1 + packages/playwright-core/src/server/fetch.ts | 4 ++- packages/protocol/src/channels.ts | 2 ++ packages/protocol/src/protocol.yml | 1 + 5 files changed, 14 insertions(+), 27 deletions(-) diff --git a/packages/playwright-core/src/client/fetch.ts b/packages/playwright-core/src/client/fetch.ts index 7aaa5069c21b8..87c31579b5180 100644 --- a/packages/playwright-core/src/client/fetch.ts +++ b/packages/playwright-core/src/client/fetch.ts @@ -175,8 +175,12 @@ export class APIRequestContext extends ChannelOwner= 0, `'maxRedirects' must be greater than or equal to '0'`); assert(options.maxRetries === undefined || options.maxRetries >= 0, `'maxRetries' must be greater than or equal to '0'`); const url = options.url !== undefined ? options.url : options.request!.url(); - const params = mapParamsToArray(options.params); const method = options.method || options.request?.method(); + let encodedParams = undefined; + if (typeof options.params === 'string') + encodedParams = options.params; + else if (options.params instanceof URLSearchParams) + encodedParams = options.params.toString(); // Cannot call allHeaders() here as the request may be paused inside route handler. const headersObj = options.headers || options.request?.headers(); const headers = headersObj ? headersObjectToArray(headersObj) : undefined; @@ -228,7 +232,8 @@ export class APIRequestContext extends ChannelOwner Date: Mon, 9 Sep 2024 14:00:51 -0700 Subject: [PATCH 035/805] test: fix project filter test (#32525) It was erroneously passing projects separate by comma, which never worked. --- tests/playwright-test/reporter-blob.spec.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/playwright-test/reporter-blob.spec.ts b/tests/playwright-test/reporter-blob.spec.ts index 8f3064a07334c..91b32e76a2ec9 100644 --- a/tests/playwright-test/reporter-blob.spec.ts +++ b/tests/playwright-test/reporter-blob.spec.ts @@ -2040,12 +2040,15 @@ test('project filter in report name', async ({ runInlineTest }) => { const reportDir = test.info().outputPath('blob-report'); { - await runInlineTest(files, { shard: `2/2`, project: 'foo' }); + const result = await runInlineTest(files, { shard: `2/2`, project: 'foo' }); + expect(result.exitCode).toBe(0); const reportFiles = await fs.promises.readdir(reportDir); expect(reportFiles.sort()).toEqual(['report-foo-2.zip']); } + { - await runInlineTest(files, { shard: `1/2`, project: 'foo,b*r', grep: 'smoke' }); + const result = await runInlineTest(files, { shard: `1/2`, project: ['foo', 'b*r'], grep: 'smoke' }); + expect(result.exitCode).toBe(0); const reportFiles = await fs.promises.readdir(reportDir); expect(reportFiles.sort()).toEqual(['report-foo-b-r-6d9d49e-1.zip']); } From 6bb005db85c047f1a3708c4ec0f10659e7ae0046 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 9 Sep 2024 14:01:02 -0700 Subject: [PATCH 036/805] fix(test runner): improve error message when not able to parse tsconfig (#32526) --- .../src/third_party/tsconfig-loader.ts | 10 +++++++--- tests/playwright-test/resolver.spec.ts | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/playwright/src/third_party/tsconfig-loader.ts b/packages/playwright/src/third_party/tsconfig-loader.ts index 61ad11a3bdd94..b654a3b963925 100644 --- a/packages/playwright/src/third_party/tsconfig-loader.ts +++ b/packages/playwright/src/third_party/tsconfig-loader.ts @@ -53,9 +53,13 @@ export interface LoadedTsConfig { } export function loadTsConfig(configPath: string): LoadedTsConfig[] { - const references: LoadedTsConfig[] = []; - const config = innerLoadTsConfig(configPath, references); - return [config, ...references]; + try { + const references: LoadedTsConfig[] = []; + const config = innerLoadTsConfig(configPath, references); + return [config, ...references]; + } catch (e) { + throw new Error(`Failed to load tsconfig file at ${configPath}:\n${e.message}`); + } } function resolveConfigFile(baseConfigFile: string, referencedConfigFile: string) { diff --git a/tests/playwright-test/resolver.spec.ts b/tests/playwright-test/resolver.spec.ts index 5a0e91b099412..e06959558c8a2 100644 --- a/tests/playwright-test/resolver.spec.ts +++ b/tests/playwright-test/resolver.spec.ts @@ -16,6 +16,24 @@ import { test, expect } from './playwright-test-fixtures'; +test('should print tsconfig parsing error', async ({ runInlineTest }) => { + const files = { + 'a.spec.ts': ` + import { test } from '@playwright/test'; + test('pass', async () => {}); + `, + 'tsconfig.json': ` + "foo": "bar" + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(1); + expect(result.output).toContain(`Failed to load tsconfig file at`); + expect(result.output).toContain(`tsconfig.json`); + expect(result.output).toContain(`JSON5: invalid character ':' at 2:12`); +}); + test('should respect path resolver', async ({ runInlineTest }) => { test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11656' }); From ae118674b8d3a42c905058f612703b2ddbc42751 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 9 Sep 2024 14:01:20 -0700 Subject: [PATCH 037/805] fix(test runner): allow directory imports with path mapping (#32491) We now hopefully align with `moduleResolution: bundler` tsconfig option, allowing directory imports in every scenario, and allowing proper module imports when not going through the type mapping. This regressed in #32078. Fixes #32480, fixes #31811. --- .../playwright/src/transform/transform.ts | 13 +- packages/playwright/src/util.ts | 57 ++- tests/playwright-test/resolver.spec.ts | 460 ++++++++++++++++-- 3 files changed, 484 insertions(+), 46 deletions(-) diff --git a/packages/playwright/src/transform/transform.ts b/packages/playwright/src/transform/transform.ts index 9ca80399fb7f5..f70f385b5bc72 100644 --- a/packages/playwright/src/transform/transform.ts +++ b/packages/playwright/src/transform/transform.ts @@ -24,7 +24,7 @@ import type { LoadedTsConfig } from '../third_party/tsconfig-loader'; import { loadTsConfig } from '../third_party/tsconfig-loader'; import Module from 'module'; import type { BabelPlugin, BabelTransformFunction } from './babelBundle'; -import { createFileMatcher, fileIsModule, resolveImportSpecifierExtension } from '../util'; +import { createFileMatcher, fileIsModule, resolveImportSpecifierAfterMapping } from '../util'; import type { Matcher } from '../util'; import { getFromCompilationCache, currentFileDepsCollector, belongsToNodeModules, installSourceMapSupport } from './compilationCache'; @@ -136,8 +136,13 @@ export function resolveHook(filename: string, specifier: string): string | undef return; if (isRelativeSpecifier(specifier)) - return resolveImportSpecifierExtension(path.resolve(path.dirname(filename), specifier)); + return resolveImportSpecifierAfterMapping(path.resolve(path.dirname(filename), specifier), false); + /** + * TypeScript discourages path-mapping into node_modules: + * https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages + * However, if path-mapping doesn't yield a result, TypeScript falls back to the default resolution through node_modules. + */ const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx'); const tsconfigs = loadAndValidateTsconfigsForFile(filename); for (const tsconfig of tsconfigs) { @@ -179,7 +184,7 @@ export function resolveHook(filename: string, specifier: string): string | undef if (value.includes('*')) candidate = candidate.replace('*', matchedPartOfSpecifier); candidate = path.resolve(tsconfig.pathsBase!, candidate); - const existing = resolveImportSpecifierExtension(candidate); + const existing = resolveImportSpecifierAfterMapping(candidate, true); if (existing) { longestPrefixLength = keyPrefix.length; pathMatchedByLongestPrefix = existing; @@ -193,7 +198,7 @@ export function resolveHook(filename: string, specifier: string): string | undef if (path.isAbsolute(specifier)) { // Handle absolute file paths like `import '/path/to/file'` // Do not handle module imports like `import 'fs'` - return resolveImportSpecifierExtension(specifier); + return resolveImportSpecifierAfterMapping(specifier, false); } } diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 0531f167a0442..d25f77947b387 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -307,8 +307,23 @@ function folderIsModule(folder: string): boolean { return require(packageJsonPath).type === 'module'; } -// This follows the --moduleResolution=bundler strategy from tsc. -// https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#moduleresolution-bundler +const packageJsonMainFieldCache = new Map(); + +function getMainFieldFromPackageJson(packageJsonPath: string) { + if (!packageJsonMainFieldCache.has(packageJsonPath)) { + let mainField: string | undefined; + try { + mainField = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).main; + } catch { + } + packageJsonMainFieldCache.set(packageJsonPath, mainField); + } + return packageJsonMainFieldCache.get(packageJsonPath); +} + +// This method performs "file extension subsitution" to find the ts, js or similar source file +// based on the import specifier, which might or might not have an extension. See TypeScript docs: +// https://www.typescriptlang.org/docs/handbook/modules/reference.html#file-extension-substitution. const kExtLookups = new Map([ ['.js', ['.jsx', '.ts', '.tsx']], ['.jsx', ['.tsx']], @@ -316,7 +331,7 @@ const kExtLookups = new Map([ ['.mjs', ['.mts']], ['', ['.js', '.ts', '.jsx', '.tsx', '.cjs', '.mjs', '.cts', '.mts']], ]); -export function resolveImportSpecifierExtension(resolved: string): string | undefined { +function resolveImportSpecifierExtension(resolved: string): string | undefined { if (fileExists(resolved)) return resolved; @@ -330,13 +345,45 @@ export function resolveImportSpecifierExtension(resolved: string): string | unde } break; // Do not try '' when a more specific extension like '.jsx' matched. } +} + +// This method resolves directory imports and performs "file extension subsitution". +// It is intended to be called after the path mapping resolution. +// +// Directory imports follow the --moduleResolution=bundler strategy from tsc. +// https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution +// https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler +// +// See also Node.js "folder as module" behavior: +// https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules. +export function resolveImportSpecifierAfterMapping(resolved: string, afterPathMapping: boolean): string | undefined { + const resolvedFile = resolveImportSpecifierExtension(resolved); + if (resolvedFile) + return resolvedFile; if (dirExists(resolved)) { + const packageJsonPath = path.join(resolved, 'package.json'); + + if (afterPathMapping) { + // Most notably, the module resolution algorithm is not performed after the path mapping. + // This means no node_modules lookup or package.json#exports. + // + // Only the "folder as module" Node.js behavior is respected: + // - consult `package.json#main`; + // - look for `index.js` or similar. + const mainField = getMainFieldFromPackageJson(packageJsonPath); + const mainFieldResolved = mainField ? resolveImportSpecifierExtension(path.resolve(resolved, mainField)) : undefined; + return mainFieldResolved || resolveImportSpecifierExtension(path.join(resolved, 'index')); + } + // If we import a package, let Node.js figure out the correct import based on package.json. - if (fileExists(path.join(resolved, 'package.json'))) + // This also covers the "main" field for "folder as module". + if (fileExists(packageJsonPath)) return resolved; - // Otherwise, try to find a corresponding index file. + // Implement the "folder as module" Node.js behavior. + // Note that we do not delegate to Node.js, because we support this for ESM as well, + // following the TypeScript "bundler" mode. const dirImport = path.join(resolved, 'index'); return resolveImportSpecifierExtension(dirImport); } diff --git a/tests/playwright-test/resolver.spec.ts b/tests/playwright-test/resolver.spec.ts index e06959558c8a2..037ba14f223cf 100644 --- a/tests/playwright-test/resolver.spec.ts +++ b/tests/playwright-test/resolver.spec.ts @@ -587,43 +587,6 @@ test('should resolve paths relative to the originating config when extending and expect(result.exitCode).toBe(0); }); -test('should import packages with non-index main script through path resolver', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'app/pkg/main.ts': ` - export const foo = 42; - `, - 'app/pkg/package.json': ` - { "main": "main.ts" } - `, - 'package.json': ` - { "name": "example-project" } - `, - 'playwright.config.ts': ` - export default {}; - `, - 'tsconfig.json': `{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "app/*": ["app/*"], - }, - }, - }`, - 'example.spec.ts': ` - import { foo } from 'app/pkg'; - import { test, expect } from '@playwright/test'; - test('test', ({}) => { - console.log('foo=' + foo); - }); - `, - }); - - expect(result.exitCode).toBe(0); - expect(result.passed).toBe(1); - expect(result.output).not.toContain(`find module`); - expect(result.output).toContain(`foo=42`); -}); - test('should respect tsconfig project references', async ({ runInlineTest }) => { test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29256' }); @@ -711,3 +674,426 @@ test('should respect --tsconfig option', async ({ runInlineTest }) => { expect(result.exitCode).toBe(0); expect(result.output).not.toContain(`Could not`); }); + +test.describe('directory imports', () => { + test('should resolve index.js without path mapping in CJS', async ({ runInlineTest, runTSC }) => { + const files = { + 'foo-pkg/index.js': ` + exports.foo = 'bar'; + `, + 'foo-pkg/index.d.ts': ` + export const foo: 'bar'; + `, + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + import { foo } from './foo-pkg'; + test('pass', async () => { + const bar: 'bar' = foo; + expect(bar).toBe('bar'); + }); + `, + }; + + const result = await runInlineTest(files); + expect(result.passed).toBe(1); + expect(result.exitCode).toBe(0); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should resolve index.js without path mapping in ESM', async ({ runInlineTest, runTSC }) => { + const files = { + 'foo-pkg/index.js': ` + export const foo = 'bar'; + `, + 'foo-pkg/index.d.ts': ` + export const foo: 'bar'; + `, + 'package.json': ` + { "type": "module" } + `, + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + import { foo } from './foo-pkg'; + test('pass', async () => { + const bar: 'bar' = foo; + expect(bar).toBe('bar'); + }); + `, + }; + + const result = await runInlineTest(files); + expect(result.passed).toBe(1); + expect(result.exitCode).toBe(0); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should resolve index.js after path mapping in CJS', async ({ runInlineTest, runTSC }) => { + test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' }); + + const files = { + '@acme/lib/index.js': ` + exports.greet = () => 2; + `, + '@acme/lib/index.d.ts': ` + export const greet: () => number; + `, + 'tests/hello.test.ts': ` + import { greet } from '@acme/lib'; + import { test, expect } from '@playwright/test'; + test('hello', async ({}) => { + const foo: number = greet(); + expect(foo).toBe(2); + }); + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "paths": { + "@acme/*": ["./@acme/*"] + }, + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + } + } + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should resolve index.js after path mapping in ESM', async ({ runInlineTest, runTSC }) => { + test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' }); + + const files = { + '@acme/lib/index.js': ` + export const greet = () => 2; + `, + '@acme/lib/index.d.ts': ` + export const greet: () => number; + `, + 'package.json': ` + { "type": "module" } + `, + 'tests/hello.test.ts': ` + import { greet } from '@acme/lib'; + import { test, expect } from '@playwright/test'; + test('hello', async ({}) => { + const foo: number = greet(); + expect(foo).toBe(2); + }); + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "paths": { + "@acme/*": ["./@acme/*"] + }, + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + } + } + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should respect package.json#main after path mapping in CJS', async ({ runInlineTest, runTSC }) => { + const files = { + 'app/pkg/main.ts': ` + export const foo = 42; + `, + 'app/pkg/package.json': ` + { "main": "main.ts" } + `, + 'package.json': ` + { "name": "example-project" } + `, + 'playwright.config.ts': ` + export default {}; + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "baseUrl": ".", + "paths": { + "app/*": ["app/*"] + }, + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + } + } + `, + 'example.spec.ts': ` + import { foo } from 'app/pkg'; + import { test, expect } from '@playwright/test'; + test('test', ({}) => { + const bar: number = foo; + expect(bar).toBe(42); + }); + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + expect(result.output).not.toContain(`find module`); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should respect package.json#main after path mapping in ESM', async ({ runInlineTest, runTSC }) => { + const files = { + 'app/pkg/main.ts': ` + export const foo = 42; + `, + 'app/pkg/package.json': ` + { "main": "main.ts", "type": "module" } + `, + 'package.json': ` + { "name": "example-project", "type": "module" } + `, + 'playwright.config.ts': ` + export default {}; + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "baseUrl": ".", + "paths": { + "app/*": ["app/*"] + }, + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + }, + } + `, + 'example.spec.ts': ` + import { foo } from 'app/pkg'; + import { test, expect } from '@playwright/test'; + test('test', ({}) => { + const bar: number = foo; + expect(bar).toBe(42); + }); + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should respect package.json#exports without path mapping in CJS', async ({ runInlineTest, runTSC }) => { + const files = { + 'node_modules/foo-pkg/package.json': ` + { "name": "foo-pkg", "exports": { ".": "./foo.js" } } + `, + 'node_modules/foo-pkg/foo.js': ` + exports.foo = 'bar'; + `, + 'node_modules/foo-pkg/foo.d.ts': ` + export const foo: 'bar'; + `, + 'package.json': ` + { "name": "test-project" } + `, + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + import { foo } from 'foo-pkg'; + test('pass', async () => { + const bar: 'bar' = foo; + expect(bar).toBe('bar'); + }); + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + }, + } + `, + }; + + const result = await runInlineTest(files); + expect(result.passed).toBe(1); + expect(result.exitCode).toBe(0); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should respect package.json#exports without path mapping in ESM', async ({ runInlineTest, runTSC }) => { + const files = { + 'node_modules/foo-pkg/package.json': ` + { "name": "foo-pkg", "type": "module", "exports": { "default": "./foo.js" } } + `, + 'node_modules/foo-pkg/foo.js': ` + export const foo = 'bar'; + `, + 'node_modules/foo-pkg/foo.d.ts': ` + export const foo: 'bar'; + `, + 'package.json': ` + { "name": "test-project", "type": "module" } + `, + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + import { foo } from 'foo-pkg'; + test('pass', async () => { + const bar: 'bar' = foo; + expect(bar).toBe('bar'); + }); + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + }, + } + `, + }; + + const result = await runInlineTest(files); + expect(result.passed).toBe(1); + expect(result.exitCode).toBe(0); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should not respect package.json#exports after type mapping in CJS', async ({ runInlineTest, runTSC }) => { + const files = { + 'app/pkg/main.ts': ` + export const filename: 'main.ts' = 'main.ts'; + `, + 'app/pkg/index.js': ` + export const filename = 'index.js'; + `, + 'app/pkg/index.d.ts': ` + export const filename: 'index.js'; + `, + 'app/pkg/package.json': ` + { "exports": { ".": "./main.ts" } } + `, + 'package.json': ` + { "name": "example-project" } + `, + 'playwright.config.ts': ` + export default {}; + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "baseUrl": ".", + "paths": { + "app/*": ["app/*"] + }, + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + } + } + `, + 'example.spec.ts': ` + import { filename } from 'app/pkg'; + import { test, expect } from '@playwright/test'; + test('test', ({}) => { + const foo: 'index.js' = filename; + expect(foo).toBe('index.js'); + }); + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); + + test('should not respect package.json#exports after type mapping in ESM', async ({ runInlineTest, runTSC }) => { + const files = { + 'app/pkg/main.ts': ` + export const filename: 'main.ts' = 'main.ts'; + `, + 'app/pkg/index.js': ` + export const filename = 'index.js'; + `, + 'app/pkg/index.d.ts': ` + export const filename: 'index.js'; + `, + 'app/pkg/package.json': ` + { "exports": { ".": "./main.ts" }, "type": "module" } + `, + 'package.json': ` + { "name": "example-project", "type": "module" } + `, + 'playwright.config.ts': ` + export default {}; + `, + 'tsconfig.json': ` + { + "compilerOptions": { + "baseUrl": ".", + "paths": { + "app/*": ["app/*"] + }, + "moduleResolution": "bundler", + "module": "preserve", + "noEmit": true, + "noImplicitAny": true + } + } + `, + 'example.spec.ts': ` + import { filename } from 'app/pkg'; + import { test, expect } from '@playwright/test'; + test('test', ({}) => { + const foo: 'index.js' = filename; + expect(foo).toBe('index.js'); + }); + `, + }; + + const result = await runInlineTest(files); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + const tscResult = await runTSC(files); + expect(tscResult.exitCode).toBe(0); + }); +}); From 6d5889a52c2f78ae141b84517e3f0c90b8a0b494 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 9 Sep 2024 16:44:32 -0700 Subject: [PATCH 038/805] chore: revert the matcherResult in API (#32524) --- .../class-testinfoerror-matcherresult.md | 35 ----- docs/src/test-api/class-testinfoerror.md | 6 - .../class-testerror-matcherresult.md | 35 ----- docs/src/test-reporter-api/class-testerror.md | 6 - packages/playwright/src/reporters/base.ts | 3 - packages/playwright/src/util.ts | 16 +- packages/playwright/types/test.d.ts | 35 ----- packages/playwright/types/testReporter.d.ts | 36 ----- tests/playwright-test/reporter-errors.spec.ts | 145 ------------------ .../overrides-testReporter.d.ts | 1 - 10 files changed, 2 insertions(+), 316 deletions(-) delete mode 100644 docs/src/test-api/class-testinfoerror-matcherresult.md delete mode 100644 docs/src/test-reporter-api/class-testerror-matcherresult.md delete mode 100644 tests/playwright-test/reporter-errors.spec.ts diff --git a/docs/src/test-api/class-testinfoerror-matcherresult.md b/docs/src/test-api/class-testinfoerror-matcherresult.md deleted file mode 100644 index f68e2db1ae908..0000000000000 --- a/docs/src/test-api/class-testinfoerror-matcherresult.md +++ /dev/null @@ -1,35 +0,0 @@ -# class: TestInfoErrorMatcherResult -* since: v1.48 -* langs: js - -Matcher-specific details for the error thrown during the `expect` call. - -## property: TestInfoErrorMatcherResult.actual -* since: v1.48 -- type: ?<[unknown]> - -Actual value. - -## property: TestInfoErrorMatcherResult.expected -* since: v1.48 -- type: ?<[unknown]> - -Expected value. - -## property: TestInfoErrorMatcherResult.name -* since: v1.48 -- type: ?<[string]> - -Matcher name. - -## property: TestInfoErrorMatcherResult.pass -* since: v1.48 -- type: <[string]> - -Whether the matcher passed. - -## property: TestInfoErrorMatcherResult.timeout -* since: v1.48 -- type: ?<[int]> - -Timeout that was used during matching. diff --git a/docs/src/test-api/class-testinfoerror.md b/docs/src/test-api/class-testinfoerror.md index b084aaf54b65e..66e78ecabdafc 100644 --- a/docs/src/test-api/class-testinfoerror.md +++ b/docs/src/test-api/class-testinfoerror.md @@ -4,12 +4,6 @@ Information about an error thrown during test execution. -## property: TestInfoError.matcherResult -* since: v1.48 -- type: ?<[TestInfoErrorMatcherResult]> - -Matcher result details. - ## property: TestInfoError.message * since: v1.10 - type: ?<[string]> diff --git a/docs/src/test-reporter-api/class-testerror-matcherresult.md b/docs/src/test-reporter-api/class-testerror-matcherresult.md deleted file mode 100644 index b8d0f1dce70c1..0000000000000 --- a/docs/src/test-reporter-api/class-testerror-matcherresult.md +++ /dev/null @@ -1,35 +0,0 @@ -# class: TestErrorMatcherResult -* since: v1.48 -* langs: js - -Matcher-specific details for the error thrown during the `expect` call. - -## property: TestErrorMatcherResult.actual -* since: v1.48 -- type: ?<[unknown]> - -Actual value. - -## property: TestErrorMatcherResult.expected -* since: v1.48 -- type: ?<[unknown]> - -Expected value. - -## property: TestErrorMatcherResult.name -* since: v1.48 -- type: ?<[string]> - -Matcher name. - -## property: TestErrorMatcherResult.pass -* since: v1.48 -- type: <[string]> - -Whether the matcher passed. - -## property: TestErrorMatcherResult.timeout -* since: v1.48 -- type: ?<[int]> - -Timeout that was used during matching. diff --git a/docs/src/test-reporter-api/class-testerror.md b/docs/src/test-reporter-api/class-testerror.md index cc59c3a4c68c9..7a872c63fcb8a 100644 --- a/docs/src/test-reporter-api/class-testerror.md +++ b/docs/src/test-reporter-api/class-testerror.md @@ -4,12 +4,6 @@ Information about an error thrown during test execution. -## property: TestError.matcherResult -* since: v1.48 -- type: ?<[TestErrorMatcherResult]> - -Matcher result details. - ## property: TestError.message * since: v1.10 - type: ?<[string]> diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 22470b0954d10..c9ce2f7bcd4cd 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -32,7 +32,6 @@ type Annotation = { type ErrorDetails = { message: string; location?: Location; - matcherResult?: TestError['matcherResult']; }; type TestSummary = { @@ -400,7 +399,6 @@ export function formatResultFailure(test: TestCase, result: TestResult, initialI errorDetails.push({ message: indent(formattedError.message, initialIndent), location: formattedError.location, - matcherResult: formattedError.matcherResult }); } return errorDetails; @@ -491,7 +489,6 @@ export function formatError(error: TestError, highlightCode: boolean): ErrorDeta return { location, message: tokens.join('\n'), - matcherResult: error.matcherResult }; } diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index d25f77947b387..460b3de07e746 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -63,20 +63,8 @@ export function filteredStackTrace(rawStack: RawStack): StackFrame[] { } export function serializeError(error: Error | any): TestInfoError { - if (error instanceof Error) { - const result: TestInfoError = filterStackTrace(error); - if ('matcherResult' in error && error.matcherResult) { - const matcherResult = (error.matcherResult as TestInfoError['matcherResult'])!; - result.matcherResult = { - pass: matcherResult.pass, - name: matcherResult.name, - expected: matcherResult.expected, - actual: matcherResult.actual, - timeout: matcherResult.timeout, - }; - } - return result; - } + if (error instanceof Error) + return filterStackTrace(error); return { value: util.inspect(error) }; diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 09b5c7efdb82c..74aeb641337a9 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -8222,45 +8222,10 @@ export interface TestInfo { workerIndex: number; } -/** - * Matcher-specific details for the error thrown during the `expect` call. - */ -export interface TestInfoErrorMatcherResult { - /** - * Actual value. - */ - actual?: unknown; - - /** - * Expected value. - */ - expected?: unknown; - - /** - * Matcher name. - */ - name?: string; - - /** - * Whether the matcher passed. - */ - pass: string; - - /** - * Timeout that was used during matching. - */ - timeout?: number; -} - /** * Information about an error thrown during test execution. */ export interface TestInfoError { - /** - * Matcher result details. - */ - matcherResult?: TestInfoErrorMatcherResult; - /** * Error message. Set when [Error] (or its subclass) has been thrown. */ diff --git a/packages/playwright/types/testReporter.d.ts b/packages/playwright/types/testReporter.d.ts index b600e3c80178e..52073066f0efb 100644 --- a/packages/playwright/types/testReporter.d.ts +++ b/packages/playwright/types/testReporter.d.ts @@ -284,7 +284,6 @@ export interface JSONReportTest { export interface JSONReportError { message: string; location?: Location; - matcherResult?: TestErrorMatcherResult; } export interface JSONReportTestResult { @@ -568,36 +567,6 @@ export interface TestCase { type: "test"; } -/** - * Matcher-specific details for the error thrown during the `expect` call. - */ -export interface TestErrorMatcherResult { - /** - * Actual value. - */ - actual?: unknown; - - /** - * Expected value. - */ - expected?: unknown; - - /** - * Matcher name. - */ - name?: string; - - /** - * Whether the matcher passed. - */ - pass: string; - - /** - * Timeout that was used during matching. - */ - timeout?: number; -} - /** * Information about an error thrown during test execution. */ @@ -607,11 +576,6 @@ export interface TestError { */ location?: Location; - /** - * Matcher result details. - */ - matcherResult?: TestErrorMatcherResult; - /** * Error message. Set when [Error] (or its subclass) has been thrown. */ diff --git a/tests/playwright-test/reporter-errors.spec.ts b/tests/playwright-test/reporter-errors.spec.ts deleted file mode 100644 index ad0923723426e..0000000000000 --- a/tests/playwright-test/reporter-errors.spec.ts +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { test, expect } from './playwright-test-fixtures'; - -test('should report matcherResults for generic matchers', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'a.test.js': ` - import { test, expect as baseExpect } from '@playwright/test'; - const expect = baseExpect.soft; - test('fail', ({}) => { - expect(1).toBe(2); - expect(1).toBeCloseTo(2); - expect(undefined).toBeDefined(); - expect(1).toBeFalsy(); - expect(1).toBeGreaterThan(2); - expect(1).toBeGreaterThanOrEqual(2); - expect('a').toBeInstanceOf(Number); - expect(2).toBeLessThan(1); - expect(2).toBeLessThanOrEqual(1); - expect(1).toBeNaN(); - expect(1).toBeNull(); - expect(0).toBeTruthy(); - expect(1).toBeUndefined(); - expect([1]).toContain(2); - expect([1]).toContainEqual(2); - expect([1]).toEqual([2]); - expect([1]).toHaveLength(2); - expect({ a: 1 }).toHaveProperty('b'); - expect('a').toMatch(/b/); - expect({ a: 1 }).toMatchObject({ b: 2 }); - expect({ a: 1 }).toStrictEqual({ b: 2 }); - expect(() => {}).toThrow(); - expect(() => {}).toThrowError('a'); - }); - ` - }, { }); - expect(result.exitCode).toBe(1); - - const { errors } = result.report.suites[0].specs[0].tests[0].results[0]; - const matcherResults = errors.map(e => e.matcherResult); - expect(matcherResults).toEqual([ - { name: 'toBe', pass: false, expected: 2, actual: 1 }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { name: 'toEqual', pass: false, expected: [2], actual: [1] }, - { pass: false }, - { pass: false }, - { pass: false }, - { pass: false }, - { name: 'toStrictEqual', pass: false, expected: { b: 2 }, actual: { a: 1 } }, - { pass: false }, - { pass: false }, - ]); -}); - -test('should report matcherResults for web matchers', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'a.test.js': ` - import { test, expect as baseExpect } from '@playwright/test'; - - const expect = baseExpect.configure({ soft: true, timeout: 1 }); - test('fail', async ({ page }) => { - await page.setContent('Hello
World
'); - await expect(page.locator('input')).toBeChecked(); - await expect(page.locator('input')).toBeDisabled(); - await expect(page.locator('textarea')).not.toBeEditable(); - await expect(page.locator('span')).toBeEmpty(); - await expect(page.locator('button')).not.toBeEnabled(); - await expect(page.locator('button')).toBeFocused(); - await expect(page.locator('span')).toBeHidden(); - await expect(page.locator('div')).not.toBeInViewport(); - await expect(page.locator('div')).not.toBeVisible(); - await expect(page.locator('span')).toContainText('World'); - await expect(page.locator('span')).toHaveAccessibleDescription('World'); - await expect(page.locator('span')).toHaveAccessibleName('World'); - await expect(page.locator('span')).toHaveAttribute('name', 'value'); - await expect(page.locator('span')).toHaveAttribute('name'); - await expect(page.locator('span')).toHaveClass('name'); - await expect(page.locator('span')).toHaveCount(2); - await expect(page.locator('span')).toHaveCSS('width', '10'); - await expect(page.locator('span')).toHaveId('id'); - await expect(page.locator('span')).toHaveJSProperty('name', 'value'); - await expect(page.locator('span')).toHaveRole('role'); - await expect(page.locator('span')).toHaveText('World'); - await expect(page.locator('textarea')).toHaveValue('value'); - await expect(page.locator('select')).toHaveValues(['value']); - }); - ` - }, { }); - expect(result.exitCode).toBe(1); - - const { errors } = result.report.suites[0].specs[0].tests[0].results[0]; - const matcherResults = errors.map(e => e.matcherResult); - expect(matcherResults).toEqual([ - { name: 'toBeChecked', pass: false, expected: 'checked', actual: 'unchecked', timeout: 1 }, - { name: 'toBeDisabled', pass: false, expected: 'disabled', actual: 'enabled', timeout: 1 }, - { name: 'toBeEditable', pass: true, expected: 'editable', actual: 'editable', timeout: 1 }, - { name: 'toBeEmpty', pass: false, expected: 'empty', actual: 'notEmpty', timeout: 1 }, - { name: 'toBeEnabled', pass: true, expected: 'enabled', actual: 'enabled', timeout: 1 }, - { name: 'toBeFocused', pass: false, expected: 'focused', actual: 'inactive', timeout: 1 }, - { name: 'toBeHidden', pass: false, expected: 'hidden', actual: 'visible', timeout: 1 }, - { name: 'toBeInViewport', pass: true, expected: 'in viewport', actual: 'in viewport', timeout: 1 }, - { name: 'toBeVisible', pass: true, expected: 'visible', actual: 'visible', timeout: 1 }, - { name: 'toContainText', pass: false, expected: 'World', actual: 'Hello', timeout: 1 }, - { name: 'toHaveAccessibleDescription', pass: false, expected: 'World', actual: '', timeout: 1 }, - { name: 'toHaveAccessibleName', pass: false, expected: 'World', actual: '', timeout: 1 }, - { name: 'toHaveAttribute', pass: false, expected: 'value', actual: null, timeout: 1 }, - { name: 'toHaveAttribute', pass: false, expected: 'have attribute', actual: 'not have attribute', timeout: 1 }, - { name: 'toHaveClass', pass: false, expected: 'name', actual: '', timeout: 1 }, - { name: 'toHaveCount', pass: false, expected: 2, actual: 1, timeout: 1 }, - { name: 'toHaveCSS', pass: false, expected: '10', actual: 'auto', timeout: 1 }, - { name: 'toHaveId', pass: false, expected: 'id', actual: '', timeout: 1 }, - { name: 'toHaveJSProperty', pass: false, expected: 'value', timeout: 1 }, - { name: 'toHaveRole', pass: false, expected: 'role', actual: '', timeout: 1 }, - { name: 'toHaveText', pass: false, expected: 'World', actual: 'Hello', timeout: 1 }, - { name: 'toHaveValue', pass: false, expected: 'value', actual: '', timeout: 1 }, - { name: 'toHaveValues', pass: false, expected: ['value'], actual: [], timeout: 1 }, - ]); -}); diff --git a/utils/generate_types/overrides-testReporter.d.ts b/utils/generate_types/overrides-testReporter.d.ts index 0b81724373048..51eab7e370508 100644 --- a/utils/generate_types/overrides-testReporter.d.ts +++ b/utils/generate_types/overrides-testReporter.d.ts @@ -105,7 +105,6 @@ export interface JSONReportTest { export interface JSONReportError { message: string; location?: Location; - matcherResult?: TestErrorMatcherResult; } export interface JSONReportTestResult { From c8a72d63adbfc974925d25b31037e411f157f5d6 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 9 Sep 2024 17:22:19 -0700 Subject: [PATCH 039/805] chore: run bidi firefox tests on ci (#32527) --- .github/workflows/tests_bidi.yml | 6 +- .../src/server/registry/index.ts | 78 +++++++++++++++++-- tests/bidi/README.md | 23 ++++++ tests/bidi/playwright.config.ts | 4 +- 4 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 tests/bidi/README.md diff --git a/.github/workflows/tests_bidi.yml b/.github/workflows/tests_bidi.yml index 433294dbea6a9..b534a7b7474df 100644 --- a/.github/workflows/tests_bidi.yml +++ b/.github/workflows/tests_bidi.yml @@ -26,8 +26,7 @@ jobs: strategy: fail-fast: false matrix: - # TODO: add Firefox - channel: [bidi-chrome-stable] + channel: [bidi-chromium, bidi-firefox-beta] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -38,5 +37,8 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' - run: npm run build - run: npx playwright install --with-deps chromium + if: matrix.channel == 'bidi-chromium' + - run: npx -y @puppeteer/browsers install firefox@beta + if: matrix.channel == 'bidi-firefox-beta' - name: Run tests run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run biditest -- --project=${{ matrix.channel }}* diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index 058e0bcbc34b4..4e942967a48eb 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -354,7 +354,7 @@ function readDescriptors(browsersJSON: BrowsersJSON) { export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi'; type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'android'; -type BidiChannel = 'bidi-firefox-stable' | 'bidi-chrome-canary' | 'bidi-chrome-stable'; +type BidiChannel = 'bidi-firefox-stable' | 'bidi-firefox-beta' | 'bidi-firefox-nightly' | 'bidi-chrome-canary' | 'bidi-chrome-stable' | 'bidi-chromium'; type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree']; @@ -525,11 +525,22 @@ export class Registry { 'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`, })); - this._executables.push(this._createBidiChannel('bidi-firefox-stable', { - 'linux': '/usr/bin/firefox', - 'darwin': '/Applications/Firefox.app/Contents/MacOS/firefox', - 'win32': '\\Mozilla Firefox\\firefox.exe', + this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-stable', { + 'linux': '/firefox/firefox', + 'darwin': '/Firefox.app/Contents/MacOS/firefox', + 'win32': '\\core\\firefox.exe', })); + this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-beta', { + 'linux': '/firefox/firefox', + 'darwin': '/Firefox.app/Contents/MacOS/firefox', + 'win32': '\\core\\firefox.exe', + })); + this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-nightly', { + 'linux': '/firefox/firefox', + 'darwin': '/Firefox Nightly.app/Contents/MacOS/firefox', + 'win32': '\\firefox\\firefox.exe', + })); + this._executables.push(this._createBidiChannel('bidi-chrome-stable', { 'linux': '/opt/google/chrome/chrome', 'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', @@ -540,6 +551,21 @@ export class Registry { 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', 'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`, })); + this._executables.push({ + type: 'browser', + name: 'bidi-chromium', + browserName: 'bidi', + directory: chromium.dir, + executablePath: () => chromiumExecutable, + executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage), + installType: 'download-on-demand', + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']), + downloadURLs: this._downloadURLs(chromium), + browserVersion: chromium.browserVersion, + _install: () => this._downloadExecutable(chromium, chromiumExecutable), + _dependencyGroup: 'chromium', + _isHermeticInstallation: true, + }); const firefox = descriptors.find(d => d.name === 'firefox')!; const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox'); @@ -691,6 +717,48 @@ export class Registry { }; } + private _createBidiFirefoxChannel(name: BidiChannel, lookAt: Record<'linux' | 'darwin' | 'win32', string>, install?: () => Promise): ExecutableImpl { + const executablePath = (sdkLanguage: string, shouldThrow: boolean) => { + const suffix = lookAt[process.platform as 'linux' | 'darwin' | 'win32']; + if (!suffix) { + if (shouldThrow) + throw new Error(`Firefox distribution '${name}' is not supported on ${process.platform}`); + return undefined; + } + const folder = path.resolve('firefox'); + let channelName = 'stable'; + if (name.includes('beta')) + channelName = 'beta'; + else if (name.includes('nightly')) + channelName = 'nightly'; + const installedVersions = fs.readdirSync(folder); + const found = installedVersions.filter(e => e.includes(channelName)); + if (found.length === 1) + return path.join(folder, found[0], suffix); + if (found.length > 1) { + if (shouldThrow) + throw new Error(`Multiple Firefox installations found for channel '${name}': ${found.join(', ')}`); + else + return undefined; + } + if (shouldThrow) + throw new Error(`Cannot find Firefox installation for channel '${name}' under ${folder}`); + return undefined; + }; + return { + type: 'channel', + name, + browserName: 'bidi', + directory: undefined, + executablePath: (sdkLanguage: string) => executablePath(sdkLanguage, false), + executablePathOrDie: (sdkLanguage: string) => executablePath(sdkLanguage, true)!, + installType: 'none', + _validateHostRequirements: () => Promise.resolve(), + _isHermeticInstallation: true, + _install: install, + }; + } + private _createBidiChannel(name: BidiChannel, lookAt: Record<'linux' | 'darwin' | 'win32', string>, install?: () => Promise): ExecutableImpl { const executablePath = (sdkLanguage: string, shouldThrow: boolean) => { const suffix = lookAt[process.platform as 'linux' | 'darwin' | 'win32']; diff --git a/tests/bidi/README.md b/tests/bidi/README.md new file mode 100644 index 0000000000000..caac9288a4ae7 --- /dev/null +++ b/tests/bidi/README.md @@ -0,0 +1,23 @@ +## Running Bidi tests + +To run Playwright tests with Bidi: + +```sh +git clone https://github.com/microsoft/playwright.git +cd playwright +npm run build # call `npm run watch` for watch mode +npx playwright install chromium +npm run biditest -- --project='bidi-firefox-beta-*' +``` + +To install beta channel of Firefox, run the following command in the project root: +```sh +npx -y @puppeteer/browsers install firefox@beta +``` + +You can also pass custom binary path via `BIDIPATH`: +```sh +BIDIPATH='/Users/myself/Downloads/chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing' +``` + + diff --git a/tests/bidi/playwright.config.ts b/tests/bidi/playwright.config.ts index bc7b29e56bc8a..b04af32253f61 100644 --- a/tests/bidi/playwright.config.ts +++ b/tests/bidi/playwright.config.ts @@ -63,8 +63,8 @@ if (executablePath && !process.env.TEST_WORKER_INDEX) console.error(`Using executable at ${executablePath}`); const testIgnore: RegExp[] = []; const browserToChannels = { - '_bidiChromium': ['bidi-chrome-stable'], - '_bidiFirefox': ['bidi-firefox-stable'], + '_bidiChromium': ['bidi-chromium', 'bidi-chrome-canary', 'bidi-chrome-stable'], + '_bidiFirefox': ['bidi-firefox-nightly', 'bidi-firefox-beta', 'bidi-firefox-stable'], }; for (const [key, channels] of Object.entries(browserToChannels)) { const browserName: any = key; From 8995ace8253ad25865a04452408967e929911205 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Mon, 9 Sep 2024 23:57:40 -0700 Subject: [PATCH 040/805] feat(firefox-beta): roll to r1463 (#32529) --- packages/playwright-core/browsers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 2b0dc63ce7bb4..906ab12218230 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -21,9 +21,9 @@ }, { "name": "firefox-beta", - "revision": "1462", + "revision": "1463", "installByDefault": false, - "browserVersion": "130.0b2" + "browserVersion": "131.0b2" }, { "name": "webkit", From 9fa06be49ef83e65e83ebeb42a3e6aa7487479d9 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 10 Sep 2024 11:15:20 +0200 Subject: [PATCH 041/805] fix(ct): throw error if inline component is getting mounted (#32531) What was happening? - When we use CT, we go over the test files, look at the imports using `tsxTransform.ts` and store them inside a map, these we feed into the import registry which we build using Vite and have access inside the browser - In case of an inline component in the same file as where the test file is, this is not happening. - jsx-runtime via babel kicks in, transforms every JSX component in something like that: ``` { __pw_type: 'jsx', type: [Function: MyInlineComponent], props: { value: 'Max' }, key: undefined } ``` this then gets passed into `wrapObject` which maps any function from the Node.js side into expose function calls so they work inside the browser. The assumption for `wrapObject` was to do it mostly for callbacks. So it does for `type` - which is actually our component. We then pass this to the React render function, which calls back the exposed function but we never return anything, so it mounts `undefined`. --- While there have been experiments from certain vendors to get the 'client only' code inside a server side file, we should throw for now to not confuse users. We might revisit this in the future since Babel / TSX doesn't support it outside of the box. Fixes https://github.com/microsoft/playwright/issues/32167 --- .../src/injected/serializers.ts | 7 +++++++ .../ct-react-vite/tests/render.spec.tsx | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/packages/playwright-ct-core/src/injected/serializers.ts b/packages/playwright-ct-core/src/injected/serializers.ts index d07be7c1f8cf7..be083e27db72f 100644 --- a/packages/playwright-ct-core/src/injected/serializers.ts +++ b/packages/playwright-ct-core/src/injected/serializers.ts @@ -66,6 +66,13 @@ export function transformObject(value: any, mapping: (v: any) => { result: any } result.push(transformObject(item, mapping)); return result; } + if (value?.__pw_type === 'jsx' && typeof value.type === 'function') { + throw new Error([ + `Component "${value.type.name}" cannot be mounted.`, + `Most likely, this component is defined in the test file. Create a test story instead.`, + `For more information, see https://playwright.dev/docs/test-components#test-stories.`, + ].join('\n')); + } const result2: any = {}; for (const [key, prop] of Object.entries(value)) result2[key] = transformObject(prop, mapping); diff --git a/tests/components/ct-react-vite/tests/render.spec.tsx b/tests/components/ct-react-vite/tests/render.spec.tsx index 1d82d21b3aa98..d00a313e9e433 100644 --- a/tests/components/ct-react-vite/tests/render.spec.tsx +++ b/tests/components/ct-react-vite/tests/render.spec.tsx @@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-react'; import Button from '@/components/Button'; import EmptyFragment from '@/components/EmptyFragment'; import { ComponentAsProp } from '@/components/ComponentAsProp'; +import DefaultChildren from '@/components/DefaultChildren'; test('render props', async ({ mount }) => { const component = await mount(`); + }); + + const traceViewer = await runAndTrace(async () => { + await page.goto(server.PREFIX + '/level-0.html'); + await page.frameLocator('iframe').frameLocator('iframe').locator('button').click({ position: { x: 5, y: 5 } }); + }); + const snapshotFrame = await traceViewer.snapshotFrame('locator.click'); + await expect.soft(snapshotFrame.locator('x-pw-pointer')).not.toBeAttached(); + await expect.soft(snapshotFrame.frameLocator('iframe').locator('x-pw-pointer')).not.toBeAttached(); + await expect.soft(snapshotFrame.frameLocator('iframe').frameLocator('iframe').locator('x-pw-pointer')).toBeVisible(); +}); From aaac57b94856bd59fe4894554dc7c6226ea4cf05 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Wed, 11 Sep 2024 04:02:03 -0700 Subject: [PATCH 048/805] feat(webkit): roll to r2072 (#32550) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 906ab12218230..4570f3560ae92 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -27,7 +27,7 @@ }, { "name": "webkit", - "revision": "2071", + "revision": "2072", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", From 1f0514536e1ca8a0b93ab774c03eef7c6966bd31 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 11 Sep 2024 08:28:29 -0700 Subject: [PATCH 049/805] chore: add bidi test expectations in separate file (#32549) Based on the expectations the tests that are expected to timeout or fail will be skipped to save resources. The expectations can be manually updated when corresponding feature is fixed. --- tests/bidi/expectationReporter.ts | 76 + tests/bidi/expectationUtil.ts | 50 + .../expectations/bidi-chromium-library.txt | 1910 ++++++++++++++++ .../bidi/expectations/bidi-chromium-page.txt | 1966 +++++++++++++++++ tests/bidi/playwright.config.ts | 3 +- tests/config/browserTest.ts | 17 +- 6 files changed, 4020 insertions(+), 2 deletions(-) create mode 100644 tests/bidi/expectationReporter.ts create mode 100644 tests/bidi/expectationUtil.ts create mode 100644 tests/bidi/expectations/bidi-chromium-library.txt create mode 100644 tests/bidi/expectations/bidi-chromium-page.txt diff --git a/tests/bidi/expectationReporter.ts b/tests/bidi/expectationReporter.ts new file mode 100644 index 0000000000000..e83c93a5244be --- /dev/null +++ b/tests/bidi/expectationReporter.ts @@ -0,0 +1,76 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { + FullConfig, FullResult, Reporter, Suite, TestCase +} from '@playwright/test/reporter'; +import fs from 'fs'; +import { projectExpectationPath } from './expectationUtil'; + +type ReporterOptions = { + rebase?: boolean; +}; + +class ExpectationReporter implements Reporter { + private _suite: Suite; + private _options: ReporterOptions; + + constructor(options: ReporterOptions) { + this._options = options; + } + + onBegin(config: FullConfig, suite: Suite) { + this._suite = suite; + } + + onEnd(result: FullResult) { + if (!this._options.rebase) + return; + for (const project of this._suite.suites) + this._updateProjectExpectations(project); + } + + private _updateProjectExpectations(project: Suite) { + const results = project.allTests().map(test => { + const outcome = getOutcome(test); + const line = `${test.titlePath().slice(1).join(' › ')} [${outcome}]`; + return line; + }); + const outputFile = projectExpectationPath(project.title); + console.log('Writing new expectations to', outputFile); + fs.writeFileSync(outputFile, results.join('\n')); + } + + printsToStdio(): boolean { + return false; + } +} + +function getOutcome(test: TestCase): 'unknown' | 'flaky' | 'pass' | 'fail' | 'timeout' { + if (test.results.length === 0) + return 'unknown'; + if (test.results.every(r => r.status === 'timedOut')) + return 'timeout'; + if (test.outcome() === 'expected') + return 'pass'; + if (test.outcome() === 'unexpected') + return 'fail'; + if (test.outcome() === 'flaky') + return 'flaky'; + return 'unknown'; +} + +export default ExpectationReporter; \ No newline at end of file diff --git a/tests/bidi/expectationUtil.ts b/tests/bidi/expectationUtil.ts new file mode 100644 index 0000000000000..f271a4981c3ac --- /dev/null +++ b/tests/bidi/expectationUtil.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs'; +import path from 'path'; +import type { TestInfo } from 'playwright/test'; + +type ShouldSkipPredicate = (info: TestInfo) => boolean; + +export async function parseBidiExpectations(projectName: string): Promise { + const filePath = projectExpectationPath(projectName); + try { + await fs.promises.access(filePath); + } catch (e) { + return () => false; + } + const content = await fs.promises.readFile(filePath); + const pairs = content.toString().split('\n').map(line => { + const match = /(?.+) \[(?[^\]]+)\]$/.exec(line); + if (!match) { + console.error('Bad expectation line: ' + line); + return undefined; + } + return [match.groups!.titlePath, match.groups!.expectation]; + }).filter(Boolean) as [string, string][]; + const expectationsMap = new Map(pairs); + + return (info: TestInfo) => { + const key = [info.project.name, ...info.titlePath].join(' › '); + const expectation = expectationsMap.get(key); + return expectation === 'fail' || expectation === 'timeout'; + }; +} + +export function projectExpectationPath(project: string): string { + return path.join(__dirname, 'expectations', project + '.txt'); +} diff --git a/tests/bidi/expectations/bidi-chromium-library.txt b/tests/bidi/expectations/bidi-chromium-library.txt new file mode 100644 index 0000000000000..16df95a6d2252 --- /dev/null +++ b/tests/bidi/expectations/bidi-chromium-library.txt @@ -0,0 +1,1910 @@ +bidi-chromium-library › library/beforeunload.spec.ts › should close browser with beforeunload page [pass] +bidi-chromium-library › library/beforeunload.spec.ts › should close browsercontext with beforeunload page [pass] +bidi-chromium-library › library/beforeunload.spec.ts › should be able to navigate away from page with beforeunload [pass] +bidi-chromium-library › library/beforeunload.spec.ts › should close page with beforeunload listener [pass] +bidi-chromium-library › library/beforeunload.spec.ts › should run beforeunload if asked for @smoke [timeout] +bidi-chromium-library › library/beforeunload.spec.ts › should access page after beforeunload [timeout] +bidi-chromium-library › library/beforeunload.spec.ts › should not stall on evaluate when dismissing beforeunload [pass] +bidi-chromium-library › library/browser.spec.ts › should return browserType [pass] +bidi-chromium-library › library/browser.spec.ts › should create new page @smoke [pass] +bidi-chromium-library › library/browser.spec.ts › should throw upon second create new page [pass] +bidi-chromium-library › library/browser.spec.ts › version should work [unknown] +bidi-chromium-library › library/browser.spec.ts › should dispatch page.on(close) upon browser.close and reject evaluate [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should work @smoke [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should work with expires=-1 [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should add cookies with empty value [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should roundtrip cookie [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should send cookie header [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate cookies in browser contexts [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate session cookies [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate persistent cookies [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate send cookie header [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate cookies between launches [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set multiple cookies [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should have |expires| set to |-1| for session cookies [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set cookie with reasonable defaults [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set a cookie with a path [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should not set a cookie with blank page URL [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should not set a cookie on a data URL page [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should default to setting secure cookie for HTTPS websites [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should be able to set unsecure cookie for HTTP website [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set a cookie on a different domain [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set cookies for a frame [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should(not) block third party cookies [pass] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should not block third party SameSite=None cookies [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should allow unnamed cookies [unknown] +bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set secure cookies on secure WebSocket [unknown] +bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts @smoke [pass] +bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work without navigation, after all bindings [unknown] +bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work without navigation in popup [unknown] +bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts with a path [pass] +bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts for already created pages [pass] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newContext is passed to page.goto @smoke [pass] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newPage is passed to page.goto [pass] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browserType.launchPersistentContext is passed to page.goto [unknown] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL without a trailing slash in browser.newPage is passed to page.goto [pass] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL with a trailing slash in browser.newPage is passed to page.goto [pass] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should not construct a new URL when valid URLs are passed [pass] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should be able to match a URL relative to its given URL with urlMatcher [unknown] +bidi-chromium-library › library/browsercontext-base-url.spec.ts › should not construct a new URL with baseURL when a glob was used [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should create new context @smoke [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should be able to click across browser contexts [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › window.open should use parent tab context [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should isolate localStorage and cookies @smoke [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should propagate default viewport to the page [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should make a copy of default viewport [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should respect deviceScaleFactor [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should not allow deviceScaleFactor with null viewport [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should not allow isMobile with null viewport [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › close() should work for empty context [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › close() should abort waitForEvent [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › close() should be callable twice [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should pass self to close event [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should not report frameless pages on error [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should return all of the pages [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should close all belonging pages once closing context [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should disable javascript [unknown] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should be able to navigate after disabling javascript [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should not hang on promises after disabling javascript [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › setContent should work after disabling javascript [pass] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should work with offline option [unknown] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should emulate navigator.onLine [unknown] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should emulate media in popup [unknown] +bidi-chromium-library › library/browsercontext-basic.spec.ts › should emulate media in cross-process iframe [unknown] +bidi-chromium-library › library/browsercontext-basic.spec.ts › default user agent [pass] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should clear cookies [pass] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should isolate cookies when clearing [pass] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name [unknown] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name regex [unknown] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by domain [unknown] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by path [unknown] +bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name and domain [unknown] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should return no cookies in pristine browser context [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get a cookie @smoke [unknown] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get a non-session cookie [fail] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should properly report httpOnly cookie [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should properly report "Strict" sameSite cookie [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should properly report "Lax" sameSite cookie [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get multiple cookies [unknown] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get cookies from multiple urls [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should work with subdomain cookie [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should return cookies with empty value [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should return secure cookies based on HTTP(S) protocol [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should add cookies with an expiration [pass] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should be able to send third party cookies via an iframe [fail] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should support requestStorageAccess [fail] +bidi-chromium-library › library/browsercontext-cookies.spec.ts › should parse cookie with large Max-Age correctly [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail without credentials [pass] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with setHTTPCredentials [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with correct credentials @smoke [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with wrong credentials [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should return resource body [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin case insensitive [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching scheme [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching hostname [fail] +bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching port [fail] +bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass CSP meta tag @smoke [fail] +bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass CSP header [fail] +bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass after cross-process navigation [fail] +bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass CSP in iframes as well [fail] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should work @smoke [fail] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should support clicking [pass] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should scroll to click [pass] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should scroll twice when emulated [pass] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should reset scroll top after a navigation [pass] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should scroll to a precise position with mobile scale [pass] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should emulate viewport and screen size [fail] +bidi-chromium-library › library/browsercontext-device.spec.ts › device › should emulate viewport without screen size [fail] +bidi-chromium-library › library/browsercontext-dsf.spec.ts › should fetch lodpi assets @smoke [pass] +bidi-chromium-library › library/browsercontext-dsf.spec.ts › should fetch hidpi assets [pass] +bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work @smoke [pass] +bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work in popup [pass] +bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work in popup 2 [timeout] +bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work in immediately closed popup [timeout] +bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work @smoke [pass] +bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work in popup [timeout] +bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work in popup 2 [pass] +bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work in immediately closed popup [timeout] +bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work with inline script tag [timeout] +bidi-chromium-library › library/browsercontext-events.spec.ts › weberror event should work [timeout] +bidi-chromium-library › library/browsercontext-expose-function.spec.ts › expose binding should work [fail] +bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should work [fail] +bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should throw for duplicate registrations [pass] +bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should be callable from-inside addInitScript [fail] +bidi-chromium-library › library/browsercontext-expose-function.spec.ts › exposeBindingHandle should work [fail] +bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should work with CSP [fail] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should support decompression [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail if response content-length header is missing (gzip) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with chunked responses (without Content-Length header) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should support decompression [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail if response content-length header is missing (deflate) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with chunked responses (without Content-Length header) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should support decompression [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail if response content-length header is missing (br) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with chunked responses (without Content-Length header) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work [pass] +bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work on request fixture [pass] +bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › https post should work with ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › should work with ip6 and port as the host [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should work @smoke [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should work [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error after redirect [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error when sending body [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error when sending body after redirect [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add session cookies to request [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetchshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › deleteshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › getshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › headshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › patchshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › postshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support params passed as object [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support params passed as URLSearchParams [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support params passed as string [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support failOnStatusCode [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › putshould support ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not add context cookie if cookie header passed as a parameter [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should follow redirects [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should follow redirects correctly when Location header contains UTF-8 characters [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add cookies from Set-Cookie header [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should preserve cookie order from Set-Cookie header [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support cookie with empty value [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not lose body while handling Set-Cookie header [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should remove cookie with negative max-age [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should remove cookie with expires far in the past [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should handle cookies on redirects [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should return raw headers [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should work with http credentials [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should work with setHTTPCredentials [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should return error with wrong credentials [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for newContext [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for browser.newPage [fail] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support post data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support post data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support post data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support post data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support post data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support post data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add default headers [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should send content-length [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add default headers to redirects [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should allow to override default headers [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should propagate custom headers with redirects [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should propagate extra http headers with redirects [fail] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on invalid header value [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on non-http(s) protocol [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support https [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should inherit ignoreHTTPSErrors from context [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should resolve url relative to baseURL [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support gzip compression [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted gzip body [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support brotli compression [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted brotli body [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support deflate compression [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted deflate body [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support timeout option [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support a timeout of 0 [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should respect timeout after redirects [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not hang on a brotli encoded Range request [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should dispose [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should dispose when context closes [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should override request parameters [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support application/x-www-form-urlencoded [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should encode to application/json by default [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data with ReadStream values [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data and keep the order [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support repeating names in multipart/form-data [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should serialize data to json regardless of content-type [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw nice error on unsupported data type [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › context request should export same storage state as context [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should send secure cookie over http for localhost [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should accept bool and numeric params [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should abort requests when browser context closes [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should work with connectOverCDP [unknown] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support SameSite cookie attribute over https [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should set domain=localhost cookie [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should not throw on long set-cookie value [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support set-cookie with SameSite and without Secure attribute over HTTP [fail] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should update host header on redirect [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not work after dispose [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not work after context dispose [pass] +bidi-chromium-library › library/browsercontext-fetch.spec.ts › should retry on ECONNRESET [pass] +bidi-chromium-library › library/browsercontext-har.spec.ts › should context.routeFromHAR, matching the method and following redirects [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should page.routeFromHAR, matching the method and following redirects [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › fallback:continue should continue when not found in har [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › by default should abort requests not found in har [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › fallback:continue should continue requests on bad har [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should only handle requests matching url filter [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should only context.routeFromHAR requests matching url filter [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should only page.routeFromHAR requests matching url filter [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should apply overrides before routing from har [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should support regex filter [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › newPage should fulfill from har, matching the method and following redirects [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should goForward to redirected navigation [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should reload redirected navigation [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should fulfill from har with content in a file [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should round-trip har.zip [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should produce extracted zip [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should round-trip extracted har.zip [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should round-trip har with postData [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should record overridden requests to har [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should disambiguate by header [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should update har.zip for context [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should ignore boundary when matching multipart/form-data body [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should update har.zip for page [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should update har.zip for page with different options [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should update extracted har.zip for page [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › page.unrouteAll should stop page.routeFromHAR [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › context.unrouteAll should stop context.routeFromHAR [fail] +bidi-chromium-library › library/browsercontext-har.spec.ts › should ignore aborted requests [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect accept-language header @smoke [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect navigator.language [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should format number [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should format date [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should format number in popups [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect navigator.language in popups [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should work for multiple pages sharing same process [pass] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should be isolated between contexts [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should not change default locale in another context [fail] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should format number in workers [timeout] +bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().locale [fail] +bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.Request [pass] +bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.Response [pass] +bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFailed [fail] +bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFinished [pass] +bidi-chromium-library › library/browsercontext-network-event.spec.ts › should fire events in proper order [pass] +bidi-chromium-library › library/browsercontext-network-event.spec.ts › should not fire events for favicon or favicon redirects [unknown] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have url [pass] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have url after domcontentloaded [pass] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have about:blank url with domcontentloaded [fail] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have about:blank for empty url with domcontentloaded [fail] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should report when a new page is created and closed [fail] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should report initialized pages [fail] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should not crash while redirecting of original request was missed [pass] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have an opener [pass] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should fire page lifecycle events [fail] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should work with Shift-clicking [pass] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should work with Ctrl-clicking [pass] +bidi-chromium-library › library/browsercontext-page-event.spec.ts › should not hang on ctrl-click during provisional load [timeout] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should not be visible in context.pages [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › page.context should return the correct instance [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › frame.focus should work multiple times [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should click with disabled javascript [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should not hang with touch-enabled viewports [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should click the button with deviceScaleFactor set [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should click the button with offset with page scale [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should return bounding box with page scale [pass] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should not leak listeners during navigation of 20 pages [fail] +bidi-chromium-library › library/browsercontext-pages.spec.ts › should keep selection in multiple pages [pass] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should work when passing the proxy only on the context level [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should throw for bad server value [pass] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should set cookie for top-level domain [pass] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › localhost [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › link-local [timeout] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [timeout] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use ipv6 proxy [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy twice [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy for second page [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy for https urls [timeout] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should work with IP:PORT notion [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should throw for socks5 authentication [pass] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should throw for socks4 authentication [pass] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should authenticate [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should authenticate with empty password [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should exclude patterns [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use socks proxy [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use socks proxy in second page [fail] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › does launch without a port [pass] +bidi-chromium-library › library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts on navigation [fail] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should re-add binding after reset [fail] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset serviceworker [fail] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset serviceworker that hangs in importScripts [fail] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should not cache resources [fail] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should ignore binding from beforeunload [pass] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset mouse position [pass] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset tracing [pass] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should work with clock emulation [pass] +bidi-chromium-library › library/browsercontext-reuse.spec.ts › should continue issuing events after closing the reused page [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should intercept [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should unroute [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should yield to page.route [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should fall back to context.route [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should support Set-Cookie header [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should ignore secure Set-Cookie header for insecure requests [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should use Set-Cookie header in future requests [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should work with ignoreHTTPSErrors [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should support the times parameter with route matching [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should support async handler w/ times [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should overwrite post body with empty string [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should chain fallback [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should chain fallback w/ dynamic URL [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should not chain fulfill [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should not chain abort [pass] +bidi-chromium-library › library/browsercontext-route.spec.ts › should chain fallback into page [fail] +bidi-chromium-library › library/browsercontext-route.spec.ts › should fall back async [fail] +bidi-chromium-library › library/browsercontext-service-worker-policy.spec.ts › should allow service workers by default [pass] +bidi-chromium-library › library/browsercontext-service-worker-policy.spec.ts › block › blocks service worker registration [timeout] +bidi-chromium-library › library/browsercontext-service-worker-policy.spec.ts › block › should not throw error on about:blank [pass] +bidi-chromium-library › library/browsercontext-set-extra-http-headers.spec.ts › should override extra headers from browser context [fail] +bidi-chromium-library › library/browsercontext-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should capture local storage [fail] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should set local storage [fail] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should round-trip through the file [fail] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should capture cookies [fail] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should not emit events about internal page [fail] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should not restore localStorage twice [fail] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should handle missing file [pass] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should handle malformed file [pass] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should serialize storageState with lone surrogates [pass] +bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should work when service worker is intefering [pass] +bidi-chromium-library › library/browsercontext-strict.spec.ts › should not fail page.textContent in non-strict mode [pass] +bidi-chromium-library › library/browsercontext-strict.spec.ts › strict context mode › should fail page.textContent in strict mode [fail] +bidi-chromium-library › library/browsercontext-strict.spec.ts › strict context mode › should fail page.click in strict mode [fail] +bidi-chromium-library › library/browsercontext-strict.spec.ts › strict context mode › should opt out of strict mode [pass] +bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should work @smoke [fail] +bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should throw for invalid timezone IDs when creating pages [fail] +bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should work for multiple pages sharing same process [pass] +bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should not change default timezone in another context [fail] +bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().timeZone [fail] +bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should work [fail] +bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should work for subframes [fail] +bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should emulate device user-agent [fail] +bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should make a copy of default options [fail] +bidi-chromium-library › library/browsercontext-user-agent.spec.ts › custom user agent for download [timeout] +bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should work for navigator.userAgentData and sec-ch-ua headers [unknown] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support mobile emulation [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support touch emulation [fail] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should be detectable [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should detect touch when applying viewport with touches [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support landscape emulation [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support window.orientation emulation [fail] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should fire orientationchange event [timeout] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › default mobile viewports to 980 width [fail] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › respect meta viewport tag [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should emulate the hover media feature [fail] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › mouse should work with mobile viewports and cross process navigations [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should scroll when emulating a mobile viewport [pass] +bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › view scale should reset after navigation [fail] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should get the proper default viewport size [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should set the proper viewport size [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should return correct outerWidth and outerHeight [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should emulate device width [fail] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should emulate device height [fail] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should emulate availWidth and availHeight [fail] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should not have touch by default [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should throw on tap if hasTouch is not enabled [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should support touch with null viewport [fail] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should set both screen and viewport options [fail] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should report null viewportSize when given null viewport [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should drag with high dpi [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › WebKit Windows headed should have a minimal viewport [unknown] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should be able to get correct orientation angle on non-mobile devices [pass] +bidi-chromium-library › library/browsercontext-viewport.spec.ts › should set window.screen.orientation.type for mobile devices [fail] +bidi-chromium-library › library/browsertype-basic.spec.ts › browserType.executablePath should work [unknown] +bidi-chromium-library › library/browsertype-basic.spec.ts › browserType.name should work [fail] +bidi-chromium-library › library/browsertype-basic.spec.ts › should throw when trying to connect with not-chromium [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should connect over wss [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should print HTTP error [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should print ws error [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should print custom ws close error [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to reconnect to a browser [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should ignore page.pause when headed [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 through localhost [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect two browsers at the same time [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should timeout in socket while connecting [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should timeout in connect while connecting [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should send extra headers with connect request [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should support slowmo option [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › disconnected event should be emitted when browser is closed or server is closed [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › disconnected event should have browser as argument [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should handle exceptions during connect [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should set the browser connected state [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should throw when used after isConnected returns false [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should throw when calling waitForNavigation after disconnect [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject navigation when browser closes [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForSelector when browser closes [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should emit close events on pages and contexts [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should terminate network waiters [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.close finishes [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.onDisconnect fires [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should respect selectors [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should not throw on close after disconnect [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should saveAs videos from remote browser [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect 20 times to a single server without warnings [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should save download [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should error when saving download after deletion [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should properly disconnect when connection closes from the client side [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect when the wsEndpoint is passed as an option [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should save har [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should filter launch options [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should record trace with sources [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should fulfill with global fetch result [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should upload large file [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › setInputFiles should preserve lastModified timestamp [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should connect over http [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should forward non-forwarded requests [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests @smoke [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy ipv6 localhost requests @smoke [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests from fetch api [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy local.playwright requests [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should lead to the error page for forwarded requests when the connection is refused [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy based on the pattern [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should check proxy pattern on the client [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should connect over wss [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should print HTTP error [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should print ws error [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should print custom ws close error [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to reconnect to a browser [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should ignore page.pause when headed [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 through localhost [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to connect two browsers at the same time [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should timeout in socket while connecting [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should timeout in connect while connecting [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should send extra headers with connect request [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should support slowmo option [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › disconnected event should be emitted when browser is closed or server is closed [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › disconnected event should have browser as argument [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should handle exceptions during connect [pass] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should set the browser connected state [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should throw when used after isConnected returns false [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should throw when calling waitForNavigation after disconnect [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject navigation when browser closes [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject waitForSelector when browser closes [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should emit close events on pages and contexts [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should terminate network waiters [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.close finishes [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.onDisconnect fires [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should respect selectors [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should not throw on close after disconnect [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should saveAs videos from remote browser [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to connect 20 times to a single server without warnings [unknown] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should save download [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should error when saving download after deletion [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should properly disconnect when connection closes from the client side [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to connect when the wsEndpoint is passed as an option [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should save har [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should filter launch options [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should record trace with sources [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should fulfill with global fetch result [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should upload large file [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › setInputFiles should preserve lastModified timestamp [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should connect over http [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should forward non-forwarded requests [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests @smoke [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy ipv6 localhost requests @smoke [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests from fetch api [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy local.playwright requests [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should lead to the error page for forwarded requests when the connection is refused [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy based on the pattern [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should check proxy pattern on the client [fail] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer only › should work with cluster [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer only › should properly disconnect when connection closes from the server side [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer only › should be able to reconnect to a browser 12 times without warnings [timeout] +bidi-chromium-library › library/browsertype-connect.spec.ts › should refuse connecting when versions do not match [pass] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium [unknown] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 hub + node chromium [unknown] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium [unknown] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 hub + node chromium [unknown] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium broken driver [unknown] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone non-chromium [unknown] +bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium through run-driver [unknown] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work with host [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work with port [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work with wsPath [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work when wsPath is missing leading slash [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should default to random wsPath [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should provide an error when ws endpoint is incorrect [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should fire "close" event during kill [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should return child_process instance [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should fire close event [fail] +bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should log protocol [fail] +bidi-chromium-library › library/browsertype-launch.spec.ts › should reject all promises when browser is closed [fail] +bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if userDataDir option is passed [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if userDataDir is passed as an argument [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if port option is passed [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if port option is passed for persistent context [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if page argument is passed [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should reject if launched browser fails immediately [fail] +bidi-chromium-library › library/browsertype-launch.spec.ts › should reject if executable path is invalid [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should handle timeout [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should handle exception [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should report launch log [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should accept objects as options [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should fire close event for all contexts [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should be callable twice [pass] +bidi-chromium-library › library/browsertype-launch.spec.ts › should allow await using [pass] +bidi-chromium-library › library/capabilities.spec.ts › SharedArrayBuffer should work @smoke [fail] +bidi-chromium-library › library/capabilities.spec.ts › Web Assembly should work @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › WebSocket should work @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should respect CSP @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should play video @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should play webm video @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should play audio @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should support webgl @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should support webgl 2 @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should not crash on page with mp4 @smoke [pass] +bidi-chromium-library › library/capabilities.spec.ts › should not crash on showDirectoryPicker [unknown] +bidi-chromium-library › library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] +bidi-chromium-library › library/capabilities.spec.ts › navigator.clipboard should be present [pass] +bidi-chromium-library › library/capabilities.spec.ts › should set CloseEvent.wasClean to false when the server terminates a WebSocket connection [pass] +bidi-chromium-library › library/capabilities.spec.ts › serviceWorker should intercept document request [pass] +bidi-chromium-library › library/capabilities.spec.ts › webkit should define window.safari [unknown] +bidi-chromium-library › library/capabilities.spec.ts › make sure that XMLHttpRequest upload events are emitted correctly [pass] +bidi-chromium-library › library/capabilities.spec.ts › loading in HTMLImageElement.prototype [pass] +bidi-chromium-library › library/capabilities.spec.ts › window.GestureEvent in WebKit [pass] +bidi-chromium-library › library/capabilities.spec.ts › requestFullscreen [pass] +bidi-chromium-library › library/capabilities.spec.ts › should send no Content-Length header for GET requests with a Content-Type [pass] +bidi-chromium-library › library/capabilities.spec.ts › Intl.ListFormat should work [pass] +bidi-chromium-library › library/capabilities.spec.ts › service worker should cover the iframe [pass] +bidi-chromium-library › library/capabilities.spec.ts › service worker should register in an iframe [pass] +bidi-chromium-library › library/channels.spec.ts › should scope context handles [pass] +bidi-chromium-library › library/channels.spec.ts › should scope CDPSession handles [unknown] +bidi-chromium-library › library/channels.spec.ts › should scope browser handles [pass] +bidi-chromium-library › library/channels.spec.ts › should not generate dispatchers for subresources w/o listeners [pass] +bidi-chromium-library › library/channels.spec.ts › should work with the domain module [timeout] +bidi-chromium-library › library/channels.spec.ts › exposeFunction should not leak [fail] +bidi-chromium-library › library/chromium/bfcache.spec.ts › bindings should work after restoring from bfcache [fail] +bidi-chromium-library › library/chromium/chromium.spec.ts › should create a worker from a service worker [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › should create a worker from service worker with noop routing [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › should emit new service worker on update [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › http credentials › httpCredentials [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › serviceWorkers() should return current workers [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › should not create a worker from a shared worker [pass] +bidi-chromium-library › library/chromium/chromium.spec.ts › Page.route should work with intervention headers [fail] +bidi-chromium-library › library/chromium/chromium.spec.ts › should close service worker together with the context [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › should pass args with spaces [fail] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › serviceWorker(), and fromServiceWorker() work [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker requests (main and within) [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to content-type) of main service worker request [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to redirect) of main service worker request [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker importScripts [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report intercepted service worker requests in HAR [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept only serviceworker request, not page [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker [fail] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker (advanced) [fail] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker update requests [unknown] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setOffline [timeout] +bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setExtraHTTPHeaders [timeout] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should use logger in default context [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should cleanup artifacts dir after connectOverCDP disconnects due to ws close [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connectOverCDP and manage downloads in default context [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session twice [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to existing page with iframe and navigate [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to existing service workers [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect over a ws endpoint [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should send extra headers with connect request [timeout] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should send default User-Agent header with connect request [timeout] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should report all pages in an existing browser [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect via https [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should return valid browser from context.browser() [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpointURL returns a non-expected status code [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpoint URL JSON webSocketDebuggerUrl is undefined [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session when passed as a first argument [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should use proxy with connectOverCDP [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should be able to connect via localhost [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › emulate media should not be affected by second connectOverCDP [unknown] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should allow tracing over cdp session [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › setInputFiles should preserve lastModified timestamp [fail] +bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should print custom ws close error [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report sourceURLs [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report multiple stylesheets [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report stylesheets that have no coverage [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work with media queries [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work with complicated usecases [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should ignore injected stylesheets [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report stylesheets across navigations [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should NOT report scripts across navigations [fail] +bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work with a recently loaded stylesheet [fail] +bidi-chromium-library › library/chromium/disable-web-security.spec.ts › test utility world in popup w/ --disable-web-security [pass] +bidi-chromium-library › library/chromium/disable-web-security.spec.ts › test init script w/ --disable-web-security [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should work [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should report sourceURLs [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should ignore eval() scripts by default [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › shouldn't ignore eval() scripts if reportAnonymousScripts is true [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should report multiple scripts [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should report scripts across navigations when disabled [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should NOT report scripts across navigations when enabled [fail] +bidi-chromium-library › library/chromium/js-coverage.spec.ts › should not hang when there is a debugger statement [fail] +bidi-chromium-library › library/chromium/launcher.spec.ts › should throw with remote-debugging-pipe argument [fail] +bidi-chromium-library › library/chromium/launcher.spec.ts › should not throw with remote-debugging-port argument [fail] +bidi-chromium-library › library/chromium/launcher.spec.ts › should open devtools when "devtools: true" option is given [unknown] +bidi-chromium-library › library/chromium/launcher.spec.ts › should return background pages [fail] +bidi-chromium-library › library/chromium/launcher.spec.ts › should return background pages when recording video [fail] +bidi-chromium-library › library/chromium/launcher.spec.ts › should support request/response events when using backgroundPage() [fail] +bidi-chromium-library › library/chromium/launcher.spec.ts › should not create pages automatically [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should report oopif frames [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should handle oopif detach [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should handle remote -> local -> remote transitions [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should get the proper viewport [unknown] +bidi-chromium-library › library/chromium/oopif.spec.ts › should expose function [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should emulate media [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should emulate offline [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should support context options [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should respect route [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should take screenshot [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should load oopif iframes with subresources and route [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should report main requests [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should support exposeFunction [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should support addInitScript [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should click a button when it overlays oopif [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should report google.com frame with headed [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › ElementHandle.boundingBox() should work [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should click [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › contentFrame should work [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should allow cdp sessions on oopifs [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should emit filechooser event for iframe [timeout] +bidi-chromium-library › library/chromium/oopif.spec.ts › should be able to click in iframe [pass] +bidi-chromium-library › library/chromium/oopif.spec.ts › should not throw on exposeFunction when oopif detaches [fail] +bidi-chromium-library › library/chromium/oopif.spec.ts › should intercept response body from oopif [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should work [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should send events [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should only accept a page or frame [pass] +bidi-chromium-library › library/chromium/session.spec.ts › should enable and disable domains independently [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should be able to detach session [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should throw nice errors [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should work with main frame [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should throw if target is part of main [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should not break page.close() [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should detach when page closes [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should reject protocol calls when page closes [fail] +bidi-chromium-library › library/chromium/session.spec.ts › should work with newBrowserCDPSession [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should output a trace [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should create directories as needed [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should run with custom categories if provided [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should throw if tracing on two pages [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should return a buffer [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should work without options [fail] +bidi-chromium-library › library/chromium/tracing.spec.ts › should support a buffer without a path [fail] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › validate input [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › should fail with no client certificates provided [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › should keep supporting http [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › should throw with untrusted client certs [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › pass with trusted client certificates [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › pass with trusted client certificates in pfx format [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › should throw a http error if the pfx passphrase is incorect [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › should fail with matching certificates in legacy pfx format [pass] +bidi-chromium-library › library/client-certificates.spec.ts › fetch › should work in the browser with request interception [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › validate input [pass] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should keep supporting http [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should fail with no client certificates [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should fail with self-signed client certificates [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates when passing as content [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should not hang on tls errors during TLS 1.2 handshake [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should handle TLS renegotiation with client certificates [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format when passing as content [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should fail with matching certificates in legacy pfx format [pass] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should throw a http error if the pfx passphrase is incorect [pass] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates on context APIRequestContext instance [pass] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates and trailing slash [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should have ignoreHTTPSErrors=false by default [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › support http2 [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › support http2 if the browser only supports http1.1 [unknown] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should return target connection errors when using http2 [fail] +bidi-chromium-library › library/client-certificates.spec.ts › browser › should handle rejected certificate in handshake with HTTP/2 [pass] +bidi-chromium-library › library/client-certificates.spec.ts › browser › persistentContext › validate input [pass] +bidi-chromium-library › library/client-certificates.spec.ts › browser › persistentContext › should pass with matching certificates [fail] +bidi-chromium-library › library/clock.spec.ts › setTimeout › throws if no arguments [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › does not throw if |undefined| or |null| is passed as a callback [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › returns numeric id or object with numeric id [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › returns unique id [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › starts id from a large number [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › sets timers on instance [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › parses numeric string times [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › parses no-numeric string times [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › passes setTimeout parameters [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › calls correct timeout on recursive tick [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › does not depend on this [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › is not influenced by forward system clock changes [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › is not influenced by backward system clock changes [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › use of eval when not in node › evals non-function callbacks [pass] +bidi-chromium-library › library/clock.spec.ts › setTimeout › use of eval when not in node › only evals on global scope [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers immediately without specified delay [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers after sufficient delay [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers simultaneous timers [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers multiple simultaneous timers [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers multiple simultaneous timers with zero callAt [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › waits after setTimeout was called [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › mini integration test [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers even when some throw [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › calls function with global object or null (strict mode) as this [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers in the order scheduled [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › creates updated Date while ticking [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › fires timer in intervals of 13 [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › fires timer in intervals of "13" [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › fires timers in correct order [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › triggers timeouts and intervals in the order scheduled [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › does not fire canceled intervals [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › throws for negative minutes [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › fires nested setTimeout calls properly [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › does not silently catch errors [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes 2 [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown 2 [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › throws on negative ticks [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › creates updated Date while ticking promises [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › fires promise timers in correct order [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › does not fire intervals canceled in a promise [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › fires nested setTimeout calls in user-created promises properly [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes in promises [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle user-created promises [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle chained user-created promises [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle multiple user-created promises [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle nested user-created promises [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle user-created promises even if some throw [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle user-created promises before calling more timeouts [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle local promises before calling timeouts [pass] +bidi-chromium-library › library/clock.spec.ts › runFor › should settle local nested promises before calling timeouts [pass] +bidi-chromium-library › library/clock.spec.ts › clearTimeout › removes timeout [pass] +bidi-chromium-library › library/clock.spec.ts › clearTimeout › removes interval [pass] +bidi-chromium-library › library/clock.spec.ts › clearTimeout › removes interval with undefined interval [pass] +bidi-chromium-library › library/clock.spec.ts › clearTimeout › ignores null argument [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › throws if no arguments [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › does not throw if |undefined| or |null| is passed as a callback [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › returns numeric id or object with numeric id [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › returns unique id [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › schedules recurring timeout [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › is not influenced by forward system clock changes [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › is not influenced by backward system clock changes [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › does not schedule recurring timeout when cleared [pass] +bidi-chromium-library › library/clock.spec.ts › setInterval › passes setTimeout parameters [pass] +bidi-chromium-library › library/clock.spec.ts › clearInterval › removes interval [pass] +bidi-chromium-library › library/clock.spec.ts › clearInterval › removes interval with undefined interval [pass] +bidi-chromium-library › library/clock.spec.ts › clearInterval › removes timeout [pass] +bidi-chromium-library › library/clock.spec.ts › clearInterval › ignores null argument [pass] +bidi-chromium-library › library/clock.spec.ts › date › provides date constructor [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates real Date objects [pass] +bidi-chromium-library › library/clock.spec.ts › date › returns date as string when called as function [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates Date objects representing clock time [pass] +bidi-chromium-library › library/clock.spec.ts › date › returns date as string representing clock time [pass] +bidi-chromium-library › library/clock.spec.ts › date › listens to ticking clock [pass] +bidi-chromium-library › library/clock.spec.ts › date › listens to system clock changes [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing timestamp [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing a date as string [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing a date as RFC 2822 string [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing year, month [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s [pass] +bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s, ms [pass] +bidi-chromium-library › library/clock.spec.ts › date › returns date as string when calling with arguments [pass] +bidi-chromium-library › library/clock.spec.ts › date › returns date as string when calling with timestamp [pass] +bidi-chromium-library › library/clock.spec.ts › date › mirrors native Date.prototype [pass] +bidi-chromium-library › library/clock.spec.ts › date › supports now method if present [pass] +bidi-chromium-library › library/clock.spec.ts › date › returns clock.now() [pass] +bidi-chromium-library › library/clock.spec.ts › date › mirrors parse method [pass] +bidi-chromium-library › library/clock.spec.ts › date › mirrors UTC method [pass] +bidi-chromium-library › library/clock.spec.ts › date › mirrors toUTCString method [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › returns clock object [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › takes an object parameter [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › sets initial timestamp [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global setTimeout [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global setInterval [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global clearInterval [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global performance.now [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › replace Event.prototype.timeStamp [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › uninstalls global performance.now [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › should let performance.mark still be callable after install() (#136) [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › should not alter the global performance properties and methods [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › should replace the getEntries, getEntriesByX methods with noops that return [] [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › deletes global property on uninstall if it was inherited onto the global object [unknown] +bidi-chromium-library › library/clock.spec.ts › stubTimers › fakes Date constructor [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › fake Date constructor should mirror Date's properties [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › mirrors custom Date properties [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › uninstalls Date constructor [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › fakes provided methods [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › resets faked methods [pass] +bidi-chromium-library › library/clock.spec.ts › stubTimers › does not fake methods not provided [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › throws if no arguments [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › returns numeric id or object with numeric id [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › returns unique id [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should run every 16ms [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() when available [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() even when performance unavailable [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should call callback once [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should schedule two callbacks before the next frame at the same time [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should properly schedule callback for 3rd frame [pass] +bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should schedule for next frame if on current frame [pass] +bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › removes animation frame [pass] +bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › does not remove timeout [pass] +bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › does not remove interval [pass] +bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › ignores null argument [pass] +bidi-chromium-library › library/clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +bidi-chromium-library › library/clock.spec.ts › fastForward › pushes back execution time for skipped timers [pass] +bidi-chromium-library › library/clock.spec.ts › fastForward › handles multiple pending timers and types [pass] +bidi-chromium-library › library/clock.spec.ts › pauseAt › pause at target time [pass] +bidi-chromium-library › library/clock.spec.ts › pauseAt › fire target timers [pass] +bidi-chromium-library › library/clock.spec.ts › pauseAt › returns consumed clicks [pass] +bidi-chromium-library › library/clock.spec.ts › performance.now() › should start at 0 [pass] +bidi-chromium-library › library/clock.spec.ts › performance.now() › should run along with clock.tick [pass] +bidi-chromium-library › library/clock.spec.ts › performance.now() › should listen to multiple ticks in performance.now [pass] +bidi-chromium-library › library/clock.spec.ts › performance.now() › should run with ticks with timers set [pass] +bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › throws if no arguments [pass] +bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › returns numeric id [pass] +bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › returns unique id [pass] +bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › runs after all timers [pass] +bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › runs no later than timeout option even if there are any timers [pass] +bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › doesn't runs if there are any timers and no timeout option [pass] +bidi-chromium-library › library/clock.spec.ts › cancelIdleCallback › removes idle callback [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › Executes formatRange like normal [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › Executes formatRangeToParts like normal [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › Executes resolvedOptions like normal [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed a timestamp argument that is first of the month [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed a timestamp argument that is not first of the month [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed no timestamp and system time is first of the month [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed no timestamp and system time is not first of the month [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › Executes supportedLocalesOf like normal [pass] +bidi-chromium-library › library/clock.spec.ts › Intl API › Creates a RelativeTimeFormat like normal [pass] +bidi-chromium-library › library/clock.spec.ts › works with concurrent runFor calls [pass] +bidi-chromium-library › library/clock.spec.ts › works with slow setTimeout in busy embedder [pass] +bidi-chromium-library › library/clock.spec.ts › works with slow setTimeout in busy embedder when not paused [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse short attributes [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse all operators [pass] +bidi-chromium-library › library/component-parser.spec.ts › should tolerate spacing [pass] +bidi-chromium-library › library/component-parser.spec.ts › should escape [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse int values [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse float values [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse bool [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse regex [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse identifiers [pass] +bidi-chromium-library › library/component-parser.spec.ts › should parse unquoted string [pass] +bidi-chromium-library › library/component-parser.spec.ts › should throw on malformed selector [pass] +bidi-chromium-library › library/css-parser.spec.ts › should parse css [pass] +bidi-chromium-library › library/css-parser.spec.ts › should throw on malformed css [pass] +bidi-chromium-library › library/debug-controller.spec.ts › should pick element [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should report pages [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should navigate all [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should reset for reuse [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should highlight all [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should record [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should record custom data-testid [fail] +bidi-chromium-library › library/debug-controller.spec.ts › should reset routes before reuse [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › context.cookies() should work @smoke [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › context.addCookies() should work [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › context.clearCookies() should work [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should(not) block third party cookies [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support viewport option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support deviceScaleFactor option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support userAgent option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support bypassCSP option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support javascriptEnabled option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support httpCredentials option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support offline option [fail] +bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support acceptDownloads option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support hasTouch option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should work in persistent context [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support colorScheme option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support reducedMotion option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support forcedColors option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support timezoneId option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support locale option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support geolocation and permissions options [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support ignoreHTTPSErrors option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support extraHTTPHeaders option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should accept userDataDir [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should restore state from userDataDir [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should create userDataDir if it does not exist [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should have default URL when launching browser [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should throw if page argument is passed [pass] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should have passed URL when launching with ignoreDefaultArgs: true [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should handle timeout [pass] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should handle exception [timeout] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should fire close event for a persistent context [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › coverage should work [unknown] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should respect selectors [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should connect to a browser with the default page [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support har option [fail] +bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › user agent is up to date [fail] +bidi-chromium-library › library/download.spec.ts › download event › should report download when navigation turns into download @smoke [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should work with Cross-Origin-Opener-Policy [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report downloads with acceptDownloads: false [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report downloads with acceptDownloads: true [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report proper download url when download is from download attribute [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report downloads for download attribute [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should save to user-specified path without updating original path [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should save to two different paths with multiple saveAs calls [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should save to overwritten filepath [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should create subdirectories when saving to non-existent user-specified path [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should error when saving with downloads disabled [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should error when saving after deletion [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report non-navigation downloads [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Files [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Blobs [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report alt-click downloads [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report new window downloads [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should delete file [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should expose stream [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should delete downloads on context destruction [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should delete downloads on browser gone [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should close the context without awaiting the failed download [unknown] +bidi-chromium-library › library/download.spec.ts › download event › should close the context without awaiting the download [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should throw if browser dies [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should download large binary.zip [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should be able to cancel pending downloads [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should not fail explicitly to cancel a download even if that is already finished [timeout] +bidi-chromium-library › library/download.spec.ts › download event › should report downloads with interception [fail] +bidi-chromium-library › library/download.spec.ts › download event › should emit download event from nested iframes [timeout] +bidi-chromium-library › library/download.spec.ts › should be able to download a PDF file [timeout] +bidi-chromium-library › library/download.spec.ts › should be able to download a inline PDF file via response interception [fail] +bidi-chromium-library › library/download.spec.ts › should be able to download a inline PDF file via navigation [timeout] +bidi-chromium-library › library/download.spec.ts › should save to user-specified path [timeout] +bidi-chromium-library › library/download.spec.ts › should download even if there is no "attachment" value [timeout] +bidi-chromium-library › library/download.spec.ts › should convert navigation to a resource with unsupported mime type into download [timeout] +bidi-chromium-library › library/download.spec.ts › should download links with data url [timeout] +bidi-chromium-library › library/download.spec.ts › should download successfully when routing [timeout] +bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should keep downloadsPath folder [timeout] +bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should delete downloads when context closes [timeout] +bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder [timeout] +bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder with a relative path [timeout] +bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should accept downloads in persistent context [fail] +bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should delete downloads when persistent context closes [fail] +bidi-chromium-library › library/emulation-focus.spec.ts › should think that it is focused by default [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should think that all pages are focused @smoke [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should focus popups by default [fail] +bidi-chromium-library › library/emulation-focus.spec.ts › should provide target for keyboard events [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should not affect mouse event target page [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should change document.activeElement [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should not affect screenshots [fail] +bidi-chromium-library › library/emulation-focus.spec.ts › should change focused iframe [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should focus with more than one page/context [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should not fire blur events when interacting with more than one page/context [pass] +bidi-chromium-library › library/emulation-focus.spec.ts › should trigger hover state concurrently [pass] +bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › should work [pass] +bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › set max listeners test [pass] +bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › Listener order [pass] +bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › listener type check [pass] +bidi-chromium-library › library/events/check-listener-leaks.spec.ts › defaultMaxListeners [pass] +bidi-chromium-library › library/events/check-listener-leaks.spec.ts › process-wide [pass] +bidi-chromium-library › library/events/check-listener-leaks.spec.ts › _maxListeners still has precedence over defaultMaxListeners [pass] +bidi-chromium-library › library/events/events-list.spec.ts › EventEmitter › should maintain event names correctly [pass] +bidi-chromium-library › library/events/listener-count.spec.ts › Listener count test [pass] +bidi-chromium-library › library/events/listeners-side-effects.spec.ts › listeners empty check [pass] +bidi-chromium-library › library/events/listeners.spec.ts › EventEmitter listeners with one listener [pass] +bidi-chromium-library › library/events/listeners.spec.ts › Array copy modification does not modify orig [pass] +bidi-chromium-library › library/events/listeners.spec.ts › Modify array copy after multiple adds [pass] +bidi-chromium-library › library/events/listeners.spec.ts › listeners and once [pass] +bidi-chromium-library › library/events/listeners.spec.ts › listeners with conflicting types [pass] +bidi-chromium-library › library/events/listeners.spec.ts › EventEmitter with no members [pass] +bidi-chromium-library › library/events/listeners.spec.ts › listeners on prototype [pass] +bidi-chromium-library › library/events/listeners.spec.ts › raw listeners [pass] +bidi-chromium-library › library/events/listeners.spec.ts › raw listeners order [pass] +bidi-chromium-library › library/events/max-listeners.spec.ts › emit maxListeners on e [pass] +bidi-chromium-library › library/events/method-names.spec.ts › EventEmitter prototype test [pass] +bidi-chromium-library › library/events/modify-in-emit.spec.ts › add and remove listeners [pass] +bidi-chromium-library › library/events/modify-in-emit.spec.ts › removing callbacks in emit [pass] +bidi-chromium-library › library/events/num-args.spec.ts › should work [pass] +bidi-chromium-library › library/events/once.spec.ts › should work [pass] +bidi-chromium-library › library/events/once.spec.ts › once() has different code paths based on the number of arguments being emitted [pass] +bidi-chromium-library › library/events/prepend.spec.ts › EventEmitter functionality [pass] +bidi-chromium-library › library/events/prepend.spec.ts › Verify that the listener must be a function [pass] +bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › should not throw with ignoreErrors [pass] +bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › should wait [pass] +bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › should wait all [pass] +bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › wait should throw [pass] +bidi-chromium-library › library/events/remove-all-listeners.spec.ts › listeners [pass] +bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners removes all listeners [pass] +bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners with no event type [pass] +bidi-chromium-library › library/events/remove-all-listeners.spec.ts › listener count after removeAllListeners [pass] +bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners returns EventEmitter [pass] +bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners on undefined _events [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › First test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Second test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Third test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Fourth test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Fifth test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Sixth test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Seventh test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Eighth test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Ninth test [pass] +bidi-chromium-library › library/events/remove-listeners.spec.ts › Tenth test [pass] +bidi-chromium-library › library/events/set-max-listeners-side-effects.spec.ts › set max listeners test [pass] +bidi-chromium-library › library/events/special-event-names.spec.ts › should support special event names [pass] +bidi-chromium-library › library/events/subclass.spec.ts › myee instance [pass] +bidi-chromium-library › library/events/subclass.spec.ts › MyEE2 instance [pass] +bidi-chromium-library › library/events/symbols.spec.ts › should support symbols [pass] +bidi-chromium-library › library/favicon.spec.ts › should load svg favicon with prefer-color-scheme [unknown] +bidi-chromium-library › library/fetch-proxy.spec.ts › context request should pick up proxy credentials [pass] +bidi-chromium-library › library/fetch-proxy.spec.ts › global request should pick up proxy credentials [pass] +bidi-chromium-library › library/fetch-proxy.spec.ts › should work with context level proxy [pass] +bidi-chromium-library › library/fetch-proxy.spec.ts › should support proxy.bypass [pass] +bidi-chromium-library › library/fetch-proxy.spec.ts › should use socks proxy [pass] +bidi-chromium-library › library/firefox/launcher.spec.ts › should pass firefox user preferences [fail] +bidi-chromium-library › library/firefox/launcher.spec.ts › should pass firefox user preferences in persistent [fail] +bidi-chromium-library › library/geolocation.spec.ts › should work @smoke [timeout] +bidi-chromium-library › library/geolocation.spec.ts › should throw when invalid longitude [fail] +bidi-chromium-library › library/geolocation.spec.ts › should isolate contexts [timeout] +bidi-chromium-library › library/geolocation.spec.ts › should throw with missing latitude [pass] +bidi-chromium-library › library/geolocation.spec.ts › should not modify passed default options object [pass] +bidi-chromium-library › library/geolocation.spec.ts › should throw with missing longitude in default options [pass] +bidi-chromium-library › library/geolocation.spec.ts › should use context options [timeout] +bidi-chromium-library › library/geolocation.spec.ts › watchPosition should be notified [timeout] +bidi-chromium-library › library/geolocation.spec.ts › should use context options for popup [timeout] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should filter outgoing cookies by path [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should filter outgoing cookies by domain [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should do case-insensitive match of cookie domain [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should do case-insensitive match of request domain [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send secure cookie over https [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send secure cookie over http for localhost [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send not expired cookies [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should remove expired cookies [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should remove cookie with negative max-age [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should remove cookie with expires far in the past [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header even if it contains equal signs [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header even if it expired [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should export cookies to storage state [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should preserve local storage on import/export of storage state [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send cookies from storage state [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › storage state should round-trip through file [pass] +bidi-chromium-library › library/global-fetch-cookie.spec.ts › should work with empty storage state [pass] +bidi-chromium-library › library/global-fetch.spec.ts › fetch should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › delete should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › get should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › head should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › patch should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › post should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › put should work @smoke [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should dispose global request [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should support global userAgent option [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should support global timeout option [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should propagate extra http headers with redirects [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should support global httpCredentials option [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should return error with wrong credentials [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should work with correct credentials and matching origin [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should work with correct credentials and matching origin case insensitive [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching scheme [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching hostname [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching port [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should support WWW-Authenticate: Basic [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should support HTTPCredentials.send [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should support global ignoreHTTPSErrors option [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should propagate ignoreHTTPSErrors on redirects [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should resolve url relative to global baseURL option [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should set playwright as user-agent [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should be able to construct with context options [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should return empty body [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should abort requests when context is disposed [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should abort redirected requests when context is disposed [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should remove content-length from redirected post requests [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify object body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify object body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify array body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify array body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify string body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify string body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify string (falsey) body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify string (falsey) body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify bool body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify bool body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify bool (false) body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify bool (false) body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify number body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify number body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify number (falsey) body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify number (falsey) body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify null body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify null body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should json stringify literal string undefined body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify literal string undefined body when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should accept already serialized data as Buffer when content-type is application/json [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should have nice toString [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not fail on empty body with encoding [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should return body for failing requests [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should throw an error when maxRedirects is exceeded [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should not follow redirects when maxRedirects is set to 0 [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should throw an error when maxRedirects is less than 0 [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should keep headers capitalization [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should serialize post data on the client [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should throw after dispose [pass] +bidi-chromium-library › library/global-fetch.spec.ts › should retry ECONNRESET [pass] +bidi-chromium-library › library/har.spec.ts › should throw without path [pass] +bidi-chromium-library › library/har.spec.ts › should have version and creator [pass] +bidi-chromium-library › library/har.spec.ts › should have browser [fail] +bidi-chromium-library › library/har.spec.ts › should have pages [pass] +bidi-chromium-library › library/har.spec.ts › should have pages in persistent context [fail] +bidi-chromium-library › library/har.spec.ts › should include request [pass] +bidi-chromium-library › library/har.spec.ts › should include response [pass] +bidi-chromium-library › library/har.spec.ts › should include redirectURL [pass] +bidi-chromium-library › library/har.spec.ts › should include query params [pass] +bidi-chromium-library › library/har.spec.ts › should include postData [fail] +bidi-chromium-library › library/har.spec.ts › should include binary postData [fail] +bidi-chromium-library › library/har.spec.ts › should include form params [fail] +bidi-chromium-library › library/har.spec.ts › should include cookies [pass] +bidi-chromium-library › library/har.spec.ts › should include set-cookies [fail] +bidi-chromium-library › library/har.spec.ts › should skip invalid Expires [pass] +bidi-chromium-library › library/har.spec.ts › should include set-cookies with comma [fail] +bidi-chromium-library › library/har.spec.ts › should include secure set-cookies [fail] +bidi-chromium-library › library/har.spec.ts › should record request overrides [fail] +bidi-chromium-library › library/har.spec.ts › should include content @smoke [fail] +bidi-chromium-library › library/har.spec.ts › should use attach mode for zip extension [fail] +bidi-chromium-library › library/har.spec.ts › should omit content [pass] +bidi-chromium-library › library/har.spec.ts › should omit content legacy [pass] +bidi-chromium-library › library/har.spec.ts › should attach content [fail] +bidi-chromium-library › library/har.spec.ts › should filter by glob [pass] +bidi-chromium-library › library/har.spec.ts › should filter by regexp [pass] +bidi-chromium-library › library/har.spec.ts › should include sizes [fail] +bidi-chromium-library › library/har.spec.ts › should work with gzip compression [fail] +bidi-chromium-library › library/har.spec.ts › should calculate time [pass] +bidi-chromium-library › library/har.spec.ts › should return receive time [fail] +bidi-chromium-library › library/har.spec.ts › should report the correct _transferSize with PNG files [fail] +bidi-chromium-library › library/har.spec.ts › should have -1 _transferSize when its a failed request [pass] +bidi-chromium-library › library/har.spec.ts › should record failed request headers [pass] +bidi-chromium-library › library/har.spec.ts › should record failed request overrides [fail] +bidi-chromium-library › library/har.spec.ts › should report the correct request body size [pass] +bidi-chromium-library › library/har.spec.ts › should report the correct request body size when the bodySize is 0 [pass] +bidi-chromium-library › library/har.spec.ts › should report the correct response body size when the bodySize is 0 [pass] +bidi-chromium-library › library/har.spec.ts › should have popup requests [pass] +bidi-chromium-library › library/har.spec.ts › should not contain internal pages [pass] +bidi-chromium-library › library/har.spec.ts › should have connection details [fail] +bidi-chromium-library › library/har.spec.ts › should have security details [fail] +bidi-chromium-library › library/har.spec.ts › should have connection details for redirects [fail] +bidi-chromium-library › library/har.spec.ts › should have connection details for failed requests [fail] +bidi-chromium-library › library/har.spec.ts › should return server address directly from response [fail] +bidi-chromium-library › library/har.spec.ts › should return security details directly from response [fail] +bidi-chromium-library › library/har.spec.ts › should contain http2 for http2 requests [fail] +bidi-chromium-library › library/har.spec.ts › should filter favicon and favicon redirects [unknown] +bidi-chromium-library › library/har.spec.ts › should have different hars for concurrent contexts [pass] +bidi-chromium-library › library/har.spec.ts › should include API request [pass] +bidi-chromium-library › library/har.spec.ts › should not hang on resources served from cache [pass] +bidi-chromium-library › library/har.spec.ts › should not hang on slow chunked response [fail] +bidi-chromium-library › library/headful.spec.ts › should have default url when launching browser @smoke [fail] +bidi-chromium-library › library/headful.spec.ts › should close browser with beforeunload page [fail] +bidi-chromium-library › library/headful.spec.ts › should close browsercontext with pending beforeunload dialog [timeout] +bidi-chromium-library › library/headful.spec.ts › should not crash when creating second context [pass] +bidi-chromium-library › library/headful.spec.ts › should click when viewport size is larger than screen [pass] +bidi-chromium-library › library/headful.spec.ts › should dispatch click events to oversized viewports [pass] +bidi-chromium-library › library/headful.spec.ts › should click background tab [timeout] +bidi-chromium-library › library/headful.spec.ts › should close browser after context menu was triggered [pass] +bidi-chromium-library › library/headful.spec.ts › should(not) block third party cookies [pass] +bidi-chromium-library › library/headful.spec.ts › should not block third party SameSite=None cookies [fail] +bidi-chromium-library › library/headful.spec.ts › should not override viewport size when passed null [fail] +bidi-chromium-library › library/headful.spec.ts › Page.bringToFront should work [pass] +bidi-chromium-library › library/headful.spec.ts › should click in OOPIF [fail] +bidi-chromium-library › library/headful.spec.ts › should click bottom row w/ infobar in OOPIF [fail] +bidi-chromium-library › library/headful.spec.ts › headless and headful should use same default fonts [fail] +bidi-chromium-library › library/hit-target.spec.ts › should block all events when hit target is wrong [pass] +bidi-chromium-library › library/hit-target.spec.ts › should block click when mousedown fails [pass] +bidi-chromium-library › library/hit-target.spec.ts › should click when element detaches in mousedown [pass] +bidi-chromium-library › library/hit-target.spec.ts › should block all events when hit target is wrong and element detaches [pass] +bidi-chromium-library › library/hit-target.spec.ts › should not block programmatic events [pass] +bidi-chromium-library › library/hit-target.spec.ts › should click the button again after document.write [pass] +bidi-chromium-library › library/hit-target.spec.ts › should work with mui select [pass] +bidi-chromium-library › library/hit-target.spec.ts › should work with drag and drop that moves the element under cursor [pass] +bidi-chromium-library › library/hit-target.spec.ts › should work with block inside inline [pass] +bidi-chromium-library › library/hit-target.spec.ts › should work with block-block-block inside inline-inline [pass] +bidi-chromium-library › library/hit-target.spec.ts › should work with block inside inline in shadow dom [pass] +bidi-chromium-library › library/hit-target.spec.ts › should not click iframe overlaying the target [pass] +bidi-chromium-library › library/hit-target.spec.ts › should not click an element overlaying iframe with the target [pass] +bidi-chromium-library › library/hit-target.spec.ts › should click into frame inside closed shadow root [fail] +bidi-chromium-library › library/hit-target.spec.ts › should click an element inside closed shadow root [pass] +bidi-chromium-library › library/hit-target.spec.ts › should detect overlay from another shadow root [pass] +bidi-chromium-library › library/hit-target.spec.ts › should detect overlaid element in a transformed iframe [fail] +bidi-chromium-library › library/hit-target.spec.ts › should click in iframe with padding [pass] +bidi-chromium-library › library/hit-target.spec.ts › should click in iframe with padding 2 [pass] +bidi-chromium-library › library/hit-target.spec.ts › should click in custom element [pass] +bidi-chromium-library › library/ignorehttpserrors.spec.ts › should work @smoke [fail] +bidi-chromium-library › library/ignorehttpserrors.spec.ts › should isolate contexts [fail] +bidi-chromium-library › library/ignorehttpserrors.spec.ts › should work with mixed content [fail] +bidi-chromium-library › library/ignorehttpserrors.spec.ts › should work with WebSocket [fail] +bidi-chromium-library › library/ignorehttpserrors.spec.ts › should fail with WebSocket if not ignored [pass] +bidi-chromium-library › library/ignorehttpserrors.spec.ts › serviceWorker should intercept document request [fail] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore programmatic events [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click after same-document navigation [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should make a positioned click on a canvas [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should work with TrustedTypes [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should not target selector preview by text regexp [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill japanese text [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea with new lines at the end [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [contentEditable] [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should press [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should update selected element after pressing Tab [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record ArrowDown [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should emit single keyup on ArrowDown [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check a radio button [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check with keyboard [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should uncheck [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should select [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should select with size attribute [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should await popup [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should assert navigation [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore AltGraph [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should middle click [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record slider [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click button with nested div [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after performAction [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after recordAction [timeout] +bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should not throw csp directive violation errors [pass] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain open page [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain second page [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain close page [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should not lead to an error if html gets clicked [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload a single file [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload multiple files [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should clear files [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should download files [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle dialogs [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle history.postData [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should record open in a new tab with url [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should not clash pages [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › click should emit events in order [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should update hover model on action [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should reset hover model on action when element detaches [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should update active model on action [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should check input with chaining id [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should record navigations after identical pushState [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should --save-trace [fail] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should save assets via SIGINT [fail] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should fill tricky characters [timeout] +bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › should --test-id-attribute [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.first [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.nth [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with special characters in name attribute [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with title attribute [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with name attribute [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with id attribute [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with testId [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate role locators undef frame locators [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByTestId [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByPlaceholder [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByAltText [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel without regex [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume pointer events [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume contextmenu events, despite a custom context menu [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled input [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled select [timeout] +bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert visibility [timeout] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options for custom settings [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device [unknown] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print load/save storageState [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should work with --save-har [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in nunit if no options were passed [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in nunit if options were passed [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in mstest if no options were passed [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in mstest if options were passed [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in mstest [fail] +bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in nunit [fail] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options for custom settings [fail] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device [unknown] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print load/save storage_state [fail] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should work with --save-har [fail] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct imports in junit [fail] +bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print a valid basic program in junit [fail] +bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options for custom settings [fail] +bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device [unknown] +bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should save the codegen output to a file if specified [fail] +bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print load/save storageState [fail] +bidi-chromium-library › library/inspector/cli-codegen-pytest.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-pytest.spec.ts › should print the correct context options when using a device and lang [unknown] +bidi-chromium-library › library/inspector/cli-codegen-pytest.spec.ts › should save the codegen output to a file if specified [fail] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options for custom settings [fail] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device [unknown] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should save the codegen output to a file if specified [fail] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print load/save storage_state [fail] +bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should work with --save-har [fail] +bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options for custom settings [fail] +bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device [unknown] +bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should save the codegen output to a file if specified [fail] +bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print load/save storage_state [fail] +bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct imports and context options [fail] +bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options for custom settings [fail] +bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device [unknown] +bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print load storageState [fail] +bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should work with --save-har [fail] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.$, playwright.$$ [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.selector [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator.value [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator.values [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator({ has }) [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator({ hasNot }) [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support locator.and() [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support locator.or() [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.getBy* [pass] +bidi-chromium-library › library/inspector/console-api.spec.ts › expected properties on playwright object [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › should resume when closing inspector [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › should not reset timeouts [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause and resume the script [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause and resume the script with keyboard shortcut [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should resume from console [fail] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause after a navigation [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should show source [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause on next pause [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should step [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should step with keyboard shortcut [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight pointer, only in main frame [timeout] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should skip input when resuming [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should hide internal calls [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should show expect.toHaveText [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight waitForEvent [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log with waitForEvent [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log with error [fail] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log with error in waitForEvent [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause on page close [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause on context close [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight on explore [timeout] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight on explore (csharp) [timeout] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should not prevent key events [pass] +bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight locators with custom testId [timeout] +bidi-chromium-library › library/launcher.spec.ts › should have an errors object [pass] +bidi-chromium-library › library/launcher.spec.ts › should have a devices object [pass] +bidi-chromium-library › library/launcher.spec.ts › should kill browser process on timeout after close [pass] +bidi-chromium-library › library/launcher.spec.ts › should throw a friendly error if its headed and there is no xserver on linux running [unknown] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer locators [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer getByRole [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer ignore-case locators [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer ordered locators [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer locators with regex [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer hasText [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer hasNotText [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer has [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer hasNot [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer has + hasText [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer frameLocator [pass] +bidi-chromium-library › library/locator-generator.spec.ts › generate multiple locators [pass] +bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer internal:has-text locators [pass] +bidi-chromium-library › library/locator-generator.spec.ts › asLocator internal:and [pass] +bidi-chromium-library › library/locator-generator.spec.ts › asLocator internal:or [pass] +bidi-chromium-library › library/locator-generator.spec.ts › asLocator internal:chain [pass] +bidi-chromium-library › library/locator-generator.spec.ts › asLocator xpath [pass] +bidi-chromium-library › library/locator-generator.spec.ts › parseLocator quotes [pass] +bidi-chromium-library › library/locator-generator.spec.ts › parseLocator css [pass] +bidi-chromium-library › library/locator-generator.spec.ts › parse locators strictly [pass] +bidi-chromium-library › library/logger.spec.ts › should log @smoke [pass] +bidi-chromium-library › library/logger.spec.ts › should log context-level [pass] +bidi-chromium-library › library/modernizr.spec.ts › Safari Desktop [unknown] +bidi-chromium-library › library/modernizr.spec.ts › Mobile Safari [unknown] +bidi-chromium-library › library/page-clock.frozen.spec.ts › clock should be frozen [unknown] +bidi-chromium-library › library/page-clock.frozen.spec.ts › clock should be realtime [unknown] +bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers immediately without specified delay [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers after sufficient delay [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers simultaneous timers [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers multiple simultaneous timers [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › waits after setTimeout was called [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers event when some throw [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › creates updated Date while ticking [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › passes 8 seconds [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › passes 1 minute [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › passes 2 hours, 34 minutes and 10 seconds [fail] +bidi-chromium-library › library/page-clock.spec.ts › runFor › throws for invalid format [pass] +bidi-chromium-library › library/page-clock.spec.ts › runFor › returns the current now value [pass] +bidi-chromium-library › library/page-clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +bidi-chromium-library › library/page-clock.spec.ts › fastForward › pushes back execution time for skipped timers [fail] +bidi-chromium-library › library/page-clock.spec.ts › fastForward › supports string time arguments [fail] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › sets initial timestamp [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › should throw for invalid date [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global setTimeout [fail] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global setInterval [fail] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global clearInterval [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global performance.now [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › fakes Date constructor [pass] +bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global performance.timeOrigin [pass] +bidi-chromium-library › library/page-clock.spec.ts › popup › should tick after popup [fail] +bidi-chromium-library › library/page-clock.spec.ts › popup › should tick before popup [fail] +bidi-chromium-library › library/page-clock.spec.ts › popup › should run time before popup [pass] +bidi-chromium-library › library/page-clock.spec.ts › popup › should not run time before popup on pause [fail] +bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › does not fake methods [pass] +bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › allows setting time multiple times [pass] +bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › fixed time is not affected by clock manipulation [pass] +bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › allows installing fake timers after settings time [fail] +bidi-chromium-library › library/page-clock.spec.ts › while running › should progress time [pass] +bidi-chromium-library › library/page-clock.spec.ts › while running › should runFor [pass] +bidi-chromium-library › library/page-clock.spec.ts › while running › should fastForward [pass] +bidi-chromium-library › library/page-clock.spec.ts › while running › should fastForwardTo [pass] +bidi-chromium-library › library/page-clock.spec.ts › while running › should pause [pass] +bidi-chromium-library › library/page-clock.spec.ts › while running › should pause and fastForward [pass] +bidi-chromium-library › library/page-clock.spec.ts › while running › should set system time on pause [pass] +bidi-chromium-library › library/page-clock.spec.ts › while on pause › fastForward should not run nested immediate [fail] +bidi-chromium-library › library/page-clock.spec.ts › while on pause › runFor should not run nested immediate [fail] +bidi-chromium-library › library/page-clock.spec.ts › while on pause › runFor should not run nested immediate from microtask [fail] +bidi-chromium-library › library/page-clock.spec.ts › Date.now › check Date.now is an integer [pass] +bidi-chromium-library › library/page-clock.spec.ts › Date.now › check Date.now is an integer (2) [pass] +bidi-chromium-library › library/page-event-crash.spec.ts › should emit crash event when page crashes [timeout] +bidi-chromium-library › library/page-event-crash.spec.ts › should throw on any action after page crashes [timeout] +bidi-chromium-library › library/page-event-crash.spec.ts › should cancel waitForEvent when page crashes [timeout] +bidi-chromium-library › library/page-event-crash.spec.ts › should cancel navigation when page crashes [timeout] +bidi-chromium-library › library/page-event-crash.spec.ts › should be able to close context when page crashes [timeout] +bidi-chromium-library › library/pdf.spec.ts › should be able to save file [unknown] +bidi-chromium-library › library/pdf.spec.ts › should be able to generate outline [unknown] +bidi-chromium-library › library/permissions.spec.ts › permissions › should be prompt by default [pass] +bidi-chromium-library › library/permissions.spec.ts › permissions › should deny permission when not listed [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should fail when bad permission is given [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should grant geolocation permission when origin is listed [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should prompt for geolocation permission when origin is not listed [pass] +bidi-chromium-library › library/permissions.spec.ts › permissions › should grant notifications permission when listed [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should accumulate when adding [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should clear permissions [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should grant permission when listed for all domains [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should grant permission when creating context [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should reset permissions [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should trigger permission onchange [fail] +bidi-chromium-library › library/permissions.spec.ts › permissions › should isolate permissions between browser contexts [fail] +bidi-chromium-library › library/permissions.spec.ts › should support clipboard read [fail] +bidi-chromium-library › library/permissions.spec.ts › storage access [unknown] +bidi-chromium-library › library/popup.spec.ts › should inherit user agent from browser context @smoke [fail] +bidi-chromium-library › library/popup.spec.ts › should respect routes from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should inherit extra headers from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should inherit offline from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should inherit http credentials from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should inherit touch support from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should inherit viewport size from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should use viewport size from window features [timeout] +bidi-chromium-library › library/popup.spec.ts › should respect routes from browser context when using window.open [fail] +bidi-chromium-library › library/popup.spec.ts › BrowserContext.addInitScript should apply to an in-process popup [fail] +bidi-chromium-library › library/popup.spec.ts › BrowserContext.addInitScript should apply to a cross-process popup [fail] +bidi-chromium-library › library/popup.spec.ts › should expose function from browser context [fail] +bidi-chromium-library › library/popup.spec.ts › should not dispatch binding on a closed page [fail] +bidi-chromium-library › library/popup.spec.ts › should not throttle rAF in the opener page [pass] +bidi-chromium-library › library/popup.spec.ts › should not throw when click closes popup [pass] +bidi-chromium-library › library/proxy-pattern.spec.ts › socks proxy patter matcher [pass] +bidi-chromium-library › library/proxy.spec.ts › should throw for bad server value [pass] +bidi-chromium-library › library/proxy.spec.ts › should use proxy @smoke [pass] +bidi-chromium-library › library/proxy.spec.ts › should use proxy for second page [pass] +bidi-chromium-library › library/proxy.spec.ts › should work with IP:PORT notion [pass] +bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › by default › localhost [pass] +bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › by default › loopback address [pass] +bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › by default › link-local [pass] +bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [pass] +bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [pass] +bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [pass] +bidi-chromium-library › library/proxy.spec.ts › should authenticate [fail] +bidi-chromium-library › library/proxy.spec.ts › should work with authenticate followed by redirect [fail] +bidi-chromium-library › library/proxy.spec.ts › should exclude patterns [pass] +bidi-chromium-library › library/proxy.spec.ts › should use socks proxy [pass] +bidi-chromium-library › library/proxy.spec.ts › should use socks proxy in second page [pass] +bidi-chromium-library › library/proxy.spec.ts › does launch without a port [pass] +bidi-chromium-library › library/proxy.spec.ts › should use proxy with emulated user agent [unknown] +bidi-chromium-library › library/proxy.spec.ts › should use SOCKS proxy for websocket requests [pass] +bidi-chromium-library › library/resource-timing.spec.ts › should work @smoke [pass] +bidi-chromium-library › library/resource-timing.spec.ts › should work for subresource [fail] +bidi-chromium-library › library/resource-timing.spec.ts › should work for SSL [fail] +bidi-chromium-library › library/resource-timing.spec.ts › should work for redirect [fail] +bidi-chromium-library › library/resource-timing.spec.ts › should work when serving from memory cache [fail] +bidi-chromium-library › library/role-utils.spec.ts › wpt accname #0 [pass] +bidi-chromium-library › library/role-utils.spec.ts › wpt accname #1 [pass] +bidi-chromium-library › library/role-utils.spec.ts › wpt accname #2 [pass] +bidi-chromium-library › library/role-utils.spec.ts › wpt accname #3 [pass] +bidi-chromium-library › library/role-utils.spec.ts › wpt accname non-manual [pass] +bidi-chromium-library › library/role-utils.spec.ts › axe-core implicit-role [pass] +bidi-chromium-library › library/role-utils.spec.ts › axe-core accessible-text [pass] +bidi-chromium-library › library/role-utils.spec.ts › accessible name with slots [pass] +bidi-chromium-library › library/role-utils.spec.ts › accessible name nested treeitem [pass] +bidi-chromium-library › library/role-utils.spec.ts › svg title [pass] +bidi-chromium-library › library/role-utils.spec.ts › native controls [pass] +bidi-chromium-library › library/role-utils.spec.ts › native controls labelled-by [pass] +bidi-chromium-library › library/role-utils.spec.ts › display:contents should be visible when contents are visible [pass] +bidi-chromium-library › library/role-utils.spec.ts › label/labelled-by aria-hidden with descendants [pass] +bidi-chromium-library › library/role-utils.spec.ts › own aria-label concatenated with aria-labelledby [pass] +bidi-chromium-library › library/role-utils.spec.ts › control embedded in a label [pass] +bidi-chromium-library › library/role-utils.spec.ts › control embedded in a target element [pass] +bidi-chromium-library › library/role-utils.spec.ts › svg role=presentation [pass] +bidi-chromium-library › library/role-utils.spec.ts › should work with form and tricky input names [pass] +bidi-chromium-library › library/role-utils.spec.ts › should ignore stylesheet from hidden aria-labelledby subtree [pass] +bidi-chromium-library › library/role-utils.spec.ts › should not include hidden pseudo into accessible name [pass] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should run in parallel in multiple pages [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and clip [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and fullPage [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor and clip [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor and scale:css [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor, clip and scale:css [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should throw if screenshot size is too large with device scale factor [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with large size [fail] +bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should handle vh units [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › element screenshot should work with a mobile viewport [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › element screenshot should work with device scale factor [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should take screenshots when default viewport is null [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should take fullPage screenshots when default viewport is null [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore default viewport after fullPage screenshot [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and exception [pass] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and timeout [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should take element screenshot when default viewport is null and restore back [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore viewport after element screenshot and exception [pass] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › element screenshots should handle vh units [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should work if the main resource hangs [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor and scale:css [fail] +bidi-chromium-library › library/screenshot.spec.ts › element screenshot › page screenshot should capture css transform with device pixels [fail] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer button over inner span [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate text and normalize whitespace [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate text for [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve role name [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not improve guid text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape text with >> [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should escape text with quote [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should escape text with slash [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use text for select [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer data-testid [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use readable id [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use generated id [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should chain text after parent [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use parent text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should separate selectors by >> [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim long text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use nested ordinals [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use input[value] [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should find text in shadow dom [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in shadow dom [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work with tricky attributes [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work without CSS.escape [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate label selector [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate title selector [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate relative selector [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work when registered on global [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work with path [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work in main and isolated world [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should handle errors [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should not rely on engines working from the root [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] +bidi-chromium-library › library/shared-worker.spec.ts › should survive shared worker restart [timeout] +bidi-chromium-library › library/signals.spec.ts › should close the browser when the node process closes [timeout] +bidi-chromium-library › library/signals.spec.ts › should remove temp dir on process.exit [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should report browser close signal 2 [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo check [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo click [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo fill [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo focus [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo goto [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo hover [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo press [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo reload [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo type [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo check [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo click [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo fill [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo focus [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo goto [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo hover [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo press [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo type [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect snapshot [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture resources [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect multiple [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect node removal [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect attr removal [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should have a custom doctype [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture frame [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture iframe [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture snapshot target [timeout] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect on attribute change [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [pass] +bidi-chromium-library › library/tap.spec.ts › should send all of the correct events @smoke [fail] +bidi-chromium-library › library/tap.spec.ts › trial run should not tap [fail] +bidi-chromium-library › library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] +bidi-chromium-library › library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] +bidi-chromium-library › library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] +bidi-chromium-library › library/tap.spec.ts › should work with modifiers [fail] +bidi-chromium-library › library/tap.spec.ts › should send well formed touch points [fail] +bidi-chromium-library › library/tap.spec.ts › should wait until an element is visible to tap it [fail] +bidi-chromium-library › library/tap.spec.ts › locators › should send all of the correct events [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show empty trace viewer [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace viewers [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open trace viewer on specific host [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open simple trace viewer [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should contain action info [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should render network bars [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should render console [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should open console errors on click [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show params and return value [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show null as a param [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should have correct snapshot size [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should have correct stack trace [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should have network requests [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should filter network requests by resource type [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show font preview [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should filter network requests by url [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides 2 [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show snapshot URL [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should popup snapshot [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should capture data-url svg iframe [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should contain adopted style sheets [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with nesting CSS selectors [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should restore scroll positions [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should restore control values [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with meta CSP [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should handle multiple headers [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should handle src=blob [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should handle file URIs [unknown] +bidi-chromium-library › library/trace-viewer.spec.ts › should preserve currentSrc [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should register custom elements [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target elements [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight expect failure [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show action source [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should follow redirects [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should include metainfo [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files of the same test [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should not crash with broken locator [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.abort [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should serve overridden request [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should display language-specific locators [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should update highlight when typing [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open trace-1.31 [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open trace-1.37 [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should ignore 304 responses [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator in iframe [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should remove noscript by default [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open snapshot in new browser context [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show similar actions from library-only trace [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show correct request start time [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should allow hiding route actions [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show baseURL in metadata pane [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should serve css without content-type [timeout] +bidi-chromium-library › library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [pass] +bidi-chromium-library › library/tracing.spec.ts › should collect trace with resources, but no js [timeout] +bidi-chromium-library › library/tracing.spec.ts › should use the correct apiName for event driven callbacks [fail] +bidi-chromium-library › library/tracing.spec.ts › should not collect snapshots by default [pass] +bidi-chromium-library › library/tracing.spec.ts › should not include buffers in the trace [fail] +bidi-chromium-library › library/tracing.spec.ts › should exclude internal pages [pass] +bidi-chromium-library › library/tracing.spec.ts › should include context API requests [pass] +bidi-chromium-library › library/tracing.spec.ts › should collect two traces [pass] +bidi-chromium-library › library/tracing.spec.ts › should respect tracesDir and name [fail] +bidi-chromium-library › library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] +bidi-chromium-library › library/tracing.spec.ts › should overwrite existing file [fail] +bidi-chromium-library › library/tracing.spec.ts › should collect sources [pass] +bidi-chromium-library › library/tracing.spec.ts › should record network failures [fail] +bidi-chromium-library › library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] +bidi-chromium-library › library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] +bidi-chromium-library › library/tracing.spec.ts › should not stall on dialogs [pass] +bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames fit [fail] +bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames crop [fail] +bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames scale [fail] +bidi-chromium-library › library/tracing.spec.ts › should include interrupted actions [pass] +bidi-chromium-library › library/tracing.spec.ts › should throw when starting with different options [pass] +bidi-chromium-library › library/tracing.spec.ts › should throw when stopping without start [pass] +bidi-chromium-library › library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] +bidi-chromium-library › library/tracing.spec.ts › should work with multiple chunks [pass] +bidi-chromium-library › library/tracing.spec.ts › should export trace concurrently to second navigation [fail] +bidi-chromium-library › library/tracing.spec.ts › should not hang for clicks that open dialogs [pass] +bidi-chromium-library › library/tracing.spec.ts › should ignore iframes in head [pass] +bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames [pass] +bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames in expect [pass] +bidi-chromium-library › library/tracing.spec.ts › should record global request trace [pass] +bidi-chromium-library › library/tracing.spec.ts › should store global request traces separately [pass] +bidi-chromium-library › library/tracing.spec.ts › should store postData for global request [pass] +bidi-chromium-library › library/tracing.spec.ts › should not flush console events [pass] +bidi-chromium-library › library/tracing.spec.ts › should flush console events on tracing stop [pass] +bidi-chromium-library › library/tracing.spec.ts › should not emit after w/o before [pass] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [pass] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [fail] +bidi-chromium-library › library/video.spec.ts › screencast › videoSize should require videosPath [pass] +bidi-chromium-library › library/video.spec.ts › screencast › should work with old options [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] +bidi-chromium-library › library/video.spec.ts › screencast › should capture static page [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should expose video path [timeout] +bidi-chromium-library › library/video.spec.ts › screencast › saveAs should throw when no video frames [pass] +bidi-chromium-library › library/video.spec.ts › screencast › should delete video [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should expose video path blank page [timeout] +bidi-chromium-library › library/video.spec.ts › screencast › should work with weird screen resolution [timeout] +bidi-chromium-library › library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] +bidi-chromium-library › library/video.spec.ts › screencast › should expose video path blank popup [timeout] +bidi-chromium-library › library/video.spec.ts › screencast › should capture navigation [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture css transformation [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should work for popups [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should scale frames down to the requested size [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should be 800x450 by default [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should be 800x600 with null viewport [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should emulate an iphone [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should throw on browser close [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should throw if browser dies [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should not create video for internal pages [unknown] +bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should work with video+trace [fail] +bidi-chromium-library › library/video.spec.ts › should saveAs video [fail] +bidi-chromium-library › library/web-socket.spec.ts › should work @smoke [pass] +bidi-chromium-library › library/web-socket.spec.ts › should emit close events [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should emit frame events [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should pass self as argument to close event [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should emit binary frame events [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should emit error [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should not have stray error events [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should turn off when offline [unknown] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-chromium-page.txt b/tests/bidi/expectations/bidi-chromium-page.txt new file mode 100644 index 0000000000000..d1f28632f748d --- /dev/null +++ b/tests/bidi/expectations/bidi-chromium-page.txt @@ -0,0 +1,1966 @@ +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should work [pass] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should handle nested frames [fail] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should get frame box [pass] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [pass] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should return null for invisible elements [fail] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should force a layout [pass] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [pass] +bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should work with Node removed [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should work for Shadow DOM v1 [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should work for TextNodes [fail] +bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for detached nodes [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for hidden nodes with force [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for recursively hidden nodes with force [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for
elements with force [pass] +bidi-chromium-page › page/elementhandle-click.spec.ts › should double click the button [pass] +bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should work [pass] +bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should work for cross-process iframes [pass] +bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should work for cross-frame evaluations [fail] +bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should return null for non-iframes [pass] +bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should return null for document.documentElement [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › should have a nice preview [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › should have a nice preview for non-ascii attributes/children [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › getAttribute should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › inputValue should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › innerHTML should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › innerText should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › innerText should throw [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › textContent should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › textContent should work on ShadowRoot [fail] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › isVisible and isHidden should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › isVisible should not throw when the DOM element is not connected [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work with [fail] +bidi-chromium-page › page/page-fill.spec.ts › should throw if passed a non-string value [pass] +bidi-chromium-page › page/page-fill.spec.ts › should retry on disabled element [pass] +bidi-chromium-page › page/page-fill.spec.ts › should retry on readonly element [pass] +bidi-chromium-page › page/page-fill.spec.ts › should retry on invisible element [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill the body [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill fixed position input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill the input[type=number] [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill exponent into the input[type=number] [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill input[type=number] with empty string [pass] +bidi-chromium-page › page/page-fill.spec.ts › should not be able to fill text into the input[type=number] [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to clear using fill() [pass] +bidi-chromium-page › page/page-fill.spec.ts › should not throw when fill causes navigation [pass] +bidi-chromium-page › page/page-fill.spec.ts › fill back to back [pass] +bidi-chromium-page › page/page-focus.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-focus.spec.ts › should emit focus event [fail] +bidi-chromium-page › page/page-focus.spec.ts › should emit blur event [fail] +bidi-chromium-page › page/page-focus.spec.ts › should traverse focus [fail] +bidi-chromium-page › page/page-focus.spec.ts › should traverse focus in all directions [pass] +bidi-chromium-page › page/page-focus.spec.ts › should traverse only form elements [unknown] +bidi-chromium-page › page/page-focus.spec.ts › clicking checkbox should activate it [unknown] +bidi-chromium-page › page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with file URL [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with file URL with subframes [pass] +bidi-chromium-page › page/page-goto.spec.ts › should use http for no protocol [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work cross-process [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [fail] +bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] +bidi-chromium-page › page/page-goto.spec.ts › should capture iframe navigation request [pass] +bidi-chromium-page › page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with anchor navigation [timeout] +bidi-chromium-page › page/page-goto.spec.ts › should work with redirects [pass] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to about:blank [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return response when page changes its URL after load [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when server returns 204 [fail] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when page calls history API in beforeunload [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad url [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] +bidi-chromium-page › page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] +bidi-chromium-page › page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when main resources failed to load [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when replaced by another navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [fail] +bidi-chromium-page › page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to valid url [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to data url [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to 404 [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return last response in redirect chain [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with self requesting page [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating and show the url at the error message [pass] +bidi-chromium-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] +bidi-chromium-page › page/page-goto.spec.ts › should send referer [fail] +bidi-chromium-page › page/page-goto.spec.ts › should send referer of cross-origin URL [fail] +bidi-chromium-page › page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] +bidi-chromium-page › page/page-goto.spec.ts › should override referrer-policy [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when canceled by another navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with lazy loading iframes [pass] +bidi-chromium-page › page/page-goto.spec.ts › should report raw buffer for main resource [fail] +bidi-chromium-page › page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] +bidi-chromium-page › page/page-goto.spec.ts › should properly wait for load [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return from goto if new navigation is started [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] +bidi-chromium-page › page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return url with basic auth info [pass] +bidi-chromium-page › page/page-history.spec.ts › page.goBack should work @smoke [fail] +bidi-chromium-page › page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] +bidi-chromium-page › page/page-history.spec.ts › page.goBack should work for file urls [fail] +bidi-chromium-page › page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work with data url [timeout] +bidi-chromium-page › page/page-history.spec.ts › page.reload during renderer-initiated navigation [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work with same origin redirect [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work on a page with a hash [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] +bidi-chromium-page › page/page-history.spec.ts › page.goBack during renderer-initiated navigation [timeout] +bidi-chromium-page › page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] +bidi-chromium-page › page/page-history.spec.ts › regression test for issue 20791 [pass] +bidi-chromium-page › page/page-history.spec.ts › should reload proper page [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should move with the arrow keys [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should send a character with insertText [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › insertText should only emit input event [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should report shiftKey [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should report multiple modifiers [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should send proper codes while typing [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should send proper codes while typing with shift [timeout] +bidi-chromium-page › page/page-keyboard.spec.ts › should not type canceled events [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should press plus [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should press shift plus [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should shift raw codes [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should specify repeat property [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type all kinds of characters [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should specify location [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should press Enter [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should throw on unknown keys [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji into an iframe [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should handle selectAll [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support MacOS shortcuts [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should press the meta key [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] +bidi-chromium-page › page/page-keyboard.spec.ts › should scroll with PageDown [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should move around the selection in a contenteditable [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should move to the start of the document [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support simple copy-pasting [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support simple cut-pasting [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support undo-redo [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type after context menu was opened [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] +bidi-chromium-page › page/page-leaks.spec.ts › click should not leak [pass] +bidi-chromium-page › page/page-leaks.spec.ts › fill should not leak [pass] +bidi-chromium-page › page/page-leaks.spec.ts › expect should not leak [pass] +bidi-chromium-page › page/page-leaks.spec.ts › waitFor should not leak [pass] +bidi-chromium-page › page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] +bidi-chromium-page › page/page-listeners.spec.ts › should wait [pass] +bidi-chromium-page › page/page-listeners.spec.ts › wait should throw [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should click the document @smoke [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should dblclick the div [pass] +bidi-chromium-page › page/page-mouse.spec.ts › down and up should generate click [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should pointerdown the div with a custom button [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should report correct buttons property [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should select the text with mouse [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should set modifier keys on click [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should tween mouse movement [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should always round down [fail] +bidi-chromium-page › page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] +bidi-chromium-page › page/page-navigation.spec.ts › should work with _blank target [pass] +bidi-chromium-page › page/page-navigation.spec.ts › should work with cross-process _blank target [pass] +bidi-chromium-page › page/page-navigation.spec.ts › should work with _blank target in form [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the popup [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should work after repeated navigations in the same page [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should work for main frame navigation request [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work for subframe navigation request [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work for a redirect [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should not work for a redirect and interception [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should return headers [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should get the same headers as the server [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should return postData [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data and interception [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should override post data content type [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should parse the json post data [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should return multipart/form-data [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should return event source [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should return navigation bit [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should report raw headers [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should report raw response headers in redirects [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should report all cookies in one header [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [pass] +bidi-chromium-page › page/page-network-request.spec.ts › page.reload return 304 status code [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] +bidi-chromium-page › page/page-network-response.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return multiple header value [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return text [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return uncompressed text [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] +bidi-chromium-page › page/page-network-response.spec.ts › should wait until response completes [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if page closes [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if context closes [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return json [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return body [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return body with compression [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return status text [pass] +bidi-chromium-page › page/page-network-response.spec.ts › should report all headers [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should provide a Response with a file URL [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return headers after route.fulfill [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return body for prefetch script [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize and headersSize [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should handle redirects [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should throw for failed requests [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 200 status code [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 401 status code [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 404 status code [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 500 status code [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should return sizes without hanging [pass] +bidi-chromium-page › page/page-object-count.spec.ts › should count objects [unknown] +bidi-chromium-page › page/page-request-continue.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should amend HTTP headers [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should delete header with undefined value [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should amend method [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should override request url [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing while page is closing [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should override method along with url [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should amend method on main request [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend method and post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend utf8 post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend longer post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend binary post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should use content-type from original request [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should delete the origin header [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should continue preload link requests [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should intercept css variable with background url [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back async [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain fulfill [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain abort [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back after exception [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should chain once [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should amend HTTP headers [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should delete header with undefined value [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should amend method [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should override request url [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend post data [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend json post data [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with buffer as body [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with status code 422 [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with file path [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should include the origin header [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fetch original request and fulfill [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with har response [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill preload link requests [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill json [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill with any response [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should give access to the intercepted response body [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [unknown] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with url override [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with post data override [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] +bidi-chromium-page › page/page-route.spec.ts › should intercept @smoke [fail] +bidi-chromium-page › page/page-route.spec.ts › should unroute [fail] +bidi-chromium-page › page/page-route.spec.ts › should support ? in glob pattern [fail] +bidi-chromium-page › page/page-route.spec.ts › should work when POST is redirected with 302 [fail] +bidi-chromium-page › page/page-route.spec.ts › should work when header manipulation headers with redirect [fail] +bidi-chromium-page › page/page-route.spec.ts › should be able to remove headers [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain referer header [fail] +bidi-chromium-page › page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] +bidi-chromium-page › page/page-route.spec.ts › should override cookie header [pass] +bidi-chromium-page › page/page-route.spec.ts › should show custom HTTP headers [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with redirect inside sync XHR [fail] +bidi-chromium-page › page/page-route.spec.ts › should pause intercepted XHR until continue [fail] +bidi-chromium-page › page/page-route.spec.ts › should pause intercepted fetch request until continue [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with custom referer headers [fail] +bidi-chromium-page › page/page-route.spec.ts › should be abortable [fail] +bidi-chromium-page › page/page-route.spec.ts › should be abortable with custom error codes [fail] +bidi-chromium-page › page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-route.spec.ts › should send referer [fail] +bidi-chromium-page › page/page-route.spec.ts › should fail navigation when aborting main resource [fail] +bidi-chromium-page › page/page-route.spec.ts › should not work with redirects [fail] +bidi-chromium-page › page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with redirects for subresources [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with equal requests [fail] +bidi-chromium-page › page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] +bidi-chromium-page › page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [fail] +bidi-chromium-page › page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with encoded server [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with badly encoded server [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with encoded server - 2 [fail] +bidi-chromium-page › page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] +bidi-chromium-page › page/page-route.spec.ts › should intercept main resource during cross-process navigation [fail] +bidi-chromium-page › page/page-route.spec.ts › should fulfill with redirect status [fail] +bidi-chromium-page › page/page-route.spec.ts › should not fulfill with redirect status [unknown] +bidi-chromium-page › page/page-route.spec.ts › should support cors with GET [fail] +bidi-chromium-page › page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] +bidi-chromium-page › page/page-route.spec.ts › should allow null origin for about:blank [fail] +bidi-chromium-page › page/page-route.spec.ts › should respect cors overrides [fail] +bidi-chromium-page › page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] +bidi-chromium-page › page/page-route.spec.ts › should support cors with POST [fail] +bidi-chromium-page › page/page-route.spec.ts › should support cors with credentials [fail] +bidi-chromium-page › page/page-route.spec.ts › should reject cors with disallowed credentials [fail] +bidi-chromium-page › page/page-route.spec.ts › should support cors for different methods [fail] +bidi-chromium-page › page/page-route.spec.ts › should support the times parameter with route matching [fail] +bidi-chromium-page › page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] +bidi-chromium-page › page/page-route.spec.ts › should support async handler w/ times [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain raw request header [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain raw response header [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain raw response header after fulfill [fail] +bidi-chromium-page › page/page-route.spec.ts › route.fulfill should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › route.continue should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › route.fallback should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › route.abort should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should work [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › should throw if screenshot size is too large [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot should capture css transform [unknown] +bidi-chromium-page › page/page-screenshot.spec.ts › should capture css box-shadow [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select single option @smoke [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select single option by value [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should fall back to selecting by label [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select single option by label [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select single option by handle [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select single option by index [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select single option by multiple attributes [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should not select single option when some attributes do not match [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select only first option [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should not throw when select causes navigation [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select multiple options [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should select multiple options with attributes [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should respect event bubbling [unknown] +bidi-chromium-page › page/page-select-option.spec.ts › should throw when element is not a option/optgroup correctly [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › isEditable should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › isChecked should work [pass] -bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › isVisible and isHidden should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › isVisible should not throw when the DOM element is not connected [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › should have a nice preview [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › should have a nice preview for non-ascii attributes/children [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › textContent should work [pass] +bidi-chromium-page › page/elementhandle-convenience.spec.ts › textContent should work on ShadowRoot [fail] +bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should not throw in case of missing selector for all [pass] bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree [pass] +bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree for all [pass] bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should throw in case of missing selector [pass] +bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should work [pass] bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should work for all [pass] -bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree for all [pass] -bidi-chromium-page › page/elementhandle-eval-on-selector.spec.ts › should not throw in case of missing selector for all [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should hover [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should hover when Node is removed [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should fill input [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should fill input when Node is removed [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should allow disposing twice [pass] bidi-chromium-page › page/elementhandle-misc.spec.ts › should check the box [pass] bidi-chromium-page › page/elementhandle-misc.spec.ts › should check the box using setChecked [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should uncheck the box [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should select single option [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should fill input [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should fill input when Node is removed [pass] bidi-chromium-page › page/elementhandle-misc.spec.ts › should focus a button [pass] -bidi-chromium-page › page/elementhandle-misc.spec.ts › should allow disposing twice [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should hover [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should hover when Node is removed [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should select single option [pass] +bidi-chromium-page › page/elementhandle-misc.spec.ts › should uncheck the box [pass] bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work [fail] +bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for adopted elements [fail] +bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for cross-frame evaluations [fail] bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for cross-process iframes [fail] +bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for detached elements [fail] bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for document [fail] bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for iframe elements [fail] -bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for cross-frame evaluations [fail] -bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for detached elements [fail] -bidi-chromium-page › page/elementhandle-owner-frame.spec.ts › should work for adopted elements [fail] -bidi-chromium-page › page/elementhandle-press.spec.ts › should work [pass] +bidi-chromium-page › page/elementhandle-press.spec.ts › should not modify selection when focused [pass] bidi-chromium-page › page/elementhandle-press.spec.ts › should not select existing value [pass] bidi-chromium-page › page/elementhandle-press.spec.ts › should reset selection when not focused [pass] -bidi-chromium-page › page/elementhandle-press.spec.ts › should not modify selection when focused [pass] +bidi-chromium-page › page/elementhandle-press.spec.ts › should work [pass] bidi-chromium-page › page/elementhandle-press.spec.ts › should work with number input [pass] bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should query existing element [pass] -bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should return null for non-existing element [pass] -bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should work for adopted elements [fail] bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should query existing elements [fail] bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [fail] +bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should return null for non-existing element [pass] +bidi-chromium-page › page/elementhandle-query-selector.spec.ts › should work for adopted elements [fail] bidi-chromium-page › page/elementhandle-query-selector.spec.ts › xpath should query existing element [fail] bidi-chromium-page › page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work when main world busts JSON.stringify [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should take into account padding and border [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport in parallel [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [fail] bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should scroll element into view [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should scroll 15000px into view [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work with a rotated element [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport in parallel [fail] bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should fail to screenshot a detached element [pass] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should not issue resize event [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should prefer type over extension [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should scroll 15000px into view [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should scroll element into view [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should take into account padding and border [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should take screenshot of disabled button [fail] bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should timeout waiting for visible [pass] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should wait for element to stop moving [fail] bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should wait for visible [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with fractional dimensions [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work [fail] bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with an offset [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should wait for element to stop moving [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should take screenshot of disabled button [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should prefer type over extension [fail] -bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should not issue resize event [fail] -bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with fractional dimensions [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work when main world busts JSON.stringify [fail] +bidi-chromium-page › page/elementhandle-screenshot.spec.ts › element screenshot › should work with a rotated element [fail] +bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should scroll display:contents into view [fail] bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should throw for detached element [fail] +bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should timeout waiting for visible [fail] bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should wait for display:none to become visible [fail] -bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should scroll display:contents into view [fail] +bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should wait for element to stop moving [pass] +bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should wait for nested display:none to become visible [fail] +bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should work @smoke [pass] bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should work for visibility:hidden element [pass] bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should work for zero-sized element [pass] -bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should wait for nested display:none to become visible [fail] -bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should wait for element to stop moving [pass] -bidi-chromium-page › page/elementhandle-scroll-into-view.spec.ts › should timeout waiting for visible [fail] -bidi-chromium-page › page/elementhandle-select-text.spec.ts › should select textarea [pass] bidi-chromium-page › page/elementhandle-select-text.spec.ts › should select input [pass] bidi-chromium-page › page/elementhandle-select-text.spec.ts › should select plain div [pass] +bidi-chromium-page › page/elementhandle-select-text.spec.ts › should select textarea [pass] bidi-chromium-page › page/elementhandle-select-text.spec.ts › should timeout waiting for invisible element [pass] bidi-chromium-page › page/elementhandle-select-text.spec.ts › should wait for visible [pass] -bidi-chromium-page › page/elementhandle-type.spec.ts › should work [pass] +bidi-chromium-page › page/elementhandle-type.spec.ts › should not modify selection when focused [pass] bidi-chromium-page › page/elementhandle-type.spec.ts › should not select existing value [pass] bidi-chromium-page › page/elementhandle-type.spec.ts › should reset selection when not focused [pass] -bidi-chromium-page › page/elementhandle-type.spec.ts › should not modify selection when focused [pass] +bidi-chromium-page › page/elementhandle-type.spec.ts › should work [pass] bidi-chromium-page › page/elementhandle-type.spec.ts › should work with number input [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for visible [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for already visible [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should timeout waiting for visible [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for enabled when detached [pass] bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for visible when detached [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should timeout waiting for visible [pass] bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for already hidden [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden when detached [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for enabled when detached [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for already visible [pass] bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for aria enabled button [pass] bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for button with an aria-disabled parent [pass] -bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for stable position [pass] bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for editable input [pass] -bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with css selector [pass] -bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with text selector [pass] -bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with xpath selector [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden when detached [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for stable position [pass] +bidi-chromium-page › page/elementhandle-wait-for-element-state.spec.ts › should wait for visible [pass] bidi-chromium-page › page/eval-on-selector-all.spec.ts › should auto-detect css selector [pass] -bidi-chromium-page › page/eval-on-selector-all.spec.ts › should support >> syntax [pass] +bidi-chromium-page › page/eval-on-selector-all.spec.ts › should return complex values [pass] bidi-chromium-page › page/eval-on-selector-all.spec.ts › should support * capture [pass] bidi-chromium-page › page/eval-on-selector-all.spec.ts › should support * capture when multiple paths match [pass] -bidi-chromium-page › page/eval-on-selector-all.spec.ts › should return complex values [pass] +bidi-chromium-page › page/eval-on-selector-all.spec.ts › should support >> syntax [pass] bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with bogus Array.from [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with css selector [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with id selector [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with data-test selector [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with data-testid selector [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with data-test-id selector [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with text selector in quotes [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with xpath selector [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with text selector [pass] +bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with css selector [pass] +bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with text selector [pass] +bidi-chromium-page › page/eval-on-selector-all.spec.ts › should work with xpath selector [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should accept ElementHandles as arguments [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should accept arguments [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should auto-detect css selector [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should auto-detect css selector with attributes [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should auto-detect nested selectors [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should accept arguments [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should accept ElementHandles as arguments [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should throw error if no element is found [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should not stop at first failure with >> syntax [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should return complex values [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should support * capture [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should support >> syntax [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should support >> syntax with different engines [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should support spaces with >> syntax [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should not stop at first failure with >> syntax [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should support * capture [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should throw on multiple * captures [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should throw error if no element is found [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should throw on malformed * capture [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with spaces in css attributes [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should throw on multiple * captures [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with css selector [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with data-test selector [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with data-test-id selector [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with data-testid selector [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with id selector [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should work with quotes in css attributes [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should work with spaces in css attributes when missing [pass] bidi-chromium-page › page/eval-on-selector.spec.ts › should work with quotes in css attributes when missing [pass] -bidi-chromium-page › page/eval-on-selector.spec.ts › should return complex values [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with spaces in css attributes [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with spaces in css attributes when missing [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with text selector [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with text selector in quotes [pass] +bidi-chromium-page › page/eval-on-selector.spec.ts › should work with xpath selector [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › not.toBeDisabled div [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › not.toBeEmpty [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › not.toBeOK [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › should print selector syntax error [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › should print unknown engine error [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › default [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › eventually [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › eventually with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › fail [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › fail with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › over navigation [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with attached:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with attached:true [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with frameLocator [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with hidden element [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with impossible timeout [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with impossible timeout .not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with not and attached:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked with value [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › default [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with checked:true [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with checked:false [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › fail [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with not and checked:false [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › fail with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › fail with checked:false [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › fail missing [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with role [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › fail with checked:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › fail with not [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › friendly log [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with checked:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with checked:true [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with impossible timeout [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with impossible timeout .not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with not and checked:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked › with role [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeDisabled with value [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › default [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › with editable:true [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › with editable:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › with editable:true [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › with not [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEditable › with not and editable:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEmpty div [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEmpty input [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › default [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › with enabled:true [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › with enabled:false [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › failed [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › eventually [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › eventually with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › with not and enabled:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › failed [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › toBeDisabled [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEmpty input [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › not.toBeEmpty [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeEmpty div [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeDisabled with value [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeChecked with value [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › with enabled:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › with enabled:true [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeEnabled › with not and enabled:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeFocused [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeFocused with shadow elements [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden with value [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › not.toBeDisabled div [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › default [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with visible:true [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with visible:false [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with not and visible:false [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › eventually [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › eventually with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › fail [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › fail with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with impossible timeout [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with impossible timeout .not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with frameLocator [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with frameLocator 2 [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › over navigation [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › default [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › when nothing matches [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › eventually with not [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › eventually [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › eventually with not [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › fail [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › fail with not [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › fail with not when nothing matching [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › with impossible timeout .not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › when nothing matches [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › with impossible timeout [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeFocused [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeFocused with shadow elements [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › should print unknown engine error [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › should print selector syntax error [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › with impossible timeout .not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeHidden › with not [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › not.toBeOK [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK fail with invalid argument [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK fail with promise [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › text content type [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › no content type [pass] bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › image content type [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › default [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with hidden element [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with attached:true [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with attached:false [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with not and attached:false [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › eventually [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › eventually with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › fail [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › fail with not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with impossible timeout [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with impossible timeout .not [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › with frameLocator [pass] -bidi-chromium-page › page/expect-boolean.spec.ts › toBeAttached › over navigation [pass] -bidi-chromium-page › page/expect-matcher-result.spec.ts › toMatchText-based assertions should have matcher result [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › no content type [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › text content type [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › default [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › eventually [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › eventually with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › fail [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › fail with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › over navigation [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with frameLocator [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with frameLocator 2 [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with impossible timeout [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with impossible timeout .not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with not [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with not and visible:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with visible:false [pass] +bidi-chromium-page › page/expect-boolean.spec.ts › toBeVisible › with visible:true [pass] +bidi-chromium-page › page/expect-matcher-result.spec.ts › toBeChecked({ checked: false }) should have expected: false [pass] bidi-chromium-page › page/expect-matcher-result.spec.ts › toBeTruthy-based assertions should have matcher result [pass] bidi-chromium-page › page/expect-matcher-result.spec.ts › toEqual-based assertions should have matcher result [pass] -bidi-chromium-page › page/expect-matcher-result.spec.ts › toBeChecked({ checked: false }) should have expected: false [pass] bidi-chromium-page › page/expect-matcher-result.spec.ts › toHaveScreenshot should populate matcherResult [fail] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › toHaveCount pass [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › pass zero [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › eventually pass zero [pass] +bidi-chromium-page › page/expect-matcher-result.spec.ts › toMatchText-based assertions should have matcher result [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should have good stack [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should report intersection even if fully covered by other element [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should respect ratio option [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should work [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAccessibleDescription [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAccessibleName [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should match attribute without value [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should match boolean attribute [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should not match missing attribute [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should support boolean attribute with options [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › support ignoreCase [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveCSS › custom css properties [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveCSS › pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › fail [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › fail with array [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › pass with SVGs [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › pass with array [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount should not produce logs twice [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › eventually pass non-zero [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › eventually pass not non-zero [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › eventually pass zero [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › fail zero [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › fail zero 2 [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › pass zero [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount › toHaveCount pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveId › pass [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass string [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail string [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass number [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail boolean [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail boolean 2 [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail nested [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail number [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail string [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass boolean [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail boolean [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass boolean 2 [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail boolean 2 [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass undefined [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass null [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass nested [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › fail nested [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › pass [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › pass with SVGs [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › fail [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › pass with array [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveClass › fail with array [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveTitle › pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass null [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass number [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass string [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveJSProperty › pass undefined [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveRole [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveText should not produce logs twice [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveText that does not match should not produce logs twice [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveTitle › fail [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveURL › pass [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveTitle › pass [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveURL › fail [pass] +bidi-chromium-page › page/expect-misc.spec.ts › toHaveURL › pass [pass] bidi-chromium-page › page/expect-misc.spec.ts › toHaveURL › support ignoreCase [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › pass [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should not match missing attribute [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should match boolean attribute [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should match attribute without value [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › should support boolean attribute with options [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAttribute › support ignoreCase [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveCSS › pass [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveCSS › custom css properties [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveId › pass [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should work [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should respect ratio option [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should have good stack [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toBeInViewport › should report intersection even if fully covered by other element [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveCount should not produce logs twice [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveText should not produce logs twice [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveText that does not match should not produce logs twice [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAccessibleName [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveAccessibleDescription [pass] -bidi-chromium-page › page/expect-misc.spec.ts › toHaveRole [pass] +bidi-chromium-page › page/expect-timeout.spec.ts › should have timeout error name [pass] +bidi-chromium-page › page/expect-timeout.spec.ts › should not print timed out error message when page closes [timeout] +bidi-chromium-page › page/expect-timeout.spec.ts › should not throw when navigating during first locator handler check [pass] +bidi-chromium-page › page/expect-timeout.spec.ts › should not throw when navigating during one-shot check [pass] bidi-chromium-page › page/expect-timeout.spec.ts › should print timed out error message [pass] bidi-chromium-page › page/expect-timeout.spec.ts › should print timed out error message when value does not match [pass] -bidi-chromium-page › page/expect-timeout.spec.ts › should print timed out error message with impossible timeout [pass] bidi-chromium-page › page/expect-timeout.spec.ts › should print timed out error message when value does not match with impossible timeout [pass] -bidi-chromium-page › page/expect-timeout.spec.ts › should not print timed out error message when page closes [timeout] -bidi-chromium-page › page/expect-timeout.spec.ts › should have timeout error name [pass] -bidi-chromium-page › page/expect-timeout.spec.ts › should not throw when navigating during one-shot check [pass] -bidi-chromium-page › page/expect-timeout.spec.ts › should not throw when navigating during first locator handler check [pass] +bidi-chromium-page › page/expect-timeout.spec.ts › should print timed out error message with impossible timeout [pass] bidi-chromium-page › page/expect-timeout.spec.ts › should timeout during first locator handler check [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with regex › pass [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with regex › fail [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with regex › pass [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with regex › fail [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › pass [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › pass contain [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › fail [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › pass eventually [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › with userInnerText [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › in shadow dom [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › fail with impossible timeout [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › not.toHaveText › pass [pass] bidi-chromium-page › page/expect-to-have-text.spec.ts › not.toHaveText › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › not.toHaveText › pass [pass] bidi-chromium-page › page/expect-to-have-text.spec.ts › not.toHaveText › should work when selector does not match [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with array › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with array › pass [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with regex › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with regex › pass [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › fail on not+empty [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › fail on repeating array matchers [pass] bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass lazy [pass] bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass empty [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass eventually empty [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass lazy [pass] bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass not empty [pass] bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass on empty [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › fail on not+empty [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › pass eventually empty [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › fail [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with array › fail on repeating array matchers [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with array › pass [pass] -bidi-chromium-page › page/expect-to-have-text.spec.ts › toContainText with array › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with regex › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with regex › pass [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › fail [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › fail with impossible timeout [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › in shadow dom [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › pass [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › pass contain [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › pass eventually [pass] +bidi-chromium-page › page/expect-to-have-text.spec.ts › toHaveText with text › with userInnerText [pass] +bidi-chromium-page › page/expect-to-have-value.spec.ts › should support failure [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › should work [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › should work with label [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › should work with regex [pass] -bidi-chromium-page › page/expect-to-have-value.spec.ts › should support failure [pass] -bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with text [pass] -bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › follows labels [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › exact match with text failure [pass] -bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with regex [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when items not selected [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when multiple not specified [pass] bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when not a select element [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › should have different execution contexts [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › should have correct execution contexts @smoke [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › should dispose context on navigation [fail] +bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › follows labels [pass] +bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with regex [pass] +bidi-chromium-page › page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with text [pass] +bidi-chromium-page › page/frame-evaluate.spec.ts › evaluateHandle should work [pass] +bidi-chromium-page › page/frame-evaluate.spec.ts › should allow cross-frame element handles [fail] +bidi-chromium-page › page/frame-evaluate.spec.ts › should be isolated between frames [pass] bidi-chromium-page › page/frame-evaluate.spec.ts › should dispose context on cross-origin navigation [fail] +bidi-chromium-page › page/frame-evaluate.spec.ts › should dispose context on navigation [fail] bidi-chromium-page › page/frame-evaluate.spec.ts › should execute after cross-site navigation [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › should not allow cross-frame js handles [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › should allow cross-frame element handles [fail] +bidi-chromium-page › page/frame-evaluate.spec.ts › should have correct execution contexts @smoke [pass] +bidi-chromium-page › page/frame-evaluate.spec.ts › should have different execution contexts [pass] bidi-chromium-page › page/frame-evaluate.spec.ts › should not allow cross-frame element handles when frames do not script each other [fail] +bidi-chromium-page › page/frame-evaluate.spec.ts › should not allow cross-frame js handles [pass] bidi-chromium-page › page/frame-evaluate.spec.ts › should throw for detached frames [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › should be isolated between frames [pass] bidi-chromium-page › page/frame-evaluate.spec.ts › should work in iframes that failed initial navigation [fail] bidi-chromium-page › page/frame-evaluate.spec.ts › should work in iframes that interrupted initial javascript url navigation [pass] -bidi-chromium-page › page/frame-evaluate.spec.ts › evaluateHandle should work [pass] -bidi-chromium-page › page/frame-frame-element.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/frame-frame-element.spec.ts › should work with contentFrame [pass] -bidi-chromium-page › page/frame-frame-element.spec.ts › should work with frameset [pass] bidi-chromium-page › page/frame-frame-element.spec.ts › should throw when detached [pass] +bidi-chromium-page › page/frame-frame-element.spec.ts › should work @smoke [pass] bidi-chromium-page › page/frame-frame-element.spec.ts › should work inside closed shadow root [fail] bidi-chromium-page › page/frame-frame-element.spec.ts › should work inside declarative shadow root [fail] +bidi-chromium-page › page/frame-frame-element.spec.ts › should work with contentFrame [pass] +bidi-chromium-page › page/frame-frame-element.spec.ts › should work with frameset [pass] +bidi-chromium-page › page/frame-goto.spec.ts › should continue after client redirect [pass] bidi-chromium-page › page/frame-goto.spec.ts › should navigate subframes @smoke [pass] bidi-chromium-page › page/frame-goto.spec.ts › should reject when frame detaches [pass] -bidi-chromium-page › page/frame-goto.spec.ts › should continue after client redirect [pass] bidi-chromium-page › page/frame-goto.spec.ts › should return matching responses [fail] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should detach child frames on navigation [pass] bidi-chromium-page › page/frame-hierarchy.spec.ts › should handle nested frames @smoke [fail] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should send events when frames are manipulated dynamically [pass] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should send "framenavigated" when navigating on anchor URLs [timeout] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should persist mainFrame on cross-process navigation [pass] bidi-chromium-page › page/frame-hierarchy.spec.ts › should not send attach/detach events for main frame [pass] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should detach child frames on navigation [pass] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should support framesets [fail] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should persist mainFrame on cross-process navigation [pass] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should refuse to display x-frame-options:deny iframe [timeout] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should report different frame instance when frame re-attaches [pass] bidi-chromium-page › page/frame-hierarchy.spec.ts › should report frame from-inside shadow DOM [pass] bidi-chromium-page › page/frame-hierarchy.spec.ts › should report frame.name() [fail] bidi-chromium-page › page/frame-hierarchy.spec.ts › should report frame.parent() [pass] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should report different frame instance when frame re-attaches [pass] -bidi-chromium-page › page/frame-hierarchy.spec.ts › should refuse to display x-frame-options:deny iframe [timeout] bidi-chromium-page › page/frame-hierarchy.spec.ts › should return frame.page() [pass] -bidi-chromium-page › page/interception.spec.ts › should work with navigation @smoke [fail] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should send "framenavigated" when navigating on anchor URLs [timeout] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should send events when frames are manipulated dynamically [pass] +bidi-chromium-page › page/frame-hierarchy.spec.ts › should support framesets [fail] +bidi-chromium-page › page/interception.spec.ts › should disable memory cache when intercepting [fail] bidi-chromium-page › page/interception.spec.ts › should intercept after a service worker [fail] -bidi-chromium-page › page/interception.spec.ts › should work with glob [pass] +bidi-chromium-page › page/interception.spec.ts › should intercept blob url requests [unknown] bidi-chromium-page › page/interception.spec.ts › should intercept network activity from worker [fail] -bidi-chromium-page › page/interception.spec.ts › should intercept worker requests when enabled after worker creation [fail] bidi-chromium-page › page/interception.spec.ts › should intercept network activity from worker 2 [fail] -bidi-chromium-page › page/interception.spec.ts › should work with regular expression passed from a different context [fail] +bidi-chromium-page › page/interception.spec.ts › should intercept worker requests when enabled after worker creation [fail] bidi-chromium-page › page/interception.spec.ts › should not break remote worker importScripts [fail] -bidi-chromium-page › page/interception.spec.ts › should disable memory cache when intercepting [fail] -bidi-chromium-page › page/interception.spec.ts › should intercept blob url requests [unknown] -bidi-chromium-page › page/jshandle-as-element.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/jshandle-as-element.spec.ts › should return null for non-elements [pass] +bidi-chromium-page › page/interception.spec.ts › should work with glob [pass] +bidi-chromium-page › page/interception.spec.ts › should work with navigation @smoke [fail] +bidi-chromium-page › page/interception.spec.ts › should work with regular expression passed from a different context [fail] bidi-chromium-page › page/jshandle-as-element.spec.ts › should return ElementHandle for TextNodes [pass] +bidi-chromium-page › page/jshandle-as-element.spec.ts › should return null for non-elements [pass] +bidi-chromium-page › page/jshandle-as-element.spec.ts › should work @smoke [pass] bidi-chromium-page › page/jshandle-as-element.spec.ts › should work with nullified Node [pass] -bidi-chromium-page › page/jshandle-evaluate.spec.ts › should work with function @smoke [pass] bidi-chromium-page › page/jshandle-evaluate.spec.ts › should work with expression [pass] +bidi-chromium-page › page/jshandle-evaluate.spec.ts › should work with function @smoke [pass] +bidi-chromium-page › page/jshandle-json-value.spec.ts › should handle circular objects [pass] bidi-chromium-page › page/jshandle-json-value.spec.ts › should work @smoke [pass] bidi-chromium-page › page/jshandle-json-value.spec.ts › should work with dates [pass] -bidi-chromium-page › page/jshandle-json-value.spec.ts › should handle circular objects [pass] -bidi-chromium-page › page/jshandle-properties.spec.ts › should work @smoke [fail] -bidi-chromium-page › page/jshandle-properties.spec.ts › should work with undefined, null, and empty [fail] -bidi-chromium-page › page/jshandle-properties.spec.ts › should work with unserializable values [fail] -bidi-chromium-page › page/jshandle-properties.spec.ts › getProperties should work [fail] bidi-chromium-page › page/jshandle-properties.spec.ts › getProperties should return empty map for non-objects [pass] bidi-chromium-page › page/jshandle-properties.spec.ts › getProperties should return even non-own properties [fail] +bidi-chromium-page › page/jshandle-properties.spec.ts › getProperties should work [fail] bidi-chromium-page › page/jshandle-properties.spec.ts › getProperties should work with elements [fail] -bidi-chromium-page › page/jshandle-to-string.spec.ts › should work for primitives [pass] -bidi-chromium-page › page/jshandle-to-string.spec.ts › should work for complicated objects [fail] +bidi-chromium-page › page/jshandle-properties.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/jshandle-properties.spec.ts › should work with undefined, null, and empty [fail] +bidi-chromium-page › page/jshandle-properties.spec.ts › should work with unserializable values [fail] bidi-chromium-page › page/jshandle-to-string.spec.ts › should beautifully render sparse arrays [fail] +bidi-chromium-page › page/jshandle-to-string.spec.ts › should work for complicated objects [fail] +bidi-chromium-page › page/jshandle-to-string.spec.ts › should work for primitives [pass] bidi-chromium-page › page/jshandle-to-string.spec.ts › should work for promises [fail] bidi-chromium-page › page/jshandle-to-string.spec.ts › should work with different subtypes @smoke [fail] bidi-chromium-page › page/jshandle-to-string.spec.ts › should work with previewable subtypes [fail] +bidi-chromium-page › page/locator-click.spec.ts › should click if the target element is removed in pointerdown event [pass] +bidi-chromium-page › page/locator-click.spec.ts › should click if the target element is removed in pointerup event [pass] +bidi-chromium-page › page/locator-click.spec.ts › should double click the button [pass] bidi-chromium-page › page/locator-click.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/locator-click.spec.ts › should work with Node removed [pass] bidi-chromium-page › page/locator-click.spec.ts › should work for TextNodes [fail] -bidi-chromium-page › page/locator-click.spec.ts › should double click the button [pass] -bidi-chromium-page › page/locator-click.spec.ts › should click if the target element is removed in pointerup event [pass] -bidi-chromium-page › page/locator-click.spec.ts › should click if the target element is removed in pointerdown event [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › should have a nice preview [pass] +bidi-chromium-page › page/locator-click.spec.ts › should work with Node removed [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › allInnerTexts should work [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › allTextContents should work [pass] bidi-chromium-page › page/locator-convenience.spec.ts › getAttribute should work [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › inputValue should work [pass] bidi-chromium-page › page/locator-convenience.spec.ts › innerHTML should work [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › innerText should work [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › innerText should throw [pass] bidi-chromium-page › page/locator-convenience.spec.ts › innerText should produce log [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › textContent should work [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › isEnabled and isDisabled should work [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › isEditable should work [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › innerText should throw [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › innerText should work [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › inputValue should work [pass] bidi-chromium-page › page/locator-convenience.spec.ts › isChecked should work [pass] bidi-chromium-page › page/locator-convenience.spec.ts › isChecked should work for indeterminate input [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › allTextContents should work [pass] -bidi-chromium-page › page/locator-convenience.spec.ts › allInnerTexts should work [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › isEditable should work [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › isEnabled and isDisabled should work [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › should have a nice preview [pass] bidi-chromium-page › page/locator-convenience.spec.ts › should return page [pass] +bidi-chromium-page › page/locator-convenience.spec.ts › textContent should work [pass] bidi-chromium-page › page/locator-element-handle.spec.ts › should query existing element @smoke [pass] bidi-chromium-page › page/locator-element-handle.spec.ts › should query existing elements [fail] bidi-chromium-page › page/locator-element-handle.spec.ts › should return empty array for non-existing elements [fail] bidi-chromium-page › page/locator-element-handle.spec.ts › xpath should query existing element [pass] bidi-chromium-page › page/locator-element-handle.spec.ts › xpath should return null for non-existing element [fail] -bidi-chromium-page › page/locator-evaluate.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/locator-evaluate.spec.ts › should not throw in case of missing selector for all [pass] bidi-chromium-page › page/locator-evaluate.spec.ts › should retrieve content from subtree [pass] -bidi-chromium-page › page/locator-evaluate.spec.ts › should work for all [pass] bidi-chromium-page › page/locator-evaluate.spec.ts › should retrieve content from subtree for all [pass] -bidi-chromium-page › page/locator-evaluate.spec.ts › should not throw in case of missing selector for all [pass] -bidi-chromium-page › page/locator-frame.spec.ts › should work for iframe @smoke [fail] -bidi-chromium-page › page/locator-frame.spec.ts › should work for nested iframe [fail] -bidi-chromium-page › page/locator-frame.spec.ts › should work for $ and $$ [fail] -bidi-chromium-page › page/locator-frame.spec.ts › should wait for frame [pass] -bidi-chromium-page › page/locator-frame.spec.ts › should wait for frame 2 [fail] -bidi-chromium-page › page/locator-frame.spec.ts › should wait for frame to go [fail] -bidi-chromium-page › page/locator-frame.spec.ts › should not wait for frame [pass] -bidi-chromium-page › page/locator-frame.spec.ts › should not wait for frame 2 [pass] -bidi-chromium-page › page/locator-frame.spec.ts › should not wait for frame 3 [pass] -bidi-chromium-page › page/locator-frame.spec.ts › should click in lazy iframe [fail] -bidi-chromium-page › page/locator-frame.spec.ts › waitFor should survive frame reattach [fail] +bidi-chromium-page › page/locator-evaluate.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/locator-evaluate.spec.ts › should work for all [pass] bidi-chromium-page › page/locator-frame.spec.ts › click should survive frame reattach [fail] bidi-chromium-page › page/locator-frame.spec.ts › click should survive iframe navigation [fail] -bidi-chromium-page › page/locator-frame.spec.ts › should non work for non-frame [fail] -bidi-chromium-page › page/locator-frame.spec.ts › locator.frameLocator should work for iframe [fail] -bidi-chromium-page › page/locator-frame.spec.ts › locator.frameLocator should throw on ambiguity [fail] -bidi-chromium-page › page/locator-frame.spec.ts › locator.frameLocator should not throw on first/last/nth [fail] +bidi-chromium-page › page/locator-frame.spec.ts › frameLocator.owner should work [fail] bidi-chromium-page › page/locator-frame.spec.ts › getBy coverage [fail] -bidi-chromium-page › page/locator-frame.spec.ts › wait for hidden should succeed when frame is not in dom [pass] -bidi-chromium-page › page/locator-frame.spec.ts › should work with COEP/COOP/CORP isolated iframe [fail] bidi-chromium-page › page/locator-frame.spec.ts › locator.contentFrame should work [fail] -bidi-chromium-page › page/locator-frame.spec.ts › frameLocator.owner should work [fail] +bidi-chromium-page › page/locator-frame.spec.ts › locator.frameLocator should not throw on first/last/nth [fail] +bidi-chromium-page › page/locator-frame.spec.ts › locator.frameLocator should throw on ambiguity [fail] +bidi-chromium-page › page/locator-frame.spec.ts › locator.frameLocator should work for iframe [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should click in lazy iframe [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should non work for non-frame [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should not wait for frame [pass] +bidi-chromium-page › page/locator-frame.spec.ts › should not wait for frame 2 [pass] +bidi-chromium-page › page/locator-frame.spec.ts › should not wait for frame 3 [pass] +bidi-chromium-page › page/locator-frame.spec.ts › should wait for frame [pass] +bidi-chromium-page › page/locator-frame.spec.ts › should wait for frame 2 [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should wait for frame to go [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should work for $ and $$ [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should work for iframe @smoke [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should work for nested iframe [fail] +bidi-chromium-page › page/locator-frame.spec.ts › should work with COEP/COOP/CORP isolated iframe [fail] +bidi-chromium-page › page/locator-frame.spec.ts › wait for hidden should succeed when frame is not in dom [pass] +bidi-chromium-page › page/locator-frame.spec.ts › waitFor should survive frame reattach [fail] bidi-chromium-page › page/locator-highlight.spec.ts › should highlight locator [pass] bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible and isHidden should work [pass] -bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible should be true for opacity:0 [pass] -bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible should be true for element outside view [pass] bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible and isHidden should work with details [pass] +bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible during navigation should not throw [timeout] bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible inside a button [pass] bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible inside a role=button [pass] -bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible during navigation should not throw [timeout] +bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible should be true for element outside view [pass] +bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible should be true for opacity:0 [pass] bidi-chromium-page › page/locator-is-visible.spec.ts › isVisible with invalid selector should throw [pass] bidi-chromium-page › page/locator-list.spec.ts › locator.all should work [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should hover @smoke [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should hover when Node is removed [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should fill input [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should fill input when Node is removed [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should clear input [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › focus should respect strictness [pass] bidi-chromium-page › page/locator-misc-1.spec.ts › should check the box [pass] bidi-chromium-page › page/locator-misc-1.spec.ts › should check the box using setChecked [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should uncheck the box [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should select single option [pass] -bidi-chromium-page › page/locator-misc-1.spec.ts › should focus and blur a button [fail] -bidi-chromium-page › page/locator-misc-1.spec.ts › focus should respect strictness [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should clear input [pass] bidi-chromium-page › page/locator-misc-1.spec.ts › should dispatch click event via ElementHandles [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should fill input [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should fill input when Node is removed [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should focus and blur a button [fail] +bidi-chromium-page › page/locator-misc-1.spec.ts › should hover @smoke [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should hover when Node is removed [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should select single option [pass] +bidi-chromium-page › page/locator-misc-1.spec.ts › should uncheck the box [pass] bidi-chromium-page › page/locator-misc-1.spec.ts › should upload the file [timeout] +bidi-chromium-page › page/locator-misc-2.spec.ts › Locator.locator() and FrameLocator.locator() should accept locator [pass] +bidi-chromium-page › page/locator-misc-2.spec.ts › locator.count should work with deleted Map in main world [pass] +bidi-chromium-page › page/locator-misc-2.spec.ts › should combine visible with other selectors [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should press @smoke [pass] +bidi-chromium-page › page/locator-misc-2.spec.ts › should pressSequentially [pass] +bidi-chromium-page › page/locator-misc-2.spec.ts › should return bounding box [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should scroll into view [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should scroll zero-sized element into view [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should select textarea [pass] -bidi-chromium-page › page/locator-misc-2.spec.ts › should type [pass] -bidi-chromium-page › page/locator-misc-2.spec.ts › should pressSequentially [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should take screenshot [fail] -bidi-chromium-page › page/locator-misc-2.spec.ts › should return bounding box [pass] +bidi-chromium-page › page/locator-misc-2.spec.ts › should type [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should waitFor [pass] bidi-chromium-page › page/locator-misc-2.spec.ts › should waitFor hidden [pass] -bidi-chromium-page › page/locator-misc-2.spec.ts › should combine visible with other selectors [pass] -bidi-chromium-page › page/locator-misc-2.spec.ts › locator.count should work with deleted Map in main world [pass] -bidi-chromium-page › page/locator-misc-2.spec.ts › Locator.locator() and FrameLocator.locator() should accept locator [pass] -bidi-chromium-page › page/locator-query.spec.ts › should respect first() and last() @smoke [pass] -bidi-chromium-page › page/locator-query.spec.ts › should respect nth() [pass] -bidi-chromium-page › page/locator-query.spec.ts › should throw on capture w/ nth() [pass] -bidi-chromium-page › page/locator-query.spec.ts › should throw on due to strictness [pass] -bidi-chromium-page › page/locator-query.spec.ts › should throw on due to strictness 2 [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by text [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by text 2 [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by regex [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by text with quotes [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by regex with quotes [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by regex with a single quote [pass] -bidi-chromium-page › page/locator-query.spec.ts › should filter by regex and regexp flags [pass] +bidi-chromium-page › page/locator-query.spec.ts › alias methods coverage [pass] +bidi-chromium-page › page/locator-query.spec.ts › should allow some, but not all nested frameLocators [pass] +bidi-chromium-page › page/locator-query.spec.ts › should enforce same frame for has/leftOf/rightOf/above/below/near [pass] bidi-chromium-page › page/locator-query.spec.ts › should filter by case-insensitive regex in a child [pass] bidi-chromium-page › page/locator-query.spec.ts › should filter by case-insensitive regex in multiple children [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by regex [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by regex and regexp flags [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by regex with a single quote [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by regex with quotes [pass] bidi-chromium-page › page/locator-query.spec.ts › should filter by regex with special symbols [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by text [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by text 2 [pass] +bidi-chromium-page › page/locator-query.spec.ts › should filter by text with quotes [pass] +bidi-chromium-page › page/locator-query.spec.ts › should respect first() and last() @smoke [pass] +bidi-chromium-page › page/locator-query.spec.ts › should respect nth() [pass] bidi-chromium-page › page/locator-query.spec.ts › should support has:locator [pass] -bidi-chromium-page › page/locator-query.spec.ts › should support locator.filter [pass] bidi-chromium-page › page/locator-query.spec.ts › should support locator.and [pass] -bidi-chromium-page › page/locator-query.spec.ts › should support locator.or [pass] +bidi-chromium-page › page/locator-query.spec.ts › should support locator.filter [pass] bidi-chromium-page › page/locator-query.spec.ts › should support locator.locator with and/or [pass] -bidi-chromium-page › page/locator-query.spec.ts › should allow some, but not all nested frameLocators [pass] -bidi-chromium-page › page/locator-query.spec.ts › should enforce same frame for has/leftOf/rightOf/above/below/near [pass] -bidi-chromium-page › page/locator-query.spec.ts › alias methods coverage [pass] +bidi-chromium-page › page/locator-query.spec.ts › should support locator.or [pass] +bidi-chromium-page › page/locator-query.spec.ts › should throw on capture w/ nth() [pass] +bidi-chromium-page › page/locator-query.spec.ts › should throw on due to strictness [pass] +bidi-chromium-page › page/locator-query.spec.ts › should throw on due to strictness 2 [pass] bidi-chromium-page › page/matchers.misc.spec.ts › should outlive frame navigation [pass] bidi-chromium-page › page/matchers.misc.spec.ts › should print no-locator-resolved error when locator matcher did not resolve to any element [pass] +bidi-chromium-page › page/network-post-data.spec.ts › should get post data for file/blob [fail] +bidi-chromium-page › page/network-post-data.spec.ts › should get post data for navigator.sendBeacon api calls [fail] bidi-chromium-page › page/network-post-data.spec.ts › should return correct postData buffer for utf-8 body [fail] +bidi-chromium-page › page/network-post-data.spec.ts › should return post data for PUT requests [fail] bidi-chromium-page › page/network-post-data.spec.ts › should return post data w/o content-type @smoke [fail] bidi-chromium-page › page/network-post-data.spec.ts › should throw on invalid JSON in post data [fail] -bidi-chromium-page › page/network-post-data.spec.ts › should return post data for PUT requests [fail] -bidi-chromium-page › page/network-post-data.spec.ts › should get post data for file/blob [fail] -bidi-chromium-page › page/network-post-data.spec.ts › should get post data for navigator.sendBeacon api calls [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › should work @smoke [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › should work with regular text [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › roledescription [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › orientation [fail] bidi-chromium-page › page/page-accessibility.spec.ts › autocomplete [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › multiselectable [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › checkbox with and tabIndex and label should not have children [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › checkbox without label should not have children [fail] bidi-chromium-page › page/page-accessibility.spec.ts › keyshortcuts [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › should not report text nodes inside controls [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › multiselectable [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › non editable textbox with role and tabIndex and label should not have children [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › orientation [fail] bidi-chromium-page › page/page-accessibility.spec.ts › rich text editable fields should have children [fail] bidi-chromium-page › page/page-accessibility.spec.ts › rich text editable fields with role should have children [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › non editable textbox with role and tabIndex and label should not have children [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › checkbox with and tabIndex and label should not have children [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › checkbox without label should not have children [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › roledescription [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › should not report text nodes inside controls [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › should return null when the element is no longer in DOM [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › should show uninteresting nodes [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › should work @smoke [fail] bidi-chromium-page › page/page-accessibility.spec.ts › should work a button [fail] bidi-chromium-page › page/page-accessibility.spec.ts › should work an input [fail] bidi-chromium-page › page/page-accessibility.spec.ts › should work on a menu [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › should return null when the element is no longer in DOM [fail] -bidi-chromium-page › page/page-accessibility.spec.ts › should show uninteresting nodes [fail] bidi-chromium-page › page/page-accessibility.spec.ts › should work when there is a title [fail] bidi-chromium-page › page/page-accessibility.spec.ts › should work with aria-invalid accessibility tree [fail] +bidi-chromium-page › page/page-accessibility.spec.ts › should work with regular text [fail] +bidi-chromium-page › page/page-add-init-script.spec.ts › init script should run only once in iframe [pass] +bidi-chromium-page › page/page-add-init-script.spec.ts › init script should run only once in popup [fail] bidi-chromium-page › page/page-add-init-script.spec.ts › should evaluate before anything else on the page [pass] +bidi-chromium-page › page/page-add-init-script.spec.ts › should support multiple scripts [pass] +bidi-chromium-page › page/page-add-init-script.spec.ts › should throw without path and content [pass] +bidi-chromium-page › page/page-add-init-script.spec.ts › should work after a cross origin navigation [pass] +bidi-chromium-page › page/page-add-init-script.spec.ts › should work with CSP [pass] bidi-chromium-page › page/page-add-init-script.spec.ts › should work with a path [pass] bidi-chromium-page › page/page-add-init-script.spec.ts › should work with content @smoke [pass] -bidi-chromium-page › page/page-add-init-script.spec.ts › should throw without path and content [pass] bidi-chromium-page › page/page-add-init-script.spec.ts › should work with trailing comments [pass] -bidi-chromium-page › page/page-add-init-script.spec.ts › should support multiple scripts [pass] -bidi-chromium-page › page/page-add-init-script.spec.ts › should work with CSP [pass] -bidi-chromium-page › page/page-add-init-script.spec.ts › should work after a cross origin navigation [pass] -bidi-chromium-page › page/page-add-init-script.spec.ts › init script should run only once in iframe [pass] -bidi-chromium-page › page/page-add-init-script.spec.ts › init script should run only once in popup [fail] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with a custom check [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with locator.hover() [pass] bidi-chromium-page › page/page-add-locator-handler.spec.ts › should not work with force:true [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should throw when page closes [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should removeLocatorHandler [pass] bidi-chromium-page › page/page-add-locator-handler.spec.ts › should throw when handler times out [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with toBeVisible [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with toHaveScreenshot [fail] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work when owner frame detaches [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with times: option [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should throw when page closes [pass] bidi-chromium-page › page/page-add-locator-handler.spec.ts › should wait for hidden by default [pass] bidi-chromium-page › page/page-add-locator-handler.spec.ts › should wait for hidden by default 2 [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work when owner frame detaches [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with a custom check [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with locator.hover() [pass] bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with noWaitAfter [pass] -bidi-chromium-page › page/page-add-locator-handler.spec.ts › should removeLocatorHandler [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with times: option [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with toBeVisible [pass] +bidi-chromium-page › page/page-add-locator-handler.spec.ts › should work with toHaveScreenshot [fail] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should include sourceURL when path is provided [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw a nice error when the request fails [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw an error if loading from url fail [pass] bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw an error if no options are provided [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a url [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a url and type=module [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a path and type=module [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw when added with URL to the CSP page [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw when added with content to the CSP page [fail] bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a content and type=module [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw an error if loading from url fail [pass] bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a path [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should include sourceURL when path is provided [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a path and type=module [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a url [pass] +bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with a url and type=module [pass] bidi-chromium-page › page/page-add-script-tag.spec.ts › should work with content [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw when added with content to the CSP page [fail] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw when added with URL to the CSP page [pass] -bidi-chromium-page › page/page-add-script-tag.spec.ts › should throw a nice error when the request fails [pass] -bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw an error if no options are provided [pass] -bidi-chromium-page › page/page-add-style-tag.spec.ts › should work with a url @smoke [pass] +bidi-chromium-page › page/page-add-style-tag.spec.ts › should include sourceURL when path is provided [pass] bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw an error if loading from url fail [pass] +bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw an error if no options are provided [pass] +bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw when added with URL to the CSP page [pass] +bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw when added with content to the CSP page [pass] bidi-chromium-page › page/page-add-style-tag.spec.ts › should work with a path [pass] -bidi-chromium-page › page/page-add-style-tag.spec.ts › should include sourceURL when path is provided [pass] +bidi-chromium-page › page/page-add-style-tag.spec.ts › should work with a url @smoke [pass] bidi-chromium-page › page/page-add-style-tag.spec.ts › should work with content [pass] -bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw when added with content to the CSP page [pass] -bidi-chromium-page › page/page-add-style-tag.spec.ts › should throw when added with URL to the CSP page [pass] -bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should await navigation when clicking anchor [pass] -bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should not stall on JS navigation link [pass] bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should await cross-process navigation when clicking anchor [pass] bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should await form-get on click [pass] bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should await form-post on click [pass] -bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should work with noWaitAfter: true [pass] +bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should await navigation when clicking anchor [pass] +bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should not stall on JS navigation link [pass] +bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should report navigation in the log when clicking anchor [pass] bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should work with dblclick without noWaitAfter when navigation is stalled [pass] -bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should work with waitForLoadState(load) [pass] bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should work with goto following click [pass] -bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should report navigation in the log when clicking anchor [pass] -bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › clicking on links which do not commit navigation [pass] -bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › calling window.stop async [pass] -bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › calling window.stop sync [pass] +bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should work with noWaitAfter: true [pass] +bidi-chromium-page › page/page-autowaiting-basic.spec.ts › should work with waitForLoadState(load) [pass] bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank [pass] bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank after non-about:blank [pass] bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › calling window.open and window.close [pass] +bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › calling window.stop async [pass] +bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › calling window.stop sync [pass] +bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › clicking on links which do not commit navigation [pass] bidi-chromium-page › page/page-autowaiting-no-hang.spec.ts › opening a popup [pass] -bidi-chromium-page › page/page-basic.spec.ts › should reject all promises when page is closed [fail] -bidi-chromium-page › page/page-basic.spec.ts › should set the page close state [pass] -bidi-chromium-page › page/page-basic.spec.ts › should pass page to close event [pass] -bidi-chromium-page › page/page-basic.spec.ts › should terminate network waiters [pass] -bidi-chromium-page › page/page-basic.spec.ts › should be callable twice [pass] -bidi-chromium-page › page/page-basic.spec.ts › should fire load when expected [pass] bidi-chromium-page › page/page-basic.spec.ts › async stacks should work [pass] -bidi-chromium-page › page/page-basic.spec.ts › should provide access to the opener page [pass] -bidi-chromium-page › page/page-basic.spec.ts › should return null if parent page has been closed [pass] -bidi-chromium-page › page/page-basic.spec.ts › should fire domcontentloaded when expected [pass] -bidi-chromium-page › page/page-basic.spec.ts › should pass self as argument to domcontentloaded event [pass] -bidi-chromium-page › page/page-basic.spec.ts › should pass self as argument to load event [pass] -bidi-chromium-page › page/page-basic.spec.ts › should fail with error upon disconnect [pass] -bidi-chromium-page › page/page-basic.spec.ts › page.url should work [fail] -bidi-chromium-page › page/page-basic.spec.ts › page.url should include hashes [pass] -bidi-chromium-page › page/page-basic.spec.ts › page.title should return the page title [pass] -bidi-chromium-page › page/page-basic.spec.ts › page.close should work with window.close [pass] +bidi-chromium-page › page/page-basic.spec.ts › frame.press should work [fail] +bidi-chromium-page › page/page-basic.spec.ts › has navigator.webdriver set to true [pass] bidi-chromium-page › page/page-basic.spec.ts › page.close should work with page.close [pass] +bidi-chromium-page › page/page-basic.spec.ts › page.close should work with window.close [pass] bidi-chromium-page › page/page-basic.spec.ts › page.frame should respect name [fail] bidi-chromium-page › page/page-basic.spec.ts › page.frame should respect url [pass] -bidi-chromium-page › page/page-basic.spec.ts › should have sane user agent [fail] bidi-chromium-page › page/page-basic.spec.ts › page.press should work [pass] bidi-chromium-page › page/page-basic.spec.ts › page.press should work for Enter [pass] -bidi-chromium-page › page/page-basic.spec.ts › frame.press should work [fail] -bidi-chromium-page › page/page-basic.spec.ts › has navigator.webdriver set to true [pass] +bidi-chromium-page › page/page-basic.spec.ts › page.title should return the page title [pass] +bidi-chromium-page › page/page-basic.spec.ts › page.url should include hashes [pass] +bidi-chromium-page › page/page-basic.spec.ts › page.url should work [fail] +bidi-chromium-page › page/page-basic.spec.ts › should be callable twice [pass] +bidi-chromium-page › page/page-basic.spec.ts › should fail with error upon disconnect [pass] +bidi-chromium-page › page/page-basic.spec.ts › should fire domcontentloaded when expected [pass] +bidi-chromium-page › page/page-basic.spec.ts › should fire load when expected [pass] +bidi-chromium-page › page/page-basic.spec.ts › should have sane user agent [fail] bidi-chromium-page › page/page-basic.spec.ts › should iterate over page properties [pass] -bidi-chromium-page › page/page-check.spec.ts › should check the box @smoke [pass] -bidi-chromium-page › page/page-check.spec.ts › should not check the checked box [pass] -bidi-chromium-page › page/page-check.spec.ts › should uncheck the box [pass] -bidi-chromium-page › page/page-check.spec.ts › should not uncheck the unchecked box [pass] +bidi-chromium-page › page/page-basic.spec.ts › should pass page to close event [pass] +bidi-chromium-page › page/page-basic.spec.ts › should pass self as argument to domcontentloaded event [pass] +bidi-chromium-page › page/page-basic.spec.ts › should pass self as argument to load event [pass] +bidi-chromium-page › page/page-basic.spec.ts › should provide access to the opener page [pass] +bidi-chromium-page › page/page-basic.spec.ts › should reject all promises when page is closed [fail] +bidi-chromium-page › page/page-basic.spec.ts › should return null if parent page has been closed [pass] +bidi-chromium-page › page/page-basic.spec.ts › should set the page close state [pass] +bidi-chromium-page › page/page-basic.spec.ts › should terminate network waiters [pass] bidi-chromium-page › page/page-check.spec.ts › should check radio [pass] bidi-chromium-page › page/page-check.spec.ts › should check radio by aria role [pass] -bidi-chromium-page › page/page-check.spec.ts › should uncheck radio by aria role [pass] +bidi-chromium-page › page/page-check.spec.ts › should check the box @smoke [pass] bidi-chromium-page › page/page-check.spec.ts › should check the box by aria role [pass] -bidi-chromium-page › page/page-check.spec.ts › should uncheck the box by aria role [pass] -bidi-chromium-page › page/page-check.spec.ts › should throw when not a checkbox [pass] -bidi-chromium-page › page/page-check.spec.ts › should throw when not a checkbox 2 [pass] bidi-chromium-page › page/page-check.spec.ts › should check the box inside a button [pass] +bidi-chromium-page › page/page-check.spec.ts › should check the box using setChecked [pass] bidi-chromium-page › page/page-check.spec.ts › should check the label with position [pass] +bidi-chromium-page › page/page-check.spec.ts › should not check the checked box [pass] +bidi-chromium-page › page/page-check.spec.ts › should not uncheck the unchecked box [pass] +bidi-chromium-page › page/page-check.spec.ts › should throw when not a checkbox [pass] +bidi-chromium-page › page/page-check.spec.ts › should throw when not a checkbox 2 [pass] +bidi-chromium-page › page/page-check.spec.ts › should uncheck radio by aria role [pass] +bidi-chromium-page › page/page-check.spec.ts › should uncheck the box [pass] +bidi-chromium-page › page/page-check.spec.ts › should uncheck the box by aria role [pass] bidi-chromium-page › page/page-check.spec.ts › trial run should not check [pass] bidi-chromium-page › page/page-check.spec.ts › trial run should not uncheck [pass] -bidi-chromium-page › page/page-check.spec.ts › should check the box using setChecked [pass] bidi-chromium-page › page/page-click-during-navigation.spec.ts › should not fail with internal error upon navigation [pass] -bidi-chromium-page › page/page-click-react.spec.ts › should report that selector does not match anymore [unknown] bidi-chromium-page › page/page-click-react.spec.ts › should not retarget the handle when element is recycled [unknown] -bidi-chromium-page › page/page-click-react.spec.ts › should timeout when click opens alert [pass] -bidi-chromium-page › page/page-click-react.spec.ts › should retarget when element is recycled during hit testing [unknown] -bidi-chromium-page › page/page-click-react.spec.ts › should retarget when element is recycled before enabled check [unknown] bidi-chromium-page › page/page-click-react.spec.ts › should not retarget when element changes on hover [pass] bidi-chromium-page › page/page-click-react.spec.ts › should not retarget when element is recycled on hover [pass] +bidi-chromium-page › page/page-click-react.spec.ts › should report that selector does not match anymore [unknown] +bidi-chromium-page › page/page-click-react.spec.ts › should retarget when element is recycled before enabled check [unknown] +bidi-chromium-page › page/page-click-react.spec.ts › should retarget when element is recycled during hit testing [unknown] +bidi-chromium-page › page/page-click-react.spec.ts › should timeout when click opens alert [pass] +bidi-chromium-page › page/page-click-scroll.spec.ts › should not crash when force-clicking hidden input [pass] bidi-chromium-page › page/page-click-scroll.spec.ts › should not hit scroll bar [pass] bidi-chromium-page › page/page-click-scroll.spec.ts › should scroll into view display:contents [fail] bidi-chromium-page › page/page-click-scroll.spec.ts › should scroll into view display:contents with a child [pass] bidi-chromium-page › page/page-click-scroll.spec.ts › should scroll into view display:contents with position [fail] -bidi-chromium-page › page/page-click-scroll.spec.ts › should not crash when force-clicking hidden input [pass] -bidi-chromium-page › page/page-click-scroll.spec.ts › should scroll into view span element [pass] bidi-chromium-page › page/page-click-scroll.spec.ts › should scroll into view element in iframe [pass] +bidi-chromium-page › page/page-click-scroll.spec.ts › should scroll into view span element [pass] bidi-chromium-page › page/page-click-timeout-1.spec.ts › should avoid side effects after timeout [pass] bidi-chromium-page › page/page-click-timeout-1.spec.ts › should timeout waiting for button to be enabled [pass] bidi-chromium-page › page/page-click-timeout-2.spec.ts › should timeout waiting for display:none to be gone [pass] bidi-chromium-page › page/page-click-timeout-2.spec.ts › should timeout waiting for visibility:hidden to be gone [pass] bidi-chromium-page › page/page-click-timeout-3.spec.ts › should fail when element jumps during hit testing [pass] -bidi-chromium-page › page/page-click-timeout-3.spec.ts › should timeout waiting for hit target [pass] -bidi-chromium-page › page/page-click-timeout-3.spec.ts › should still click when force but hit target is obscured [pass] bidi-chromium-page › page/page-click-timeout-3.spec.ts › should report wrong hit target subtree [pass] -bidi-chromium-page › page/page-click-timeout-4.spec.ts › should timeout waiting for stable position [pass] +bidi-chromium-page › page/page-click-timeout-3.spec.ts › should still click when force but hit target is obscured [pass] +bidi-chromium-page › page/page-click-timeout-3.spec.ts › should timeout waiting for hit target [pass] bidi-chromium-page › page/page-click-timeout-4.spec.ts › should click for the second time after first timeout [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button @smoke [pass] +bidi-chromium-page › page/page-click-timeout-4.spec.ts › should timeout waiting for stable position [pass] +bidi-chromium-page › page/page-click.spec.ts › ensure events are dispatched in the individual tasks [pass] +bidi-chromium-page › page/page-click.spec.ts › should click a button in scrolling container with offset [pass] +bidi-chromium-page › page/page-click.spec.ts › should click a button that is overlaid by a permission popup [pass] +bidi-chromium-page › page/page-click.spec.ts › should click a partially obscured button [pass] +bidi-chromium-page › page/page-click.spec.ts › should click a rotated button [pass] +bidi-chromium-page › page/page-click.spec.ts › should click a very large button with offset [pass] +bidi-chromium-page › page/page-click.spec.ts › should click an offscreen element when scroll-behavior is smooth [pass] bidi-chromium-page › page/page-click.spec.ts › should click button inside frameset [pass] -bidi-chromium-page › page/page-click.spec.ts › should issue clicks in parallel in page and popup [pass] -bidi-chromium-page › page/page-click.spec.ts › should click svg [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button if window.Node is removed [pass] +bidi-chromium-page › page/page-click.spec.ts › should click disabled div [pass] +bidi-chromium-page › page/page-click.spec.ts › should click if opened select covers the button [pass] +bidi-chromium-page › page/page-click.spec.ts › should click in a nested transformed iframe [timeout] +bidi-chromium-page › page/page-click.spec.ts › should click in a transformed iframe [timeout] +bidi-chromium-page › page/page-click.spec.ts › should click in a transformed iframe with force [fail] +bidi-chromium-page › page/page-click.spec.ts › should click in an iframe with border [pass] +bidi-chromium-page › page/page-click.spec.ts › should click in an iframe with border 2 [pass] +bidi-chromium-page › page/page-click.spec.ts › should click links which cause navigation [pass] +bidi-chromium-page › page/page-click.spec.ts › should click offscreen buttons [pass] bidi-chromium-page › page/page-click.spec.ts › should click on a span with an inline element inside [pass] -bidi-chromium-page › page/page-click.spec.ts › should not throw UnhandledPromiseRejection when page closes [pass] +bidi-chromium-page › page/page-click.spec.ts › should click on checkbox input and toggle [pass] +bidi-chromium-page › page/page-click.spec.ts › should click on checkbox label and toggle [pass] +bidi-chromium-page › page/page-click.spec.ts › should click svg [pass] bidi-chromium-page › page/page-click.spec.ts › should click the 1x1 div [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button after navigation [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button @smoke [pass] bidi-chromium-page › page/page-click.spec.ts › should click the button after a cross origin navigation [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button after navigation [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button behind sticky header [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button if window.Node is removed [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button inside an iframe [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button when window.innerWidth is corrupted [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button with em border with offset [pass] +bidi-chromium-page › page/page-click.spec.ts › should click the button with fixed position inside an iframe [timeout] +bidi-chromium-page › page/page-click.spec.ts › should click the button with px border with offset [pass] bidi-chromium-page › page/page-click.spec.ts › should click when one of inline box children is outside of viewport [pass] -bidi-chromium-page › page/page-click.spec.ts › should select the text by triple clicking [pass] -bidi-chromium-page › page/page-click.spec.ts › should click offscreen buttons [pass] -bidi-chromium-page › page/page-click.spec.ts › should waitFor visible when already visible [pass] -bidi-chromium-page › page/page-click.spec.ts › should not wait with force [pass] -bidi-chromium-page › page/page-click.spec.ts › should waitFor display:none to be gone [pass] -bidi-chromium-page › page/page-click.spec.ts › should waitFor visibility:hidden to be gone [pass] -bidi-chromium-page › page/page-click.spec.ts › should waitFor visible when parent is hidden [pass] bidi-chromium-page › page/page-click.spec.ts › should click wrapped links [pass] -bidi-chromium-page › page/page-click.spec.ts › should click on checkbox input and toggle [pass] -bidi-chromium-page › page/page-click.spec.ts › should click on checkbox label and toggle [pass] -bidi-chromium-page › page/page-click.spec.ts › should scroll and click the button [pass] -bidi-chromium-page › page/page-click.spec.ts › should scroll and click the button with smooth scroll behavior [pass] +bidi-chromium-page › page/page-click.spec.ts › should click zero-sized input by label [pass] +bidi-chromium-page › page/page-click.spec.ts › should climb dom for inner label with pointer-events:none [pass] +bidi-chromium-page › page/page-click.spec.ts › should climb up to [role=button] [pass] +bidi-chromium-page › page/page-click.spec.ts › should climb up to a [role=link] [pass] +bidi-chromium-page › page/page-click.spec.ts › should climb up to a anchor [pass] +bidi-chromium-page › page/page-click.spec.ts › should dispatch microtasks in order [pass] bidi-chromium-page › page/page-click.spec.ts › should double click the button [pass] -bidi-chromium-page › page/page-click.spec.ts › should click a partially obscured button [pass] -bidi-chromium-page › page/page-click.spec.ts › should click a rotated button [pass] +bidi-chromium-page › page/page-click.spec.ts › should fail when element detaches after animation [pass] +bidi-chromium-page › page/page-click.spec.ts › should fail when element is animating from outside the viewport with force [pass] +bidi-chromium-page › page/page-click.spec.ts › should fail when obscured and not waiting for hit target [pass] bidi-chromium-page › page/page-click.spec.ts › should fire contextmenu event on right click [pass] -bidi-chromium-page › page/page-click.spec.ts › should click links which cause navigation [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button inside an iframe [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button with fixed position inside an iframe [timeout] -bidi-chromium-page › page/page-click.spec.ts › should click the button behind sticky header [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button with px border with offset [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button with em border with offset [pass] -bidi-chromium-page › page/page-click.spec.ts › should click a very large button with offset [pass] -bidi-chromium-page › page/page-click.spec.ts › should click a button in scrolling container with offset [pass] -bidi-chromium-page › page/page-click.spec.ts › should wait for stable position [pass] +bidi-chromium-page › page/page-click.spec.ts › should fire contextmenu event on right click in correct order [fail] +bidi-chromium-page › page/page-click.spec.ts › should issue clicks in parallel in page and popup [pass] +bidi-chromium-page › page/page-click.spec.ts › should not hang when frame is detached [pass] +bidi-chromium-page › page/page-click.spec.ts › should not throw UnhandledPromiseRejection when page closes [pass] +bidi-chromium-page › page/page-click.spec.ts › should not throw protocol error when navigating during the click [pass] +bidi-chromium-page › page/page-click.spec.ts › should not wait with force [pass] +bidi-chromium-page › page/page-click.spec.ts › should report nice error when element is detached and force-clicked [pass] +bidi-chromium-page › page/page-click.spec.ts › should retry when element detaches after animation [pass] +bidi-chromium-page › page/page-click.spec.ts › should retry when element is animating from outside the viewport [pass] +bidi-chromium-page › page/page-click.spec.ts › should retry when navigating during the click [pass] +bidi-chromium-page › page/page-click.spec.ts › should scroll and click the button [pass] +bidi-chromium-page › page/page-click.spec.ts › should scroll and click the button with smooth scroll behavior [pass] +bidi-chromium-page › page/page-click.spec.ts › should select the text by triple clicking [pass] +bidi-chromium-page › page/page-click.spec.ts › should update modifiers correctly [pass] +bidi-chromium-page › page/page-click.spec.ts › should wait for BUTTON to be clickable when it has pointer-events:none [pass] +bidi-chromium-page › page/page-click.spec.ts › should wait for LABEL to be clickable when it has pointer-events:none [pass] bidi-chromium-page › page/page-click.spec.ts › should wait for becoming hit target [pass] bidi-chromium-page › page/page-click.spec.ts › should wait for becoming hit target with trial run [pass] -bidi-chromium-page › page/page-click.spec.ts › trial run should work with short timeout [pass] -bidi-chromium-page › page/page-click.spec.ts › trial run should not click [pass] -bidi-chromium-page › page/page-click.spec.ts › trial run should not double click [pass] -bidi-chromium-page › page/page-click.spec.ts › should fail when obscured and not waiting for hit target [pass] bidi-chromium-page › page/page-click.spec.ts › should wait for button to be enabled [pass] bidi-chromium-page › page/page-click.spec.ts › should wait for input to be enabled [pass] bidi-chromium-page › page/page-click.spec.ts › should wait for select to be enabled [pass] -bidi-chromium-page › page/page-click.spec.ts › should click disabled div [pass] -bidi-chromium-page › page/page-click.spec.ts › should wait for BUTTON to be clickable when it has pointer-events:none [pass] -bidi-chromium-page › page/page-click.spec.ts › should wait for LABEL to be clickable when it has pointer-events:none [pass] -bidi-chromium-page › page/page-click.spec.ts › should update modifiers correctly [pass] -bidi-chromium-page › page/page-click.spec.ts › should click an offscreen element when scroll-behavior is smooth [pass] -bidi-chromium-page › page/page-click.spec.ts › should report nice error when element is detached and force-clicked [pass] -bidi-chromium-page › page/page-click.spec.ts › should fail when element detaches after animation [pass] -bidi-chromium-page › page/page-click.spec.ts › should retry when element detaches after animation [pass] -bidi-chromium-page › page/page-click.spec.ts › should retry when element is animating from outside the viewport [pass] -bidi-chromium-page › page/page-click.spec.ts › should fail when element is animating from outside the viewport with force [pass] -bidi-chromium-page › page/page-click.spec.ts › should dispatch microtasks in order [pass] -bidi-chromium-page › page/page-click.spec.ts › should click the button when window.innerWidth is corrupted [pass] -bidi-chromium-page › page/page-click.spec.ts › should click zero-sized input by label [pass] -bidi-chromium-page › page/page-click.spec.ts › should not throw protocol error when navigating during the click [pass] -bidi-chromium-page › page/page-click.spec.ts › should retry when navigating during the click [pass] -bidi-chromium-page › page/page-click.spec.ts › should not hang when frame is detached [pass] -bidi-chromium-page › page/page-click.spec.ts › should climb dom for inner label with pointer-events:none [pass] -bidi-chromium-page › page/page-click.spec.ts › should climb up to [role=button] [pass] -bidi-chromium-page › page/page-click.spec.ts › should climb up to a anchor [pass] -bidi-chromium-page › page/page-click.spec.ts › should climb up to a [role=link] [pass] -bidi-chromium-page › page/page-click.spec.ts › should click in an iframe with border [pass] -bidi-chromium-page › page/page-click.spec.ts › should click in an iframe with border 2 [pass] -bidi-chromium-page › page/page-click.spec.ts › should click in a transformed iframe [timeout] -bidi-chromium-page › page/page-click.spec.ts › should click a button that is overlaid by a permission popup [pass] -bidi-chromium-page › page/page-click.spec.ts › should click in a transformed iframe with force [fail] -bidi-chromium-page › page/page-click.spec.ts › should click in a nested transformed iframe [timeout] -bidi-chromium-page › page/page-click.spec.ts › ensure events are dispatched in the individual tasks [pass] -bidi-chromium-page › page/page-click.spec.ts › should click if opened select covers the button [pass] -bidi-chromium-page › page/page-click.spec.ts › should fire contextmenu event on right click in correct order [fail] +bidi-chromium-page › page/page-click.spec.ts › should wait for stable position [pass] +bidi-chromium-page › page/page-click.spec.ts › should waitFor display:none to be gone [pass] +bidi-chromium-page › page/page-click.spec.ts › should waitFor visibility:hidden to be gone [pass] +bidi-chromium-page › page/page-click.spec.ts › should waitFor visible when already visible [pass] +bidi-chromium-page › page/page-click.spec.ts › should waitFor visible when parent is hidden [pass] +bidi-chromium-page › page/page-click.spec.ts › trial run should not click [pass] +bidi-chromium-page › page/page-click.spec.ts › trial run should not double click [pass] +bidi-chromium-page › page/page-click.spec.ts › trial run should work with short timeout [pass] bidi-chromium-page › page/page-close.spec.ts › should close page with active dialog [pass] bidi-chromium-page › page/page-close.spec.ts › should not accept dialog after close [pass] -bidi-chromium-page › page/page-dialog.spec.ts › should fire [pass] -bidi-chromium-page › page/page-dialog.spec.ts › should allow accepting prompts @smoke [pass] -bidi-chromium-page › page/page-dialog.spec.ts › should dismiss the prompt [pass] bidi-chromium-page › page/page-dialog.spec.ts › should accept the confirm prompt [pass] -bidi-chromium-page › page/page-dialog.spec.ts › should dismiss the confirm prompt [pass] +bidi-chromium-page › page/page-dialog.spec.ts › should allow accepting prompts @smoke [pass] +bidi-chromium-page › page/page-dialog.spec.ts › should auto-dismiss the alert without listeners [pass] +bidi-chromium-page › page/page-dialog.spec.ts › should auto-dismiss the prompt without listeners [pass] bidi-chromium-page › page/page-dialog.spec.ts › should be able to close context with open alert [pass] +bidi-chromium-page › page/page-dialog.spec.ts › should dismiss the confirm prompt [pass] +bidi-chromium-page › page/page-dialog.spec.ts › should dismiss the prompt [pass] +bidi-chromium-page › page/page-dialog.spec.ts › should fire [pass] bidi-chromium-page › page/page-dialog.spec.ts › should handle multiple alerts [timeout] bidi-chromium-page › page/page-dialog.spec.ts › should handle multiple confirms [timeout] -bidi-chromium-page › page/page-dialog.spec.ts › should auto-dismiss the prompt without listeners [pass] -bidi-chromium-page › page/page-dialog.spec.ts › should auto-dismiss the alert without listeners [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should be atomic [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch absolute device orientation event [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click after a cross origin navigation [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click after navigation [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click event @smoke [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click event properties [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click svg [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click event via ElementHandles [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click on a span with an inline element inside [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click after navigation [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click after a cross origin navigation [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should not fail when element is blocked on hover [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click svg [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click when node is added in shadow dom [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should be atomic [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch device motion event [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch device orientation event [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch drag drop events [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch drag drop events via ElementHandles [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch click event via ElementHandles [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch wheel event [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch device orientation event [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch absolute device orientation event [pass] -bidi-chromium-page › page/page-dispatchevent.spec.ts › should dispatch device motion event [pass] +bidi-chromium-page › page/page-dispatchevent.spec.ts › should not fail when element is blocked on hover [pass] bidi-chromium-page › page/page-dispatchevent.spec.ts › should throw if argument is from different frame [pass] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work @smoke [pass] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should send the right events [pass] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should not send dragover on the first mousemove [unknown] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work inside iframe [pass] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should cancel on escape [fail] bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › iframe › should drag into an iframe [unknown] bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › iframe › should drag out of an iframe [unknown] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should respect the drop effect [fail] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work if the drag is canceled [pass] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work if the drag event is captured but not canceled [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should allow specifying the position [pass] bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should be able to drag the mouse in a frame [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should cancel on escape [fail] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should not send dragover on the first mousemove [unknown] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should respect the drop effect [fail] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should send the right events [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work @smoke [pass] bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work if a frame is stalled [fail] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work with the helper method [pass] -bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should allow specifying the position [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work if the drag event is captured but not canceled [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work if the drag is canceled [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work inside iframe [pass] bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work with locators [pass] -bidi-chromium-page › page/page-drag.spec.ts › should work if not doing a drag [pass] -bidi-chromium-page › page/page-drag.spec.ts › should report event.buttons [pass] +bidi-chromium-page › page/page-drag.spec.ts › Drag and drop › should work with the helper method [pass] bidi-chromium-page › page/page-drag.spec.ts › should handle custom dataTransfer [pass] +bidi-chromium-page › page/page-drag.spec.ts › should report event.buttons [pass] +bidi-chromium-page › page/page-drag.spec.ts › should work if not doing a drag [pass] bidi-chromium-page › page/page-drag.spec.ts › what happens when dragging element is destroyed [pass] -bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate type @smoke [fail] -bidi-chromium-page › page/page-emulate-media.spec.ts › should throw in case of bad media argument [pass] -bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate colorScheme should work @smoke [fail] -bidi-chromium-page › page/page-emulate-media.spec.ts › should default to light [fail] -bidi-chromium-page › page/page-emulate-media.spec.ts › should throw in case of bad colorScheme argument [pass] -bidi-chromium-page › page/page-emulate-media.spec.ts › should work during navigation [fail] bidi-chromium-page › page/page-emulate-media.spec.ts › should change the actual colors in css [fail] +bidi-chromium-page › page/page-emulate-media.spec.ts › should default to light [fail] +bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate colorScheme should work @smoke [fail] +bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate forcedColors [fail] bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate reduced motion [fail] +bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate type @smoke [fail] bidi-chromium-page › page/page-emulate-media.spec.ts › should keep reduced motion and color emulation after reload [fail] -bidi-chromium-page › page/page-emulate-media.spec.ts › should emulate forcedColors [fail] -bidi-chromium-page › page/page-evaluate-handle.spec.ts › should work [pass] -bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept object handle as an argument [pass] -bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept object handle to primitive types [pass] +bidi-chromium-page › page/page-emulate-media.spec.ts › should throw in case of bad colorScheme argument [pass] +bidi-chromium-page › page/page-emulate-media.spec.ts › should throw in case of bad media argument [pass] +bidi-chromium-page › page/page-emulate-media.spec.ts › should work during navigation [fail] +bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept multiple nested handles [pass] bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept nested handle [pass] bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept nested window handle [pass] -bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept multiple nested handles [pass] +bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept object handle as an argument [pass] +bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept object handle to primitive types [pass] +bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept object handle to unserializable value [pass] bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept same handle multiple times [pass] bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept same nested object multiple times [pass] -bidi-chromium-page › page/page-evaluate-handle.spec.ts › should accept object handle to unserializable value [pass] bidi-chromium-page › page/page-evaluate-handle.spec.ts › should pass configurable args [pass] +bidi-chromium-page › page/page-evaluate-handle.spec.ts › should work [pass] bidi-chromium-page › page/page-evaluate-handle.spec.ts › should work with primitives [pass] -bidi-chromium-page › page/page-evaluate-no-stall.spec.ts › should work [pass] -bidi-chromium-page › page/page-evaluate-no-stall.spec.ts › should throw while pending navigation [fail] bidi-chromium-page › page/page-evaluate-no-stall.spec.ts › should throw when no main execution context [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer NaN [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer -0 [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer Infinity [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer -Infinity [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip unserializable values [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip promise to value [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip promise to unserializable values [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer arrays [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer arrays as arrays, not objects [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer bigint [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer maps as empty objects [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should modify global environment [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate in the page context [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return undefined for objects with symbols [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with function shorthands [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with unicode chars [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with large strings [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with large unicode strings [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should throw when evaluation triggers reload [fail] -bidi-chromium-page › page/page-evaluate.spec.ts › should await promise [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work right after framenavigated [fail] -bidi-chromium-page › page/page-evaluate.spec.ts › should work right after a cross-origin navigation [fail] -bidi-chromium-page › page/page-evaluate.spec.ts › should work from-inside an exposed function [fail] -bidi-chromium-page › page/page-evaluate.spec.ts › should reject promise with exception [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should support thrown strings as error messages [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should support thrown numbers as error messages [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return complex objects [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return NaN [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return -0 [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return Infinity [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return -Infinity [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with overwritten Promise [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should throw when passed more than one parameter [pass] +bidi-chromium-page › page/page-evaluate-no-stall.spec.ts › should throw while pending navigation [fail] +bidi-chromium-page › page/page-evaluate-no-stall.spec.ts › should work [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should accept "undefined" as one of multiple parameters [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize undefined arguments [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize undefined fields [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return undefined properties [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize null arguments [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize null fields [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize PerformanceMeasure object [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize window.performance object [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should return undefined for non-serializable objects [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should alias Window, Document and Node [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work for circular object [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should be able to throw a tricky error [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should accept a string [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should accept a string with semi colons [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should accept a string with comments [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should accept a string with semi colons [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should accept element handle as an argument [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should throw if underlying element was disposed [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should simulate a user gesture [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should throw a nice error after a navigation [fail] +bidi-chromium-page › page/page-evaluate.spec.ts › should alias Window, Document and Node [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should await promise [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should await promise from popup [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should be able to throw a tricky error [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate date [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate exception [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate exception with a function on the stack [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate in the page context [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate url [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should ignore buggy toJSON [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should jsonValue() date [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should jsonValue() url [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should modify global environment [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not add a toJSON property to newly created Arrays after evaluation [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not expose the injected script export [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not leak handles [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not leak utility script [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should not throw an error when evaluation does a navigation [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should not throw an error when evaluation does a synchronous navigation and returns an object [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should not throw an error when evaluation does a synchronous navigation and returns undefined [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should transfer 100Mb of data from page to node.js [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should throw error with detailed information on exception inside promise [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work even when JSON is set to null [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should await promise from popup [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with new Function() and CSP [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with non-strict expressions [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should respect use strict expression [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not leak utility script [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not leak handles [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with CSP [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate exception with a function on the stack [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate exception [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not use Array.prototype.toJSON when evaluating [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not use toJSON in jsonValue [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should not use toJSON when evaluating [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should pass exception argument [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate date [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize PerformanceMeasure object [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize null arguments [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize null fields [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize undefined arguments [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize undefined fields [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should properly serialize window.performance object [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should reject promise with exception [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should respect use strict expression [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return -0 [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return -Infinity [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return Infinity [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return NaN [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return complex objects [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return undefined for non-serializable objects [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return undefined for objects with symbols [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should return undefined properties [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip date [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip promise to unserializable values [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip promise to value [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip regex [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should jsonValue() date [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should evaluate url [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip unserializable values [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should roundtrip url [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should jsonValue() url [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not use toJSON when evaluating [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not use Array.prototype.toJSON when evaluating [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not add a toJSON property to newly created Arrays after evaluation [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not use toJSON in jsonValue [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should ignore buggy toJSON [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should not expose the injected script export [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should simulate a user gesture [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should support thrown numbers as error messages [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should support thrown strings as error messages [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should throw a nice error after a navigation [fail] +bidi-chromium-page › page/page-evaluate.spec.ts › should throw error with detailed information on exception inside promise [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should throw if underlying element was disposed [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should throw when evaluation triggers reload [fail] bidi-chromium-page › page/page-evaluate.spec.ts › should throw when frame is detached [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with overridden Object.defineProperty [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should throw when passed more than one parameter [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer -0 [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer -Infinity [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer 100Mb of data from page to node.js [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer Infinity [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer NaN [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer arrays [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer arrays as arrays, not objects [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer bigint [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should transfer maps as empty objects [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work even when JSON is set to null [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work for circular object [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work from-inside an exposed function [fail] +bidi-chromium-page › page/page-evaluate.spec.ts › should work right after a cross-origin navigation [fail] +bidi-chromium-page › page/page-evaluate.spec.ts › should work right after framenavigated [fail] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with Array.from/map [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with CSP [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should work with busted Array.prototype.map/push [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with overridden globalThis.Window/Document/Node [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with function shorthands [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with large strings [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with large unicode strings [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with new Function() and CSP [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with non-strict expressions [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with overridden Object.defineProperty [pass] bidi-chromium-page › page/page-evaluate.spec.ts › should work with overridden URL/Date/RegExp [pass] -bidi-chromium-page › page/page-evaluate.spec.ts › should work with Array.from/map [pass] -bidi-chromium-page › page/page-event-console.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with overridden globalThis.Window/Document/Node [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with overwritten Promise [pass] +bidi-chromium-page › page/page-evaluate.spec.ts › should work with unicode chars [pass] +bidi-chromium-page › page/page-event-console.spec.ts › do not update console count on unhandled rejections [pass] bidi-chromium-page › page/page-event-console.spec.ts › should emit same log twice [pass] -bidi-chromium-page › page/page-event-console.spec.ts › should use text() for inspection [pass] -bidi-chromium-page › page/page-event-console.spec.ts › should work for different console API calls [fail] bidi-chromium-page › page/page-event-console.spec.ts › should format the message correctly with time/timeLog/timeEnd [pass] -bidi-chromium-page › page/page-event-console.spec.ts › should not fail for window object [fail] -bidi-chromium-page › page/page-event-console.spec.ts › should trigger correct Log [timeout] bidi-chromium-page › page/page-event-console.spec.ts › should have location for console API calls [pass] +bidi-chromium-page › page/page-event-console.spec.ts › should not fail for window object [fail] bidi-chromium-page › page/page-event-console.spec.ts › should not throw when there are console messages in detached iframes [pass] +bidi-chromium-page › page/page-event-console.spec.ts › should trigger correct Log [timeout] bidi-chromium-page › page/page-event-console.spec.ts › should use object previews for arrays and objects [fail] bidi-chromium-page › page/page-event-console.spec.ts › should use object previews for errors [pass] -bidi-chromium-page › page/page-event-console.spec.ts › do not update console count on unhandled rejections [pass] +bidi-chromium-page › page/page-event-console.spec.ts › should use text() for inspection [pass] +bidi-chromium-page › page/page-event-console.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/page-event-console.spec.ts › should work for different console API calls [fail] bidi-chromium-page › page/page-event-load.spec.ts › should fire once [pass] bidi-chromium-page › page/page-event-load.spec.ts › should fire once with iframe navigation [pass] bidi-chromium-page › page/page-event-network.spec.ts › Page.Events.Request @smoke [fail] -bidi-chromium-page › page/page-event-network.spec.ts › Page.Events.Response @smoke [pass] bidi-chromium-page › page/page-event-network.spec.ts › Page.Events.RequestFailed @smoke [fail] bidi-chromium-page › page/page-event-network.spec.ts › Page.Events.RequestFinished @smoke [pass] +bidi-chromium-page › page/page-event-network.spec.ts › Page.Events.Response @smoke [pass] +bidi-chromium-page › page/page-event-network.spec.ts › interrupt request.response() and request.allHeaders() on page.close [fail] bidi-chromium-page › page/page-event-network.spec.ts › should fire events in proper order [pass] -bidi-chromium-page › page/page-event-network.spec.ts › should support redirects [pass] bidi-chromium-page › page/page-event-network.spec.ts › should resolve responses after a navigation [timeout] -bidi-chromium-page › page/page-event-network.spec.ts › interrupt request.response() and request.allHeaders() on page.close [fail] -bidi-chromium-page › page/page-event-pageerror.spec.ts › should fire [timeout] -bidi-chromium-page › page/page-event-pageerror.spec.ts › should not receive console message for pageError [timeout] +bidi-chromium-page › page/page-event-network.spec.ts › should support redirects [pass] bidi-chromium-page › page/page-event-pageerror.spec.ts › should contain sourceURL [timeout] bidi-chromium-page › page/page-event-pageerror.spec.ts › should contain the Error.name property [timeout] -bidi-chromium-page › page/page-event-pageerror.spec.ts › should support an empty Error.name property [timeout] -bidi-chromium-page › page/page-event-pageerror.spec.ts › should handle odd values [timeout] +bidi-chromium-page › page/page-event-pageerror.spec.ts › should emit error from unhandled rejects [timeout] +bidi-chromium-page › page/page-event-pageerror.spec.ts › should fire [timeout] bidi-chromium-page › page/page-event-pageerror.spec.ts › should handle object [timeout] +bidi-chromium-page › page/page-event-pageerror.spec.ts › should handle odd values [timeout] bidi-chromium-page › page/page-event-pageerror.spec.ts › should handle window [timeout] +bidi-chromium-page › page/page-event-pageerror.spec.ts › should not receive console message for pageError [timeout] bidi-chromium-page › page/page-event-pageerror.spec.ts › should remove a listener of a non-existing event handler [pass] -bidi-chromium-page › page/page-event-pageerror.spec.ts › should emit error from unhandled rejects [timeout] -bidi-chromium-page › page/page-event-popup.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should work with window features [pass] +bidi-chromium-page › page/page-event-pageerror.spec.ts › should support an empty Error.name property [timeout] +bidi-chromium-page › page/page-event-popup.spec.ts › should be able to capture alert [timeout] bidi-chromium-page › page/page-event-popup.spec.ts › should emit for immediately closed popups [pass] bidi-chromium-page › page/page-event-popup.spec.ts › should emit for immediately closed popups 2 [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should be able to capture alert [timeout] +bidi-chromium-page › page/page-event-popup.spec.ts › should not treat navigations as new popups [pass] +bidi-chromium-page › page/page-event-popup.spec.ts › should report popup opened from iframes [fail] +bidi-chromium-page › page/page-event-popup.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-event-popup.spec.ts › should work with clicking target=_blank [pass] +bidi-chromium-page › page/page-event-popup.spec.ts › should work with clicking target=_blank and rel=noopener [pass] bidi-chromium-page › page/page-event-popup.spec.ts › should work with empty url [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should work with noopener and no url [fail] +bidi-chromium-page › page/page-event-popup.spec.ts › should work with fake-clicking target=_blank and rel=noopener [pass] bidi-chromium-page › page/page-event-popup.spec.ts › should work with noopener and about:blank [pass] +bidi-chromium-page › page/page-event-popup.spec.ts › should work with noopener and no url [fail] bidi-chromium-page › page/page-event-popup.spec.ts › should work with noopener and url [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should work with clicking target=_blank [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should work with fake-clicking target=_blank and rel=noopener [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should work with clicking target=_blank and rel=noopener [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should not treat navigations as new popups [pass] -bidi-chromium-page › page/page-event-popup.spec.ts › should report popup opened from iframes [fail] -bidi-chromium-page › page/page-event-request.spec.ts › should fire for navigation requests [pass] -bidi-chromium-page › page/page-event-request.spec.ts › should fire for iframes [pass] +bidi-chromium-page › page/page-event-popup.spec.ts › should work with window features [pass] +bidi-chromium-page › page/page-event-request.spec.ts › main resource xhr should have type xhr [fail] bidi-chromium-page › page/page-event-request.spec.ts › should fire for fetches [pass] -bidi-chromium-page › page/page-event-request.spec.ts › should report requests and responses handled by service worker [fail] -bidi-chromium-page › page/page-event-request.spec.ts › should report requests and responses handled by service worker with routing [fail] +bidi-chromium-page › page/page-event-request.spec.ts › should fire for iframes [pass] +bidi-chromium-page › page/page-event-request.spec.ts › should fire for navigation requests [pass] +bidi-chromium-page › page/page-event-request.spec.ts › should fire requestfailed when intercepting race [unknown] bidi-chromium-page › page/page-event-request.spec.ts › should report navigation requests and responses handled by service worker [fail] bidi-chromium-page › page/page-event-request.spec.ts › should report navigation requests and responses handled by service worker with routing [fail] +bidi-chromium-page › page/page-event-request.spec.ts › should report requests and responses handled by service worker [fail] +bidi-chromium-page › page/page-event-request.spec.ts › should report requests and responses handled by service worker with routing [fail] bidi-chromium-page › page/page-event-request.spec.ts › should return response body when Cross-Origin-Opener-Policy is set [fail] -bidi-chromium-page › page/page-event-request.spec.ts › should fire requestfailed when intercepting race [unknown] -bidi-chromium-page › page/page-event-request.spec.ts › main resource xhr should have type xhr [fail] bidi-chromium-page › page/page-expose-function.spec.ts › exposeBinding should work @smoke [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should work [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should work with handles and complex objects [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should throw exception in page context [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should support throwing "null" [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › exposeBinding(handle) should work with element handles [timeout] +bidi-chromium-page › page/page-expose-function.spec.ts › exposeBindingHandle should not throw during navigation [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › exposeBindingHandle should throw for multiple arguments [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › exposeBindingHandle should work [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should alias Window, Document and Node [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should await returned promise [fail] bidi-chromium-page › page/page-expose-function.spec.ts › should be callable from-inside addInitScript [timeout] +bidi-chromium-page › page/page-expose-function.spec.ts › should fail with busted Array.prototype.toJSON [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should not result in unhandled rejection [timeout] +bidi-chromium-page › page/page-expose-function.spec.ts › should serialize cycles [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should support throwing "null" [fail] bidi-chromium-page › page/page-expose-function.spec.ts › should survive navigation [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should await returned promise [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should throw exception in page context [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should throw for duplicate registrations [pass] +bidi-chromium-page › page/page-expose-function.spec.ts › should work [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should work after cross origin navigation [fail] bidi-chromium-page › page/page-expose-function.spec.ts › should work on frames [fail] bidi-chromium-page › page/page-expose-function.spec.ts › should work on frames before navigation [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should work after cross origin navigation [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should work with busted Array.prototype.map/push [fail] bidi-chromium-page › page/page-expose-function.spec.ts › should work with complex objects [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › exposeBindingHandle should work [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › exposeBindingHandle should not throw during navigation [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should throw for duplicate registrations [pass] -bidi-chromium-page › page/page-expose-function.spec.ts › exposeBindingHandle should throw for multiple arguments [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should not result in unhandled rejection [timeout] -bidi-chromium-page › page/page-expose-function.spec.ts › exposeBinding(handle) should work with element handles [timeout] -bidi-chromium-page › page/page-expose-function.spec.ts › should work with setContent [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should alias Window, Document and Node [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should serialize cycles [fail] +bidi-chromium-page › page/page-expose-function.spec.ts › should work with handles and complex objects [fail] bidi-chromium-page › page/page-expose-function.spec.ts › should work with overridden console object [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should work with busted Array.prototype.map/push [fail] -bidi-chromium-page › page/page-expose-function.spec.ts › should fail with busted Array.prototype.toJSON [fail] -bidi-chromium-page › page/page-fill.spec.ts › should fill textarea @smoke [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on unsupported inputs [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill different input types [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill range input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect range value [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill color input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect color value [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill date input after clicking [pass] +bidi-chromium-page › page/page-expose-function.spec.ts › should work with setContent [fail] +bidi-chromium-page › page/page-fill.spec.ts › fill back to back [pass] bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - color [pass] bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - date [pass] -bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - time [pass] bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - datetime-local [pass] bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - month [unknown] bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - range [pass] +bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - time [pass] bidi-chromium-page › page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - week [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect date [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill time input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill month input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect month [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should fill week input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect week [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect time [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill datetime-local input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should fill contenteditable [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill contenteditable with new lines [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill elements with existing value and selection [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw nice error without injected script stack when element is not an [fail] -bidi-chromium-page › page/page-fill.spec.ts › should throw if passed a non-string value [pass] -bidi-chromium-page › page/page-fill.spec.ts › should retry on disabled element [pass] -bidi-chromium-page › page/page-fill.spec.ts › should retry on readonly element [pass] -bidi-chromium-page › page/page-fill.spec.ts › should retry on invisible element [pass] -bidi-chromium-page › page/page-fill.spec.ts › should be able to fill the body [pass] -bidi-chromium-page › page/page-fill.spec.ts › should fill fixed position input [pass] -bidi-chromium-page › page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [pass] -bidi-chromium-page › page/page-fill.spec.ts › should be able to fill the input[type=number] [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to clear using fill() [pass] bidi-chromium-page › page/page-fill.spec.ts › should be able to fill exponent into the input[type=number] [pass] bidi-chromium-page › page/page-fill.spec.ts › should be able to fill input[type=number] with empty string [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill the body [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill the input[type=number] [pass] +bidi-chromium-page › page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill color input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill contenteditable [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill contenteditable with new lines [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill date input after clicking [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill datetime-local input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill different input types [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill elements with existing value and selection [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill fixed position input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill month input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill range input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill textarea @smoke [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill time input [pass] +bidi-chromium-page › page/page-fill.spec.ts › should fill week input [pass] bidi-chromium-page › page/page-fill.spec.ts › should not be able to fill text into the input[type=number] [pass] -bidi-chromium-page › page/page-fill.spec.ts › should be able to clear using fill() [pass] bidi-chromium-page › page/page-fill.spec.ts › should not throw when fill causes navigation [pass] -bidi-chromium-page › page/page-fill.spec.ts › fill back to back [pass] -bidi-chromium-page › page/page-focus.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/page-focus.spec.ts › should emit focus event [fail] +bidi-chromium-page › page/page-fill.spec.ts › should retry on disabled element [pass] +bidi-chromium-page › page/page-fill.spec.ts › should retry on invisible element [pass] +bidi-chromium-page › page/page-fill.spec.ts › should retry on readonly element [pass] +bidi-chromium-page › page/page-fill.spec.ts › should throw if passed a non-string value [pass] +bidi-chromium-page › page/page-fill.spec.ts › should throw nice error without injected script stack when element is not an [fail] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect color value [pass] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect date [pass] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect month [unknown] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect range value [pass] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect time [pass] +bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect week [unknown] +bidi-chromium-page › page/page-fill.spec.ts › should throw on unsupported inputs [pass] +bidi-chromium-page › page/page-focus.spec.ts › clicking checkbox should activate it [unknown] +bidi-chromium-page › page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [pass] bidi-chromium-page › page/page-focus.spec.ts › should emit blur event [fail] +bidi-chromium-page › page/page-focus.spec.ts › should emit focus event [fail] bidi-chromium-page › page/page-focus.spec.ts › should traverse focus [fail] bidi-chromium-page › page/page-focus.spec.ts › should traverse focus in all directions [pass] bidi-chromium-page › page/page-focus.spec.ts › should traverse only form elements [unknown] -bidi-chromium-page › page/page-focus.spec.ts › clicking checkbox should activate it [unknown] -bidi-chromium-page › page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with file URL [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with file URL with subframes [pass] -bidi-chromium-page › page/page-goto.spec.ts › should use http for no protocol [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work cross-process [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [fail] -bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] -bidi-chromium-page › page/page-goto.spec.ts › should capture iframe navigation request [pass] +bidi-chromium-page › page/page-focus.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [fail] +bidi-chromium-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] bidi-chromium-page › page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with anchor navigation [timeout] -bidi-chromium-page › page/page-goto.spec.ts › should work with redirects [pass] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to about:blank [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return response when page changes its URL after load [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when server returns 204 [fail] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when page calls history API in beforeunload [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad url [fail] +bidi-chromium-page › page/page-goto.spec.ts › should capture iframe navigation request [pass] +bidi-chromium-page › page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when canceled by another navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when main resources failed to load [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating and show the url at the error message [pass] bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad url [fail] +bidi-chromium-page › page/page-goto.spec.ts › should fail when replaced by another navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should fail when server returns 204 [fail] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to about:blank [pass] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] +bidi-chromium-page › page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] bidi-chromium-page › page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] bidi-chromium-page › page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] -bidi-chromium-page › page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when main resources failed to load [fail] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context timeout [pass] +bidi-chromium-page › page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] +bidi-chromium-page › page/page-goto.spec.ts › should override referrer-policy [fail] bidi-chromium-page › page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when replaced by another navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [fail] -bidi-chromium-page › page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to valid url [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to data url [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to 404 [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return last response in redirect chain [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with self requesting page [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating and show the url at the error message [pass] -bidi-chromium-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] -bidi-chromium-page › page/page-goto.spec.ts › should send referer [fail] -bidi-chromium-page › page/page-goto.spec.ts › should send referer of cross-origin URL [fail] +bidi-chromium-page › page/page-goto.spec.ts › should properly wait for load [pass] bidi-chromium-page › page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] -bidi-chromium-page › page/page-goto.spec.ts › should override referrer-policy [fail] -bidi-chromium-page › page/page-goto.spec.ts › should fail when canceled by another navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with lazy loading iframes [pass] bidi-chromium-page › page/page-goto.spec.ts › should report raw buffer for main resource [fail] -bidi-chromium-page › page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] -bidi-chromium-page › page/page-goto.spec.ts › should properly wait for load [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] bidi-chromium-page › page/page-goto.spec.ts › should return from goto if new navigation is started [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return last response in redirect chain [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return response when page changes its URL after load [pass] +bidi-chromium-page › page/page-goto.spec.ts › should return url with basic auth info [pass] bidi-chromium-page › page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] +bidi-chromium-page › page/page-goto.spec.ts › should send referer [fail] +bidi-chromium-page › page/page-goto.spec.ts › should send referer of cross-origin URL [fail] +bidi-chromium-page › page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [pass] +bidi-chromium-page › page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] +bidi-chromium-page › page/page-goto.spec.ts › should use http for no protocol [pass] bidi-chromium-page › page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return url with basic auth info [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work cross-process [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to 404 [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to data url [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to valid url [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work when page calls history API in beforeunload [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [fail] +bidi-chromium-page › page/page-goto.spec.ts › should work with anchor navigation [timeout] +bidi-chromium-page › page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with file URL [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with file URL with subframes [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with lazy loading iframes [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with redirects [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with self requesting page [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 [pass] +bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] +bidi-chromium-page › page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] +bidi-chromium-page › page/page-history.spec.ts › page.goBack during renderer-initiated navigation [timeout] bidi-chromium-page › page/page-history.spec.ts › page.goBack should work @smoke [fail] -bidi-chromium-page › page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] bidi-chromium-page › page/page-history.spec.ts › page.goBack should work for file urls [fail] -bidi-chromium-page › page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work with data url [timeout] +bidi-chromium-page › page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] +bidi-chromium-page › page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] bidi-chromium-page › page/page-history.spec.ts › page.reload during renderer-initiated navigation [pass] bidi-chromium-page › page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work with same origin redirect [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work [pass] bidi-chromium-page › page/page-history.spec.ts › page.reload should work on a page with a hash [pass] bidi-chromium-page › page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] -bidi-chromium-page › page/page-history.spec.ts › page.goBack during renderer-initiated navigation [timeout] -bidi-chromium-page › page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work with data url [timeout] +bidi-chromium-page › page/page-history.spec.ts › page.reload should work with same origin redirect [pass] bidi-chromium-page › page/page-history.spec.ts › regression test for issue 20791 [pass] bidi-chromium-page › page/page-history.spec.ts › should reload proper page [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › insertText should only emit input event [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] +bidi-chromium-page › page/page-keyboard.spec.ts › should handle selectAll [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should move around the selection in a contenteditable [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should move to the start of the document [fail] bidi-chromium-page › page/page-keyboard.spec.ts › should move with the arrow keys [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should not type canceled events [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should press Enter [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should press plus [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should press shift plus [fail] +bidi-chromium-page › page/page-keyboard.spec.ts › should press the meta key [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should report multiple modifiers [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should report shiftKey [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should scroll with PageDown [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should send a character with insertText [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › insertText should only emit input event [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should report shiftKey [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should report multiple modifiers [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should send proper codes while typing [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should send proper codes while typing with shift [timeout] -bidi-chromium-page › page/page-keyboard.spec.ts › should not type canceled events [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should press plus [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should press shift plus [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should shift raw codes [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should specify repeat property [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type all kinds of characters [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should specify location [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should press Enter [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should throw on unknown keys [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji into an iframe [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should handle selectAll [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should specify repeat property [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should support MacOS shortcuts [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should press the meta key [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] -bidi-chromium-page › page/page-keyboard.spec.ts › should scroll with PageDown [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should move around the selection in a contenteditable [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should move to the start of the document [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should support simple copy-pasting [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should support simple cut-pasting [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should support undo-redo [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should throw on unknown keys [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type after context menu was opened [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type all kinds of characters [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji into an iframe [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [pass] bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] +bidi-chromium-page › page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] bidi-chromium-page › page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type after context menu was opened [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] bidi-chromium-page › page/page-leaks.spec.ts › click should not leak [pass] -bidi-chromium-page › page/page-leaks.spec.ts › fill should not leak [pass] bidi-chromium-page › page/page-leaks.spec.ts › expect should not leak [pass] +bidi-chromium-page › page/page-leaks.spec.ts › fill should not leak [pass] bidi-chromium-page › page/page-leaks.spec.ts › waitFor should not leak [pass] bidi-chromium-page › page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] bidi-chromium-page › page/page-listeners.spec.ts › should wait [pass] bidi-chromium-page › page/page-listeners.spec.ts › wait should throw [pass] +bidi-chromium-page › page/page-mouse.spec.ts › down and up should generate click [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should always round down [fail] bidi-chromium-page › page/page-mouse.spec.ts › should click the document @smoke [pass] bidi-chromium-page › page/page-mouse.spec.ts › should dblclick the div [pass] -bidi-chromium-page › page/page-mouse.spec.ts › down and up should generate click [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] bidi-chromium-page › page/page-mouse.spec.ts › should pointerdown the div with a custom button [pass] bidi-chromium-page › page/page-mouse.spec.ts › should report correct buttons property [pass] bidi-chromium-page › page/page-mouse.spec.ts › should select the text with mouse [pass] +bidi-chromium-page › page/page-mouse.spec.ts › should set modifier keys on click [pass] bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state [pass] bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should set modifier keys on click [pass] bidi-chromium-page › page/page-mouse.spec.ts › should tween mouse movement [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should always round down [fail] -bidi-chromium-page › page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] bidi-chromium-page › page/page-navigation.spec.ts › should work with _blank target [pass] -bidi-chromium-page › page/page-navigation.spec.ts › should work with cross-process _blank target [pass] bidi-chromium-page › page/page-navigation.spec.ts › should work with _blank target in form [pass] +bidi-chromium-page › page/page-navigation.spec.ts › should work with cross-process _blank target [pass] bidi-chromium-page › page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the popup [pass] bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [pass] bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [pass] +bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [pass] bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the popup [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [pass] bidi-chromium-page › page/page-network-idle.spec.ts › should work after repeated navigations in the same page [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should work for main frame navigation request [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work for subframe navigation request [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work for a redirect [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should not work for a redirect and interception [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should return headers [pass] +bidi-chromium-page › page/page-network-request.spec.ts › page.reload return 304 status code [fail] bidi-chromium-page › page/page-network-request.spec.ts › should get the same headers as the server [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] bidi-chromium-page › page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] +bidi-chromium-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [pass] bidi-chromium-page › page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should return postData [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data and interception [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should not work for a redirect and interception [fail] bidi-chromium-page › page/page-network-request.spec.ts › should override post data content type [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should parse the json post data [fail] bidi-chromium-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] bidi-chromium-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should return multipart/form-data [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should parse the json post data [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should report all cookies in one header [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should report raw headers [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should report raw response headers in redirects [fail] bidi-chromium-page › page/page-network-request.spec.ts › should return event source [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should return headers [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should return multipart/form-data [fail] bidi-chromium-page › page/page-network-request.spec.ts › should return navigation bit [pass] bidi-chromium-page › page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should report raw headers [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should report raw response headers in redirects [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should report all cookies in one header [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [pass] -bidi-chromium-page › page/page-network-request.spec.ts › page.reload return 304 status code [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] -bidi-chromium-page › page/page-network-response.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should return postData [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should work for a redirect [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work for main frame navigation request [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work for subframe navigation request [pass] +bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data [fail] +bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data and interception [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should provide a Response with a file URL [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if context closes [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if page closes [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should report all headers [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return body [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return body for prefetch script [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return body with compression [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return headers after route.fulfill [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return json [fail] bidi-chromium-page › page/page-network-response.spec.ts › should return multiple header value [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [fail] +bidi-chromium-page › page/page-network-response.spec.ts › should return status text [pass] bidi-chromium-page › page/page-network-response.spec.ts › should return text [fail] bidi-chromium-page › page/page-network-response.spec.ts › should return uncompressed text [fail] bidi-chromium-page › page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] bidi-chromium-page › page/page-network-response.spec.ts › should wait until response completes [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if page closes [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if context closes [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return json [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return body [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return body with compression [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return status text [pass] -bidi-chromium-page › page/page-network-response.spec.ts › should report all headers [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should provide a Response with a file URL [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return headers after route.fulfill [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return body for prefetch script [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize and headersSize [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] +bidi-chromium-page › page/page-network-response.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should handle redirects [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize [fail] bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should handle redirects [fail] +bidi-chromium-page › page/page-network-sizes.spec.ts › should return sizes without hanging [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize and headersSize [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] +bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [fail] bidi-chromium-page › page/page-network-sizes.spec.ts › should throw for failed requests [pass] bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 200 status code [fail] bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 401 status code [fail] bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 404 status code [fail] bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 500 status code [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should return sizes without hanging [pass] bidi-chromium-page › page/page-object-count.spec.ts › should count objects [unknown] -bidi-chromium-page › page/page-request-continue.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend binary post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend longer post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend method and post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend utf8 post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › post data › should use content-type from original request [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] bidi-chromium-page › page/page-request-continue.spec.ts › should amend HTTP headers [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should delete header with undefined value [fail] bidi-chromium-page › page/page-request-continue.spec.ts › should amend method [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should override request url [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should amend method on main request [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should continue preload link requests [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should delete header with undefined value [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should delete the origin header [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should intercept css variable with background url [fail] bidi-chromium-page › page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing while page is closing [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] bidi-chromium-page › page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing while page is closing [fail] bidi-chromium-page › page/page-request-continue.spec.ts › should override method along with url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should amend method on main request [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend method and post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend utf8 post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend longer post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend binary post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should use content-type from original request [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should override request url [fail] +bidi-chromium-page › page/page-request-continue.spec.ts › should work [fail] bidi-chromium-page › page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should delete the origin header [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should continue preload link requests [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should intercept css variable with background url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend json post data [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend post data [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should amend HTTP headers [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should amend method [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should chain once [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should delete header with undefined value [fail] bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back after exception [fail] bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back async [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain fulfill [fail] bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain abort [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back after exception [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should chain once [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should amend HTTP headers [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should delete header with undefined value [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should amend method [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain fulfill [fail] bidi-chromium-page › page/page-request-fallback.spec.ts › should override request url [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend post data [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend json post data [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with buffer as body [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with status code 422 [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-request-fallback.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [fail] bidi-chromium-page › page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] bidi-chromium-page › page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with file path [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should include the origin header [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] bidi-chromium-page › page/page-request-fulfill.spec.ts › should fetch original request and fulfill [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with har response [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill preload link requests [fail] bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill json [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill preload link requests [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with har response [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should include the origin header [fail] bidi-chromium-page › page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with buffer as body [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with file path [fail] +bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with status code 422 [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill with any response [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should give access to the intercepted response body [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [unknown] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with url override [fail] bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with post data override [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] -bidi-chromium-page › page/page-route.spec.ts › should intercept @smoke [fail] -bidi-chromium-page › page/page-route.spec.ts › should unroute [fail] -bidi-chromium-page › page/page-route.spec.ts › should support ? in glob pattern [fail] -bidi-chromium-page › page/page-route.spec.ts › should work when POST is redirected with 302 [fail] -bidi-chromium-page › page/page-route.spec.ts › should work when header manipulation headers with redirect [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with url override [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] +bidi-chromium-page › page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] +bidi-chromium-page › page/page-route.spec.ts › route.abort should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › route.continue should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › route.fallback should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › route.fulfill should throw if called twice [fail] +bidi-chromium-page › page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] +bidi-chromium-page › page/page-route.spec.ts › should allow null origin for about:blank [fail] +bidi-chromium-page › page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [fail] bidi-chromium-page › page/page-route.spec.ts › should be able to remove headers [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain referer header [fail] -bidi-chromium-page › page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] -bidi-chromium-page › page/page-route.spec.ts › should override cookie header [pass] -bidi-chromium-page › page/page-route.spec.ts › should show custom HTTP headers [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with redirect inside sync XHR [fail] -bidi-chromium-page › page/page-route.spec.ts › should pause intercepted XHR until continue [fail] -bidi-chromium-page › page/page-route.spec.ts › should pause intercepted fetch request until continue [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with custom referer headers [fail] bidi-chromium-page › page/page-route.spec.ts › should be abortable [fail] bidi-chromium-page › page/page-route.spec.ts › should be abortable with custom error codes [fail] -bidi-chromium-page › page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] -bidi-chromium-page › page/page-route.spec.ts › should send referer [fail] -bidi-chromium-page › page/page-route.spec.ts › should fail navigation when aborting main resource [fail] -bidi-chromium-page › page/page-route.spec.ts › should not work with redirects [fail] bidi-chromium-page › page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with redirects for subresources [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with equal requests [fail] -bidi-chromium-page › page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] -bidi-chromium-page › page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [fail] -bidi-chromium-page › page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with encoded server [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with badly encoded server [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with encoded server - 2 [fail] -bidi-chromium-page › page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] -bidi-chromium-page › page/page-route.spec.ts › should intercept main resource during cross-process navigation [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain raw request header [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain raw response header [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain raw response header after fulfill [fail] +bidi-chromium-page › page/page-route.spec.ts › should contain referer header [fail] +bidi-chromium-page › page/page-route.spec.ts › should fail navigation when aborting main resource [fail] bidi-chromium-page › page/page-route.spec.ts › should fulfill with redirect status [fail] +bidi-chromium-page › page/page-route.spec.ts › should intercept @smoke [fail] +bidi-chromium-page › page/page-route.spec.ts › should intercept main resource during cross-process navigation [fail] +bidi-chromium-page › page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] +bidi-chromium-page › page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [fail] +bidi-chromium-page › page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] +bidi-chromium-page › page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] bidi-chromium-page › page/page-route.spec.ts › should not fulfill with redirect status [unknown] -bidi-chromium-page › page/page-route.spec.ts › should support cors with GET [fail] -bidi-chromium-page › page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] -bidi-chromium-page › page/page-route.spec.ts › should allow null origin for about:blank [fail] +bidi-chromium-page › page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] +bidi-chromium-page › page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-chromium-page › page/page-route.spec.ts › should not work with redirects [fail] +bidi-chromium-page › page/page-route.spec.ts › should override cookie header [pass] +bidi-chromium-page › page/page-route.spec.ts › should pause intercepted XHR until continue [fail] +bidi-chromium-page › page/page-route.spec.ts › should pause intercepted fetch request until continue [fail] +bidi-chromium-page › page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] +bidi-chromium-page › page/page-route.spec.ts › should reject cors with disallowed credentials [fail] bidi-chromium-page › page/page-route.spec.ts › should respect cors overrides [fail] -bidi-chromium-page › page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] +bidi-chromium-page › page/page-route.spec.ts › should send referer [fail] +bidi-chromium-page › page/page-route.spec.ts › should show custom HTTP headers [fail] +bidi-chromium-page › page/page-route.spec.ts › should support ? in glob pattern [fail] +bidi-chromium-page › page/page-route.spec.ts › should support async handler w/ times [fail] +bidi-chromium-page › page/page-route.spec.ts › should support cors for different methods [fail] +bidi-chromium-page › page/page-route.spec.ts › should support cors with GET [fail] bidi-chromium-page › page/page-route.spec.ts › should support cors with POST [fail] bidi-chromium-page › page/page-route.spec.ts › should support cors with credentials [fail] -bidi-chromium-page › page/page-route.spec.ts › should reject cors with disallowed credentials [fail] -bidi-chromium-page › page/page-route.spec.ts › should support cors for different methods [fail] bidi-chromium-page › page/page-route.spec.ts › should support the times parameter with route matching [fail] +bidi-chromium-page › page/page-route.spec.ts › should unroute [fail] bidi-chromium-page › page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] -bidi-chromium-page › page/page-route.spec.ts › should support async handler w/ times [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain raw request header [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain raw response header [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain raw response header after fulfill [fail] -bidi-chromium-page › page/page-route.spec.ts › route.fulfill should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › route.continue should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › route.fallback should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › route.abort should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +bidi-chromium-page › page/page-route.spec.ts › should work when POST is redirected with 302 [fail] +bidi-chromium-page › page/page-route.spec.ts › should work when header manipulation headers with redirect [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with badly encoded server [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with custom referer headers [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with encoded server [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with encoded server - 2 [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with equal requests [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with redirect inside sync XHR [fail] +bidi-chromium-page › page/page-route.spec.ts › should work with redirects for subresources [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should work [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should work [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [pass] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] +bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › should throw if screenshot size is too large [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot should capture css transform [unknown] -bidi-chromium-page › page/page-screenshot.spec.ts › should capture css box-shadow [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option @smoke [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by value [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should fall back to selecting by label [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by label [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by handle [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by index [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by multiple attributes [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should not select single option when some attributes do not match [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select only first option [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should not throw when select causes navigation [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select multiple options [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should select multiple options with attributes [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should respect event bubbling [unknown] -bidi-chromium-page › page/page-select-option.spec.ts › should throw when element is not a [pass] +bidi-chromium-page › page/page-select-option.spec.ts › should unselect with null [pass] +bidi-chromium-page › page/page-select-option.spec.ts › should wait for multiple options to be present [pass] +bidi-chromium-page › page/page-select-option.spec.ts › should wait for option index to be present [pass] +bidi-chromium-page › page/page-select-option.spec.ts › should wait for option to be present [pass] +bidi-chromium-page › page/page-select-option.spec.ts › should work when re-defining top-level Event class [pass] +bidi-chromium-page › page/page-set-content.spec.ts › content() should throw nice error during navigation [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should await resources to load [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should respect default navigation timeout [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should respect timeout [pass] bidi-chromium-page › page/page-set-content.spec.ts › should return empty content there is no iframe src [unknown] -bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should work @smoke [unknown] -bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should work with redirects [unknown] -bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should work with extra headers from browser context [unknown] -bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should throw for non-string header values [unknown] -bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should not duplicate referer header [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload the file [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload a folder [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload a folder and throw for multiple directories [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should throw if a directory and files are passed [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should throw when uploading a folder in a normal file upload input [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should throw when uploading a file in a directory upload input [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload a file after popup [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload large file [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should throw an error if the file does not exist [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload multiple large files [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload large file with relative path [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should upload the file with spaces in name [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work @smoke [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should set from memory [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event once [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event via prepend [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event for iframe [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event on/off [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event addListener/removeListener [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work when file input is attached to DOM [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work when file input is not attached to DOM [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should not throw when filechooser belongs to iframe [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should not throw when frame is detached immediately [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work with CSP [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should respect default timeout when there is no custom timeout [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should prioritize exact timeout over default timeout [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work with no timeout [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should return the same file chooser when there are many watchdogs simultaneously [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should accept single file [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should detect mime type [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should not trim big uploaded files [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should be able to read selected file [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should be able to reset selected files with empty file list [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should not accept multiple files for single-file input [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit input and change events [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › input event.composed should be true and cross shadow dom boundary [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work for single file pick [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work for "multiple" [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should work for "webkitdirectory" [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event after navigation [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should trigger listener added before navigation [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › input should trigger events when files changed second time [unknown] -bidi-chromium-page › page/page-set-input-files.spec.ts › should preserve lastModified timestamp [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should fail page.textContent in strict mode [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should fail page.getAttribute in strict mode [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should fail page.fill in strict mode [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should fail page.$ in strict mode [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should fail page.waitForSelector in strict mode [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should fail page.dispatchEvent in strict mode [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should properly format :nth-child() in strict mode message [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should escape class names [unknown] -bidi-chromium-page › page/page-strict.spec.ts › should escape tag names [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should timeout [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should accept a string [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should work when resolved right before execution context disposal [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should poll on interval [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should avoid side effects after timeout [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw on polling:mutation [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should poll on raf [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should fail with predicate throwing on first call [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should fail with predicate throwing sometimes [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should fail with ReferenceError on wrong page [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should work with strict CSP policy [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw on bad polling value [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw negative polling interval [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should return the success value as a JSHandle [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should return the window as a success value [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should accept ElementHandle arguments [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should respect default timeout [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should disable timeout when its set to 0 [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should survive cross-process navigation [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should survive navigations [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should work with multiline body [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should wait for predicate with arguments [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should not be called after finishing successfully [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should not be called after finishing unsuccessfully [unknown] -bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw when frame is detached [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should pick up ongoing navigation [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should resolve immediately if loaded [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should throw for bad state [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should resolve immediately if load state matches [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with pages that have loaded before being connected to [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of empty url popup [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup with noopener [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of popup with network url [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of popup with network url and noopener [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with clicking target=_blank [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of newPage [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should resolve after popup load [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work for frame [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with javascript: iframe [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with broken data-url iframe [unknown] -bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with broken blob-url iframe [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with both domcontentloaded and load [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with commit [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with clicking on anchor links [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with clicking on links which do not commit navigation [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with history.pushState() [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with history.replaceState() [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with DOM history.back()/history.forward() [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work when subframe issues window.stop() [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with url match [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with url match for same document navigations [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work for cross-process navigations [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work on frame [unknown] -bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should fail when frame detaches [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should work [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with predicate [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should respect default timeout [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should log the url [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with no timeout [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with url match [unknown] -bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with url match regular expression from a different context [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should work [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should respect default timeout [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should log the url [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with predicate [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with async predicate [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › sync predicate should be only called once [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with no timeout [unknown] -bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with re-rendered cached IMG elements [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should throw on waitFor [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should tolerate waitFor=visible [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should immediately resolve promise if node exists [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should immediately resolve if node exists [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should wait [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should timeout [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should throw on navigation [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should work with removed MutationObserver [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should resolve promise when node is added [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should report logs while waiting for visible [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should report logs while waiting for hidden [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should report logs when the selector resolves to multiple elements [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should resolve promise when node is added in shadow dom [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should work when node is added through innerHTML [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › page.waitForSelector is shortcut for main frame [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should run in specified frame [unknown] -bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should throw when frame is detached [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should survive cross-process navigation [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for visible [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should not consider visible when zero-sized [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for visible recursively [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should consider outside of viewport visible [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › hidden should wait for hidden [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › hidden should wait for display: none [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › hidden should wait for removal [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should return null if waiting to hide non-existing element [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should have an error message specifically for awaiting an element to be hidden [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should respond to node attribute mutation [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should return the element handle [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should have correct stack trace for timeout [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for unknown state option [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for visibility option [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for true state option [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for false state option [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should support >> selector syntax [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for detached if already detached [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for detached [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should support some fancy xpath [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should respect timeout xpath [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should run in specified frame xpath [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw when frame is detached xpath [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should return the element handle xpath [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should allow you to select an element with single slash xpath [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should correctly handle hidden shadow host [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should work when navigating before node adoption [unknown] -bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should fail when navigating while on handle [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should respect timeout [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with both domcontentloaded and load [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with commit [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with commit and about:blank [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with clicking on anchor links [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with history.pushState() [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with history.replaceState() [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with DOM history.back()/history.forward() [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with url match for same document navigations [unknown] -bidi-chromium-page › page/page-wait-for-url.spec.ts › should work on frame [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should throw for non-string selector [unknown] +bidi-chromium-page › page/page-set-content.spec.ts › should work @smoke [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work fast enough [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with HTML 4 doctype [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with accents [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with commit [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with doctype [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with domcontentloaded [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with emojis [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with newline [pass] +bidi-chromium-page › page/page-set-content.spec.ts › should work with tricky content [pass] +bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should not duplicate referer header [fail] +bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] +bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should work with extra headers from browser context [fail] +bidi-chromium-page › page/page-set-extra-http-headers.spec.ts › should work with redirects [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › input event.composed should be true and cross shadow dom boundary [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › input should trigger events when files changed second time [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should accept single file [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should be able to read selected file [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should be able to reset selected files with empty file list [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should detect mime type [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event addListener/removeListener [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event after navigation [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event for iframe [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event on/off [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event once [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit event via prepend [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should emit input and change events [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should not accept multiple files for single-file input [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should not throw when filechooser belongs to iframe [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should not throw when frame is detached immediately [pass] +bidi-chromium-page › page/page-set-input-files.spec.ts › should not trim big uploaded files [pass] +bidi-chromium-page › page/page-set-input-files.spec.ts › should preserve lastModified timestamp [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should prioritize exact timeout over default timeout [pass] +bidi-chromium-page › page/page-set-input-files.spec.ts › should respect default timeout when there is no custom timeout [pass] +bidi-chromium-page › page/page-set-input-files.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-set-input-files.spec.ts › should return the same file chooser when there are many watchdogs simultaneously [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should set from memory [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should throw an error if the file does not exist [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should throw if a directory and files are passed [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should throw when uploading a file in a directory upload input [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should throw when uploading a folder in a normal file upload input [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should trigger listener added before navigation [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload a file after popup [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload a folder [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload a folder and throw for multiple directories [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload large file [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload large file with relative path [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload multiple large files [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload the file [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should upload the file with spaces in name [fail] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work @smoke [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work for "multiple" [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work for "webkitdirectory" [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work for single file pick [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work when file input is attached to DOM [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work when file input is not attached to DOM [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work with CSP [timeout] +bidi-chromium-page › page/page-set-input-files.spec.ts › should work with no timeout [timeout] +bidi-chromium-page › page/page-strict.spec.ts › should escape class names [pass] +bidi-chromium-page › page/page-strict.spec.ts › should escape tag names [pass] +bidi-chromium-page › page/page-strict.spec.ts › should fail page.$ in strict mode [pass] +bidi-chromium-page › page/page-strict.spec.ts › should fail page.dispatchEvent in strict mode [pass] +bidi-chromium-page › page/page-strict.spec.ts › should fail page.fill in strict mode [pass] +bidi-chromium-page › page/page-strict.spec.ts › should fail page.getAttribute in strict mode [pass] +bidi-chromium-page › page/page-strict.spec.ts › should fail page.textContent in strict mode [pass] +bidi-chromium-page › page/page-strict.spec.ts › should fail page.waitForSelector in strict mode [pass] +bidi-chromium-page › page/page-strict.spec.ts › should properly format :nth-child() in strict mode message [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should accept ElementHandle arguments [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should accept a string [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should avoid side effects after timeout [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should disable timeout when its set to 0 [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should fail with ReferenceError on wrong page [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should fail with predicate throwing on first call [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should fail with predicate throwing sometimes [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should not be called after finishing successfully [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should not be called after finishing unsuccessfully [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should poll on interval [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should poll on raf [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should respect default timeout [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should return the success value as a JSHandle [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should return the window as a success value [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should survive cross-process navigation [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should survive navigations [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw negative polling interval [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw on bad polling value [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw on polling:mutation [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should throw when frame is detached [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should timeout [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should wait for predicate with arguments [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should work when resolved right before execution context disposal [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should work with multiline body [pass] +bidi-chromium-page › page/page-wait-for-function.spec.ts › should work with strict CSP policy [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should pick up ongoing navigation [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should resolve after popup load [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should resolve immediately if load state matches [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should resolve immediately if loaded [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should throw for bad state [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup with noopener [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of empty url popup [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of newPage [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of popup with network url [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should wait for load state of popup with network url and noopener [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work for frame [fail] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with broken blob-url iframe [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with broken data-url iframe [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with clicking target=_blank [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with javascript: iframe [pass] +bidi-chromium-page › page/page-wait-for-load-state.spec.ts › should work with pages that have loaded before being connected to [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should fail when frame detaches [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work for cross-process navigations [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work on frame [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work when subframe issues window.stop() [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with DOM history.back()/history.forward() [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with both domcontentloaded and load [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with clicking on anchor links [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with clicking on links which do not commit navigation [fail] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with commit [fail] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with history.pushState() [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with history.replaceState() [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with url match [pass] +bidi-chromium-page › page/page-wait-for-navigation.spec.ts › should work with url match for same document navigations [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should log the url [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should respect default timeout [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should work [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with no timeout [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with predicate [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with url match [pass] +bidi-chromium-page › page/page-wait-for-request.spec.ts › should work with url match regular expression from a different context [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should log the url [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should respect default timeout [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should work [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with async predicate [fail] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with no timeout [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with predicate [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › should work with re-rendered cached IMG elements [pass] +bidi-chromium-page › page/page-wait-for-response.spec.ts › sync predicate should be only called once [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should immediately resolve if node exists [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should throw on navigation [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should timeout [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › elementHandle.waitForSelector should wait [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › page.waitForSelector is shortcut for main frame [fail] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should immediately resolve promise if node exists [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should report logs when the selector resolves to multiple elements [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should report logs while waiting for hidden [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should report logs while waiting for visible [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should resolve promise when node is added [fail] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should resolve promise when node is added in shadow dom [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should run in specified frame [fail] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should throw on waitFor [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should throw when frame is detached [fail] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should tolerate waitFor=visible [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should work when node is added through innerHTML [pass] +bidi-chromium-page › page/page-wait-for-selector-1.spec.ts › should work with removed MutationObserver [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › hidden should wait for display: none [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › hidden should wait for hidden [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › hidden should wait for removal [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should allow you to select an element with single slash xpath [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should consider outside of viewport visible [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should correctly handle hidden shadow host [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should fail when navigating while on handle [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should have an error message specifically for awaiting an element to be hidden [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should have correct stack trace for timeout [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should not consider visible when zero-sized [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should respect timeout xpath [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should respond to node attribute mutation [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should return null if waiting to hide non-existing element [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should return the element handle [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should return the element handle xpath [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should run in specified frame xpath [fail] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should support >> selector syntax [fail] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should support some fancy xpath [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should survive cross-process navigation [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for false state option [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for true state option [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for unknown state option [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw for visibility option [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should throw when frame is detached xpath [fail] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for detached [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for detached if already detached [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for visible [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should wait for visible recursively [pass] +bidi-chromium-page › page/page-wait-for-selector-2.spec.ts › should work when navigating before node adoption [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should respect timeout [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work on frame [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with DOM history.back()/history.forward() [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with both domcontentloaded and load [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with clicking on anchor links [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with commit [fail] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with commit and about:blank [timeout] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with history.pushState() [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with history.replaceState() [pass] +bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with url match for same document navigations [pass] +bidi-chromium-page › page/queryselector.spec.ts › $$ should work with bogus Array.from [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect css selector [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect text selector [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector starting with .. [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector with starting parenthesis [unknown] bidi-chromium-page › page/queryselector.spec.ts › should query existing element with css selector @smoke [unknown] bidi-chromium-page › page/queryselector.spec.ts › should query existing element with text selector [unknown] bidi-chromium-page › page/queryselector.spec.ts › should query existing element with xpath selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should return null for non-existing element [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector with starting parenthesis [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector starting with .. [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect text selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect css selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should support >> syntax [unknown] bidi-chromium-page › page/queryselector.spec.ts › should query existing elements [unknown] bidi-chromium-page › page/queryselector.spec.ts › should return empty array if nothing is found [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should return null for non-existing element [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should support >> syntax [unknown] +bidi-chromium-page › page/queryselector.spec.ts › should throw for non-string selector [unknown] bidi-chromium-page › page/queryselector.spec.ts › xpath should query existing element [unknown] bidi-chromium-page › page/queryselector.spec.ts › xpath should return empty array for non-existing element [unknown] bidi-chromium-page › page/queryselector.spec.ts › xpath should return multiple elements [unknown] -bidi-chromium-page › page/queryselector.spec.ts › $$ should work with bogus Array.from [unknown] +bidi-chromium-page › page/retarget.spec.ts › check retargeting [unknown] +bidi-chromium-page › page/retarget.spec.ts › direct actions retargeting [unknown] +bidi-chromium-page › page/retarget.spec.ts › editable retargeting [unknown] bidi-chromium-page › page/retarget.spec.ts › element state checks should work as expected for label with zero-sized input [unknown] -bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing disabled button [unknown] -bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing button with a disabled fieldset [unknown] -bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing enabled button [unknown] -bidi-chromium-page › page/retarget.spec.ts › should check the box outside shadow dom label [unknown] -bidi-chromium-page › page/retarget.spec.ts › setInputFiles should work with label [unknown] bidi-chromium-page › page/retarget.spec.ts › enabled/disabled retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › visible/hidden retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › editable retargeting [unknown] bidi-chromium-page › page/retarget.spec.ts › input value retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › selection retargeting [unknown] bidi-chromium-page › page/retarget.spec.ts › select options retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › direct actions retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › check retargeting [unknown] +bidi-chromium-page › page/retarget.spec.ts › selection retargeting [unknown] +bidi-chromium-page › page/retarget.spec.ts › setInputFiles should work with label [unknown] +bidi-chromium-page › page/retarget.spec.ts › should check the box outside shadow dom label [unknown] bidi-chromium-page › page/retarget.spec.ts › should not retarget anchor into parent label [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with large DOM @smoke [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work for open shadow roots [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with > combinator and spaces [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list [unknown] +bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing button with a disabled fieldset [unknown] +bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing disabled button [unknown] +bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing enabled button [unknown] +bidi-chromium-page › page/retarget.spec.ts › visible/hidden retargeting [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › css on the handle should be relative [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should absolutize relative selectors [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should keep dom order with comma separated list [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should not match root after >> [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should return multiple captures for the same node [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should return multiple captures when going up the hierarchy [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list in various positions [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with comma inside text [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with attribute selectors [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should not match root after >> [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with numerical id [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with wrong-case id [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work for open shadow roots [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should work with * [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child(of) notation with nested functions [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :not [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with ~ [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should work with + [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with spaces in :nth-child and :not [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :is [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should work with :has [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :is [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :not [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child(of) notation with nested functions [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should work with :scope [unknown] bidi-chromium-page › page/selectors-css.spec.ts › should work with :scope and class [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should absolutize relative selectors [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › css on the handle should be relative [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe @smoke [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with > combinator and spaces [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with attribute selectors [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with comma inside text [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list in various positions [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with large DOM @smoke [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with numerical id [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with spaces in :nth-child and :not [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with wrong-case id [unknown] +bidi-chromium-page › page/selectors-css.spec.ts › should work with ~ [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › $ should not wait for frame [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › $$ should not wait for frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › $eval should throw for missing frame [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › $$eval should throw for missing frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › $eval should throw for missing frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › click should survive frame reattach [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › click should survive iframe navigation [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › click should survive navigation [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should capture after the enter-frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should click in lazy iframe [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should non work for non-frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should not allow capturing before enter-frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should not allow dangling enter-frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should not allow leading enter-frame [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval (handle) [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › should work for $$eval [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › should work for $$eval (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should not allow dangling enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should not allow leading enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should not allow capturing before enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should capture after the enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should click in lazy iframe [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval (handle) [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe (handle) [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe @smoke [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe (handle) [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › waitFor should survive frame reattach [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › waitForSelector should survive frame reattach (handle) [unknown] bidi-chromium-page › page/selectors-frame.spec.ts › waitForSelector should survive iframe navigation (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › click should survive frame reattach [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › click should survive iframe navigation [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › click should survive navigation [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should non work for non-frame [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId with custom testId should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should escape id [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work for regex [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByText should work [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getBy escaping [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByAltText should work [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should ignore empty aria-label [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over aria-label [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over native label [unknown] bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with nested elements [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with multiply-labelled input [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and multiple controls [unknown] bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and for [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-labelledby [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over native label [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and multiple controls [unknown] bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-label [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should ignore empty aria-label [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over aria-label [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-labelledby [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with multiply-labelled input [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with nested elements [unknown] bidi-chromium-page › page/selectors-get-by.spec.ts › getByPlaceholder should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByAltText should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTitle should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getBy escaping [unknown] bidi-chromium-page › page/selectors-get-by.spec.ts › getByRole escaping [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work for open shadow roots [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should escape id [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work for regex [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId with custom testId should work [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByText should work [unknown] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTitle should work [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › chaining should work with large DOM @smoke [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › data-testid on the handle should be relative [unknown] bidi-chromium-page › page/selectors-misc.spec.ts › should click on links in shadow dom [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with :visible [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with >> visible= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with :nth-match [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with nth= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with strict mode and chaining [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with layout selectors [unknown] bidi-chromium-page › page/selectors-misc.spec.ts › should escape the scope with >> [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › xpath should be relative [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with pipe in xpath [unknown] bidi-chromium-page › page/selectors-misc.spec.ts › should print original xpath in error [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › data-testid on the handle should be relative [unknown] bidi-chromium-page › page/selectors-misc.spec.ts › should properly determine visibility of display:contents elements [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has-not= [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work for open shadow roots [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with :nth-match [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with :visible [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with >> visible= [unknown] bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:and= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:or= [unknown] bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:chain= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › chaining should work with large DOM @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should not crash when there is no match [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has-not= [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has= [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:or= [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with layout selectors [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with nth= [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with pipe in xpath [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with strict mode and chaining [unknown] +bidi-chromium-page › page/selectors-misc.spec.ts › xpath should be relative [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should exact match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should not crash when there is no match [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should partially match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support all string operators [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support nested react trees [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support regex [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multi-root elements (fragments) [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react inside shadow DOM [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should not crash when there is no match [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with single-root elements @smoke [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should exact match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should not crash when there is no match [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should partially match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support all string operators [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support nested react trees [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support regex [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multi-root elements (fragments) [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react inside shadow DOM [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should not crash when there is no match [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with single-root elements @smoke [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should exact match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should not crash when there is no match [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should partially match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support all string operators [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support nested react trees [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support regex [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multi-root elements (fragments) [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react inside shadow DOM [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should not crash when there is no match [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with single-root elements @smoke [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should exact match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should not crash when there is no match [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should partially match by props [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support all string operators [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support nested react trees [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support regex [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multi-root elements (fragments) [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react inside shadow DOM [unknown] bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › textContent should be atomic [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › innerText should be atomic [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › innerHTML should be atomic [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with react memo [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with single-root elements @smoke [unknown] bidi-chromium-page › page/selectors-register.spec.ts › getAttribute should be atomic [unknown] +bidi-chromium-page › page/selectors-register.spec.ts › innerHTML should be atomic [unknown] +bidi-chromium-page › page/selectors-register.spec.ts › innerText should be atomic [unknown] bidi-chromium-page › page/selectors-register.spec.ts › isVisible should be atomic [unknown] +bidi-chromium-page › page/selectors-register.spec.ts › textContent should be atomic [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › errors [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › hidden with shadow dom slots [unknown] bidi-chromium-page › page/selectors-role.spec.ts › should detect roles [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support selected [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › should filter hidden, unless explicitly asked for [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › should not match scope by default [unknown] bidi-chromium-page › page/selectors-role.spec.ts › should support checked [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support pressed [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support expanded [unknown] bidi-chromium-page › page/selectors-role.spec.ts › should support disabled [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › should support expanded [unknown] bidi-chromium-page › page/selectors-role.spec.ts › should support level [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should filter hidden, unless explicitly asked for [unknown] bidi-chromium-page › page/selectors-role.spec.ts › should support name [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › errors [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › hidden with shadow dom slots [unknown] bidi-chromium-page › page/selectors-role.spec.ts › should support output accessible name [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should not match scope by default [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work @smoke [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with :text [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should support empty string [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work across nodes [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with text nodes in quoted mode [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should clear caches [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with :has-text [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with large DOM [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › should support pressed [unknown] +bidi-chromium-page › page/selectors-role.spec.ts › should support selected [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › hasText and internal:text should match full node text in strict mode [unknown] bidi-chromium-page › page/selectors-text.spec.ts › should be case sensitive if quotes are specified [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should search for a substring without quotes [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should skip head, script and style [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should clear caches [unknown] bidi-chromium-page › page/selectors-text.spec.ts › should match input[type=button|submit] [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work for open shadow roots [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should prioritize light dom over shadow dom in the same parent [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should waitForSelector with distributed elements [unknown] bidi-chromium-page › page/selectors-text.spec.ts › should match root after >> [unknown] bidi-chromium-page › page/selectors-text.spec.ts › should match root after >> with * [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should prioritize light dom over shadow dom in the same parent [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should search for a substring without quotes [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should skip head, script and style [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should support empty string [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should waitForSelector with distributed elements [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work @smoke [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work across nodes [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work for open shadow roots [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work with :has-text [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work with :text [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work with large DOM [unknown] bidi-chromium-page › page/selectors-text.spec.ts › should work with leading and trailing spaces [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with unpaired quotes when not at the start [unknown] bidi-chromium-page › page/selectors-text.spec.ts › should work with paired quotes in the middle of selector [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › hasText and internal:text should match full node text in strict mode [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should not crash when there is no match [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work with text nodes in quoted mode [unknown] +bidi-chromium-page › page/selectors-text.spec.ts › should work with unpaired quotes when not at the start [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should compose [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should exact match by props [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should not crash when there is no match [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should partially match by props [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support all string operators [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support nested vue trees [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support regex [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support nested vue trees [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multi-root elements (fragments) [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multiroot react [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multiroot vue inside shadow DOM [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should not crash when there is no match [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with single-root elements @smoke [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should compose [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should exact match by props [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should not crash when there is no match [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should partially match by props [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should query by props combinations [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support all string operators [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support nested vue trees [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support regex [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support nested vue trees [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multi-root elements (fragments) [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multiroot react [unknown] bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multiroot vue inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with single-root elements @smoke [unknown] +bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel event on svg element [unknown] bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events @smoke [unknown] bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events after context menu was opened [unknown] bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events after popup was opened @smoke [unknown] -bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel event on svg element [unknown] +bidi-chromium-page › page/wheel.spec.ts › should scroll horizontally [unknown] bidi-chromium-page › page/wheel.spec.ts › should scroll when nobody is listening [unknown] bidi-chromium-page › page/wheel.spec.ts › should set the modifiers [unknown] -bidi-chromium-page › page/wheel.spec.ts › should scroll horizontally [unknown] bidi-chromium-page › page/wheel.spec.ts › should work when the event is canceled [unknown] bidi-chromium-page › page/workers.spec.ts › Page.workers @smoke [unknown] +bidi-chromium-page › page/workers.spec.ts › should attribute network activity for worker inside iframe to the iframe [unknown] +bidi-chromium-page › page/workers.spec.ts › should clear upon cross-process navigation [unknown] +bidi-chromium-page › page/workers.spec.ts › should clear upon navigation [unknown] +bidi-chromium-page › page/workers.spec.ts › should dispatch console messages when page has workers [unknown] bidi-chromium-page › page/workers.spec.ts › should emit created and destroyed events [unknown] -bidi-chromium-page › page/workers.spec.ts › should report console logs [unknown] -bidi-chromium-page › page/workers.spec.ts › should not report console logs from workers twice [unknown] -bidi-chromium-page › page/workers.spec.ts › should have JSHandles for console logs [unknown] bidi-chromium-page › page/workers.spec.ts › should evaluate [unknown] +bidi-chromium-page › page/workers.spec.ts › should have JSHandles for console logs [unknown] +bidi-chromium-page › page/workers.spec.ts › should not report console logs from workers twice [unknown] +bidi-chromium-page › page/workers.spec.ts › should report and intercept network from nested worker [unknown] +bidi-chromium-page › page/workers.spec.ts › should report console logs [unknown] bidi-chromium-page › page/workers.spec.ts › should report errors [unknown] -bidi-chromium-page › page/workers.spec.ts › should clear upon navigation [unknown] -bidi-chromium-page › page/workers.spec.ts › should clear upon cross-process navigation [unknown] -bidi-chromium-page › page/workers.spec.ts › should attribute network activity for worker inside iframe to the iframe [unknown] bidi-chromium-page › page/workers.spec.ts › should report network activity [unknown] bidi-chromium-page › page/workers.spec.ts › should report network activity on worker creation [unknown] -bidi-chromium-page › page/workers.spec.ts › should dispatch console messages when page has workers [unknown] -bidi-chromium-page › page/workers.spec.ts › should report and intercept network from nested worker [unknown] bidi-chromium-page › page/workers.spec.ts › should support extra http headers [unknown] bidi-chromium-page › page/workers.spec.ts › should support offline [unknown] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-firefox-beta-library.txt b/tests/bidi/expectations/bidi-firefox-beta-library.txt new file mode 100644 index 0000000000000..070ee241c128e --- /dev/null +++ b/tests/bidi/expectations/bidi-firefox-beta-library.txt @@ -0,0 +1,1911 @@ +bidi-firefox-beta-library › library/beforeunload.spec.ts › should access page after beforeunload [fail] +bidi-firefox-beta-library › library/beforeunload.spec.ts › should be able to navigate away from page with beforeunload [fail] +bidi-firefox-beta-library › library/beforeunload.spec.ts › should close browser with beforeunload page [fail] +bidi-firefox-beta-library › library/beforeunload.spec.ts › should close browsercontext with beforeunload page [pass] +bidi-firefox-beta-library › library/beforeunload.spec.ts › should close page with beforeunload listener [pass] +bidi-firefox-beta-library › library/beforeunload.spec.ts › should not stall on evaluate when dismissing beforeunload [fail] +bidi-firefox-beta-library › library/beforeunload.spec.ts › should run beforeunload if asked for @smoke [fail] +bidi-firefox-beta-library › library/browser.spec.ts › should create new page @smoke [pass] +bidi-firefox-beta-library › library/browser.spec.ts › should dispatch page.on(close) upon browser.close and reject evaluate [pass] +bidi-firefox-beta-library › library/browser.spec.ts › should return browserType [pass] +bidi-firefox-beta-library › library/browser.spec.ts › should throw upon second create new page [pass] +bidi-firefox-beta-library › library/browser.spec.ts › version should work [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should add cookies with empty value [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should allow unnamed cookies [fail] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should be able to set unsecure cookie for HTTP website [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should default to setting secure cookie for HTTPS websites [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should have |expires| set to |-1| for session cookies [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should isolate cookies between launches [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should isolate cookies in browser contexts [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should isolate persistent cookies [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should isolate send cookie header [fail] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should isolate session cookies [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should not block third party SameSite=None cookies [fail] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should not set a cookie on a data URL page [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should not set a cookie with blank page URL [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should roundtrip cookie [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should send cookie header [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should set a cookie on a different domain [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should set a cookie with a path [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should set cookie with reasonable defaults [fail] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should set cookies for a frame [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should set multiple cookies [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should set secure cookies on secure WebSocket [fail] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should work @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should work with expires=-1 [fail] +bidi-firefox-beta-library › library/browsercontext-add-cookies.spec.ts › should(not) block third party cookies [fail] +bidi-firefox-beta-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts for already created pages [pass] +bidi-firefox-beta-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts with a path [pass] +bidi-firefox-beta-library › library/browsercontext-add-init-script.spec.ts › should work without navigation in popup [fail] +bidi-firefox-beta-library › library/browsercontext-add-init-script.spec.ts › should work without navigation, after all bindings [fail] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should be able to match a URL relative to its given URL with urlMatcher [fail] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newContext is passed to page.goto @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newPage is passed to page.goto [pass] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browserType.launchPersistentContext is passed to page.goto [fail] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL with a trailing slash in browser.newPage is passed to page.goto [pass] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL without a trailing slash in browser.newPage is passed to page.goto [pass] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should not construct a new URL when valid URLs are passed [pass] +bidi-firefox-beta-library › library/browsercontext-base-url.spec.ts › should not construct a new URL with baseURL when a glob was used [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › close() should abort waitForEvent [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › close() should be callable twice [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › close() should work for empty context [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › default user agent [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › setContent should work after disabling javascript [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should be able to click across browser contexts [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should be able to navigate after disabling javascript [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should close all belonging pages once closing context [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should create new context @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should disable javascript [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should emulate media in cross-process iframe [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should emulate media in popup [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should emulate navigator.onLine [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should isolate localStorage and cookies @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should make a copy of default viewport [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should not allow deviceScaleFactor with null viewport [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should not allow isMobile with null viewport [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should not hang on promises after disabling javascript [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should not report frameless pages on error [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should pass self to close event [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should propagate default viewport to the page [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should respect deviceScaleFactor [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should return all of the pages [pass] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › should work with offline option [fail] +bidi-firefox-beta-library › library/browsercontext-basic.spec.ts › window.open should use parent tab context [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should clear cookies [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should isolate cookies when clearing [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by domain [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name and domain [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name regex [pass] +bidi-firefox-beta-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by path [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should add cookies with an expiration [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should be able to send third party cookies via an iframe [fail] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should get a cookie @smoke [fail] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should get a non-session cookie [fail] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should get cookies from multiple urls [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should get multiple cookies [fail] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should parse cookie with large Max-Age correctly [fail] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should properly report "Lax" sameSite cookie [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should properly report "Strict" sameSite cookie [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should properly report httpOnly cookie [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should return cookies with empty value [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should return no cookies in pristine browser context [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should return secure cookies based on HTTP(S) protocol [pass] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should support requestStorageAccess [fail] +bidi-firefox-beta-library › library/browsercontext-cookies.spec.ts › should work with subdomain cookie [pass] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching hostname [pass] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching port [pass] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching scheme [pass] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should fail with wrong credentials [timeout] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should fail without credentials [timeout] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should return resource body [fail] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should work with correct credentials @smoke [fail] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin [fail] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin case insensitive [fail] +bidi-firefox-beta-library › library/browsercontext-credentials.spec.ts › should work with setHTTPCredentials [timeout] +bidi-firefox-beta-library › library/browsercontext-csp.spec.ts › should bypass CSP header [fail] +bidi-firefox-beta-library › library/browsercontext-csp.spec.ts › should bypass CSP in iframes as well [fail] +bidi-firefox-beta-library › library/browsercontext-csp.spec.ts › should bypass CSP meta tag @smoke [fail] +bidi-firefox-beta-library › library/browsercontext-csp.spec.ts › should bypass after cross-process navigation [fail] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should emulate viewport and screen size [fail] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should emulate viewport without screen size [fail] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should reset scroll top after a navigation [pass] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should scroll to a precise position with mobile scale [pass] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should scroll to click [pass] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should scroll twice when emulated [fail] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should support clicking [pass] +bidi-firefox-beta-library › library/browsercontext-device.spec.ts › device › should work @smoke [fail] +bidi-firefox-beta-library › library/browsercontext-dsf.spec.ts › should fetch hidpi assets [fail] +bidi-firefox-beta-library › library/browsercontext-dsf.spec.ts › should fetch lodpi assets @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › console event should work @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › console event should work in immediately closed popup [fail] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › console event should work in popup [pass] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › console event should work in popup 2 [fail] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › dialog event should work @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › dialog event should work in immediately closed popup [pass] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › dialog event should work in popup [pass] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › dialog event should work in popup 2 [fail] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › dialog event should work with inline script tag [fail] +bidi-firefox-beta-library › library/browsercontext-events.spec.ts › weberror event should work [fail] +bidi-firefox-beta-library › library/browsercontext-expose-function.spec.ts › expose binding should work [fail] +bidi-firefox-beta-library › library/browsercontext-expose-function.spec.ts › exposeBindingHandle should work [fail] +bidi-firefox-beta-library › library/browsercontext-expose-function.spec.ts › should be callable from-inside addInitScript [fail] +bidi-firefox-beta-library › library/browsercontext-expose-function.spec.ts › should throw for duplicate registrations [pass] +bidi-firefox-beta-library › library/browsercontext-expose-function.spec.ts › should work [fail] +bidi-firefox-beta-library › library/browsercontext-expose-function.spec.ts › should work with CSP [fail] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail if response content-length header is missing (br) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with chunked responses (without Content-Length header) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should support decompression [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail if response content-length header is missing (deflate) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with chunked responses (without Content-Length header) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should support decompression [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail if response content-length header is missing (gzip) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with chunked responses (without Content-Length header) [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should support decompression [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work on request fixture [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › https post should work with ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › should work with ip6 and port as the host [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › context request should export same storage state as context [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › delete should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › delete should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › delete should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › delete should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › delete should support post data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › deleteshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetch should not throw on long set-cookie value [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetch should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetch should work [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › fetchshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › get should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › get should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › get should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › get should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › get should support post data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › get should work @smoke [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › getshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › head should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › head should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › head should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › head should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › head should support post data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › headshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › patch should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › patch should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › patch should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › patch should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › patch should support post data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › patchshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › post should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › post should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › post should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › post should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › post should support post data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › postshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › put should support failOnStatusCode [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › put should support params passed as URLSearchParams [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › put should support params passed as object [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › put should support params passed as string [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › put should support post data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › putshould support ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should abort requests when browser context closes [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should accept bool and numeric params [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should add cookies from Set-Cookie header [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should add default headers [fail] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should add default headers to redirects [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should add session cookies to request [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should allow to override default headers [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should dispose [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should dispose when context closes [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should encode to application/json by default [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should follow redirects [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should follow redirects correctly when Location header contains UTF-8 characters [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should handle cookies on redirects [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should inherit ignoreHTTPSErrors from context [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should not add context cookie if cookie header passed as a parameter [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should not hang on a brotli encoded Range request [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should not lose body while handling Set-Cookie header [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should not work after context dispose [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should not work after dispose [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should override request parameters [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should preserve cookie order from Set-Cookie header [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should propagate custom headers with redirects [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should propagate extra http headers with redirects [fail] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should remove cookie with expires far in the past [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should remove cookie with negative max-age [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should resolve url relative to baseURL [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should respect timeout after redirects [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should retry on ECONNRESET [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should return error with wrong credentials [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should return raw headers [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should send content-length [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should send secure cookie over http for localhost [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should serialize data to json regardless of content-type [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should set domain=localhost cookie [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for browser.newPage [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for newContext [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support SameSite cookie attribute over https [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support a timeout of 0 [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support application/x-www-form-urlencoded [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support brotli compression [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support cookie with empty value [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support deflate compression [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support gzip compression [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support https [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data and keep the order [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data with ReadStream values [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support repeating names in multipart/form-data [unknown] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support set-cookie with SameSite and without Secure attribute over HTTP [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should support timeout option [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted brotli body [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted deflate body [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted gzip body [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw nice error on unsupported data type [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw on invalid header value [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw on network error [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw on network error after redirect [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw on network error when sending body [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw on network error when sending body after redirect [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should throw on non-http(s) protocol [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should update host header on redirect [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should work with connectOverCDP [unknown] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should work with http credentials [pass] +bidi-firefox-beta-library › library/browsercontext-fetch.spec.ts › should work with setHTTPCredentials [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › by default should abort requests not found in har [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › context.unrouteAll should stop context.routeFromHAR [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › fallback:continue should continue requests on bad har [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › fallback:continue should continue when not found in har [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › newPage should fulfill from har, matching the method and following redirects [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › page.unrouteAll should stop page.routeFromHAR [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should apply overrides before routing from har [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should context.routeFromHAR, matching the method and following redirects [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should disambiguate by header [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should fulfill from har with content in a file [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should goForward to redirected navigation [timeout] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should ignore aborted requests [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should ignore boundary when matching multipart/form-data body [timeout] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should only context.routeFromHAR requests matching url filter [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should only handle requests matching url filter [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should only page.routeFromHAR requests matching url filter [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should page.routeFromHAR, matching the method and following redirects [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should produce extracted zip [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should record overridden requests to har [timeout] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should reload redirected navigation [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should round-trip extracted har.zip [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should round-trip har with postData [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should round-trip har.zip [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should support regex filter [pass] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should update extracted har.zip for page [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should update har.zip for context [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should update har.zip for page [fail] +bidi-firefox-beta-library › library/browsercontext-har.spec.ts › should update har.zip for page with different options [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().locale [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should affect accept-language header @smoke [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should affect navigator.language [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should affect navigator.language in popups [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should be isolated between contexts [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should format date [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should format number [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should format number in popups [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should format number in workers [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should not change default locale in another context [fail] +bidi-firefox-beta-library › library/browsercontext-locale.spec.ts › should work for multiple pages sharing same process [timeout] +bidi-firefox-beta-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.Request [fail] +bidi-firefox-beta-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFailed [fail] +bidi-firefox-beta-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFinished [pass] +bidi-firefox-beta-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.Response [fail] +bidi-firefox-beta-library › library/browsercontext-network-event.spec.ts › should fire events in proper order [pass] +bidi-firefox-beta-library › library/browsercontext-network-event.spec.ts › should not fire events for favicon or favicon redirects [unknown] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should fire page lifecycle events [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should have about:blank for empty url with domcontentloaded [timeout] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should have about:blank url with domcontentloaded [pass] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should have an opener [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should have url [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should have url after domcontentloaded [pass] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should not crash while redirecting of original request was missed [pass] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should not hang on ctrl-click during provisional load [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should report initialized pages [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should report when a new page is created and closed [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should work with Ctrl-clicking [fail] +bidi-firefox-beta-library › library/browsercontext-page-event.spec.ts › should work with Shift-clicking [fail] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › frame.focus should work multiple times [fail] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › page.context should return the correct instance [pass] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should click the button with deviceScaleFactor set [fail] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should click the button with offset with page scale [pass] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should click with disabled javascript [pass] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should keep selection in multiple pages [fail] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should not be visible in context.pages [fail] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should not hang with touch-enabled viewports [pass] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should not leak listeners during navigation of 20 pages [pass] +bidi-firefox-beta-library › library/browsercontext-pages.spec.ts › should return bounding box with page scale [pass] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › does launch without a port [pass] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should authenticate [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should authenticate with empty password [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should exclude patterns [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts on navigation [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › link-local [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › localhost [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should set cookie for top-level domain [pass] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should throw for bad server value [pass] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should throw for socks4 authentication [pass] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should throw for socks5 authentication [pass] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use ipv6 proxy [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use proxy [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use proxy for https urls [timeout] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use proxy for second page [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use proxy twice [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use socks proxy [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should use socks proxy in second page [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should work when passing the proxy only on the context level [fail] +bidi-firefox-beta-library › library/browsercontext-proxy.spec.ts › should work with IP:PORT notion [fail] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should continue issuing events after closing the reused page [pass] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should ignore binding from beforeunload [fail] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should not cache resources [timeout] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should re-add binding after reset [fail] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should reset mouse position [fail] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should reset serviceworker [pass] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should reset serviceworker that hangs in importScripts [pass] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should reset tracing [pass] +bidi-firefox-beta-library › library/browsercontext-reuse.spec.ts › should work with clock emulation [pass] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should chain fallback [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should chain fallback into page [pass] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should chain fallback w/ dynamic URL [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should fall back async [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should fall back to context.route [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should ignore secure Set-Cookie header for insecure requests [pass] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should intercept [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should not chain abort [pass] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should not chain fulfill [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should overwrite post body with empty string [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should support Set-Cookie header [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should support async handler w/ times [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should support the times parameter with route matching [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should unroute [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should use Set-Cookie header in future requests [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should work with ignoreHTTPSErrors [fail] +bidi-firefox-beta-library › library/browsercontext-route.spec.ts › should yield to page.route [fail] +bidi-firefox-beta-library › library/browsercontext-service-worker-policy.spec.ts › block › blocks service worker registration [timeout] +bidi-firefox-beta-library › library/browsercontext-service-worker-policy.spec.ts › block › should not throw error on about:blank [pass] +bidi-firefox-beta-library › library/browsercontext-service-worker-policy.spec.ts › should allow service workers by default [pass] +bidi-firefox-beta-library › library/browsercontext-set-extra-http-headers.spec.ts › should override extra headers from browser context [fail] +bidi-firefox-beta-library › library/browsercontext-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should capture cookies [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should capture local storage [fail] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should handle malformed file [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should handle missing file [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should not emit events about internal page [fail] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should not restore localStorage twice [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should round-trip through the file [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should serialize storageState with lone surrogates [pass] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should set local storage [fail] +bidi-firefox-beta-library › library/browsercontext-storage-state.spec.ts › should work when service worker is intefering [pass] +bidi-firefox-beta-library › library/browsercontext-strict.spec.ts › should not fail page.textContent in non-strict mode [fail] +bidi-firefox-beta-library › library/browsercontext-strict.spec.ts › strict context mode › should fail page.click in strict mode [fail] +bidi-firefox-beta-library › library/browsercontext-strict.spec.ts › strict context mode › should fail page.textContent in strict mode [fail] +bidi-firefox-beta-library › library/browsercontext-strict.spec.ts › strict context mode › should opt out of strict mode [fail] +bidi-firefox-beta-library › library/browsercontext-timezone-id.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().timeZone [fail] +bidi-firefox-beta-library › library/browsercontext-timezone-id.spec.ts › should not change default timezone in another context [fail] +bidi-firefox-beta-library › library/browsercontext-timezone-id.spec.ts › should throw for invalid timezone IDs when creating pages [fail] +bidi-firefox-beta-library › library/browsercontext-timezone-id.spec.ts › should work @smoke [fail] +bidi-firefox-beta-library › library/browsercontext-timezone-id.spec.ts › should work for multiple pages sharing same process [timeout] +bidi-firefox-beta-library › library/browsercontext-user-agent.spec.ts › custom user agent for download [fail] +bidi-firefox-beta-library › library/browsercontext-user-agent.spec.ts › should emulate device user-agent [fail] +bidi-firefox-beta-library › library/browsercontext-user-agent.spec.ts › should make a copy of default options [fail] +bidi-firefox-beta-library › library/browsercontext-user-agent.spec.ts › should work [fail] +bidi-firefox-beta-library › library/browsercontext-user-agent.spec.ts › should work for navigator.userAgentData and sec-ch-ua headers [unknown] +bidi-firefox-beta-library › library/browsercontext-user-agent.spec.ts › should work for subframes [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › default mobile viewports to 980 width [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › mouse should work with mobile viewports and cross process navigations [pass] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › respect meta viewport tag [pass] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should be detectable [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should detect touch when applying viewport with touches [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should emulate the hover media feature [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should fire orientationchange event [timeout] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should scroll when emulating a mobile viewport [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support landscape emulation [pass] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support mobile emulation [pass] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support touch emulation [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support window.orientation emulation [fail] +bidi-firefox-beta-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › view scale should reset after navigation [pass] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › WebKit Windows headed should have a minimal viewport [unknown] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should be able to get correct orientation angle on non-mobile devices [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should drag with high dpi [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should emulate availWidth and availHeight [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should emulate device height [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should emulate device width [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should get the proper default viewport size [pass] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should not have touch by default [pass] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should report null viewportSize when given null viewport [pass] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should return correct outerWidth and outerHeight [pass] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should set both screen and viewport options [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should set the proper viewport size [pass] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should set window.screen.orientation.type for mobile devices [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should support touch with null viewport [fail] +bidi-firefox-beta-library › library/browsercontext-viewport.spec.ts › should throw on tap if hasTouch is not enabled [fail] +bidi-firefox-beta-library › library/browsertype-basic.spec.ts › browserType.executablePath should work [unknown] +bidi-firefox-beta-library › library/browsertype-basic.spec.ts › browserType.name should work [fail] +bidi-firefox-beta-library › library/browsertype-basic.spec.ts › should throw when trying to connect with not-chromium [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer only › should be able to reconnect to a browser 12 times without warnings [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer only › should properly disconnect when connection closes from the server side [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer only › should work with cluster [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › disconnected event should be emitted when browser is closed or server is closed [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › disconnected event should have browser as argument [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › setInputFiles should preserve lastModified timestamp [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect 20 times to a single server without warnings [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect two browsers at the same time [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect when the wsEndpoint is passed as an option [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should be able to reconnect to a browser [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 through localhost [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should connect over http [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should connect over wss [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should emit close events on pages and contexts [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should error when saving download after deletion [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should filter launch options [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should fulfill with global fetch result [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should handle exceptions during connect [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should ignore page.pause when headed [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should not throw on close after disconnect [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should print HTTP error [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should print custom ws close error [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should print ws error [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should properly disconnect when connection closes from the client side [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should record trace with sources [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should reject navigation when browser closes [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.close finishes [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.onDisconnect fires [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForSelector when browser closes [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should respect selectors [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should save download [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should save har [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should saveAs videos from remote browser [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should send extra headers with connect request [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should set the browser connected state [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should support slowmo option [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should terminate network waiters [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should throw when calling waitForNavigation after disconnect [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should throw when used after isConnected returns false [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should timeout in connect while connecting [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should timeout in socket while connecting [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › should upload large file [timeout] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should check proxy pattern on the client [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should forward non-forwarded requests [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should lead to the error page for forwarded requests when the connection is refused [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy based on the pattern [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy ipv6 localhost requests @smoke [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy local.playwright requests [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests @smoke [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests from fetch api [unknown] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › disconnected event should be emitted when browser is closed or server is closed [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › disconnected event should have browser as argument [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › setInputFiles should preserve lastModified timestamp [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should be able to connect 20 times to a single server without warnings [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should be able to connect two browsers at the same time [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should be able to connect when the wsEndpoint is passed as an option [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should be able to reconnect to a browser [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 through localhost [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should connect over http [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should connect over wss [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should emit close events on pages and contexts [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should error when saving download after deletion [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should filter launch options [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should fulfill with global fetch result [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should handle exceptions during connect [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should ignore page.pause when headed [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should not throw on close after disconnect [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should print HTTP error [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should print custom ws close error [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should print ws error [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should properly disconnect when connection closes from the client side [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should record trace with sources [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should reject navigation when browser closes [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.close finishes [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.onDisconnect fires [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should reject waitForSelector when browser closes [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should respect selectors [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should save download [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should save har [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should saveAs videos from remote browser [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should send extra headers with connect request [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should set the browser connected state [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should support slowmo option [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should terminate network waiters [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should throw when calling waitForNavigation after disconnect [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should throw when used after isConnected returns false [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should timeout in connect while connecting [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should timeout in socket while connecting [pass] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › should upload large file [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should check proxy pattern on the client [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should forward non-forwarded requests [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should lead to the error page for forwarded requests when the connection is refused [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy based on the pattern [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy ipv6 localhost requests @smoke [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy local.playwright requests [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests @smoke [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests from fetch api [fail] +bidi-firefox-beta-library › library/browsertype-connect.spec.ts › should refuse connecting when versions do not match [pass] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 hub + node chromium [unknown] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium [unknown] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium through run-driver [unknown] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone non-chromium [unknown] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 hub + node chromium [unknown] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium [unknown] +bidi-firefox-beta-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium broken driver [unknown] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should default to random wsPath [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should fire "close" event during kill [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should fire close event [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should log protocol [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should provide an error when ws endpoint is incorrect [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should return child_process instance [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should work [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should work when wsPath is missing leading slash [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should work with host [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should work with port [fail] +bidi-firefox-beta-library › library/browsertype-launch-server.spec.ts › launch server › should work with wsPath [fail] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should accept objects as options [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should allow await using [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should be callable twice [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should fire close event for all contexts [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should handle exception [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should handle timeout [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should reject all promises when browser is closed [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should reject if executable path is invalid [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should reject if launched browser fails immediately [fail] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should report launch log [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should throw if page argument is passed [fail] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should throw if port option is passed [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should throw if port option is passed for persistent context [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should throw if userDataDir is passed as an argument [pass] +bidi-firefox-beta-library › library/browsertype-launch.spec.ts › should throw if userDataDir option is passed [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › Intl.ListFormat should work [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › SharedArrayBuffer should work @smoke [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › Web Assembly should work @smoke [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › WebSocket should work @smoke [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › loading in HTMLImageElement.prototype [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › make sure that XMLHttpRequest upload events are emitted correctly [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › navigator.clipboard should be present [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › requestFullscreen [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › service worker should cover the iframe [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › service worker should register in an iframe [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › serviceWorker should intercept document request [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on page with mp4 @smoke [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on showDirectoryPicker [unknown] +bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › should play audio @smoke [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › should play video @smoke [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › should play webm video @smoke [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › should respect CSP @smoke [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › should send no Content-Length header for GET requests with a Content-Type [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › should set CloseEvent.wasClean to false when the server terminates a WebSocket connection [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › should support webgl 2 @smoke [pass] +bidi-firefox-beta-library › library/capabilities.spec.ts › should support webgl @smoke [fail] +bidi-firefox-beta-library › library/capabilities.spec.ts › webkit should define window.safari [unknown] +bidi-firefox-beta-library › library/capabilities.spec.ts › window.GestureEvent in WebKit [pass] +bidi-firefox-beta-library › library/channels.spec.ts › exposeFunction should not leak [fail] +bidi-firefox-beta-library › library/channels.spec.ts › should not generate dispatchers for subresources w/o listeners [pass] +bidi-firefox-beta-library › library/channels.spec.ts › should scope CDPSession handles [unknown] +bidi-firefox-beta-library › library/channels.spec.ts › should scope browser handles [pass] +bidi-firefox-beta-library › library/channels.spec.ts › should scope context handles [pass] +bidi-firefox-beta-library › library/channels.spec.ts › should work with the domain module [timeout] +bidi-firefox-beta-library › library/chromium/bfcache.spec.ts › bindings should work after restoring from bfcache [fail] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › serviceWorker(), and fromServiceWorker() work [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setExtraHTTPHeaders [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setOffline [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept only serviceworker request, not page [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker importScripts [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker requests (main and within) [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker update requests [unknown] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker (advanced) [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to content-type) of main service worker request [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to redirect) of main service worker request [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report intercepted service worker requests in HAR [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › Page.route should work with intervention headers [fail] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › http credentials › httpCredentials [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › serviceWorkers() should return current workers [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › should close service worker together with the context [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › should create a worker from a service worker [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › should create a worker from service worker with noop routing [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › should emit new service worker on update [timeout] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › should not create a worker from a shared worker [pass] +bidi-firefox-beta-library › library/chromium/chromium.spec.ts › should pass args with spaces [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › emulate media should not be affected by second connectOverCDP [unknown] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › setInputFiles should preserve lastModified timestamp [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should allow tracing over cdp session [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should be able to connect via localhost [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should cleanup artifacts dir after connectOverCDP disconnects due to ws close [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect over a ws endpoint [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session twice [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session when passed as a first argument [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect to existing page with iframe and navigate [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect to existing service workers [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connect via https [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should connectOverCDP and manage downloads in default context [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should print custom ws close error [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should report all pages in an existing browser [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpoint URL JSON webSocketDebuggerUrl is undefined [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpointURL returns a non-expected status code [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should return valid browser from context.browser() [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should send default User-Agent header with connect request [timeout] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should send extra headers with connect request [timeout] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should use logger in default context [fail] +bidi-firefox-beta-library › library/chromium/connect-over-cdp.spec.ts › should use proxy with connectOverCDP [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should NOT report scripts across navigations [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should ignore injected stylesheets [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should report multiple stylesheets [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should report sourceURLs [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should report stylesheets across navigations [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should report stylesheets that have no coverage [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should work [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should work with a recently loaded stylesheet [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should work with complicated usecases [fail] +bidi-firefox-beta-library › library/chromium/css-coverage.spec.ts › should work with media queries [fail] +bidi-firefox-beta-library › library/chromium/disable-web-security.spec.ts › test init script w/ --disable-web-security [pass] +bidi-firefox-beta-library › library/chromium/disable-web-security.spec.ts › test utility world in popup w/ --disable-web-security [pass] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should NOT report scripts across navigations when enabled [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should ignore eval() scripts by default [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should not hang when there is a debugger statement [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should report multiple scripts [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should report scripts across navigations when disabled [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should report sourceURLs [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › should work [fail] +bidi-firefox-beta-library › library/chromium/js-coverage.spec.ts › shouldn't ignore eval() scripts if reportAnonymousScripts is true [fail] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should not create pages automatically [fail] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should not throw with remote-debugging-port argument [fail] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should open devtools when "devtools: true" option is given [unknown] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should return background pages [fail] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should return background pages when recording video [fail] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should support request/response events when using backgroundPage() [fail] +bidi-firefox-beta-library › library/chromium/launcher.spec.ts › should throw with remote-debugging-pipe argument [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › ElementHandle.boundingBox() should work [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › contentFrame should work [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should allow cdp sessions on oopifs [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should be able to click in iframe [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should click [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should click a button when it overlays oopif [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should emit filechooser event for iframe [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should emulate media [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should emulate offline [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should expose function [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should get the proper viewport [unknown] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should handle oopif detach [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should handle remote -> local -> remote transitions [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should intercept response body from oopif [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should load oopif iframes with subresources and route [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should not throw on exposeFunction when oopif detaches [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should report google.com frame with headed [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should report main requests [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should report oopif frames [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should respect route [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should support addInitScript [pass] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should support context options [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should support exposeFunction [fail] +bidi-firefox-beta-library › library/chromium/oopif.spec.ts › should take screenshot [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should be able to detach session [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should detach when page closes [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should enable and disable domains independently [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should not break page.close() [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should only accept a page or frame [pass] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should reject protocol calls when page closes [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should send events [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should throw if target is part of main [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should throw nice errors [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should work [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should work with main frame [fail] +bidi-firefox-beta-library › library/chromium/session.spec.ts › should work with newBrowserCDPSession [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should create directories as needed [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should output a trace [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should return a buffer [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should run with custom categories if provided [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should support a buffer without a path [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should throw if tracing on two pages [fail] +bidi-firefox-beta-library › library/chromium/tracing.spec.ts › should work without options [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › persistentContext › should pass with matching certificates [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › persistentContext › validate input [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should fail with matching certificates in legacy pfx format [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should fail with no client certificates [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should fail with self-signed client certificates [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should handle TLS renegotiation with client certificates [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should handle rejected certificate in handshake with HTTP/2 [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should have ignoreHTTPSErrors=false by default [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should keep supporting http [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should not hang on tls errors during TLS 1.2 handshake [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should pass with matching certificates [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should pass with matching certificates and trailing slash [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format when passing as content [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should pass with matching certificates on context APIRequestContext instance [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should pass with matching certificates when passing as content [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should return target connection errors when using http2 [unknown] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › should throw a http error if the pfx passphrase is incorect [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › support http2 [fail] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › support http2 if the browser only supports http1.1 [unknown] +bidi-firefox-beta-library › library/client-certificates.spec.ts › browser › validate input [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › pass with trusted client certificates [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › pass with trusted client certificates in pfx format [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › should fail with matching certificates in legacy pfx format [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › should fail with no client certificates provided [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › should keep supporting http [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › should throw a http error if the pfx passphrase is incorect [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › should throw with untrusted client certs [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › should work in the browser with request interception [pass] +bidi-firefox-beta-library › library/client-certificates.spec.ts › fetch › validate input [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › Creates a RelativeTimeFormat like normal [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › Executes formatRange like normal [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › Executes formatRangeToParts like normal [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › Executes resolvedOptions like normal [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › Executes supportedLocalesOf like normal [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed a timestamp argument that is not first of the month [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed no timestamp and system time is not first of the month [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed a timestamp argument that is first of the month [pass] +bidi-firefox-beta-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed no timestamp and system time is first of the month [pass] +bidi-firefox-beta-library › library/clock.spec.ts › cancelAnimationFrame › does not remove interval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › cancelAnimationFrame › does not remove timeout [pass] +bidi-firefox-beta-library › library/clock.spec.ts › cancelAnimationFrame › ignores null argument [pass] +bidi-firefox-beta-library › library/clock.spec.ts › cancelAnimationFrame › removes animation frame [pass] +bidi-firefox-beta-library › library/clock.spec.ts › cancelIdleCallback › removes idle callback [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearInterval › ignores null argument [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearInterval › removes interval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearInterval › removes interval with undefined interval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearInterval › removes timeout [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearTimeout › ignores null argument [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearTimeout › removes interval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearTimeout › removes interval with undefined interval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › clearTimeout › removes timeout [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates Date objects representing clock time [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates real Date objects [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing a date as RFC 2822 string [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing a date as string [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing timestamp [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing y, m, d [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s, ms [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › creates regular date when passing year, month [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › listens to system clock changes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › listens to ticking clock [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › mirrors UTC method [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › mirrors native Date.prototype [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › mirrors parse method [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › mirrors toUTCString method [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › provides date constructor [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › returns clock.now() [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › returns date as string representing clock time [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › returns date as string when called as function [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › returns date as string when calling with arguments [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › returns date as string when calling with timestamp [pass] +bidi-firefox-beta-library › library/clock.spec.ts › date › supports now method if present [pass] +bidi-firefox-beta-library › library/clock.spec.ts › fastForward › handles multiple pending timers and types [pass] +bidi-firefox-beta-library › library/clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +bidi-firefox-beta-library › library/clock.spec.ts › fastForward › pushes back execution time for skipped timers [pass] +bidi-firefox-beta-library › library/clock.spec.ts › pauseAt › fire target timers [pass] +bidi-firefox-beta-library › library/clock.spec.ts › pauseAt › pause at target time [pass] +bidi-firefox-beta-library › library/clock.spec.ts › pauseAt › returns consumed clicks [pass] +bidi-firefox-beta-library › library/clock.spec.ts › performance.now() › should listen to multiple ticks in performance.now [pass] +bidi-firefox-beta-library › library/clock.spec.ts › performance.now() › should run along with clock.tick [pass] +bidi-firefox-beta-library › library/clock.spec.ts › performance.now() › should run with ticks with timers set [pass] +bidi-firefox-beta-library › library/clock.spec.ts › performance.now() › should start at 0 [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › returns numeric id or object with numeric id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › returns unique id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() even when performance unavailable [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() when available [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should call callback once [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should properly schedule callback for 3rd frame [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should run every 16ms [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should schedule for next frame if on current frame [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › should schedule two callbacks before the next frame at the same time [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestAnimationFrame › throws if no arguments [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestIdleCallback › doesn't runs if there are any timers and no timeout option [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestIdleCallback › returns numeric id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestIdleCallback › returns unique id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestIdleCallback › runs after all timers [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestIdleCallback › runs no later than timeout option even if there are any timers [pass] +bidi-firefox-beta-library › library/clock.spec.ts › requestIdleCallback › throws if no arguments [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › calls function with global object or null (strict mode) as this [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › creates updated Date while ticking [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › creates updated Date while ticking promises [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › does not fire canceled intervals [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › does not fire intervals canceled in a promise [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › does not silently catch errors [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › fires nested setTimeout calls in user-created promises properly [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › fires nested setTimeout calls properly [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › fires promise timers in correct order [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › fires timer in intervals of "13" [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › fires timer in intervals of 13 [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › fires timers in correct order [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes 2 [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes in promises [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown 2 [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › mini integration test [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle chained user-created promises [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle local nested promises before calling timeouts [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle local promises before calling timeouts [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle multiple user-created promises [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle nested user-created promises [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle user-created promises [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle user-created promises before calling more timeouts [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › should settle user-created promises even if some throw [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › throws for negative minutes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › throws on negative ticks [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers after sufficient delay [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers even when some throw [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers immediately without specified delay [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers in the order scheduled [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers multiple simultaneous timers [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers multiple simultaneous timers with zero callAt [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers simultaneous timers [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › triggers timeouts and intervals in the order scheduled [pass] +bidi-firefox-beta-library › library/clock.spec.ts › runFor › waits after setTimeout was called [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › does not schedule recurring timeout when cleared [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › does not throw if |undefined| or |null| is passed as a callback [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › is not influenced by backward system clock changes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › is not influenced by forward system clock changes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › passes setTimeout parameters [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › returns numeric id or object with numeric id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › returns unique id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › schedules recurring timeout [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setInterval › throws if no arguments [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › calls correct timeout on recursive tick [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › does not depend on this [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › does not throw if |undefined| or |null| is passed as a callback [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › is not influenced by backward system clock changes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › is not influenced by forward system clock changes [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › parses no-numeric string times [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › parses numeric string times [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › passes setTimeout parameters [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › returns numeric id or object with numeric id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › returns unique id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › sets timers on instance [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › starts id from a large number [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › throws if no arguments [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › use of eval when not in node › evals non-function callbacks [pass] +bidi-firefox-beta-library › library/clock.spec.ts › setTimeout › use of eval when not in node › only evals on global scope [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › deletes global property on uninstall if it was inherited onto the global object [unknown] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › does not fake methods not provided [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › fake Date constructor should mirror Date's properties [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › fakes Date constructor [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › fakes provided methods [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › mirrors custom Date properties [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › replace Event.prototype.timeStamp [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › replaces global clearInterval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › replaces global performance.now [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › replaces global setInterval [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › replaces global setTimeout [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › resets faked methods [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › returns clock object [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › sets initial timestamp [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › should let performance.mark still be callable after install() (#136) [unknown] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › should not alter the global performance properties and methods [unknown] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › should replace the getEntries, getEntriesByX methods with noops that return [] [unknown] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › takes an object parameter [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › uninstalls Date constructor [pass] +bidi-firefox-beta-library › library/clock.spec.ts › stubTimers › uninstalls global performance.now [pass] +bidi-firefox-beta-library › library/clock.spec.ts › works with concurrent runFor calls [pass] +bidi-firefox-beta-library › library/clock.spec.ts › works with slow setTimeout in busy embedder [pass] +bidi-firefox-beta-library › library/clock.spec.ts › works with slow setTimeout in busy embedder when not paused [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should escape [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse all operators [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse bool [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse float values [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse identifiers [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse int values [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse regex [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse short attributes [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should parse unquoted string [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should throw on malformed selector [pass] +bidi-firefox-beta-library › library/component-parser.spec.ts › should tolerate spacing [pass] +bidi-firefox-beta-library › library/css-parser.spec.ts › should parse css [pass] +bidi-firefox-beta-library › library/css-parser.spec.ts › should throw on malformed css [pass] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should highlight all [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should navigate all [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should pick element [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should record [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should record custom data-testid [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should report pages [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should reset for reuse [fail] +bidi-firefox-beta-library › library/debug-controller.spec.ts › should reset routes before reuse [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › context.addCookies() should work [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › context.clearCookies() should work [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › context.cookies() should work @smoke [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support acceptDownloads option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support bypassCSP option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support deviceScaleFactor option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support httpCredentials option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support javascriptEnabled option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support offline option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support userAgent option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should support viewport option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-1.spec.ts › should(not) block third party cookies [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › coverage should work [unknown] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should accept userDataDir [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should connect to a browser with the default page [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should create userDataDir if it does not exist [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should fire close event for a persistent context [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should handle exception [timeout] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should handle timeout [pass] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should have default URL when launching browser [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should have passed URL when launching with ignoreDefaultArgs: true [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should respect selectors [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should restore state from userDataDir [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support colorScheme option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support extraHTTPHeaders option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support forcedColors option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support geolocation and permissions options [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support har option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support hasTouch option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support ignoreHTTPSErrors option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support locale option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support reducedMotion option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should support timezoneId option [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should throw if page argument is passed [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › should work in persistent context [fail] +bidi-firefox-beta-library › library/defaultbrowsercontext-2.spec.ts › user agent is up to date [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should be able to cancel pending downloads [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should close the context without awaiting the download [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should close the context without awaiting the failed download [unknown] +bidi-firefox-beta-library › library/download.spec.ts › download event › should create subdirectories when saving to non-existent user-specified path [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should delete downloads on browser gone [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should delete downloads on context destruction [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should delete file [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should download large binary.zip [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should emit download event from nested iframes [timeout] +bidi-firefox-beta-library › library/download.spec.ts › download event › should error when saving after deletion [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should error when saving with downloads disabled [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should expose stream [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should not fail explicitly to cancel a download even if that is already finished [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report alt-click downloads [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Blobs [timeout] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Files [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report download when navigation turns into download @smoke [timeout] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report downloads for download attribute [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report downloads with acceptDownloads: false [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report downloads with acceptDownloads: true [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report downloads with interception [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report new window downloads [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report non-navigation downloads [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should report proper download url when download is from download attribute [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should save to overwritten filepath [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should save to two different paths with multiple saveAs calls [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should save to user-specified path without updating original path [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should throw if browser dies [fail] +bidi-firefox-beta-library › library/download.spec.ts › download event › should work with Cross-Origin-Opener-Policy [timeout] +bidi-firefox-beta-library › library/download.spec.ts › should be able to download a PDF file [fail] +bidi-firefox-beta-library › library/download.spec.ts › should be able to download a inline PDF file via navigation [fail] +bidi-firefox-beta-library › library/download.spec.ts › should be able to download a inline PDF file via response interception [fail] +bidi-firefox-beta-library › library/download.spec.ts › should convert navigation to a resource with unsupported mime type into download [timeout] +bidi-firefox-beta-library › library/download.spec.ts › should download even if there is no "attachment" value [fail] +bidi-firefox-beta-library › library/download.spec.ts › should download links with data url [fail] +bidi-firefox-beta-library › library/download.spec.ts › should download successfully when routing [fail] +bidi-firefox-beta-library › library/download.spec.ts › should save to user-specified path [fail] +bidi-firefox-beta-library › library/downloads-path.spec.ts › downloads path › should accept downloads in persistent context [fail] +bidi-firefox-beta-library › library/downloads-path.spec.ts › downloads path › should delete downloads when context closes [fail] +bidi-firefox-beta-library › library/downloads-path.spec.ts › downloads path › should delete downloads when persistent context closes [fail] +bidi-firefox-beta-library › library/downloads-path.spec.ts › downloads path › should keep downloadsPath folder [fail] +bidi-firefox-beta-library › library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder [fail] +bidi-firefox-beta-library › library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder with a relative path [fail] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should change document.activeElement [pass] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should change focused iframe [pass] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should focus popups by default [fail] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should focus with more than one page/context [fail] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should not affect mouse event target page [pass] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should not affect screenshots [fail] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should not fire blur events when interacting with more than one page/context [fail] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should provide target for keyboard events [pass] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should think that all pages are focused @smoke [fail] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should think that it is focused by default [pass] +bidi-firefox-beta-library › library/emulation-focus.spec.ts › should trigger hover state concurrently [fail] +bidi-firefox-beta-library › library/events/add-listeners.spec.ts › EventEmitter tests › Listener order [pass] +bidi-firefox-beta-library › library/events/add-listeners.spec.ts › EventEmitter tests › listener type check [pass] +bidi-firefox-beta-library › library/events/add-listeners.spec.ts › EventEmitter tests › set max listeners test [pass] +bidi-firefox-beta-library › library/events/add-listeners.spec.ts › EventEmitter tests › should work [pass] +bidi-firefox-beta-library › library/events/check-listener-leaks.spec.ts › _maxListeners still has precedence over defaultMaxListeners [pass] +bidi-firefox-beta-library › library/events/check-listener-leaks.spec.ts › defaultMaxListeners [pass] +bidi-firefox-beta-library › library/events/check-listener-leaks.spec.ts › process-wide [pass] +bidi-firefox-beta-library › library/events/events-list.spec.ts › EventEmitter › should maintain event names correctly [pass] +bidi-firefox-beta-library › library/events/listener-count.spec.ts › Listener count test [pass] +bidi-firefox-beta-library › library/events/listeners-side-effects.spec.ts › listeners empty check [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › Array copy modification does not modify orig [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › EventEmitter listeners with one listener [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › EventEmitter with no members [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › Modify array copy after multiple adds [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › listeners and once [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › listeners on prototype [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › listeners with conflicting types [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › raw listeners [pass] +bidi-firefox-beta-library › library/events/listeners.spec.ts › raw listeners order [pass] +bidi-firefox-beta-library › library/events/max-listeners.spec.ts › emit maxListeners on e [pass] +bidi-firefox-beta-library › library/events/method-names.spec.ts › EventEmitter prototype test [pass] +bidi-firefox-beta-library › library/events/modify-in-emit.spec.ts › add and remove listeners [pass] +bidi-firefox-beta-library › library/events/modify-in-emit.spec.ts › removing callbacks in emit [pass] +bidi-firefox-beta-library › library/events/num-args.spec.ts › should work [pass] +bidi-firefox-beta-library › library/events/once.spec.ts › once() has different code paths based on the number of arguments being emitted [pass] +bidi-firefox-beta-library › library/events/once.spec.ts › should work [pass] +bidi-firefox-beta-library › library/events/prepend.spec.ts › EventEmitter functionality [pass] +bidi-firefox-beta-library › library/events/prepend.spec.ts › Verify that the listener must be a function [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners-wait.spec.ts › should not throw with ignoreErrors [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners-wait.spec.ts › should wait [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners-wait.spec.ts › should wait all [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners-wait.spec.ts › wait should throw [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners.spec.ts › listener count after removeAllListeners [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners.spec.ts › listeners [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners.spec.ts › removeAllListeners on undefined _events [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners.spec.ts › removeAllListeners removes all listeners [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners.spec.ts › removeAllListeners returns EventEmitter [pass] +bidi-firefox-beta-library › library/events/remove-all-listeners.spec.ts › removeAllListeners with no event type [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Eighth test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Fifth test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › First test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Fourth test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Ninth test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Second test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Seventh test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Sixth test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Tenth test [pass] +bidi-firefox-beta-library › library/events/remove-listeners.spec.ts › Third test [pass] +bidi-firefox-beta-library › library/events/set-max-listeners-side-effects.spec.ts › set max listeners test [pass] +bidi-firefox-beta-library › library/events/special-event-names.spec.ts › should support special event names [pass] +bidi-firefox-beta-library › library/events/subclass.spec.ts › MyEE2 instance [pass] +bidi-firefox-beta-library › library/events/subclass.spec.ts › myee instance [pass] +bidi-firefox-beta-library › library/events/symbols.spec.ts › should support symbols [pass] +bidi-firefox-beta-library › library/favicon.spec.ts › should load svg favicon with prefer-color-scheme [unknown] +bidi-firefox-beta-library › library/fetch-proxy.spec.ts › context request should pick up proxy credentials [timeout] +bidi-firefox-beta-library › library/fetch-proxy.spec.ts › global request should pick up proxy credentials [pass] +bidi-firefox-beta-library › library/fetch-proxy.spec.ts › should support proxy.bypass [pass] +bidi-firefox-beta-library › library/fetch-proxy.spec.ts › should use socks proxy [pass] +bidi-firefox-beta-library › library/fetch-proxy.spec.ts › should work with context level proxy [pass] +bidi-firefox-beta-library › library/firefox/launcher.spec.ts › should pass firefox user preferences [fail] +bidi-firefox-beta-library › library/firefox/launcher.spec.ts › should pass firefox user preferences in persistent [fail] +bidi-firefox-beta-library › library/geolocation.spec.ts › should isolate contexts [fail] +bidi-firefox-beta-library › library/geolocation.spec.ts › should not modify passed default options object [pass] +bidi-firefox-beta-library › library/geolocation.spec.ts › should throw when invalid longitude [fail] +bidi-firefox-beta-library › library/geolocation.spec.ts › should throw with missing latitude [pass] +bidi-firefox-beta-library › library/geolocation.spec.ts › should throw with missing longitude in default options [pass] +bidi-firefox-beta-library › library/geolocation.spec.ts › should use context options [timeout] +bidi-firefox-beta-library › library/geolocation.spec.ts › should use context options for popup [timeout] +bidi-firefox-beta-library › library/geolocation.spec.ts › should work @smoke [timeout] +bidi-firefox-beta-library › library/geolocation.spec.ts › watchPosition should be notified [timeout] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should do case-insensitive match of cookie domain [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should do case-insensitive match of request domain [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should export cookies to storage state [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should filter outgoing cookies by domain [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should filter outgoing cookies by path [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header even if it expired [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should preserve local storage on import/export of storage state [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should remove cookie with expires far in the past [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should remove cookie with negative max-age [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should remove expired cookies [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should send cookies from storage state [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should send not expired cookies [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should send secure cookie over http for localhost [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should send secure cookie over https [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header even if it contains equal signs [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › should work with empty storage state [pass] +bidi-firefox-beta-library › library/global-fetch-cookie.spec.ts › storage state should round-trip through file [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › delete should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › fetch should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › get should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › head should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › patch should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › post should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › put should work @smoke [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should abort redirected requests when context is disposed [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should abort requests when context is disposed [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should accept already serialized data as Buffer when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should be able to construct with context options [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should dispose global request [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should have nice toString [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify array body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify bool (false) body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify bool body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify literal string undefined body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify null body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify number (falsey) body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify number body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify object body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify string (falsey) body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should json stringify string body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should keep headers capitalization [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify array body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify bool (false) body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify bool body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify literal string undefined body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify null body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify number (falsey) body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify number body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify object body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify string (falsey) body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not double stringify string body when content-type is application/json [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not fail on empty body with encoding [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should not follow redirects when maxRedirects is set to 0 [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should propagate extra http headers with redirects [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should propagate ignoreHTTPSErrors on redirects [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should remove content-length from redirected post requests [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should resolve url relative to global baseURL option [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should retry ECONNRESET [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should return body for failing requests [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should return empty body [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching hostname [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching port [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching scheme [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should return error with wrong credentials [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should serialize post data on the client [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should set playwright as user-agent [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should support HTTPCredentials.send [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should support WWW-Authenticate: Basic [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should support global httpCredentials option [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should support global ignoreHTTPSErrors option [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should support global timeout option [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should support global userAgent option [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should throw after dispose [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should throw an error when maxRedirects is exceeded [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should throw an error when maxRedirects is less than 0 [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should work with correct credentials and matching origin [pass] +bidi-firefox-beta-library › library/global-fetch.spec.ts › should work with correct credentials and matching origin case insensitive [pass] +bidi-firefox-beta-library › library/har.spec.ts › should attach content [fail] +bidi-firefox-beta-library › library/har.spec.ts › should calculate time [pass] +bidi-firefox-beta-library › library/har.spec.ts › should contain http2 for http2 requests [fail] +bidi-firefox-beta-library › library/har.spec.ts › should filter by glob [pass] +bidi-firefox-beta-library › library/har.spec.ts › should filter by regexp [pass] +bidi-firefox-beta-library › library/har.spec.ts › should filter favicon and favicon redirects [unknown] +bidi-firefox-beta-library › library/har.spec.ts › should have -1 _transferSize when its a failed request [pass] +bidi-firefox-beta-library › library/har.spec.ts › should have browser [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have connection details [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have connection details for failed requests [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have connection details for redirects [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have different hars for concurrent contexts [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have pages [pass] +bidi-firefox-beta-library › library/har.spec.ts › should have pages in persistent context [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have popup requests [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have security details [fail] +bidi-firefox-beta-library › library/har.spec.ts › should have version and creator [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include API request [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include binary postData [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include content @smoke [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include cookies [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include form params [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include postData [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include query params [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include redirectURL [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include request [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include response [pass] +bidi-firefox-beta-library › library/har.spec.ts › should include secure set-cookies [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include set-cookies [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include set-cookies with comma [fail] +bidi-firefox-beta-library › library/har.spec.ts › should include sizes [fail] +bidi-firefox-beta-library › library/har.spec.ts › should not contain internal pages [pass] +bidi-firefox-beta-library › library/har.spec.ts › should not hang on resources served from cache [fail] +bidi-firefox-beta-library › library/har.spec.ts › should not hang on slow chunked response [fail] +bidi-firefox-beta-library › library/har.spec.ts › should omit content [pass] +bidi-firefox-beta-library › library/har.spec.ts › should omit content legacy [pass] +bidi-firefox-beta-library › library/har.spec.ts › should record failed request headers [pass] +bidi-firefox-beta-library › library/har.spec.ts › should record failed request overrides [timeout] +bidi-firefox-beta-library › library/har.spec.ts › should record request overrides [timeout] +bidi-firefox-beta-library › library/har.spec.ts › should report the correct _transferSize with PNG files [fail] +bidi-firefox-beta-library › library/har.spec.ts › should report the correct request body size [pass] +bidi-firefox-beta-library › library/har.spec.ts › should report the correct request body size when the bodySize is 0 [pass] +bidi-firefox-beta-library › library/har.spec.ts › should report the correct response body size when the bodySize is 0 [pass] +bidi-firefox-beta-library › library/har.spec.ts › should return receive time [pass] +bidi-firefox-beta-library › library/har.spec.ts › should return security details directly from response [fail] +bidi-firefox-beta-library › library/har.spec.ts › should return server address directly from response [fail] +bidi-firefox-beta-library › library/har.spec.ts › should skip invalid Expires [pass] +bidi-firefox-beta-library › library/har.spec.ts › should throw without path [pass] +bidi-firefox-beta-library › library/har.spec.ts › should use attach mode for zip extension [fail] +bidi-firefox-beta-library › library/har.spec.ts › should work with gzip compression [fail] +bidi-firefox-beta-library › library/headful.spec.ts › Page.bringToFront should work [fail] +bidi-firefox-beta-library › library/headful.spec.ts › headless and headful should use same default fonts [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should click background tab [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should click bottom row w/ infobar in OOPIF [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should click in OOPIF [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should click when viewport size is larger than screen [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should close browser after context menu was triggered [pass] +bidi-firefox-beta-library › library/headful.spec.ts › should close browser with beforeunload page [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should close browsercontext with pending beforeunload dialog [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should dispatch click events to oversized viewports [pass] +bidi-firefox-beta-library › library/headful.spec.ts › should have default url when launching browser @smoke [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should not block third party SameSite=None cookies [fail] +bidi-firefox-beta-library › library/headful.spec.ts › should not crash when creating second context [pass] +bidi-firefox-beta-library › library/headful.spec.ts › should not override viewport size when passed null [pass] +bidi-firefox-beta-library › library/headful.spec.ts › should(not) block third party cookies [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should block all events when hit target is wrong [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should block all events when hit target is wrong and element detaches [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should block click when mousedown fails [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click an element inside closed shadow root [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click in custom element [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click in iframe with padding [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click in iframe with padding 2 [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click into frame inside closed shadow root [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click the button again after document.write [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should click when element detaches in mousedown [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should detect overlaid element in a transformed iframe [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should detect overlay from another shadow root [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should not block programmatic events [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should not click an element overlaying iframe with the target [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should not click iframe overlaying the target [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should work with block inside inline [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should work with block inside inline in shadow dom [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should work with block-block-block inside inline-inline [fail] +bidi-firefox-beta-library › library/hit-target.spec.ts › should work with drag and drop that moves the element under cursor [pass] +bidi-firefox-beta-library › library/hit-target.spec.ts › should work with mui select [pass] +bidi-firefox-beta-library › library/ignorehttpserrors.spec.ts › serviceWorker should intercept document request [fail] +bidi-firefox-beta-library › library/ignorehttpserrors.spec.ts › should fail with WebSocket if not ignored [pass] +bidi-firefox-beta-library › library/ignorehttpserrors.spec.ts › should isolate contexts [fail] +bidi-firefox-beta-library › library/ignorehttpserrors.spec.ts › should work @smoke [fail] +bidi-firefox-beta-library › library/ignorehttpserrors.spec.ts › should work with WebSocket [fail] +bidi-firefox-beta-library › library/ignorehttpserrors.spec.ts › should work with mixed content [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should assert navigation [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should await popup [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check a radio button [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check with keyboard [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click after same-document navigation [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click button with nested div [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should emit single keyup on ArrowDown [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [contentEditable] [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill japanese text [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea with new lines at the end [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore AltGraph [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore programmatic events [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should make a positioned click on a canvas [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should middle click [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should not target selector preview by text regexp [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should not throw csp directive violation errors [pass] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should press [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record ArrowDown [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after performAction [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after recordAction [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record slider [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should select [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should select with size attribute [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should uncheck [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should update selected element after pressing Tab [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should work with TrustedTypes [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › click should emit events in order [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should --save-trace [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should check input with chaining id [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should clear files [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain close page [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain open page [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain second page [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should download files [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should fill tricky characters [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle dialogs [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle history.postData [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should not clash pages [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should not lead to an error if html gets clicked [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should record navigations after identical pushState [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should record open in a new tab with url [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should reset hover model on action when element detaches [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should save assets via SIGINT [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should update active model on action [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should update hover model on action [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload a single file [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload multiple files [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-2.spec.ts › should --test-id-attribute [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled input [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled select [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert visibility [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.first [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.nth [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume contextmenu events, despite a custom context menu [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume pointer events [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with id attribute [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with name attribute [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with special characters in name attribute [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with testId [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with title attribute [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByAltText [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel without regex [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByPlaceholder [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByTestId [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate role locators undef frame locators [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in mstest if no options were passed [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in nunit if no options were passed [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in mstest [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in nunit [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in mstest if options were passed [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in nunit if options were passed [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print load/save storageState [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options for custom settings [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-csharp.spec.ts › should work with --save-har [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print a valid basic program in junit [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print load/save storage_state [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options for custom settings [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should print the correct imports in junit [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-java.spec.ts › should work with --save-har [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-javascript.spec.ts › should print load/save storageState [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options for custom settings [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-javascript.spec.ts › should save the codegen output to a file if specified [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-pytest.spec.ts › should print the correct context options when using a device and lang [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-pytest.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-pytest.spec.ts › should save the codegen output to a file if specified [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should print load/save storage_state [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options for custom settings [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should save the codegen output to a file if specified [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python-async.spec.ts › should work with --save-har [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python.spec.ts › should print load/save storage_state [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options for custom settings [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-python.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-python.spec.ts › should save the codegen output to a file if specified [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-test.spec.ts › should print load storageState [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options for custom settings [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device and additional options [unknown] +bidi-firefox-beta-library › library/inspector/cli-codegen-test.spec.ts › should print the correct imports and context options [fail] +bidi-firefox-beta-library › library/inspector/cli-codegen-test.spec.ts › should work with --save-har [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › expected properties on playwright object [pass] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support locator.and() [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support locator.or() [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.$, playwright.$$ [pass] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.getBy* [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.locator({ has }) [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.locator({ hasNot }) [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.locator.value [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.locator.values [fail] +bidi-firefox-beta-library › library/inspector/console-api.spec.ts › should support playwright.selector [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should hide internal calls [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should highlight locators with custom testId [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should highlight on explore [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should highlight on explore (csharp) [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should highlight pointer, only in main frame [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should highlight waitForEvent [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should not prevent key events [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should pause after a navigation [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should pause and resume the script [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should pause and resume the script with keyboard shortcut [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should pause on context close [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should pause on next pause [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should pause on page close [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should populate log [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should populate log with error [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should populate log with error in waitForEvent [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should populate log with waitForEvent [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should resume from console [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should show expect.toHaveText [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should show source [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should skip input when resuming [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should step [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › pause › should step with keyboard shortcut [fail] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › should not reset timeouts [pass] +bidi-firefox-beta-library › library/inspector/pause.spec.ts › should resume when closing inspector [pass] +bidi-firefox-beta-library › library/launcher.spec.ts › should have a devices object [pass] +bidi-firefox-beta-library › library/launcher.spec.ts › should have an errors object [pass] +bidi-firefox-beta-library › library/launcher.spec.ts › should kill browser process on timeout after close [pass] +bidi-firefox-beta-library › library/launcher.spec.ts › should throw a friendly error if its headed and there is no xserver on linux running [fail] +bidi-firefox-beta-library › library/locator-generator.spec.ts › asLocator internal:and [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › asLocator internal:chain [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › asLocator internal:or [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › asLocator xpath [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › generate multiple locators [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › parse locators strictly [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › parseLocator css [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › parseLocator quotes [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer frameLocator [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer getByRole [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer has [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer has + hasText [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer hasNot [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer hasNotText [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer hasText [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer ignore-case locators [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer internal:has-text locators [fail] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer locators [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer locators with regex [pass] +bidi-firefox-beta-library › library/locator-generator.spec.ts › reverse engineer ordered locators [pass] +bidi-firefox-beta-library › library/logger.spec.ts › should log @smoke [pass] +bidi-firefox-beta-library › library/logger.spec.ts › should log context-level [fail] +bidi-firefox-beta-library › library/modernizr.spec.ts › Mobile Safari [unknown] +bidi-firefox-beta-library › library/modernizr.spec.ts › Safari Desktop [unknown] +bidi-firefox-beta-library › library/page-clock.frozen.spec.ts › clock should be frozen [unknown] +bidi-firefox-beta-library › library/page-clock.frozen.spec.ts › clock should be realtime [unknown] +bidi-firefox-beta-library › library/page-clock.spec.ts › Date.now › check Date.now is an integer [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › Date.now › check Date.now is an integer (2) [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › fastForward › pushes back execution time for skipped timers [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › fastForward › supports string time arguments [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › popup › should not run time before popup on pause [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › popup › should run time before popup [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › popup › should tick after popup [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › popup › should tick before popup [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › creates updated Date while ticking [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › passes 1 minute [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › passes 2 hours, 34 minutes and 10 seconds [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › passes 8 seconds [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › returns the current now value [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › throws for invalid format [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › triggers after sufficient delay [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › triggers event when some throw [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › triggers immediately without specified delay [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › triggers multiple simultaneous timers [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › triggers simultaneous timers [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › runFor › waits after setTimeout was called [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › setFixedTime › allows installing fake timers after settings time [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › setFixedTime › allows setting time multiple times [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › setFixedTime › does not fake methods [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › setFixedTime › fixed time is not affected by clock manipulation [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › fakes Date constructor [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › replaces global clearInterval [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › replaces global performance.now [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › replaces global performance.timeOrigin [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › replaces global setInterval [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › replaces global setTimeout [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › sets initial timestamp [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › stubTimers › should throw for invalid date [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while on pause › fastForward should not run nested immediate [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › while on pause › runFor should not run nested immediate [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › while on pause › runFor should not run nested immediate from microtask [fail] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should fastForward [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should fastForwardTo [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should pause [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should pause and fastForward [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should progress time [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should runFor [pass] +bidi-firefox-beta-library › library/page-clock.spec.ts › while running › should set system time on pause [pass] +bidi-firefox-beta-library › library/page-event-crash.spec.ts › should be able to close context when page crashes [fail] +bidi-firefox-beta-library › library/page-event-crash.spec.ts › should cancel navigation when page crashes [fail] +bidi-firefox-beta-library › library/page-event-crash.spec.ts › should cancel waitForEvent when page crashes [fail] +bidi-firefox-beta-library › library/page-event-crash.spec.ts › should emit crash event when page crashes [fail] +bidi-firefox-beta-library › library/page-event-crash.spec.ts › should throw on any action after page crashes [fail] +bidi-firefox-beta-library › library/pdf.spec.ts › should be able to generate outline [unknown] +bidi-firefox-beta-library › library/pdf.spec.ts › should be able to save file [unknown] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should accumulate when adding [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should be prompt by default [pass] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should clear permissions [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should deny permission when not listed [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should fail when bad permission is given [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should grant geolocation permission when origin is listed [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should grant notifications permission when listed [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should grant permission when creating context [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should grant permission when listed for all domains [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should isolate permissions between browser contexts [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should prompt for geolocation permission when origin is not listed [pass] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should reset permissions [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › permissions › should trigger permission onchange [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › should support clipboard read [fail] +bidi-firefox-beta-library › library/permissions.spec.ts › storage access [unknown] +bidi-firefox-beta-library › library/popup.spec.ts › BrowserContext.addInitScript should apply to a cross-process popup [fail] +bidi-firefox-beta-library › library/popup.spec.ts › BrowserContext.addInitScript should apply to an in-process popup [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should expose function from browser context [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should inherit extra headers from browser context [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should inherit http credentials from browser context [pass] +bidi-firefox-beta-library › library/popup.spec.ts › should inherit offline from browser context [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should inherit touch support from browser context [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should inherit user agent from browser context @smoke [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should inherit viewport size from browser context [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should not dispatch binding on a closed page [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should not throttle rAF in the opener page [timeout] +bidi-firefox-beta-library › library/popup.spec.ts › should not throw when click closes popup [timeout] +bidi-firefox-beta-library › library/popup.spec.ts › should respect routes from browser context [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should respect routes from browser context when using window.open [fail] +bidi-firefox-beta-library › library/popup.spec.ts › should use viewport size from window features [timeout] +bidi-firefox-beta-library › library/proxy-pattern.spec.ts › socks proxy patter matcher [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › does launch without a port [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should authenticate [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should exclude patterns [fail] +bidi-firefox-beta-library › library/proxy.spec.ts › should proxy local network requests › by default › link-local [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should proxy local network requests › by default › localhost [fail] +bidi-firefox-beta-library › library/proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] +bidi-firefox-beta-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] +bidi-firefox-beta-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] +bidi-firefox-beta-library › library/proxy.spec.ts › should throw for bad server value [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should use SOCKS proxy for websocket requests [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should use proxy @smoke [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should use proxy for second page [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should use proxy with emulated user agent [unknown] +bidi-firefox-beta-library › library/proxy.spec.ts › should use socks proxy [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should use socks proxy in second page [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should work with IP:PORT notion [pass] +bidi-firefox-beta-library › library/proxy.spec.ts › should work with authenticate followed by redirect [pass] +bidi-firefox-beta-library › library/resource-timing.spec.ts › should work @smoke [pass] +bidi-firefox-beta-library › library/resource-timing.spec.ts › should work for SSL [fail] +bidi-firefox-beta-library › library/resource-timing.spec.ts › should work for redirect [pass] +bidi-firefox-beta-library › library/resource-timing.spec.ts › should work for subresource [pass] +bidi-firefox-beta-library › library/resource-timing.spec.ts › should work when serving from memory cache [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › accessible name nested treeitem [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › accessible name with slots [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › axe-core accessible-text [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › axe-core implicit-role [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › control embedded in a label [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › control embedded in a target element [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › display:contents should be visible when contents are visible [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › label/labelled-by aria-hidden with descendants [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › native controls [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › native controls labelled-by [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › own aria-label concatenated with aria-labelledby [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › should ignore stylesheet from hidden aria-labelledby subtree [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › should not include hidden pseudo into accessible name [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › should work with form and tricky input names [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › svg role=presentation [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › svg title [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › wpt accname #0 [pass] +bidi-firefox-beta-library › library/role-utils.spec.ts › wpt accname #1 [pass] +bidi-firefox-beta-library › library/role-utils.spec.ts › wpt accname #2 [fail] +bidi-firefox-beta-library › library/role-utils.spec.ts › wpt accname #3 [pass] +bidi-firefox-beta-library › library/role-utils.spec.ts › wpt accname non-manual [pass] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › element screenshot should work with a mobile viewport [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › element screenshot should work with device scale factor [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › element screenshots should handle vh units [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › page screenshot should capture css transform with device pixels [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor and scale:css [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should restore default viewport after fullPage screenshot [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should restore viewport after element screenshot and exception [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and exception [pass] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and timeout [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should take element screenshot when default viewport is null and restore back [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should take fullPage screenshots when default viewport is null [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should take screenshots when default viewport is null [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › element screenshot › should work if the main resource hangs [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should handle vh units [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should run in parallel in multiple pages [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should throw if screenshot size is too large with device scale factor [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and clip [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and fullPage [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor and clip [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor and scale:css [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor, clip and scale:css [fail] +bidi-firefox-beta-library › library/screenshot.spec.ts › page screenshot › should work with large size [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should chain text after parent [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should escape text with quote [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should escape text with slash [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should find text in shadow dom [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate label selector [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate relative selector [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate text and normalize whitespace [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate text for [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate title selector [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should match in shadow dom [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not escape text with >> [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not improve guid text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not use generated id [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not use input[value] [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not use text for select [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer button over inner span [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer data-testid [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should separate selectors by >> [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should trim long text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should trim text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve role name [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use nested ordinals [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use parent text [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use readable id [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should work with tricky attributes [fail] +bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should work without CSS.escape [fail] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should handle errors [pass] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should not rely on engines working from the root [fail] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should work [fail] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should work in main and isolated world [fail] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should work when registered on global [fail] +bidi-firefox-beta-library › library/selectors-register.spec.ts › should work with path [fail] +bidi-firefox-beta-library › library/shared-worker.spec.ts › should survive shared worker restart [pass] +bidi-firefox-beta-library › library/signals.spec.ts › should close the browser when the node process closes [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › should remove temp dir on process.exit [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] +bidi-firefox-beta-library › library/signals.spec.ts › signals › should report browser close signal 2 [timeout] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo check [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo click [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo fill [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo focus [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo goto [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo hover [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo press [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo type [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo check [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo click [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo fill [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo focus [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo goto [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo hover [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo press [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo reload [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo type [fail] +bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture frame [pass] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture iframe [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [pass] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture resources [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture snapshot target [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should collect multiple [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should collect on attribute change [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should collect snapshot [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should have a custom doctype [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect attr removal [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect node removal [fail] +bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +bidi-firefox-beta-library › library/tap.spec.ts › locators › should send all of the correct events [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should send all of the correct events @smoke [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should send well formed touch points [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should wait until an element is visible to tap it [fail] +bidi-firefox-beta-library › library/tap.spec.ts › should work with modifiers [fail] +bidi-firefox-beta-library › library/tap.spec.ts › trial run should not tap [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should allow hiding route actions [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should capture data-url svg iframe [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should contain action info [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should contain adopted style sheets [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should display language-specific locators [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should filter network requests by resource type [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should filter network requests by url [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should follow redirects [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle file URIs [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle multiple headers [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle src=blob [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have correct snapshot size [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have correct stack trace [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have network request overrides [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have network request overrides 2 [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have network requests [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight expect failure [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight target elements [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should ignore 304 responses [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include metainfo [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include requestUrl in route.abort [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should not crash with broken locator [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open console errors on click [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open simple trace viewer [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open snapshot in new browser context [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open trace viewer on specific host [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open trace-1.31 [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open trace-1.37 [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open two trace files [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open two trace files of the same test [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open two trace viewers [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should pick locator [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should pick locator in iframe [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should popup snapshot [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should preserve currentSrc [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should register custom elements [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should remove noscript by default [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should render console [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should render network bars [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should restore control values [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should restore scroll positions [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should serve css without content-type [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should serve overridden request [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show action source [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show baseURL in metadata pane [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show correct request start time [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show empty trace viewer [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show font preview [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show null as a param [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show params and return value [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show similar actions from library-only trace [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show snapshot URL [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should update highlight when typing [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [fail] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with meta CSP [unknown] +bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with nesting CSS selectors [unknown] +bidi-firefox-beta-library › library/tracing.spec.ts › should collect sources [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should collect trace with resources, but no js [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should collect two traces [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should exclude internal pages [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should export trace concurrently to second navigation [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should flush console events on tracing stop [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should hide internal stack frames [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should hide internal stack frames in expect [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should ignore iframes in head [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should include context API requests [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should include interrupted actions [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should not collect snapshots by default [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should not emit after w/o before [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should not flush console events [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should not hang for clicks that open dialogs [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should not include buffers in the trace [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should not stall on dialogs [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should overwrite existing file [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should produce screencast frames crop [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should produce screencast frames fit [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should produce screencast frames scale [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should record global request trace [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should record network failures [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should respect tracesDir and name [fail] +bidi-firefox-beta-library › library/tracing.spec.ts › should store global request traces separately [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should store postData for global request [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should throw when starting with different options [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should throw when stopping without start [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should use the correct apiName for event driven callbacks [pass] +bidi-firefox-beta-library › library/tracing.spec.ts › should work with multiple chunks [fail] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [fail] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [pass] +bidi-firefox-beta-library › library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [pass] +bidi-firefox-beta-library › library/video.spec.ts › screencast › saveAs should throw when no video frames [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should be 800x450 by default [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should be 800x600 with null viewport [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture css transformation [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture full viewport [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture navigation [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture static page [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should delete video [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should emulate an iphone [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should expose video path [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should expose video path blank page [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should expose video path blank popup [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should not create video for internal pages [unknown] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should scale frames down to the requested size [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should throw if browser dies [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should throw on browser close [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should work for popups [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with old options [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with video+trace [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with weird screen resolution [timeout] +bidi-firefox-beta-library › library/video.spec.ts › screencast › videoSize should require videosPath [pass] +bidi-firefox-beta-library › library/video.spec.ts › should saveAs video [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should emit binary frame events [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should emit close events [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should emit error [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should emit frame events [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should not have stray error events [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should pass self as argument to close event [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] +bidi-firefox-beta-library › library/web-socket.spec.ts › should turn off when offline [unknown] +bidi-firefox-beta-library › library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-firefox-beta-page.txt b/tests/bidi/expectations/bidi-firefox-beta-page.txt new file mode 100644 index 0000000000000..10cc403562596 --- /dev/null +++ b/tests/bidi/expectations/bidi-firefox-beta-page.txt @@ -0,0 +1,1971 @@ +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should force a layout [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should get frame box [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should handle nested frames [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should return null for invisible elements [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should work [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [fail] +bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [fail] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should double click the button [fail] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for
elements with force [fail] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for detached nodes [pass] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for hidden nodes with force [pass] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for recursively hidden nodes with force [pass] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work @smoke [pass] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work for Shadow DOM v1 [pass] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work for TextNodes [fail] +bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work with Node removed [pass] +bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should return null for document.documentElement [pass] +bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should return null for non-iframes [pass] +bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should work [pass] +bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should work for cross-frame evaluations [fail] +bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should work for cross-process iframes [pass] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › getAttribute should work [pass] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › innerHTML should work [pass] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › innerText should throw [fail] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › innerText should work [pass] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › inputValue should work [fail] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isChecked should work [fail] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isEditable should work [fail] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work [fail] +bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work with [fail] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect color value [fail] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect date [fail] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect month [unknown] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect range value [fail] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect time [fail] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect week [unknown] +bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on unsupported inputs [pass] +bidi-firefox-beta-page › page/page-focus.spec.ts › clicking checkbox should activate it [unknown] +bidi-firefox-beta-page › page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [fail] +bidi-firefox-beta-page › page/page-focus.spec.ts › should emit blur event [fail] +bidi-firefox-beta-page › page/page-focus.spec.ts › should emit focus event [fail] +bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse focus [fail] +bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse focus in all directions [fail] +bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse only form elements [unknown] +bidi-firefox-beta-page › page/page-focus.spec.ts › should work @smoke [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should capture iframe navigation request [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when canceled by another navigation [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding browser context timeout [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when main resources failed to load [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating and show the url at the error message [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating to bad url [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when replaced by another navigation [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when server returns 204 [timeout] +bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to about:blank [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not leak listeners during navigation [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should override referrer-policy [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should properly wait for load [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should report raw buffer for main resource [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should return from goto if new navigation is started [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should return last response in redirect chain [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should return response when page changes its URL after load [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should return url with basic auth info [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should send referer [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should send referer of cross-origin URL [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should use http for no protocol [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work @smoke [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work cross-process [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work when navigating to 404 [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work when navigating to data url [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work when navigating to valid url [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work when page calls history API in beforeunload [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with anchor navigation [timeout] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with file URL [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with file URL with subframes [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with lazy loading iframes [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with redirects [fail] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with self requesting page [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with subframes return 204 [pass] +bidi-firefox-beta-page › page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack during renderer-initiated navigation [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack should work @smoke [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack should work for file urls [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload during renderer-initiated navigation [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work on a page with a hash [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work with data url [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work with same origin redirect [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › regression test for issue 20791 [pass] +bidi-firefox-beta-page › page/page-history.spec.ts › should reload proper page [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › insertText should only emit input event [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should handle selectAll [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should move around the selection in a contenteditable [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should move to the start of the document [unknown] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should move with the arrow keys [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should not type canceled events [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press Enter [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press plus [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press shift plus [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press the meta key [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should report multiple modifiers [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should report shiftKey [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should scroll with PageDown [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send a character with insertText [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send proper codes while typing [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send proper codes while typing with shift [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should shift raw codes [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should specify location [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should specify repeat property [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support MacOS shortcuts [unknown] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support simple copy-pasting [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support simple cut-pasting [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support undo-redo [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should throw on unknown keys [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type after context menu was opened [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type all kinds of characters [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type emoji [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type emoji into an iframe [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [fail] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] +bidi-firefox-beta-page › page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [fail] +bidi-firefox-beta-page › page/page-leaks.spec.ts › click should not leak [fail] +bidi-firefox-beta-page › page/page-leaks.spec.ts › expect should not leak [fail] +bidi-firefox-beta-page › page/page-leaks.spec.ts › fill should not leak [fail] +bidi-firefox-beta-page › page/page-leaks.spec.ts › waitFor should not leak [fail] +bidi-firefox-beta-page › page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] +bidi-firefox-beta-page › page/page-listeners.spec.ts › should wait [pass] +bidi-firefox-beta-page › page/page-listeners.spec.ts › wait should throw [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › down and up should generate click [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should always round down [fail] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should click the document @smoke [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should dblclick the div [fail] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should pointerdown the div with a custom button [fail] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should report correct buttons property [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should select the text with mouse [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should set modifier keys on click [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should trigger hover state [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] +bidi-firefox-beta-page › page/page-mouse.spec.ts › should tween mouse movement [pass] +bidi-firefox-beta-page › page/page-navigation.spec.ts › should work with _blank target [pass] +bidi-firefox-beta-page › page/page-navigation.spec.ts › should work with _blank target in form [fail] +bidi-firefox-beta-page › page/page-navigation.spec.ts › should work with cross-process _blank target [pass] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle from the popup [fail] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent [fail] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [fail] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [fail] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [fail] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [fail] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] +bidi-firefox-beta-page › page/page-network-idle.spec.ts › should work after repeated navigations in the same page [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › page.reload return 304 status code [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should get the same headers as the server [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should not work for a redirect and interception [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should override post data content type [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should parse the json post data [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should report all cookies in one header [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should report raw headers [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should report raw response headers in redirects [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should return event source [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should return headers [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should return multipart/form-data [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should return navigation bit [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should return postData [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for a redirect [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for main frame navigation request [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for subframe navigation request [pass] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should work with binary post data [fail] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should work with binary post data and interception [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should provide a Response with a file URL [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should reject response.finished if context closes [timeout] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should reject response.finished if page closes [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should report all headers [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return body [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return body for prefetch script [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return body with compression [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return headers after route.fulfill [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return json [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return multiple header value [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return status text [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return text [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should return uncompressed text [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should wait until response completes [fail] +bidi-firefox-beta-page › page/page-network-response.spec.ts › should work @smoke [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should handle redirects [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should return sizes without hanging [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize and headersSize [fail] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should throw for failed requests [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 200 status code [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 401 status code [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 404 status code [pass] +bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 500 status code [fail] +bidi-firefox-beta-page › page/page-object-count.spec.ts › should count objects [unknown] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend binary post data [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend longer post data [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend method and post data [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend post data [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend utf8 post data [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should use content-type from original request [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should amend HTTP headers [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should amend method [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should amend method on main request [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should continue preload link requests [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should delete header with undefined value [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should delete the origin header [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should intercept css variable with background url [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [timeout] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not throw when continuing while page is closing [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should override method along with url [fail] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should override request url [timeout] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should work [pass] +bidi-firefox-beta-page › page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › post data › should amend json post data [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › post data › should amend post data [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should amend HTTP headers [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should amend method [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should chain once [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should delete header with undefined value [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should fall back [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should fall back after exception [pass] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should fall back async [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should not chain abort [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should not chain fulfill [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should override request url [fail] +bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should work [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fetch original request and fulfill [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill json [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill preload link requests [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [timeout] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [timeout] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with har response [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should include the origin header [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [timeout] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work [pass] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work with buffer as body [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work with file path [fail] +bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work with status code 422 [pass] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [pass] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill with any response [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should give access to the intercepted response body [pass] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should intercept with post data override [pass] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should intercept with url override [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [pass] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] +bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › route.abort should throw if called twice [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › route.continue should throw if called twice [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › route.fallback should throw if called twice [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › route.fulfill should throw if called twice [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should allow null origin for about:blank [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should be able to remove headers [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should be abortable [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should be abortable with custom error codes [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should contain raw request header [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should contain raw response header [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should contain raw response header after fulfill [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should contain referer header [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should fail navigation when aborting main resource [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should fulfill with redirect status [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should intercept @smoke [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should intercept main resource during cross-process navigation [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should not fulfill with redirect status [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should not work with redirects [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should override cookie header [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should pause intercepted XHR until continue [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should pause intercepted fetch request until continue [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should reject cors with disallowed credentials [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should respect cors overrides [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should send referer [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should show custom HTTP headers [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should support ? in glob pattern [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should support async handler w/ times [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should support cors for different methods [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should support cors with GET [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should support cors with POST [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should support cors with credentials [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should support the times parameter with route matching [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should unroute [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should work when POST is redirected with 302 [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should work when header manipulation headers with redirect [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with badly encoded server [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with custom referer headers [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with encoded server [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with encoded server - 2 [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with equal requests [pass] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with redirect inside sync XHR [fail] +bidi-firefox-beta-page › page/page-route.spec.ts › should work with redirects for subresources [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should work [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › should capture css box-shadow [fail] +bidi-firefox-beta-page › page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] +bidi-firefox-beta-page › page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [fail] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should fall back to selecting by label [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should not allow null items [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should not select single option when some attributes do not match [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should not throw when select causes navigation [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should respect event bubbling [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should return [] on no matched values [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should return [] on no values [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should return an array of matched values [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select multiple options [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select multiple options with attributes [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select only first option [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option @smoke [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by handle [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by index [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by label [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by multiple attributes [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by value [pass] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should throw if passed wrong types [fail] +bidi-firefox-beta-page › page/page-select-option.spec.ts › should throw when element is not a [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate title selector [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in shadow dom [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape text with >> [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not improve guid text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use generated id [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use input[value] [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use text for select [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer button over inner span [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer data-testid [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should separate selectors by >> [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim long text [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve role name [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve text [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not improve guid text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape text with >> [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should escape text with quote [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should escape text with slash [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use text for select [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer data-testid [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use readable id [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use generated id [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should chain text after parent [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use parent text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should separate selectors by >> [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim long text [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use nested ordinals [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use input[value] [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should find text in shadow dom [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in shadow dom [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use parent text [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use readable id [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [pass] +bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work with tricky attributes [pass] bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work without CSS.escape [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate label selector [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate title selector [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate relative selector [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work when registered on global [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work with path [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work in main and isolated world [pass] bidi-chromium-library › library/selectors-register.spec.ts › should handle errors [pass] bidi-chromium-library › library/selectors-register.spec.ts › should not rely on engines working from the root [pass] bidi-chromium-library › library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work in main and isolated world [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work when registered on global [pass] +bidi-chromium-library › library/selectors-register.spec.ts › should work with path [pass] bidi-chromium-library › library/shared-worker.spec.ts › should survive shared worker restart [timeout] bidi-chromium-library › library/signals.spec.ts › should close the browser when the node process closes [timeout] bidi-chromium-library › library/signals.spec.ts › should remove temp dir on process.exit [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should report browser close signal 2 [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] +bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] bidi-chromium-library › library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo check [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo click [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo fill [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo focus [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo goto [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo hover [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo press [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo reload [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo type [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo check [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo click [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo fill [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo focus [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo goto [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo hover [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo press [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo type [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [pass] +bidi-chromium-library › library/signals.spec.ts › signals › should report browser close signal 2 [timeout] bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [pass] bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [pass] bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [pass] @@ -1722,189 +1695,217 @@ bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle Sl bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [pass] bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect snapshot [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture resources [fail] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect multiple [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect node removal [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect attr removal [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should have a custom doctype [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo check [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo click [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo fill [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo focus [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo goto [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo hover [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo press [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo type [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo check [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo click [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo fill [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo focus [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo goto [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo hover [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo press [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo reload [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [timeout] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo type [pass] +bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [pass] bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture frame [fail] bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture iframe [fail] bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture resources [fail] bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture snapshot target [timeout] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect multiple [pass] bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect on attribute change [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect snapshot [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should have a custom doctype [pass] bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [pass] -bidi-chromium-library › library/tap.spec.ts › should send all of the correct events @smoke [fail] -bidi-chromium-library › library/tap.spec.ts › trial run should not tap [fail] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect attr removal [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect node removal [pass] +bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +bidi-chromium-library › library/tap.spec.ts › locators › should send all of the correct events [fail] bidi-chromium-library › library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] bidi-chromium-library › library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] bidi-chromium-library › library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] -bidi-chromium-library › library/tap.spec.ts › should work with modifiers [fail] +bidi-chromium-library › library/tap.spec.ts › should send all of the correct events @smoke [fail] bidi-chromium-library › library/tap.spec.ts › should send well formed touch points [fail] bidi-chromium-library › library/tap.spec.ts › should wait until an element is visible to tap it [fail] -bidi-chromium-library › library/tap.spec.ts › locators › should send all of the correct events [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show empty trace viewer [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace viewers [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open trace viewer on specific host [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open simple trace viewer [pass] +bidi-chromium-library › library/tap.spec.ts › should work with modifiers [fail] +bidi-chromium-library › library/tap.spec.ts › trial run should not tap [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should allow hiding route actions [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should capture data-url svg iframe [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] bidi-chromium-library › library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should contain action info [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should render network bars [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should render console [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should open console errors on click [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show params and return value [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show null as a param [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should have correct snapshot size [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should have correct stack trace [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should have network requests [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should contain adopted style sheets [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should display language-specific locators [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should filter network requests by resource type [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show font preview [fail] bidi-chromium-library › library/trace-viewer.spec.ts › should filter network requests by url [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides 2 [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show snapshot URL [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should popup snapshot [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should capture data-url svg iframe [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should contain adopted style sheets [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with nesting CSS selectors [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should restore scroll positions [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should restore control values [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with meta CSP [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should follow redirects [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should handle file URIs [unknown] bidi-chromium-library › library/trace-viewer.spec.ts › should handle multiple headers [fail] bidi-chromium-library › library/trace-viewer.spec.ts › should handle src=blob [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should handle file URIs [unknown] -bidi-chromium-library › library/trace-viewer.spec.ts › should preserve currentSrc [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should register custom elements [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target elements [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should have correct snapshot size [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should have correct stack trace [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides 2 [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should have network requests [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should highlight expect failure [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show action source [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should follow redirects [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target elements [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should ignore 304 responses [fail] bidi-chromium-library › library/trace-viewer.spec.ts › should include metainfo [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files of the same test [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.abort [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [fail] bidi-chromium-library › library/trace-viewer.spec.ts › should not crash with broken locator [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.abort [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should serve overridden request [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should display language-specific locators [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should update highlight when typing [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open console errors on click [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should open simple trace viewer [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open snapshot in new browser context [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open trace viewer on specific host [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should open trace-1.31 [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should open trace-1.37 [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should ignore 304 responses [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files of the same test [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace viewers [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator in iframe [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should popup snapshot [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should preserve currentSrc [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should register custom elements [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should remove noscript by default [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open snapshot in new browser context [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show similar actions from library-only trace [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show correct request start time [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should allow hiding route actions [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show baseURL in metadata pane [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should render console [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should render network bars [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should restore control values [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should restore scroll positions [pass] bidi-chromium-library › library/trace-viewer.spec.ts › should serve css without content-type [timeout] -bidi-chromium-library › library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should serve overridden request [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show action source [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show baseURL in metadata pane [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show correct request start time [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show empty trace viewer [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show font preview [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should show null as a param [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [unknown] +bidi-chromium-library › library/trace-viewer.spec.ts › should show params and return value [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show similar actions from library-only trace [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should show snapshot URL [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should update highlight when typing [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [fail] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with meta CSP [pass] +bidi-chromium-library › library/trace-viewer.spec.ts › should work with nesting CSS selectors [pass] +bidi-chromium-library › library/tracing.spec.ts › should collect sources [pass] bidi-chromium-library › library/tracing.spec.ts › should collect trace with resources, but no js [timeout] -bidi-chromium-library › library/tracing.spec.ts › should use the correct apiName for event driven callbacks [fail] -bidi-chromium-library › library/tracing.spec.ts › should not collect snapshots by default [pass] -bidi-chromium-library › library/tracing.spec.ts › should not include buffers in the trace [fail] +bidi-chromium-library › library/tracing.spec.ts › should collect two traces [pass] bidi-chromium-library › library/tracing.spec.ts › should exclude internal pages [pass] +bidi-chromium-library › library/tracing.spec.ts › should export trace concurrently to second navigation [fail] +bidi-chromium-library › library/tracing.spec.ts › should flush console events on tracing stop [pass] +bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames [pass] +bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames in expect [pass] +bidi-chromium-library › library/tracing.spec.ts › should ignore iframes in head [pass] bidi-chromium-library › library/tracing.spec.ts › should include context API requests [pass] -bidi-chromium-library › library/tracing.spec.ts › should collect two traces [pass] -bidi-chromium-library › library/tracing.spec.ts › should respect tracesDir and name [fail] -bidi-chromium-library › library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] -bidi-chromium-library › library/tracing.spec.ts › should overwrite existing file [fail] -bidi-chromium-library › library/tracing.spec.ts › should collect sources [pass] -bidi-chromium-library › library/tracing.spec.ts › should record network failures [fail] +bidi-chromium-library › library/tracing.spec.ts › should include interrupted actions [pass] +bidi-chromium-library › library/tracing.spec.ts › should not collect snapshots by default [pass] bidi-chromium-library › library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] -bidi-chromium-library › library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] +bidi-chromium-library › library/tracing.spec.ts › should not emit after w/o before [pass] +bidi-chromium-library › library/tracing.spec.ts › should not flush console events [pass] +bidi-chromium-library › library/tracing.spec.ts › should not hang for clicks that open dialogs [pass] +bidi-chromium-library › library/tracing.spec.ts › should not include buffers in the trace [fail] +bidi-chromium-library › library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] bidi-chromium-library › library/tracing.spec.ts › should not stall on dialogs [pass] -bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames fit [fail] +bidi-chromium-library › library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] +bidi-chromium-library › library/tracing.spec.ts › should overwrite existing file [fail] bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames crop [fail] +bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames fit [fail] bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames scale [fail] -bidi-chromium-library › library/tracing.spec.ts › should include interrupted actions [pass] -bidi-chromium-library › library/tracing.spec.ts › should throw when starting with different options [pass] -bidi-chromium-library › library/tracing.spec.ts › should throw when stopping without start [pass] -bidi-chromium-library › library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] -bidi-chromium-library › library/tracing.spec.ts › should work with multiple chunks [pass] -bidi-chromium-library › library/tracing.spec.ts › should export trace concurrently to second navigation [fail] -bidi-chromium-library › library/tracing.spec.ts › should not hang for clicks that open dialogs [pass] -bidi-chromium-library › library/tracing.spec.ts › should ignore iframes in head [pass] -bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames [pass] -bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames in expect [pass] bidi-chromium-library › library/tracing.spec.ts › should record global request trace [pass] +bidi-chromium-library › library/tracing.spec.ts › should record network failures [fail] +bidi-chromium-library › library/tracing.spec.ts › should respect tracesDir and name [fail] bidi-chromium-library › library/tracing.spec.ts › should store global request traces separately [pass] bidi-chromium-library › library/tracing.spec.ts › should store postData for global request [pass] -bidi-chromium-library › library/tracing.spec.ts › should not flush console events [pass] -bidi-chromium-library › library/tracing.spec.ts › should flush console events on tracing stop [pass] -bidi-chromium-library › library/tracing.spec.ts › should not emit after w/o before [pass] +bidi-chromium-library › library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] +bidi-chromium-library › library/tracing.spec.ts › should throw when starting with different options [pass] +bidi-chromium-library › library/tracing.spec.ts › should throw when stopping without start [pass] +bidi-chromium-library › library/tracing.spec.ts › should use the correct apiName for event driven callbacks [fail] +bidi-chromium-library › library/tracing.spec.ts › should work with multiple chunks [pass] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [pass] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] +bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] +bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [fail] bidi-chromium-library › library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [fail] -bidi-chromium-library › library/video.spec.ts › screencast › videoSize should require videosPath [pass] -bidi-chromium-library › library/video.spec.ts › screencast › should work with old options [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] +bidi-chromium-library › library/video.spec.ts › screencast › saveAs should throw when no video frames [pass] +bidi-chromium-library › library/video.spec.ts › screencast › should be 800x450 by default [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should be 800x600 with null viewport [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture css transformation [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture navigation [fail] bidi-chromium-library › library/video.spec.ts › screencast › should capture static page [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] bidi-chromium-library › library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should expose video path [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › saveAs should throw when no video frames [pass] bidi-chromium-library › library/video.spec.ts › screencast › should delete video [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should emulate an iphone [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should expose video path [timeout] bidi-chromium-library › library/video.spec.ts › screencast › should expose video path blank page [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should work with weird screen resolution [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] bidi-chromium-library › library/video.spec.ts › screencast › should expose video path blank popup [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should capture navigation [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture css transformation [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should work for popups [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should not create video for internal pages [unknown] bidi-chromium-library › library/video.spec.ts › screencast › should scale frames down to the requested size [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should be 800x450 by default [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should be 800x600 with null viewport [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should emulate an iphone [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should throw on browser close [fail] bidi-chromium-library › library/video.spec.ts › screencast › should throw if browser dies [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should throw on browser close [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] +bidi-chromium-library › library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [fail] bidi-chromium-library › library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should not create video for internal pages [unknown] -bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should work for popups [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should work with old options [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] bidi-chromium-library › library/video.spec.ts › screencast › should work with video+trace [fail] +bidi-chromium-library › library/video.spec.ts › screencast › should work with weird screen resolution [timeout] +bidi-chromium-library › library/video.spec.ts › screencast › videoSize should require videosPath [pass] bidi-chromium-library › library/video.spec.ts › should saveAs video [fail] -bidi-chromium-library › library/web-socket.spec.ts › should work @smoke [pass] +bidi-chromium-library › library/web-socket.spec.ts › should emit binary frame events [timeout] bidi-chromium-library › library/web-socket.spec.ts › should emit close events [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should emit error [timeout] bidi-chromium-library › library/web-socket.spec.ts › should emit frame events [timeout] bidi-chromium-library › library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should pass self as argument to close event [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should emit binary frame events [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should emit error [timeout] bidi-chromium-library › library/web-socket.spec.ts › should not have stray error events [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should pass self as argument to close event [timeout] bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should turn off when offline [unknown] \ No newline at end of file +bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] +bidi-chromium-library › library/web-socket.spec.ts › should turn off when offline [unknown] +bidi-chromium-library › library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-chromium-page.txt b/tests/bidi/expectations/bidi-chromium-page.txt index dc35691964ce5..14d77dd0abfce 100644 --- a/tests/bidi/expectations/bidi-chromium-page.txt +++ b/tests/bidi/expectations/bidi-chromium-page.txt @@ -1690,277 +1690,277 @@ bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with commi bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with history.pushState() [pass] bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with history.replaceState() [pass] bidi-chromium-page › page/page-wait-for-url.spec.ts › should work with url match for same document navigations [pass] -bidi-chromium-page › page/queryselector.spec.ts › $$ should work with bogus Array.from [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect css selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect text selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector starting with .. [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector with starting parenthesis [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should query existing element with css selector @smoke [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should query existing element with text selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should query existing element with xpath selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should query existing elements [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should return empty array if nothing is found [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should return null for non-existing element [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should support >> syntax [unknown] -bidi-chromium-page › page/queryselector.spec.ts › should throw for non-string selector [unknown] -bidi-chromium-page › page/queryselector.spec.ts › xpath should query existing element [unknown] -bidi-chromium-page › page/queryselector.spec.ts › xpath should return empty array for non-existing element [unknown] -bidi-chromium-page › page/queryselector.spec.ts › xpath should return multiple elements [unknown] -bidi-chromium-page › page/retarget.spec.ts › check retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › direct actions retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › editable retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › element state checks should work as expected for label with zero-sized input [unknown] -bidi-chromium-page › page/retarget.spec.ts › enabled/disabled retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › input value retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › select options retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › selection retargeting [unknown] -bidi-chromium-page › page/retarget.spec.ts › setInputFiles should work with label [unknown] -bidi-chromium-page › page/retarget.spec.ts › should check the box outside shadow dom label [unknown] -bidi-chromium-page › page/retarget.spec.ts › should not retarget anchor into parent label [unknown] -bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing button with a disabled fieldset [unknown] -bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing disabled button [unknown] -bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing enabled button [unknown] -bidi-chromium-page › page/retarget.spec.ts › visible/hidden retargeting [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › css on the handle should be relative [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should absolutize relative selectors [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should keep dom order with comma separated list [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should not match root after >> [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should return multiple captures for the same node [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should return multiple captures when going up the hierarchy [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work for open shadow roots [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with * [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with + [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :has [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :is [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :not [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child(of) notation with nested functions [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :scope [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with :scope and class [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with > combinator and spaces [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with attribute selectors [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with comma inside text [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list in various positions [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with large DOM @smoke [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with numerical id [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with spaces in :nth-child and :not [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with wrong-case id [unknown] -bidi-chromium-page › page/selectors-css.spec.ts › should work with ~ [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › $ should not wait for frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › $$ should not wait for frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › $$eval should throw for missing frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › $eval should throw for missing frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › click should survive frame reattach [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › click should survive iframe navigation [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › click should survive navigation [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should capture after the enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should click in lazy iframe [unknown] +bidi-chromium-page › page/queryselector.spec.ts › $$ should work with bogus Array.from [fail] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect css selector [pass] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect text selector [pass] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector [pass] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector starting with .. [pass] +bidi-chromium-page › page/queryselector.spec.ts › should auto-detect xpath selector with starting parenthesis [pass] +bidi-chromium-page › page/queryselector.spec.ts › should query existing element with css selector @smoke [pass] +bidi-chromium-page › page/queryselector.spec.ts › should query existing element with text selector [pass] +bidi-chromium-page › page/queryselector.spec.ts › should query existing element with xpath selector [pass] +bidi-chromium-page › page/queryselector.spec.ts › should query existing elements [fail] +bidi-chromium-page › page/queryselector.spec.ts › should return empty array if nothing is found [fail] +bidi-chromium-page › page/queryselector.spec.ts › should return null for non-existing element [pass] +bidi-chromium-page › page/queryselector.spec.ts › should support >> syntax [pass] +bidi-chromium-page › page/queryselector.spec.ts › should throw for non-string selector [pass] +bidi-chromium-page › page/queryselector.spec.ts › xpath should query existing element [fail] +bidi-chromium-page › page/queryselector.spec.ts › xpath should return empty array for non-existing element [fail] +bidi-chromium-page › page/queryselector.spec.ts › xpath should return multiple elements [fail] +bidi-chromium-page › page/retarget.spec.ts › check retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › direct actions retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › editable retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › element state checks should work as expected for label with zero-sized input [pass] +bidi-chromium-page › page/retarget.spec.ts › enabled/disabled retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › input value retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › select options retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › selection retargeting [pass] +bidi-chromium-page › page/retarget.spec.ts › setInputFiles should work with label [timeout] +bidi-chromium-page › page/retarget.spec.ts › should check the box outside shadow dom label [pass] +bidi-chromium-page › page/retarget.spec.ts › should not retarget anchor into parent label [pass] +bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing button with a disabled fieldset [pass] +bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing disabled button [pass] +bidi-chromium-page › page/retarget.spec.ts › should wait for enclosing enabled button [pass] +bidi-chromium-page › page/retarget.spec.ts › visible/hidden retargeting [pass] +bidi-chromium-page › page/selectors-css.spec.ts › css on the handle should be relative [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should absolutize relative selectors [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should keep dom order with comma separated list [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should not match root after >> [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should return multiple captures for the same node [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should return multiple captures when going up the hierarchy [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work for open shadow roots [fail] +bidi-chromium-page › page/selectors-css.spec.ts › should work with * [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with + [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :has [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :is [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :not [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :nth-child(of) notation with nested functions [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :scope [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with :scope and class [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with > combinator and spaces [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with attribute selectors [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with comma inside text [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with comma separated list in various positions [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with large DOM @smoke [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with numerical id [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with spaces in :nth-child and :not [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with wrong-case id [pass] +bidi-chromium-page › page/selectors-css.spec.ts › should work with ~ [pass] +bidi-chromium-page › page/selectors-frame.spec.ts › $ should not wait for frame [pass] +bidi-chromium-page › page/selectors-frame.spec.ts › $$ should not wait for frame [pass] +bidi-chromium-page › page/selectors-frame.spec.ts › $$eval should throw for missing frame [pass] +bidi-chromium-page › page/selectors-frame.spec.ts › $eval should throw for missing frame [pass] +bidi-chromium-page › page/selectors-frame.spec.ts › click should survive frame reattach [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › click should survive iframe navigation [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › click should survive navigation [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should capture after the enter-frame [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should click in lazy iframe [fail] bidi-chromium-page › page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should non work for non-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should not allow capturing before enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should not allow dangling enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should not allow leading enter-frame [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $$eval [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $$eval (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe @smoke [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › waitFor should survive frame reattach [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › waitForSelector should survive frame reattach (handle) [unknown] -bidi-chromium-page › page/selectors-frame.spec.ts › waitForSelector should survive iframe navigation (handle) [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getBy escaping [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByAltText should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should ignore empty aria-label [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over aria-label [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over native label [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and for [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and multiple controls [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-label [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-labelledby [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with multiply-labelled input [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with nested elements [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByPlaceholder should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByRole escaping [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should escape id [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work for regex [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId with custom testId should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByText should work [unknown] -bidi-chromium-page › page/selectors-get-by.spec.ts › getByTitle should work [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › chaining should work with large DOM @smoke [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › data-testid on the handle should be relative [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should click on links in shadow dom [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should escape the scope with >> [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should print original xpath in error [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should properly determine visibility of display:contents elements [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work for open shadow roots [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with :nth-match [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with :visible [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with >> visible= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:and= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:chain= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has-not= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:or= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with layout selectors [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with nth= [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with pipe in xpath [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › should work with strict mode and chaining [unknown] -bidi-chromium-page › page/selectors-misc.spec.ts › xpath should be relative [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should exact match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should not crash when there is no match [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should partially match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should query by props combinations [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support all string operators [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support regex [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support truthy querying [unknown] +bidi-chromium-page › page/selectors-frame.spec.ts › should non work for non-frame [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should not allow capturing before enter-frame [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should not allow dangling enter-frame [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should not allow leading enter-frame [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $ and $$ (handle) [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $$eval [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $$eval (handle) [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for $eval (handle) [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe (handle) [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for iframe @smoke [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › should work for nested iframe (handle) [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › waitFor should survive frame reattach [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › waitForSelector should survive frame reattach (handle) [fail] +bidi-chromium-page › page/selectors-frame.spec.ts › waitForSelector should survive iframe navigation (handle) [fail] +bidi-chromium-page › page/selectors-get-by.spec.ts › getBy escaping [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByAltText should work [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should ignore empty aria-label [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over aria-label [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should prioritize aria-labelledby over native label [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and for [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with ancestor label and multiple controls [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-label [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with aria-labelledby [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with multiply-labelled input [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByLabel should work with nested elements [fail] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByPlaceholder should work [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByRole escaping [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should escape id [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId should work for regex [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTestId with custom testId should work [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByText should work [pass] +bidi-chromium-page › page/selectors-get-by.spec.ts › getByTitle should work [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › chaining should work with large DOM @smoke [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › data-testid on the handle should be relative [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should click on links in shadow dom [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should escape the scope with >> [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should print original xpath in error [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should properly determine visibility of display:contents elements [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work for open shadow roots [fail] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with :nth-match [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with :visible [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with >> visible= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:and= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:chain= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has-not= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:has= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with internal:or= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with layout selectors [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with nth= [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with pipe in xpath [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › should work with strict mode and chaining [pass] +bidi-chromium-page › page/selectors-misc.spec.ts › xpath should be relative [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should compose [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should exact match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should not crash when there is no match [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should partially match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should query by props combinations [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support all string operators [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support nested react trees [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support regex [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should support truthy querying [pass] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react after unmount [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with multiroot react inside shadow DOM [pass] bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with react memo [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should exact match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should not crash when there is no match [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should partially match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should query by props combinations [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support all string operators [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support regex [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react inside shadow DOM [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react15 › should work with single-root elements @smoke [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should compose [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should exact match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should not crash when there is no match [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should partially match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should query by props combinations [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support all string operators [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support nested react trees [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support regex [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should support truthy querying [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multi-root elements (fragments) [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react after unmount [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with multiroot react inside shadow DOM [pass] bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with react memo [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should exact match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should not crash when there is no match [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should partially match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should query by props combinations [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support all string operators [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support regex [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react inside shadow DOM [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with react memo [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should compose [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should exact match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should not crash when there is no match [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should partially match by props [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should query by props combinations [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support all string operators [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support nested react trees [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support regex [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react after unmount [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react inside shadow DOM [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with react memo [unknown] -bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › getAttribute should be atomic [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › innerHTML should be atomic [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › innerText should be atomic [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › isVisible should be atomic [unknown] -bidi-chromium-page › page/selectors-register.spec.ts › textContent should be atomic [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › errors [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › hidden with shadow dom slots [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should detect roles [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should filter hidden, unless explicitly asked for [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should not match scope by default [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support checked [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support disabled [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support expanded [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support level [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support name [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support output accessible name [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support pressed [unknown] -bidi-chromium-page › page/selectors-role.spec.ts › should support selected [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › hasText and internal:text should match full node text in strict mode [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should be case sensitive if quotes are specified [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should clear caches [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should match input[type=button|submit] [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should match root after >> [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should match root after >> with * [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should prioritize light dom over shadow dom in the same parent [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should search for a substring without quotes [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should skip head, script and style [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should support empty string [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should waitForSelector with distributed elements [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work @smoke [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work across nodes [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work for open shadow roots [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with :has-text [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with :text [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with large DOM [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with leading and trailing spaces [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with paired quotes in the middle of selector [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with text nodes in quoted mode [unknown] -bidi-chromium-page › page/selectors-text.spec.ts › should work with unpaired quotes when not at the start [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should compose [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should exact match by props [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should not crash when there is no match [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should partially match by props [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should query by props combinations [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support all string operators [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support nested vue trees [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support regex [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support truthy querying [unknown] +bidi-chromium-page › page/selectors-react.spec.ts › react16 › should work with single-root elements @smoke [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should compose [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should exact match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should not crash when there is no match [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should partially match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should query by props combinations [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support all string operators [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support nested react trees [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support regex [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should support truthy querying [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multi-root elements (fragments) [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react after unmount [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with multiroot react inside shadow DOM [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with react memo [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react17 › should work with single-root elements @smoke [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should compose [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should exact match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should not crash when there is no match [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should partially match by props [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should query by props combinations [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support all string operators [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support nested react trees [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support regex [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should support truthy querying [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multi-root elements (fragments) [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react after unmount [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with multiroot react inside shadow DOM [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with react memo [pass] +bidi-chromium-page › page/selectors-react.spec.ts › react18 › should work with single-root elements @smoke [pass] +bidi-chromium-page › page/selectors-register.spec.ts › getAttribute should be atomic [pass] +bidi-chromium-page › page/selectors-register.spec.ts › innerHTML should be atomic [pass] +bidi-chromium-page › page/selectors-register.spec.ts › innerText should be atomic [pass] +bidi-chromium-page › page/selectors-register.spec.ts › isVisible should be atomic [pass] +bidi-chromium-page › page/selectors-register.spec.ts › textContent should be atomic [pass] +bidi-chromium-page › page/selectors-role.spec.ts › errors [pass] +bidi-chromium-page › page/selectors-role.spec.ts › hidden with shadow dom slots [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should detect roles [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should filter hidden, unless explicitly asked for [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should not match scope by default [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support checked [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support disabled [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support expanded [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support level [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support name [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support output accessible name [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support pressed [pass] +bidi-chromium-page › page/selectors-role.spec.ts › should support selected [pass] +bidi-chromium-page › page/selectors-text.spec.ts › hasText and internal:text should match full node text in strict mode [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should be case sensitive if quotes are specified [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should clear caches [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should match input[type=button|submit] [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should match root after >> [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should match root after >> with * [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should prioritize light dom over shadow dom in the same parent [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should search for a substring without quotes [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should skip head, script and style [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should support empty string [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should waitForSelector with distributed elements [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work @smoke [fail] +bidi-chromium-page › page/selectors-text.spec.ts › should work across nodes [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work for open shadow roots [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with :has-text [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with :text [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with large DOM [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with leading and trailing spaces [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with paired quotes in the middle of selector [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with text nodes in quoted mode [pass] +bidi-chromium-page › page/selectors-text.spec.ts › should work with unpaired quotes when not at the start [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should compose [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should exact match by props [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should not crash when there is no match [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should partially match by props [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should query by props combinations [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support all string operators [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support nested vue trees [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support regex [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should support truthy querying [pass] bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multiroot vue inside shadow DOM [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should compose [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should exact match by props [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should not crash when there is no match [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should partially match by props [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should query by props combinations [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support all string operators [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support nested vue trees [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support regex [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support truthy querying [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multi-root elements (fragments) [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multiroot react [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multiroot vue inside shadow DOM [unknown] -bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with single-root elements @smoke [unknown] -bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel event on svg element [unknown] -bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events @smoke [unknown] -bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events after context menu was opened [unknown] -bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events after popup was opened @smoke [unknown] -bidi-chromium-page › page/wheel.spec.ts › should scroll horizontally [unknown] -bidi-chromium-page › page/wheel.spec.ts › should scroll when nobody is listening [unknown] -bidi-chromium-page › page/wheel.spec.ts › should set the modifiers [unknown] -bidi-chromium-page › page/wheel.spec.ts › should work when the event is canceled [unknown] -bidi-chromium-page › page/workers.spec.ts › Page.workers @smoke [unknown] -bidi-chromium-page › page/workers.spec.ts › should attribute network activity for worker inside iframe to the iframe [unknown] -bidi-chromium-page › page/workers.spec.ts › should clear upon cross-process navigation [unknown] -bidi-chromium-page › page/workers.spec.ts › should clear upon navigation [unknown] -bidi-chromium-page › page/workers.spec.ts › should dispatch console messages when page has workers [unknown] -bidi-chromium-page › page/workers.spec.ts › should emit created and destroyed events [unknown] -bidi-chromium-page › page/workers.spec.ts › should evaluate [unknown] -bidi-chromium-page › page/workers.spec.ts › should have JSHandles for console logs [unknown] -bidi-chromium-page › page/workers.spec.ts › should not report console logs from workers twice [unknown] -bidi-chromium-page › page/workers.spec.ts › should report and intercept network from nested worker [unknown] -bidi-chromium-page › page/workers.spec.ts › should report console logs [unknown] -bidi-chromium-page › page/workers.spec.ts › should report errors [unknown] -bidi-chromium-page › page/workers.spec.ts › should report network activity [unknown] -bidi-chromium-page › page/workers.spec.ts › should report network activity on worker creation [unknown] -bidi-chromium-page › page/workers.spec.ts › should support extra http headers [unknown] -bidi-chromium-page › page/workers.spec.ts › should support offline [unknown] \ No newline at end of file +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multiroot react [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with multiroot vue inside shadow DOM [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue2 › should work with single-root elements @smoke [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should compose [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should exact match by props [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should not crash when there is no match [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should partially match by props [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should query by props combinations [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support all string operators [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support nested vue trees [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support regex [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should support truthy querying [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multi-root elements (fragments) [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multiroot react [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with multiroot vue inside shadow DOM [pass] +bidi-chromium-page › page/selectors-vue.spec.ts › vue3 › should work with single-root elements @smoke [pass] +bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel event on svg element [pass] +bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events @smoke [pass] +bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events after context menu was opened [pass] +bidi-chromium-page › page/wheel.spec.ts › should dispatch wheel events after popup was opened @smoke [pass] +bidi-chromium-page › page/wheel.spec.ts › should scroll horizontally [pass] +bidi-chromium-page › page/wheel.spec.ts › should scroll when nobody is listening [pass] +bidi-chromium-page › page/wheel.spec.ts › should set the modifiers [pass] +bidi-chromium-page › page/wheel.spec.ts › should work when the event is canceled [pass] +bidi-chromium-page › page/workers.spec.ts › Page.workers @smoke [timeout] +bidi-chromium-page › page/workers.spec.ts › should attribute network activity for worker inside iframe to the iframe [timeout] +bidi-chromium-page › page/workers.spec.ts › should clear upon cross-process navigation [timeout] +bidi-chromium-page › page/workers.spec.ts › should clear upon navigation [timeout] +bidi-chromium-page › page/workers.spec.ts › should dispatch console messages when page has workers [timeout] +bidi-chromium-page › page/workers.spec.ts › should emit created and destroyed events [timeout] +bidi-chromium-page › page/workers.spec.ts › should evaluate [timeout] +bidi-chromium-page › page/workers.spec.ts › should have JSHandles for console logs [timeout] +bidi-chromium-page › page/workers.spec.ts › should not report console logs from workers twice [timeout] +bidi-chromium-page › page/workers.spec.ts › should report and intercept network from nested worker [fail] +bidi-chromium-page › page/workers.spec.ts › should report console logs [timeout] +bidi-chromium-page › page/workers.spec.ts › should report errors [timeout] +bidi-chromium-page › page/workers.spec.ts › should report network activity [timeout] +bidi-chromium-page › page/workers.spec.ts › should report network activity on worker creation [timeout] +bidi-chromium-page › page/workers.spec.ts › should support extra http headers [timeout] +bidi-chromium-page › page/workers.spec.ts › should support offline [timeout] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-firefox-beta-library.txt b/tests/bidi/expectations/bidi-firefox-beta-library.txt index 070ee241c128e..65b898ac7d1d5 100644 --- a/tests/bidi/expectations/bidi-firefox-beta-library.txt +++ b/tests/bidi/expectations/bidi-firefox-beta-library.txt @@ -592,7 +592,7 @@ bidi-firefox-beta-library › library/capabilities.spec.ts › service worker sh bidi-firefox-beta-library › library/capabilities.spec.ts › service worker should register in an iframe [pass] bidi-firefox-beta-library › library/capabilities.spec.ts › serviceWorker should intercept document request [pass] bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on page with mp4 @smoke [fail] -bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on showDirectoryPicker [unknown] +bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on showDirectoryPicker [flaky] bidi-firefox-beta-library › library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] bidi-firefox-beta-library › library/capabilities.spec.ts › should play audio @smoke [fail] bidi-firefox-beta-library › library/capabilities.spec.ts › should play video @smoke [pass] diff --git a/tests/bidi/expectations/bidi-firefox-beta-page.txt b/tests/bidi/expectations/bidi-firefox-beta-page.txt index 10cc403562596..b9e4bd9bd7ea2 100644 --- a/tests/bidi/expectations/bidi-firefox-beta-page.txt +++ b/tests/bidi/expectations/bidi-firefox-beta-page.txt @@ -1035,7 +1035,7 @@ bidi-firefox-beta-page › page/page-focus.spec.ts › should emit blur event [f bidi-firefox-beta-page › page/page-focus.spec.ts › should emit focus event [fail] bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse focus [fail] bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse focus in all directions [fail] -bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse only form elements [unknown] +bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse only form elements [flaky] bidi-firefox-beta-page › page/page-focus.spec.ts › should work @smoke [fail] bidi-firefox-beta-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [pass] bidi-firefox-beta-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] @@ -1203,7 +1203,7 @@ bidi-firefox-beta-page › page/page-network-request.spec.ts › should get the bidi-firefox-beta-page › page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] bidi-firefox-beta-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] bidi-firefox-beta-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] +bidi-firefox-beta-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [flaky] bidi-firefox-beta-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [fail] bidi-firefox-beta-page › page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] bidi-firefox-beta-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] @@ -1264,7 +1264,7 @@ bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 401 status code [pass] bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 404 status code [pass] bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 500 status code [fail] -bidi-firefox-beta-page › page/page-object-count.spec.ts › should count objects [unknown] +bidi-firefox-beta-page › page/page-object-count.spec.ts › should count objects [flaky] bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [pass] bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [pass] @@ -1487,7 +1487,7 @@ bidi-firefox-beta-page › page/page-set-content.spec.ts › content() should th bidi-firefox-beta-page › page/page-set-content.spec.ts › should await resources to load [fail] bidi-firefox-beta-page › page/page-set-content.spec.ts › should respect default navigation timeout [pass] bidi-firefox-beta-page › page/page-set-content.spec.ts › should respect timeout [pass] -bidi-firefox-beta-page › page/page-set-content.spec.ts › should return empty content there is no iframe src [unknown] +bidi-firefox-beta-page › page/page-set-content.spec.ts › should return empty content there is no iframe src [flaky] bidi-firefox-beta-page › page/page-set-content.spec.ts › should work @smoke [fail] bidi-firefox-beta-page › page/page-set-content.spec.ts › should work fast enough [fail] bidi-firefox-beta-page › page/page-set-content.spec.ts › should work with HTML 4 doctype [fail] @@ -1762,7 +1762,7 @@ bidi-firefox-beta-page › page/selectors-frame.spec.ts › click should survive bidi-firefox-beta-page › page/selectors-frame.spec.ts › click should survive navigation [pass] bidi-firefox-beta-page › page/selectors-frame.spec.ts › should capture after the enter-frame [fail] bidi-firefox-beta-page › page/selectors-frame.spec.ts › should click in lazy iframe [pass] -bidi-firefox-beta-page › page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [unknown] +bidi-firefox-beta-page › page/selectors-frame.spec.ts › should fail if element removed while waiting on element handle [flaky] bidi-firefox-beta-page › page/selectors-frame.spec.ts › should non work for non-frame [fail] bidi-firefox-beta-page › page/selectors-frame.spec.ts › should not allow capturing before enter-frame [pass] bidi-firefox-beta-page › page/selectors-frame.spec.ts › should not allow dangling enter-frame [pass] @@ -1833,7 +1833,7 @@ bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should w bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should work with multiroot react [pass] bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should work with multiroot react after unmount [pass] bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should work with multiroot react inside shadow DOM [pass] -bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should work with react memo [unknown] +bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should work with react memo [flaky] bidi-firefox-beta-page › page/selectors-react.spec.ts › react15 › should work with single-root elements @smoke [pass] bidi-firefox-beta-page › page/selectors-react.spec.ts › react16 › should compose [pass] bidi-firefox-beta-page › page/selectors-react.spec.ts › react16 › should exact match by props [pass] From d1926e2f9b91e31d73acfb87e564634f55b0dbb2 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 11 Sep 2024 15:15:10 -0700 Subject: [PATCH 057/805] chore: do not store project name in expectations (#32575) --- tests/bidi/expectationReporter.ts | 3 +- tests/bidi/expectationUtil.ts | 2 +- .../expectations/bidi-chromium-library.txt | 3822 ++++++++-------- .../bidi/expectations/bidi-chromium-page.txt | 3932 ++++++++-------- .../bidi-firefox-beta-library.txt | 3822 ++++++++-------- .../expectations/bidi-firefox-beta-page.txt | 3942 ++++++++--------- 6 files changed, 7762 insertions(+), 7761 deletions(-) diff --git a/tests/bidi/expectationReporter.ts b/tests/bidi/expectationReporter.ts index a4caad9861476..a6d31ac1f5405 100644 --- a/tests/bidi/expectationReporter.ts +++ b/tests/bidi/expectationReporter.ts @@ -54,7 +54,8 @@ class ExpectationReporter implements Reporter { const expectations = await parseExpectations(project.title); for (const test of project.allTests()) { const outcome = getOutcome(test); - const key = test.titlePath().slice(1).join(' › '); + // Strip root and project names. + const key = test.titlePath().slice(2).join(' › '); if (!expectations.has(key) || expectations.get(key) === 'unknown') expectations.set(key, outcome); } diff --git a/tests/bidi/expectationUtil.ts b/tests/bidi/expectationUtil.ts index 23491d2d91224..cdf9b779f22ff 100644 --- a/tests/bidi/expectationUtil.ts +++ b/tests/bidi/expectationUtil.ts @@ -27,7 +27,7 @@ export async function createSkipTestPredicate(projectName: string): Promise false; const expectationsMap = await parseBidiExpectations(projectName); return (info: TestInfo) => { - const key = [info.project.name, ...info.titlePath].join(' › '); + const key = info.titlePath.join(' › '); const expectation = expectationsMap.get(key); return expectation === 'fail' || expectation === 'timeout'; }; diff --git a/tests/bidi/expectations/bidi-chromium-library.txt b/tests/bidi/expectations/bidi-chromium-library.txt index 54d7b8ebba239..13dbf66eb5568 100644 --- a/tests/bidi/expectations/bidi-chromium-library.txt +++ b/tests/bidi/expectations/bidi-chromium-library.txt @@ -1,1911 +1,1911 @@ -bidi-chromium-library › library/beforeunload.spec.ts › should access page after beforeunload [timeout] -bidi-chromium-library › library/beforeunload.spec.ts › should be able to navigate away from page with beforeunload [pass] -bidi-chromium-library › library/beforeunload.spec.ts › should close browser with beforeunload page [pass] -bidi-chromium-library › library/beforeunload.spec.ts › should close browsercontext with beforeunload page [pass] -bidi-chromium-library › library/beforeunload.spec.ts › should close page with beforeunload listener [pass] -bidi-chromium-library › library/beforeunload.spec.ts › should not stall on evaluate when dismissing beforeunload [pass] -bidi-chromium-library › library/beforeunload.spec.ts › should run beforeunload if asked for @smoke [timeout] -bidi-chromium-library › library/browser.spec.ts › should create new page @smoke [pass] -bidi-chromium-library › library/browser.spec.ts › should dispatch page.on(close) upon browser.close and reject evaluate [fail] -bidi-chromium-library › library/browser.spec.ts › should return browserType [pass] -bidi-chromium-library › library/browser.spec.ts › should throw upon second create new page [pass] -bidi-chromium-library › library/browser.spec.ts › version should work [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should add cookies with empty value [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should allow unnamed cookies [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should be able to set unsecure cookie for HTTP website [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should default to setting secure cookie for HTTPS websites [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should have |expires| set to |-1| for session cookies [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate cookies between launches [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate cookies in browser contexts [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate persistent cookies [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate send cookie header [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should isolate session cookies [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should not block third party SameSite=None cookies [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should not set a cookie on a data URL page [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should not set a cookie with blank page URL [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should roundtrip cookie [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should send cookie header [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set a cookie on a different domain [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set a cookie with a path [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set cookie with reasonable defaults [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set cookies for a frame [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set multiple cookies [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should set secure cookies on secure WebSocket [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should work @smoke [pass] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should work with expires=-1 [fail] -bidi-chromium-library › library/browsercontext-add-cookies.spec.ts › should(not) block third party cookies [pass] -bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts @smoke [pass] -bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts for already created pages [pass] -bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work with browser context scripts with a path [pass] -bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work without navigation in popup [fail] -bidi-chromium-library › library/browsercontext-add-init-script.spec.ts › should work without navigation, after all bindings [fail] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should be able to match a URL relative to its given URL with urlMatcher [fail] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newContext is passed to page.goto @smoke [pass] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newPage is passed to page.goto [pass] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browserType.launchPersistentContext is passed to page.goto [fail] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL with a trailing slash in browser.newPage is passed to page.goto [pass] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL without a trailing slash in browser.newPage is passed to page.goto [pass] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should not construct a new URL when valid URLs are passed [pass] -bidi-chromium-library › library/browsercontext-base-url.spec.ts › should not construct a new URL with baseURL when a glob was used [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › close() should abort waitForEvent [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › close() should be callable twice [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › close() should work for empty context [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › default user agent [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › setContent should work after disabling javascript [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should be able to click across browser contexts [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should be able to navigate after disabling javascript [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should close all belonging pages once closing context [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should create new context @smoke [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should disable javascript [fail] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should emulate media in cross-process iframe [fail] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should emulate media in popup [fail] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should emulate navigator.onLine [fail] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should isolate localStorage and cookies @smoke [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should make a copy of default viewport [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should not allow deviceScaleFactor with null viewport [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should not allow isMobile with null viewport [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should not hang on promises after disabling javascript [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should not report frameless pages on error [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should pass self to close event [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should propagate default viewport to the page [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should respect deviceScaleFactor [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should return all of the pages [pass] -bidi-chromium-library › library/browsercontext-basic.spec.ts › should work with offline option [fail] -bidi-chromium-library › library/browsercontext-basic.spec.ts › window.open should use parent tab context [pass] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should clear cookies [pass] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should isolate cookies when clearing [pass] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by domain [fail] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name [fail] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name and domain [fail] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by name regex [fail] -bidi-chromium-library › library/browsercontext-clearcookies.spec.ts › should remove cookies by path [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should add cookies with an expiration [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should be able to send third party cookies via an iframe [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get a cookie @smoke [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get a non-session cookie [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get cookies from multiple urls [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should get multiple cookies [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should parse cookie with large Max-Age correctly [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should properly report "Lax" sameSite cookie [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should properly report "Strict" sameSite cookie [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should properly report httpOnly cookie [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should return cookies with empty value [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should return no cookies in pristine browser context [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should return secure cookies based on HTTP(S) protocol [pass] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should support requestStorageAccess [fail] -bidi-chromium-library › library/browsercontext-cookies.spec.ts › should work with subdomain cookie [pass] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching hostname [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching port [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching scheme [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail with wrong credentials [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should fail without credentials [pass] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should return resource body [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with correct credentials @smoke [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin case insensitive [fail] -bidi-chromium-library › library/browsercontext-credentials.spec.ts › should work with setHTTPCredentials [fail] -bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass CSP header [fail] -bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass CSP in iframes as well [fail] -bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass CSP meta tag @smoke [fail] -bidi-chromium-library › library/browsercontext-csp.spec.ts › should bypass after cross-process navigation [fail] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should emulate viewport and screen size [fail] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should emulate viewport without screen size [fail] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should reset scroll top after a navigation [pass] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should scroll to a precise position with mobile scale [pass] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should scroll to click [pass] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should scroll twice when emulated [pass] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should support clicking [pass] -bidi-chromium-library › library/browsercontext-device.spec.ts › device › should work @smoke [fail] -bidi-chromium-library › library/browsercontext-dsf.spec.ts › should fetch hidpi assets [pass] -bidi-chromium-library › library/browsercontext-dsf.spec.ts › should fetch lodpi assets @smoke [pass] -bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work @smoke [pass] -bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work in immediately closed popup [timeout] -bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work in popup [pass] -bidi-chromium-library › library/browsercontext-events.spec.ts › console event should work in popup 2 [timeout] -bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work @smoke [pass] -bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work in immediately closed popup [timeout] -bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work in popup [timeout] -bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work in popup 2 [pass] -bidi-chromium-library › library/browsercontext-events.spec.ts › dialog event should work with inline script tag [timeout] -bidi-chromium-library › library/browsercontext-events.spec.ts › weberror event should work [timeout] -bidi-chromium-library › library/browsercontext-expose-function.spec.ts › expose binding should work [fail] -bidi-chromium-library › library/browsercontext-expose-function.spec.ts › exposeBindingHandle should work [fail] -bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should be callable from-inside addInitScript [fail] -bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should throw for duplicate registrations [pass] -bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should work [fail] -bidi-chromium-library › library/browsercontext-expose-function.spec.ts › should work with CSP [fail] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail if response content-length header is missing (br) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with chunked responses (without Content-Length header) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should support decompression [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail if response content-length header is missing (deflate) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with chunked responses (without Content-Length header) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should support decompression [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail if response content-length header is missing (gzip) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with chunked responses (without Content-Length header) [pass] -bidi-chromium-library › library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should support decompression [pass] -bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work [pass] -bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work on request fixture [pass] -bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › https post should work with ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch-happy-eyeballs.spec.ts › should work with ip6 and port as the host [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › context request should export same storage state as context [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › delete should support post data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › deleteshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should not throw on long set-cookie value [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetch should work [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › fetchshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should support post data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › get should work @smoke [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › getshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › head should support post data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › headshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › patch should support post data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › patchshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › post should support post data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › postshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support failOnStatusCode [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support params passed as URLSearchParams [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support params passed as object [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support params passed as string [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › put should support post data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › putshould support ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should abort requests when browser context closes [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should accept bool and numeric params [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add cookies from Set-Cookie header [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add default headers [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add default headers to redirects [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should add session cookies to request [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should allow to override default headers [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should dispose [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should dispose when context closes [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should encode to application/json by default [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should follow redirects [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should follow redirects correctly when Location header contains UTF-8 characters [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should handle cookies on redirects [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should inherit ignoreHTTPSErrors from context [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not add context cookie if cookie header passed as a parameter [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not hang on a brotli encoded Range request [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not lose body while handling Set-Cookie header [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not work after context dispose [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should not work after dispose [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should override request parameters [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should preserve cookie order from Set-Cookie header [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should propagate custom headers with redirects [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should propagate extra http headers with redirects [fail] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should remove cookie with expires far in the past [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should remove cookie with negative max-age [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should resolve url relative to baseURL [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should respect timeout after redirects [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should retry on ECONNRESET [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should return error with wrong credentials [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should return raw headers [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should send content-length [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should send secure cookie over http for localhost [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should serialize data to json regardless of content-type [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should set domain=localhost cookie [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for browser.newPage [fail] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for newContext [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support SameSite cookie attribute over https [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support a timeout of 0 [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support application/x-www-form-urlencoded [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support brotli compression [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support cookie with empty value [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support deflate compression [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support gzip compression [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support https [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data and keep the order [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support multipart/form-data with ReadStream values [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support repeating names in multipart/form-data [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support set-cookie with SameSite and without Secure attribute over HTTP [fail] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should support timeout option [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted brotli body [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted deflate body [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw informative error on corrupted gzip body [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw nice error on unsupported data type [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on invalid header value [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error after redirect [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error when sending body [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on network error when sending body after redirect [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should throw on non-http(s) protocol [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should update host header on redirect [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should work with connectOverCDP [unknown] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should work with http credentials [pass] -bidi-chromium-library › library/browsercontext-fetch.spec.ts › should work with setHTTPCredentials [pass] -bidi-chromium-library › library/browsercontext-har.spec.ts › by default should abort requests not found in har [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › context.unrouteAll should stop context.routeFromHAR [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › fallback:continue should continue requests on bad har [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › fallback:continue should continue when not found in har [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › newPage should fulfill from har, matching the method and following redirects [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › page.unrouteAll should stop page.routeFromHAR [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should apply overrides before routing from har [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should context.routeFromHAR, matching the method and following redirects [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should disambiguate by header [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should fulfill from har with content in a file [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should goForward to redirected navigation [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should ignore aborted requests [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should ignore boundary when matching multipart/form-data body [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should only context.routeFromHAR requests matching url filter [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should only handle requests matching url filter [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should only page.routeFromHAR requests matching url filter [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should page.routeFromHAR, matching the method and following redirects [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should produce extracted zip [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should record overridden requests to har [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should reload redirected navigation [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should round-trip extracted har.zip [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should round-trip har with postData [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should round-trip har.zip [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should support regex filter [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should update extracted har.zip for page [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should update har.zip for context [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should update har.zip for page [fail] -bidi-chromium-library › library/browsercontext-har.spec.ts › should update har.zip for page with different options [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().locale [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect accept-language header @smoke [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect navigator.language [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should affect navigator.language in popups [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should be isolated between contexts [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should format date [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should format number [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should format number in popups [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should format number in workers [timeout] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should not change default locale in another context [fail] -bidi-chromium-library › library/browsercontext-locale.spec.ts › should work for multiple pages sharing same process [pass] -bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.Request [pass] -bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFailed [fail] -bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFinished [pass] -bidi-chromium-library › library/browsercontext-network-event.spec.ts › BrowserContext.Events.Response [pass] -bidi-chromium-library › library/browsercontext-network-event.spec.ts › should fire events in proper order [pass] -bidi-chromium-library › library/browsercontext-network-event.spec.ts › should not fire events for favicon or favicon redirects [unknown] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should fire page lifecycle events [fail] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have about:blank for empty url with domcontentloaded [fail] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have about:blank url with domcontentloaded [fail] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have an opener [pass] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have url [pass] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should have url after domcontentloaded [pass] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should not crash while redirecting of original request was missed [pass] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should not hang on ctrl-click during provisional load [timeout] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should report initialized pages [fail] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should report when a new page is created and closed [fail] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should work with Ctrl-clicking [pass] -bidi-chromium-library › library/browsercontext-page-event.spec.ts › should work with Shift-clicking [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › frame.focus should work multiple times [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › page.context should return the correct instance [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should click the button with deviceScaleFactor set [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should click the button with offset with page scale [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should click with disabled javascript [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should keep selection in multiple pages [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should not be visible in context.pages [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should not hang with touch-enabled viewports [pass] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should not leak listeners during navigation of 20 pages [fail] -bidi-chromium-library › library/browsercontext-pages.spec.ts › should return bounding box with page scale [pass] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › does launch without a port [pass] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should authenticate [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should authenticate with empty password [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should exclude patterns [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts on navigation [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › link-local [timeout] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › localhost [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [timeout] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should set cookie for top-level domain [pass] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should throw for bad server value [pass] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should throw for socks4 authentication [pass] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should throw for socks5 authentication [pass] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use ipv6 proxy [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy for https urls [timeout] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy for second page [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use proxy twice [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use socks proxy [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should use socks proxy in second page [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should work when passing the proxy only on the context level [fail] -bidi-chromium-library › library/browsercontext-proxy.spec.ts › should work with IP:PORT notion [fail] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should continue issuing events after closing the reused page [fail] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should ignore binding from beforeunload [pass] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should not cache resources [fail] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should re-add binding after reset [fail] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset mouse position [pass] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset serviceworker [fail] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset serviceworker that hangs in importScripts [fail] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should reset tracing [pass] -bidi-chromium-library › library/browsercontext-reuse.spec.ts › should work with clock emulation [pass] -bidi-chromium-library › library/browsercontext-route.spec.ts › should chain fallback [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should chain fallback into page [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should chain fallback w/ dynamic URL [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should fall back async [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should fall back to context.route [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should ignore secure Set-Cookie header for insecure requests [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should intercept [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should not chain abort [pass] -bidi-chromium-library › library/browsercontext-route.spec.ts › should not chain fulfill [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should overwrite post body with empty string [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should support Set-Cookie header [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should support async handler w/ times [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should support the times parameter with route matching [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should unroute [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should use Set-Cookie header in future requests [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should work with ignoreHTTPSErrors [fail] -bidi-chromium-library › library/browsercontext-route.spec.ts › should yield to page.route [fail] -bidi-chromium-library › library/browsercontext-service-worker-policy.spec.ts › block › blocks service worker registration [timeout] -bidi-chromium-library › library/browsercontext-service-worker-policy.spec.ts › block › should not throw error on about:blank [pass] -bidi-chromium-library › library/browsercontext-service-worker-policy.spec.ts › should allow service workers by default [pass] -bidi-chromium-library › library/browsercontext-set-extra-http-headers.spec.ts › should override extra headers from browser context [fail] -bidi-chromium-library › library/browsercontext-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should capture cookies [fail] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should capture local storage [fail] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should handle malformed file [pass] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should handle missing file [pass] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should not emit events about internal page [fail] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should not restore localStorage twice [fail] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should round-trip through the file [fail] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should serialize storageState with lone surrogates [pass] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should set local storage [fail] -bidi-chromium-library › library/browsercontext-storage-state.spec.ts › should work when service worker is intefering [pass] -bidi-chromium-library › library/browsercontext-strict.spec.ts › should not fail page.textContent in non-strict mode [pass] -bidi-chromium-library › library/browsercontext-strict.spec.ts › strict context mode › should fail page.click in strict mode [fail] -bidi-chromium-library › library/browsercontext-strict.spec.ts › strict context mode › should fail page.textContent in strict mode [fail] -bidi-chromium-library › library/browsercontext-strict.spec.ts › strict context mode › should opt out of strict mode [pass] -bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().timeZone [fail] -bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should not change default timezone in another context [fail] -bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should throw for invalid timezone IDs when creating pages [fail] -bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should work @smoke [fail] -bidi-chromium-library › library/browsercontext-timezone-id.spec.ts › should work for multiple pages sharing same process [pass] -bidi-chromium-library › library/browsercontext-user-agent.spec.ts › custom user agent for download [timeout] -bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should emulate device user-agent [fail] -bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should make a copy of default options [fail] -bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should work [fail] -bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should work for navigator.userAgentData and sec-ch-ua headers [unknown] -bidi-chromium-library › library/browsercontext-user-agent.spec.ts › should work for subframes [fail] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › default mobile viewports to 980 width [fail] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › mouse should work with mobile viewports and cross process navigations [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › respect meta viewport tag [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should be detectable [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should detect touch when applying viewport with touches [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should emulate the hover media feature [fail] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should fire orientationchange event [timeout] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should scroll when emulating a mobile viewport [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support landscape emulation [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support mobile emulation [pass] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support touch emulation [fail] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support window.orientation emulation [fail] -bidi-chromium-library › library/browsercontext-viewport-mobile.spec.ts › mobile viewport › view scale should reset after navigation [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › WebKit Windows headed should have a minimal viewport [unknown] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should be able to get correct orientation angle on non-mobile devices [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should drag with high dpi [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should emulate availWidth and availHeight [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should emulate device height [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should emulate device width [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should get the proper default viewport size [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should not have touch by default [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should report null viewportSize when given null viewport [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should return correct outerWidth and outerHeight [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should set both screen and viewport options [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should set the proper viewport size [pass] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should set window.screen.orientation.type for mobile devices [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should support touch with null viewport [fail] -bidi-chromium-library › library/browsercontext-viewport.spec.ts › should throw on tap if hasTouch is not enabled [pass] -bidi-chromium-library › library/browsertype-basic.spec.ts › browserType.executablePath should work [unknown] -bidi-chromium-library › library/browsertype-basic.spec.ts › browserType.name should work [fail] -bidi-chromium-library › library/browsertype-basic.spec.ts › should throw when trying to connect with not-chromium [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer only › should be able to reconnect to a browser 12 times without warnings [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer only › should properly disconnect when connection closes from the server side [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer only › should work with cluster [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › disconnected event should be emitted when browser is closed or server is closed [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › disconnected event should have browser as argument [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › setInputFiles should preserve lastModified timestamp [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect 20 times to a single server without warnings [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect two browsers at the same time [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to connect when the wsEndpoint is passed as an option [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to reconnect to a browser [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 through localhost [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should connect over http [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should connect over wss [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should emit close events on pages and contexts [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should error when saving download after deletion [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should filter launch options [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should fulfill with global fetch result [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should handle exceptions during connect [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should ignore page.pause when headed [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should not throw on close after disconnect [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should print HTTP error [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should print custom ws close error [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should print ws error [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should properly disconnect when connection closes from the client side [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should record trace with sources [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject navigation when browser closes [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.close finishes [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.onDisconnect fires [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should reject waitForSelector when browser closes [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should respect selectors [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should save download [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should save har [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should saveAs videos from remote browser [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should send extra headers with connect request [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should set the browser connected state [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should support slowmo option [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should terminate network waiters [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should throw when calling waitForNavigation after disconnect [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should throw when used after isConnected returns false [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should timeout in connect while connecting [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should timeout in socket while connecting [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › should upload large file [timeout] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should check proxy pattern on the client [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should forward non-forwarded requests [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should lead to the error page for forwarded requests when the connection is refused [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy based on the pattern [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy ipv6 localhost requests @smoke [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy local.playwright requests [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests @smoke [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests from fetch api [unknown] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › disconnected event should be emitted when browser is closed or server is closed [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › disconnected event should have browser as argument [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › setInputFiles should preserve lastModified timestamp [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to connect 20 times to a single server without warnings [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to connect two browsers at the same time [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to connect when the wsEndpoint is passed as an option [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to reconnect to a browser [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 through localhost [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should connect over http [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should connect over wss [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should emit close events on pages and contexts [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should error when saving download after deletion [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should filter launch options [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should fulfill with global fetch result [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should handle exceptions during connect [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should ignore page.pause when headed [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should not throw on close after disconnect [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should print HTTP error [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should print custom ws close error [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should print ws error [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should properly disconnect when connection closes from the client side [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should record trace with sources [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject navigation when browser closes [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.close finishes [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.onDisconnect fires [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should reject waitForSelector when browser closes [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should respect selectors [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should save download [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should save har [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should saveAs videos from remote browser [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should send extra headers with connect request [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should set the browser connected state [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should support slowmo option [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should terminate network waiters [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should throw when calling waitForNavigation after disconnect [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should throw when used after isConnected returns false [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should timeout in connect while connecting [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should timeout in socket while connecting [pass] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › should upload large file [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should check proxy pattern on the client [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should forward non-forwarded requests [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should lead to the error page for forwarded requests when the connection is refused [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy based on the pattern [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy ipv6 localhost requests @smoke [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy local.playwright requests [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests @smoke [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests from fetch api [fail] -bidi-chromium-library › library/browsertype-connect.spec.ts › should refuse connecting when versions do not match [pass] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 hub + node chromium [unknown] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium [unknown] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium through run-driver [unknown] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone non-chromium [unknown] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 hub + node chromium [unknown] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium [unknown] -bidi-chromium-library › library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium broken driver [unknown] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should default to random wsPath [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should fire "close" event during kill [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should fire close event [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should log protocol [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should provide an error when ws endpoint is incorrect [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should return child_process instance [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work when wsPath is missing leading slash [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work with host [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work with port [fail] -bidi-chromium-library › library/browsertype-launch-server.spec.ts › launch server › should work with wsPath [fail] -bidi-chromium-library › library/browsertype-launch.spec.ts › should accept objects as options [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should allow await using [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should be callable twice [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should fire close event for all contexts [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should handle exception [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should handle timeout [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should reject all promises when browser is closed [fail] -bidi-chromium-library › library/browsertype-launch.spec.ts › should reject if executable path is invalid [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should reject if launched browser fails immediately [fail] -bidi-chromium-library › library/browsertype-launch.spec.ts › should report launch log [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if page argument is passed [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if port option is passed [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if port option is passed for persistent context [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if userDataDir is passed as an argument [pass] -bidi-chromium-library › library/browsertype-launch.spec.ts › should throw if userDataDir option is passed [pass] -bidi-chromium-library › library/capabilities.spec.ts › Intl.ListFormat should work [pass] -bidi-chromium-library › library/capabilities.spec.ts › SharedArrayBuffer should work @smoke [fail] -bidi-chromium-library › library/capabilities.spec.ts › Web Assembly should work @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › WebSocket should work @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › loading in HTMLImageElement.prototype [pass] -bidi-chromium-library › library/capabilities.spec.ts › make sure that XMLHttpRequest upload events are emitted correctly [pass] -bidi-chromium-library › library/capabilities.spec.ts › navigator.clipboard should be present [pass] -bidi-chromium-library › library/capabilities.spec.ts › requestFullscreen [pass] -bidi-chromium-library › library/capabilities.spec.ts › service worker should cover the iframe [pass] -bidi-chromium-library › library/capabilities.spec.ts › service worker should register in an iframe [pass] -bidi-chromium-library › library/capabilities.spec.ts › serviceWorker should intercept document request [pass] -bidi-chromium-library › library/capabilities.spec.ts › should not crash on page with mp4 @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › should not crash on showDirectoryPicker [unknown] -bidi-chromium-library › library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] -bidi-chromium-library › library/capabilities.spec.ts › should play audio @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › should play video @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › should play webm video @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › should respect CSP @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › should send no Content-Length header for GET requests with a Content-Type [pass] -bidi-chromium-library › library/capabilities.spec.ts › should set CloseEvent.wasClean to false when the server terminates a WebSocket connection [pass] -bidi-chromium-library › library/capabilities.spec.ts › should support webgl 2 @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › should support webgl @smoke [pass] -bidi-chromium-library › library/capabilities.spec.ts › webkit should define window.safari [unknown] -bidi-chromium-library › library/capabilities.spec.ts › window.GestureEvent in WebKit [pass] -bidi-chromium-library › library/channels.spec.ts › exposeFunction should not leak [fail] -bidi-chromium-library › library/channels.spec.ts › should not generate dispatchers for subresources w/o listeners [pass] -bidi-chromium-library › library/channels.spec.ts › should scope CDPSession handles [unknown] -bidi-chromium-library › library/channels.spec.ts › should scope browser handles [pass] -bidi-chromium-library › library/channels.spec.ts › should scope context handles [pass] -bidi-chromium-library › library/channels.spec.ts › should work with the domain module [timeout] -bidi-chromium-library › library/chromium/bfcache.spec.ts › bindings should work after restoring from bfcache [fail] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › serviceWorker(), and fromServiceWorker() work [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setExtraHTTPHeaders [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setOffline [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept only serviceworker request, not page [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker importScripts [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker requests (main and within) [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker update requests [unknown] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker [fail] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker (advanced) [fail] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to content-type) of main service worker request [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to redirect) of main service worker request [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report intercepted service worker requests in HAR [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › Page.route should work with intervention headers [fail] -bidi-chromium-library › library/chromium/chromium.spec.ts › http credentials › httpCredentials [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › serviceWorkers() should return current workers [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › should close service worker together with the context [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › should create a worker from a service worker [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › should create a worker from service worker with noop routing [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › should emit new service worker on update [timeout] -bidi-chromium-library › library/chromium/chromium.spec.ts › should not create a worker from a shared worker [pass] -bidi-chromium-library › library/chromium/chromium.spec.ts › should pass args with spaces [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › emulate media should not be affected by second connectOverCDP [unknown] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › setInputFiles should preserve lastModified timestamp [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should allow tracing over cdp session [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should be able to connect via localhost [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should cleanup artifacts dir after connectOverCDP disconnects due to ws close [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect over a ws endpoint [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session twice [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session when passed as a first argument [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to existing page with iframe and navigate [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect to existing service workers [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connect via https [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should connectOverCDP and manage downloads in default context [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should print custom ws close error [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should report all pages in an existing browser [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpoint URL JSON webSocketDebuggerUrl is undefined [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpointURL returns a non-expected status code [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should return valid browser from context.browser() [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should send default User-Agent header with connect request [timeout] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should send extra headers with connect request [timeout] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should use logger in default context [fail] -bidi-chromium-library › library/chromium/connect-over-cdp.spec.ts › should use proxy with connectOverCDP [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should NOT report scripts across navigations [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should ignore injected stylesheets [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report multiple stylesheets [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report sourceURLs [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report stylesheets across navigations [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should report stylesheets that have no coverage [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work with a recently loaded stylesheet [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work with complicated usecases [fail] -bidi-chromium-library › library/chromium/css-coverage.spec.ts › should work with media queries [fail] -bidi-chromium-library › library/chromium/disable-web-security.spec.ts › test init script w/ --disable-web-security [fail] -bidi-chromium-library › library/chromium/disable-web-security.spec.ts › test utility world in popup w/ --disable-web-security [pass] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should NOT report scripts across navigations when enabled [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should ignore eval() scripts by default [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should not hang when there is a debugger statement [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should report multiple scripts [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should report scripts across navigations when disabled [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should report sourceURLs [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › should work [fail] -bidi-chromium-library › library/chromium/js-coverage.spec.ts › shouldn't ignore eval() scripts if reportAnonymousScripts is true [fail] -bidi-chromium-library › library/chromium/launcher.spec.ts › should not create pages automatically [fail] -bidi-chromium-library › library/chromium/launcher.spec.ts › should not throw with remote-debugging-port argument [fail] -bidi-chromium-library › library/chromium/launcher.spec.ts › should open devtools when "devtools: true" option is given [unknown] -bidi-chromium-library › library/chromium/launcher.spec.ts › should return background pages [fail] -bidi-chromium-library › library/chromium/launcher.spec.ts › should return background pages when recording video [fail] -bidi-chromium-library › library/chromium/launcher.spec.ts › should support request/response events when using backgroundPage() [fail] -bidi-chromium-library › library/chromium/launcher.spec.ts › should throw with remote-debugging-pipe argument [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › ElementHandle.boundingBox() should work [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › contentFrame should work [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should allow cdp sessions on oopifs [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should be able to click in iframe [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should click [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should click a button when it overlays oopif [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should emit filechooser event for iframe [timeout] -bidi-chromium-library › library/chromium/oopif.spec.ts › should emulate media [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should emulate offline [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should expose function [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should get the proper viewport [unknown] -bidi-chromium-library › library/chromium/oopif.spec.ts › should handle oopif detach [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should handle remote -> local -> remote transitions [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should intercept response body from oopif [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should load oopif iframes with subresources and route [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should not throw on exposeFunction when oopif detaches [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should report google.com frame with headed [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should report main requests [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should report oopif frames [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should respect route [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should support addInitScript [pass] -bidi-chromium-library › library/chromium/oopif.spec.ts › should support context options [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should support exposeFunction [fail] -bidi-chromium-library › library/chromium/oopif.spec.ts › should take screenshot [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should be able to detach session [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should detach when page closes [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should enable and disable domains independently [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should not break page.close() [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should only accept a page or frame [pass] -bidi-chromium-library › library/chromium/session.spec.ts › should reject protocol calls when page closes [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should send events [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should throw if target is part of main [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should throw nice errors [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should work [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should work with main frame [fail] -bidi-chromium-library › library/chromium/session.spec.ts › should work with newBrowserCDPSession [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should create directories as needed [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should output a trace [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should return a buffer [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should run with custom categories if provided [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should support a buffer without a path [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should throw if tracing on two pages [fail] -bidi-chromium-library › library/chromium/tracing.spec.ts › should work without options [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › persistentContext › should pass with matching certificates [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › persistentContext › validate input [pass] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should fail with matching certificates in legacy pfx format [pass] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should fail with no client certificates [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should fail with self-signed client certificates [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should handle TLS renegotiation with client certificates [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should handle rejected certificate in handshake with HTTP/2 [pass] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should have ignoreHTTPSErrors=false by default [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should keep supporting http [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should not hang on tls errors during TLS 1.2 handshake [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates and trailing slash [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format when passing as content [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates on context APIRequestContext instance [pass] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should pass with matching certificates when passing as content [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should return target connection errors when using http2 [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › should throw a http error if the pfx passphrase is incorect [pass] -bidi-chromium-library › library/client-certificates.spec.ts › browser › support http2 [fail] -bidi-chromium-library › library/client-certificates.spec.ts › browser › support http2 if the browser only supports http1.1 [unknown] -bidi-chromium-library › library/client-certificates.spec.ts › browser › validate input [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › pass with trusted client certificates [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › pass with trusted client certificates in pfx format [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › should fail with matching certificates in legacy pfx format [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › should fail with no client certificates provided [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › should keep supporting http [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › should throw a http error if the pfx passphrase is incorect [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › should throw with untrusted client certs [pass] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › should work in the browser with request interception [fail] -bidi-chromium-library › library/client-certificates.spec.ts › fetch › validate input [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › Creates a RelativeTimeFormat like normal [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › Executes formatRange like normal [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › Executes formatRangeToParts like normal [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › Executes resolvedOptions like normal [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › Executes supportedLocalesOf like normal [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed a timestamp argument that is not first of the month [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed no timestamp and system time is not first of the month [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed a timestamp argument that is first of the month [pass] -bidi-chromium-library › library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed no timestamp and system time is first of the month [pass] -bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › does not remove interval [pass] -bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › does not remove timeout [pass] -bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › ignores null argument [pass] -bidi-chromium-library › library/clock.spec.ts › cancelAnimationFrame › removes animation frame [pass] -bidi-chromium-library › library/clock.spec.ts › cancelIdleCallback › removes idle callback [pass] -bidi-chromium-library › library/clock.spec.ts › clearInterval › ignores null argument [pass] -bidi-chromium-library › library/clock.spec.ts › clearInterval › removes interval [pass] -bidi-chromium-library › library/clock.spec.ts › clearInterval › removes interval with undefined interval [pass] -bidi-chromium-library › library/clock.spec.ts › clearInterval › removes timeout [pass] -bidi-chromium-library › library/clock.spec.ts › clearTimeout › ignores null argument [pass] -bidi-chromium-library › library/clock.spec.ts › clearTimeout › removes interval [pass] -bidi-chromium-library › library/clock.spec.ts › clearTimeout › removes interval with undefined interval [pass] -bidi-chromium-library › library/clock.spec.ts › clearTimeout › removes timeout [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates Date objects representing clock time [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates real Date objects [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing a date as RFC 2822 string [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing a date as string [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing timestamp [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s, ms [pass] -bidi-chromium-library › library/clock.spec.ts › date › creates regular date when passing year, month [pass] -bidi-chromium-library › library/clock.spec.ts › date › listens to system clock changes [pass] -bidi-chromium-library › library/clock.spec.ts › date › listens to ticking clock [pass] -bidi-chromium-library › library/clock.spec.ts › date › mirrors UTC method [pass] -bidi-chromium-library › library/clock.spec.ts › date › mirrors native Date.prototype [pass] -bidi-chromium-library › library/clock.spec.ts › date › mirrors parse method [pass] -bidi-chromium-library › library/clock.spec.ts › date › mirrors toUTCString method [pass] -bidi-chromium-library › library/clock.spec.ts › date › provides date constructor [pass] -bidi-chromium-library › library/clock.spec.ts › date › returns clock.now() [pass] -bidi-chromium-library › library/clock.spec.ts › date › returns date as string representing clock time [pass] -bidi-chromium-library › library/clock.spec.ts › date › returns date as string when called as function [pass] -bidi-chromium-library › library/clock.spec.ts › date › returns date as string when calling with arguments [pass] -bidi-chromium-library › library/clock.spec.ts › date › returns date as string when calling with timestamp [pass] -bidi-chromium-library › library/clock.spec.ts › date › supports now method if present [pass] -bidi-chromium-library › library/clock.spec.ts › fastForward › handles multiple pending timers and types [pass] -bidi-chromium-library › library/clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] -bidi-chromium-library › library/clock.spec.ts › fastForward › pushes back execution time for skipped timers [pass] -bidi-chromium-library › library/clock.spec.ts › pauseAt › fire target timers [pass] -bidi-chromium-library › library/clock.spec.ts › pauseAt › pause at target time [pass] -bidi-chromium-library › library/clock.spec.ts › pauseAt › returns consumed clicks [pass] -bidi-chromium-library › library/clock.spec.ts › performance.now() › should listen to multiple ticks in performance.now [pass] -bidi-chromium-library › library/clock.spec.ts › performance.now() › should run along with clock.tick [pass] -bidi-chromium-library › library/clock.spec.ts › performance.now() › should run with ticks with timers set [pass] -bidi-chromium-library › library/clock.spec.ts › performance.now() › should start at 0 [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › returns numeric id or object with numeric id [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › returns unique id [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() even when performance unavailable [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() when available [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should call callback once [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should properly schedule callback for 3rd frame [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should run every 16ms [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should schedule for next frame if on current frame [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › should schedule two callbacks before the next frame at the same time [pass] -bidi-chromium-library › library/clock.spec.ts › requestAnimationFrame › throws if no arguments [pass] -bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › doesn't runs if there are any timers and no timeout option [pass] -bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › returns numeric id [pass] -bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › returns unique id [pass] -bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › runs after all timers [pass] -bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › runs no later than timeout option even if there are any timers [pass] -bidi-chromium-library › library/clock.spec.ts › requestIdleCallback › throws if no arguments [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › calls function with global object or null (strict mode) as this [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › creates updated Date while ticking [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › creates updated Date while ticking promises [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › does not fire canceled intervals [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › does not fire intervals canceled in a promise [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › does not silently catch errors [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › does not trigger without sufficient delay [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › fires nested setTimeout calls in user-created promises properly [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › fires nested setTimeout calls properly [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › fires promise timers in correct order [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › fires timer in intervals of "13" [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › fires timer in intervals of 13 [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › fires timers in correct order [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes 2 [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes in promises [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown 2 [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › mini integration test [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle chained user-created promises [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle local nested promises before calling timeouts [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle local promises before calling timeouts [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle multiple user-created promises [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle nested user-created promises [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle user-created promises [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle user-created promises before calling more timeouts [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › should settle user-created promises even if some throw [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › throws for negative minutes [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › throws on negative ticks [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers after sufficient delay [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers even when some throw [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers immediately without specified delay [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers in the order scheduled [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers multiple simultaneous timers [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers multiple simultaneous timers with zero callAt [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers simultaneous timers [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › triggers timeouts and intervals in the order scheduled [pass] -bidi-chromium-library › library/clock.spec.ts › runFor › waits after setTimeout was called [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › does not schedule recurring timeout when cleared [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › does not throw if |undefined| or |null| is passed as a callback [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › is not influenced by backward system clock changes [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › is not influenced by forward system clock changes [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › passes setTimeout parameters [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › returns numeric id or object with numeric id [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › returns unique id [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › schedules recurring timeout [pass] -bidi-chromium-library › library/clock.spec.ts › setInterval › throws if no arguments [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › calls correct timeout on recursive tick [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › does not depend on this [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › does not throw if |undefined| or |null| is passed as a callback [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › is not influenced by backward system clock changes [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › is not influenced by forward system clock changes [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › parses no-numeric string times [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › parses numeric string times [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › passes setTimeout parameters [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › returns numeric id or object with numeric id [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › returns unique id [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › sets timers on instance [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › starts id from a large number [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › throws if no arguments [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › use of eval when not in node › evals non-function callbacks [pass] -bidi-chromium-library › library/clock.spec.ts › setTimeout › use of eval when not in node › only evals on global scope [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › deletes global property on uninstall if it was inherited onto the global object [unknown] -bidi-chromium-library › library/clock.spec.ts › stubTimers › does not fake methods not provided [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › fake Date constructor should mirror Date's properties [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › fakes Date constructor [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › fakes provided methods [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › mirrors custom Date properties [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › replace Event.prototype.timeStamp [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global clearInterval [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global clearTimeout [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global performance.now [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global setInterval [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › replaces global setTimeout [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › resets faked methods [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › returns clock object [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › sets initial timestamp [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › should let performance.mark still be callable after install() (#136) [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › should not alter the global performance properties and methods [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › should replace the getEntries, getEntriesByX methods with noops that return [] [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › takes an object parameter [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › uninstalls Date constructor [pass] -bidi-chromium-library › library/clock.spec.ts › stubTimers › uninstalls global performance.now [pass] -bidi-chromium-library › library/clock.spec.ts › works with concurrent runFor calls [pass] -bidi-chromium-library › library/clock.spec.ts › works with slow setTimeout in busy embedder [pass] -bidi-chromium-library › library/clock.spec.ts › works with slow setTimeout in busy embedder when not paused [pass] -bidi-chromium-library › library/component-parser.spec.ts › should escape [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse all operators [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse bool [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse float values [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse identifiers [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse int values [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse regex [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse short attributes [pass] -bidi-chromium-library › library/component-parser.spec.ts › should parse unquoted string [pass] -bidi-chromium-library › library/component-parser.spec.ts › should throw on malformed selector [pass] -bidi-chromium-library › library/component-parser.spec.ts › should tolerate spacing [pass] -bidi-chromium-library › library/css-parser.spec.ts › should parse css [pass] -bidi-chromium-library › library/css-parser.spec.ts › should throw on malformed css [pass] -bidi-chromium-library › library/debug-controller.spec.ts › should highlight all [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should navigate all [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should pick element [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should record [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should record custom data-testid [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should report pages [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should reset for reuse [fail] -bidi-chromium-library › library/debug-controller.spec.ts › should reset routes before reuse [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › context.addCookies() should work [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › context.clearCookies() should work [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › context.cookies() should work @smoke [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support acceptDownloads option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support bypassCSP option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support deviceScaleFactor option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support httpCredentials option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support javascriptEnabled option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support offline option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support userAgent option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should support viewport option [fail] -bidi-chromium-library › library/defaultbrowsercontext-1.spec.ts › should(not) block third party cookies [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › coverage should work [unknown] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should accept userDataDir [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should connect to a browser with the default page [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should create userDataDir if it does not exist [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should fire close event for a persistent context [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should handle exception [timeout] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should handle timeout [pass] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should have default URL when launching browser [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should have passed URL when launching with ignoreDefaultArgs: true [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should respect selectors [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should restore state from userDataDir [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support colorScheme option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support extraHTTPHeaders option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support forcedColors option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support geolocation and permissions options [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support har option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support hasTouch option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support ignoreHTTPSErrors option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support locale option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support reducedMotion option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should support timezoneId option [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should throw if page argument is passed [pass] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › should work in persistent context [fail] -bidi-chromium-library › library/defaultbrowsercontext-2.spec.ts › user agent is up to date [fail] -bidi-chromium-library › library/download.spec.ts › download event › should be able to cancel pending downloads [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should close the context without awaiting the download [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should close the context without awaiting the failed download [unknown] -bidi-chromium-library › library/download.spec.ts › download event › should create subdirectories when saving to non-existent user-specified path [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should delete downloads on browser gone [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should delete downloads on context destruction [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should delete file [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should download large binary.zip [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should emit download event from nested iframes [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should error when saving after deletion [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should error when saving with downloads disabled [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should expose stream [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should not fail explicitly to cancel a download even if that is already finished [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report alt-click downloads [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Blobs [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Files [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report download when navigation turns into download @smoke [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report downloads for download attribute [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report downloads with acceptDownloads: false [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report downloads with acceptDownloads: true [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report downloads with interception [fail] -bidi-chromium-library › library/download.spec.ts › download event › should report new window downloads [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report non-navigation downloads [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should report proper download url when download is from download attribute [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should save to overwritten filepath [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should save to two different paths with multiple saveAs calls [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should save to user-specified path without updating original path [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should throw if browser dies [timeout] -bidi-chromium-library › library/download.spec.ts › download event › should work with Cross-Origin-Opener-Policy [timeout] -bidi-chromium-library › library/download.spec.ts › should be able to download a PDF file [timeout] -bidi-chromium-library › library/download.spec.ts › should be able to download a inline PDF file via navigation [timeout] -bidi-chromium-library › library/download.spec.ts › should be able to download a inline PDF file via response interception [fail] -bidi-chromium-library › library/download.spec.ts › should convert navigation to a resource with unsupported mime type into download [timeout] -bidi-chromium-library › library/download.spec.ts › should download even if there is no "attachment" value [timeout] -bidi-chromium-library › library/download.spec.ts › should download links with data url [timeout] -bidi-chromium-library › library/download.spec.ts › should download successfully when routing [timeout] -bidi-chromium-library › library/download.spec.ts › should save to user-specified path [timeout] -bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should accept downloads in persistent context [fail] -bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should delete downloads when context closes [timeout] -bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should delete downloads when persistent context closes [fail] -bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should keep downloadsPath folder [timeout] -bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder [timeout] -bidi-chromium-library › library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder with a relative path [timeout] -bidi-chromium-library › library/emulation-focus.spec.ts › should change document.activeElement [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should change focused iframe [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should focus popups by default [fail] -bidi-chromium-library › library/emulation-focus.spec.ts › should focus with more than one page/context [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should not affect mouse event target page [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should not affect screenshots [fail] -bidi-chromium-library › library/emulation-focus.spec.ts › should not fire blur events when interacting with more than one page/context [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should provide target for keyboard events [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should think that all pages are focused @smoke [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should think that it is focused by default [pass] -bidi-chromium-library › library/emulation-focus.spec.ts › should trigger hover state concurrently [pass] -bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › Listener order [pass] -bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › listener type check [pass] -bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › set max listeners test [pass] -bidi-chromium-library › library/events/add-listeners.spec.ts › EventEmitter tests › should work [pass] -bidi-chromium-library › library/events/check-listener-leaks.spec.ts › _maxListeners still has precedence over defaultMaxListeners [pass] -bidi-chromium-library › library/events/check-listener-leaks.spec.ts › defaultMaxListeners [pass] -bidi-chromium-library › library/events/check-listener-leaks.spec.ts › process-wide [pass] -bidi-chromium-library › library/events/events-list.spec.ts › EventEmitter › should maintain event names correctly [pass] -bidi-chromium-library › library/events/listener-count.spec.ts › Listener count test [pass] -bidi-chromium-library › library/events/listeners-side-effects.spec.ts › listeners empty check [pass] -bidi-chromium-library › library/events/listeners.spec.ts › Array copy modification does not modify orig [pass] -bidi-chromium-library › library/events/listeners.spec.ts › EventEmitter listeners with one listener [pass] -bidi-chromium-library › library/events/listeners.spec.ts › EventEmitter with no members [pass] -bidi-chromium-library › library/events/listeners.spec.ts › Modify array copy after multiple adds [pass] -bidi-chromium-library › library/events/listeners.spec.ts › listeners and once [pass] -bidi-chromium-library › library/events/listeners.spec.ts › listeners on prototype [pass] -bidi-chromium-library › library/events/listeners.spec.ts › listeners with conflicting types [pass] -bidi-chromium-library › library/events/listeners.spec.ts › raw listeners [pass] -bidi-chromium-library › library/events/listeners.spec.ts › raw listeners order [pass] -bidi-chromium-library › library/events/max-listeners.spec.ts › emit maxListeners on e [pass] -bidi-chromium-library › library/events/method-names.spec.ts › EventEmitter prototype test [pass] -bidi-chromium-library › library/events/modify-in-emit.spec.ts › add and remove listeners [pass] -bidi-chromium-library › library/events/modify-in-emit.spec.ts › removing callbacks in emit [pass] -bidi-chromium-library › library/events/num-args.spec.ts › should work [pass] -bidi-chromium-library › library/events/once.spec.ts › once() has different code paths based on the number of arguments being emitted [pass] -bidi-chromium-library › library/events/once.spec.ts › should work [pass] -bidi-chromium-library › library/events/prepend.spec.ts › EventEmitter functionality [pass] -bidi-chromium-library › library/events/prepend.spec.ts › Verify that the listener must be a function [pass] -bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › should not throw with ignoreErrors [pass] -bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › should wait [pass] -bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › should wait all [pass] -bidi-chromium-library › library/events/remove-all-listeners-wait.spec.ts › wait should throw [pass] -bidi-chromium-library › library/events/remove-all-listeners.spec.ts › listener count after removeAllListeners [pass] -bidi-chromium-library › library/events/remove-all-listeners.spec.ts › listeners [pass] -bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners on undefined _events [pass] -bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners removes all listeners [pass] -bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners returns EventEmitter [pass] -bidi-chromium-library › library/events/remove-all-listeners.spec.ts › removeAllListeners with no event type [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Eighth test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Fifth test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › First test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Fourth test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Ninth test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Second test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Seventh test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Sixth test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Tenth test [pass] -bidi-chromium-library › library/events/remove-listeners.spec.ts › Third test [pass] -bidi-chromium-library › library/events/set-max-listeners-side-effects.spec.ts › set max listeners test [pass] -bidi-chromium-library › library/events/special-event-names.spec.ts › should support special event names [pass] -bidi-chromium-library › library/events/subclass.spec.ts › MyEE2 instance [pass] -bidi-chromium-library › library/events/subclass.spec.ts › myee instance [pass] -bidi-chromium-library › library/events/symbols.spec.ts › should support symbols [pass] -bidi-chromium-library › library/favicon.spec.ts › should load svg favicon with prefer-color-scheme [unknown] -bidi-chromium-library › library/fetch-proxy.spec.ts › context request should pick up proxy credentials [pass] -bidi-chromium-library › library/fetch-proxy.spec.ts › global request should pick up proxy credentials [pass] -bidi-chromium-library › library/fetch-proxy.spec.ts › should support proxy.bypass [pass] -bidi-chromium-library › library/fetch-proxy.spec.ts › should use socks proxy [pass] -bidi-chromium-library › library/fetch-proxy.spec.ts › should work with context level proxy [pass] -bidi-chromium-library › library/firefox/launcher.spec.ts › should pass firefox user preferences [fail] -bidi-chromium-library › library/firefox/launcher.spec.ts › should pass firefox user preferences in persistent [fail] -bidi-chromium-library › library/geolocation.spec.ts › should isolate contexts [timeout] -bidi-chromium-library › library/geolocation.spec.ts › should not modify passed default options object [pass] -bidi-chromium-library › library/geolocation.spec.ts › should throw when invalid longitude [fail] -bidi-chromium-library › library/geolocation.spec.ts › should throw with missing latitude [pass] -bidi-chromium-library › library/geolocation.spec.ts › should throw with missing longitude in default options [pass] -bidi-chromium-library › library/geolocation.spec.ts › should use context options [timeout] -bidi-chromium-library › library/geolocation.spec.ts › should use context options for popup [timeout] -bidi-chromium-library › library/geolocation.spec.ts › should work @smoke [timeout] -bidi-chromium-library › library/geolocation.spec.ts › watchPosition should be notified [timeout] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should do case-insensitive match of cookie domain [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should do case-insensitive match of request domain [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should export cookies to storage state [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should filter outgoing cookies by domain [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should filter outgoing cookies by path [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header even if it expired [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should preserve local storage on import/export of storage state [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should remove cookie with expires far in the past [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should remove cookie with negative max-age [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should remove expired cookies [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send cookies from storage state [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send not expired cookies [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send secure cookie over http for localhost [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should send secure cookie over https [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header even if it contains equal signs [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › should work with empty storage state [pass] -bidi-chromium-library › library/global-fetch-cookie.spec.ts › storage state should round-trip through file [pass] -bidi-chromium-library › library/global-fetch.spec.ts › delete should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › fetch should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › get should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › head should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › patch should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › post should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › put should work @smoke [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should abort redirected requests when context is disposed [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should abort requests when context is disposed [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should accept already serialized data as Buffer when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should be able to construct with context options [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should dispose global request [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should have nice toString [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify array body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify bool (false) body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify bool body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify literal string undefined body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify null body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify number (falsey) body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify number body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify object body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify string (falsey) body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should json stringify string body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should keep headers capitalization [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify array body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify bool (false) body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify bool body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify literal string undefined body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify null body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify number (falsey) body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify number body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify object body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify string (falsey) body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not double stringify string body when content-type is application/json [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not fail on empty body with encoding [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should not follow redirects when maxRedirects is set to 0 [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should propagate extra http headers with redirects [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should propagate ignoreHTTPSErrors on redirects [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should remove content-length from redirected post requests [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should resolve url relative to global baseURL option [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should retry ECONNRESET [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should return body for failing requests [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should return empty body [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching hostname [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching port [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should return error with correct credentials and mismatching scheme [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should return error with wrong credentials [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should serialize post data on the client [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should set playwright as user-agent [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should support HTTPCredentials.send [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should support WWW-Authenticate: Basic [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should support global httpCredentials option [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should support global ignoreHTTPSErrors option [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should support global timeout option [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should support global userAgent option [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should throw after dispose [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should throw an error when maxRedirects is exceeded [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should throw an error when maxRedirects is less than 0 [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should work with correct credentials and matching origin [pass] -bidi-chromium-library › library/global-fetch.spec.ts › should work with correct credentials and matching origin case insensitive [pass] -bidi-chromium-library › library/har.spec.ts › should attach content [fail] -bidi-chromium-library › library/har.spec.ts › should calculate time [pass] -bidi-chromium-library › library/har.spec.ts › should contain http2 for http2 requests [fail] -bidi-chromium-library › library/har.spec.ts › should filter by glob [pass] -bidi-chromium-library › library/har.spec.ts › should filter by regexp [pass] -bidi-chromium-library › library/har.spec.ts › should filter favicon and favicon redirects [unknown] -bidi-chromium-library › library/har.spec.ts › should have -1 _transferSize when its a failed request [pass] -bidi-chromium-library › library/har.spec.ts › should have browser [fail] -bidi-chromium-library › library/har.spec.ts › should have connection details [fail] -bidi-chromium-library › library/har.spec.ts › should have connection details for failed requests [fail] -bidi-chromium-library › library/har.spec.ts › should have connection details for redirects [fail] -bidi-chromium-library › library/har.spec.ts › should have different hars for concurrent contexts [pass] -bidi-chromium-library › library/har.spec.ts › should have pages [pass] -bidi-chromium-library › library/har.spec.ts › should have pages in persistent context [fail] -bidi-chromium-library › library/har.spec.ts › should have popup requests [pass] -bidi-chromium-library › library/har.spec.ts › should have security details [fail] -bidi-chromium-library › library/har.spec.ts › should have version and creator [pass] -bidi-chromium-library › library/har.spec.ts › should include API request [pass] -bidi-chromium-library › library/har.spec.ts › should include binary postData [fail] -bidi-chromium-library › library/har.spec.ts › should include content @smoke [fail] -bidi-chromium-library › library/har.spec.ts › should include cookies [pass] -bidi-chromium-library › library/har.spec.ts › should include form params [fail] -bidi-chromium-library › library/har.spec.ts › should include postData [fail] -bidi-chromium-library › library/har.spec.ts › should include query params [pass] -bidi-chromium-library › library/har.spec.ts › should include redirectURL [pass] -bidi-chromium-library › library/har.spec.ts › should include request [pass] -bidi-chromium-library › library/har.spec.ts › should include response [pass] -bidi-chromium-library › library/har.spec.ts › should include secure set-cookies [fail] -bidi-chromium-library › library/har.spec.ts › should include set-cookies [fail] -bidi-chromium-library › library/har.spec.ts › should include set-cookies with comma [fail] -bidi-chromium-library › library/har.spec.ts › should include sizes [fail] -bidi-chromium-library › library/har.spec.ts › should not contain internal pages [pass] -bidi-chromium-library › library/har.spec.ts › should not hang on resources served from cache [pass] -bidi-chromium-library › library/har.spec.ts › should not hang on slow chunked response [fail] -bidi-chromium-library › library/har.spec.ts › should omit content [pass] -bidi-chromium-library › library/har.spec.ts › should omit content legacy [pass] -bidi-chromium-library › library/har.spec.ts › should record failed request headers [pass] -bidi-chromium-library › library/har.spec.ts › should record failed request overrides [fail] -bidi-chromium-library › library/har.spec.ts › should record request overrides [fail] -bidi-chromium-library › library/har.spec.ts › should report the correct _transferSize with PNG files [fail] -bidi-chromium-library › library/har.spec.ts › should report the correct request body size [pass] -bidi-chromium-library › library/har.spec.ts › should report the correct request body size when the bodySize is 0 [pass] -bidi-chromium-library › library/har.spec.ts › should report the correct response body size when the bodySize is 0 [pass] -bidi-chromium-library › library/har.spec.ts › should return receive time [fail] -bidi-chromium-library › library/har.spec.ts › should return security details directly from response [fail] -bidi-chromium-library › library/har.spec.ts › should return server address directly from response [fail] -bidi-chromium-library › library/har.spec.ts › should skip invalid Expires [pass] -bidi-chromium-library › library/har.spec.ts › should throw without path [pass] -bidi-chromium-library › library/har.spec.ts › should use attach mode for zip extension [fail] -bidi-chromium-library › library/har.spec.ts › should work with gzip compression [fail] -bidi-chromium-library › library/headful.spec.ts › Page.bringToFront should work [pass] -bidi-chromium-library › library/headful.spec.ts › headless and headful should use same default fonts [fail] -bidi-chromium-library › library/headful.spec.ts › should click background tab [timeout] -bidi-chromium-library › library/headful.spec.ts › should click bottom row w/ infobar in OOPIF [fail] -bidi-chromium-library › library/headful.spec.ts › should click in OOPIF [fail] -bidi-chromium-library › library/headful.spec.ts › should click when viewport size is larger than screen [pass] -bidi-chromium-library › library/headful.spec.ts › should close browser after context menu was triggered [pass] -bidi-chromium-library › library/headful.spec.ts › should close browser with beforeunload page [fail] -bidi-chromium-library › library/headful.spec.ts › should close browsercontext with pending beforeunload dialog [timeout] -bidi-chromium-library › library/headful.spec.ts › should dispatch click events to oversized viewports [pass] -bidi-chromium-library › library/headful.spec.ts › should have default url when launching browser @smoke [fail] -bidi-chromium-library › library/headful.spec.ts › should not block third party SameSite=None cookies [fail] -bidi-chromium-library › library/headful.spec.ts › should not crash when creating second context [pass] -bidi-chromium-library › library/headful.spec.ts › should not override viewport size when passed null [fail] -bidi-chromium-library › library/headful.spec.ts › should(not) block third party cookies [pass] -bidi-chromium-library › library/hit-target.spec.ts › should block all events when hit target is wrong [pass] -bidi-chromium-library › library/hit-target.spec.ts › should block all events when hit target is wrong and element detaches [pass] -bidi-chromium-library › library/hit-target.spec.ts › should block click when mousedown fails [pass] -bidi-chromium-library › library/hit-target.spec.ts › should click an element inside closed shadow root [pass] -bidi-chromium-library › library/hit-target.spec.ts › should click in custom element [pass] -bidi-chromium-library › library/hit-target.spec.ts › should click in iframe with padding [pass] -bidi-chromium-library › library/hit-target.spec.ts › should click in iframe with padding 2 [pass] -bidi-chromium-library › library/hit-target.spec.ts › should click into frame inside closed shadow root [fail] -bidi-chromium-library › library/hit-target.spec.ts › should click the button again after document.write [pass] -bidi-chromium-library › library/hit-target.spec.ts › should click when element detaches in mousedown [pass] -bidi-chromium-library › library/hit-target.spec.ts › should detect overlaid element in a transformed iframe [fail] -bidi-chromium-library › library/hit-target.spec.ts › should detect overlay from another shadow root [pass] -bidi-chromium-library › library/hit-target.spec.ts › should not block programmatic events [pass] -bidi-chromium-library › library/hit-target.spec.ts › should not click an element overlaying iframe with the target [pass] -bidi-chromium-library › library/hit-target.spec.ts › should not click iframe overlaying the target [pass] -bidi-chromium-library › library/hit-target.spec.ts › should work with block inside inline [pass] -bidi-chromium-library › library/hit-target.spec.ts › should work with block inside inline in shadow dom [pass] -bidi-chromium-library › library/hit-target.spec.ts › should work with block-block-block inside inline-inline [pass] -bidi-chromium-library › library/hit-target.spec.ts › should work with drag and drop that moves the element under cursor [pass] -bidi-chromium-library › library/hit-target.spec.ts › should work with mui select [pass] -bidi-chromium-library › library/ignorehttpserrors.spec.ts › serviceWorker should intercept document request [fail] -bidi-chromium-library › library/ignorehttpserrors.spec.ts › should fail with WebSocket if not ignored [pass] -bidi-chromium-library › library/ignorehttpserrors.spec.ts › should isolate contexts [fail] -bidi-chromium-library › library/ignorehttpserrors.spec.ts › should work @smoke [fail] -bidi-chromium-library › library/ignorehttpserrors.spec.ts › should work with WebSocket [fail] -bidi-chromium-library › library/ignorehttpserrors.spec.ts › should work with mixed content [fail] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should assert navigation [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should await popup [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check a radio button [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should check with keyboard [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click after same-document navigation [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should click button with nested div [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should emit single keyup on ArrowDown [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [contentEditable] [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill japanese text [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea with new lines at the end [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore AltGraph [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore programmatic events [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should make a positioned click on a canvas [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should middle click [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should not target selector preview by text regexp [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should not throw csp directive violation errors [pass] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should press [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record ArrowDown [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after performAction [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after recordAction [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should record slider [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should select [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should select with size attribute [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should uncheck [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should update selected element after pressing Tab [timeout] -bidi-chromium-library › library/inspector/cli-codegen-1.spec.ts › cli codegen › should work with TrustedTypes [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › click should emit events in order [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should --save-trace [fail] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should check input with chaining id [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should clear files [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain close page [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain open page [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain second page [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should download files [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should fill tricky characters [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle dialogs [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle history.postData [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should not clash pages [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should not lead to an error if html gets clicked [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should record navigations after identical pushState [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should record open in a new tab with url [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should reset hover model on action when element detaches [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should save assets via SIGINT [fail] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should update active model on action [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should update hover model on action [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload a single file [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload multiple files [timeout] -bidi-chromium-library › library/inspector/cli-codegen-2.spec.ts › should --test-id-attribute [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled input [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled select [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert visibility [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.first [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.nth [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume contextmenu events, despite a custom context menu [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume pointer events [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with id attribute [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with name attribute [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with special characters in name attribute [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with testId [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with title attribute [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByAltText [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel without regex [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByPlaceholder [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByTestId [timeout] -bidi-chromium-library › library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate role locators undef frame locators [timeout] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in mstest if no options were passed [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in nunit if no options were passed [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in mstest [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in nunit [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in mstest if options were passed [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in nunit if options were passed [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print load/save storageState [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options for custom settings [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device [unknown] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device and additional options [unknown] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-csharp.spec.ts › should work with --save-har [fail] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print a valid basic program in junit [fail] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print load/save storage_state [fail] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options for custom settings [fail] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device [unknown] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device and additional options [unknown] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should print the correct imports in junit [fail] -bidi-chromium-library › library/inspector/cli-codegen-java.spec.ts › should work with --save-har [fail] -bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print load/save storageState [fail] -bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options for custom settings [fail] -bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device [unknown] -bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device and additional options [unknown] -bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-javascript.spec.ts › should save the codegen output to a file if specified [fail] -bidi-chromium-library › library/inspector/cli-codegen-pytest.spec.ts › should print the correct context options when using a device and lang [unknown] -bidi-chromium-library › library/inspector/cli-codegen-pytest.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-pytest.spec.ts › should save the codegen output to a file if specified [fail] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print load/save storage_state [fail] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options for custom settings [fail] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device [unknown] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device and additional options [unknown] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should save the codegen output to a file if specified [fail] -bidi-chromium-library › library/inspector/cli-codegen-python-async.spec.ts › should work with --save-har [fail] -bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print load/save storage_state [fail] -bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options for custom settings [fail] -bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device [unknown] -bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device and additional options [unknown] -bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-python.spec.ts › should save the codegen output to a file if specified [fail] -bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print load storageState [fail] -bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options for custom settings [fail] -bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device [unknown] -bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device and additional options [unknown] -bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should print the correct imports and context options [fail] -bidi-chromium-library › library/inspector/cli-codegen-test.spec.ts › should work with --save-har [fail] -bidi-chromium-library › library/inspector/console-api.spec.ts › expected properties on playwright object [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support locator.and() [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support locator.or() [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.$, playwright.$$ [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.getBy* [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator({ has }) [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator({ hasNot }) [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator.value [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.locator.values [pass] -bidi-chromium-library › library/inspector/console-api.spec.ts › should support playwright.selector [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should hide internal calls [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight locators with custom testId [timeout] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight on explore [timeout] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight on explore (csharp) [timeout] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight pointer, only in main frame [timeout] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should highlight waitForEvent [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should not prevent key events [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause after a navigation [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause and resume the script [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause and resume the script with keyboard shortcut [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause on context close [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause on next pause [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should pause on page close [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log with error [fail] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log with error in waitForEvent [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should populate log with waitForEvent [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should resume from console [fail] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should show expect.toHaveText [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should show source [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should skip input when resuming [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should step [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › pause › should step with keyboard shortcut [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › should not reset timeouts [pass] -bidi-chromium-library › library/inspector/pause.spec.ts › should resume when closing inspector [pass] -bidi-chromium-library › library/launcher.spec.ts › should have a devices object [pass] -bidi-chromium-library › library/launcher.spec.ts › should have an errors object [pass] -bidi-chromium-library › library/launcher.spec.ts › should kill browser process on timeout after close [pass] -bidi-chromium-library › library/launcher.spec.ts › should throw a friendly error if its headed and there is no xserver on linux running [fail] -bidi-chromium-library › library/locator-generator.spec.ts › asLocator internal:and [pass] -bidi-chromium-library › library/locator-generator.spec.ts › asLocator internal:chain [pass] -bidi-chromium-library › library/locator-generator.spec.ts › asLocator internal:or [pass] -bidi-chromium-library › library/locator-generator.spec.ts › asLocator xpath [pass] -bidi-chromium-library › library/locator-generator.spec.ts › generate multiple locators [pass] -bidi-chromium-library › library/locator-generator.spec.ts › parse locators strictly [pass] -bidi-chromium-library › library/locator-generator.spec.ts › parseLocator css [pass] -bidi-chromium-library › library/locator-generator.spec.ts › parseLocator quotes [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer frameLocator [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer getByRole [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer has [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer has + hasText [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer hasNot [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer hasNotText [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer hasText [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer ignore-case locators [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer internal:has-text locators [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer locators [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer locators with regex [pass] -bidi-chromium-library › library/locator-generator.spec.ts › reverse engineer ordered locators [pass] -bidi-chromium-library › library/logger.spec.ts › should log @smoke [pass] -bidi-chromium-library › library/logger.spec.ts › should log context-level [pass] -bidi-chromium-library › library/modernizr.spec.ts › Mobile Safari [unknown] -bidi-chromium-library › library/modernizr.spec.ts › Safari Desktop [unknown] -bidi-chromium-library › library/page-clock.frozen.spec.ts › clock should be frozen [unknown] -bidi-chromium-library › library/page-clock.frozen.spec.ts › clock should be realtime [unknown] -bidi-chromium-library › library/page-clock.spec.ts › Date.now › check Date.now is an integer [pass] -bidi-chromium-library › library/page-clock.spec.ts › Date.now › check Date.now is an integer (2) [pass] -bidi-chromium-library › library/page-clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] -bidi-chromium-library › library/page-clock.spec.ts › fastForward › pushes back execution time for skipped timers [fail] -bidi-chromium-library › library/page-clock.spec.ts › fastForward › supports string time arguments [fail] -bidi-chromium-library › library/page-clock.spec.ts › popup › should not run time before popup on pause [fail] -bidi-chromium-library › library/page-clock.spec.ts › popup › should run time before popup [pass] -bidi-chromium-library › library/page-clock.spec.ts › popup › should tick after popup [fail] -bidi-chromium-library › library/page-clock.spec.ts › popup › should tick before popup [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › creates updated Date while ticking [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › does not trigger without sufficient delay [pass] -bidi-chromium-library › library/page-clock.spec.ts › runFor › passes 1 minute [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › passes 2 hours, 34 minutes and 10 seconds [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › passes 8 seconds [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › returns the current now value [pass] -bidi-chromium-library › library/page-clock.spec.ts › runFor › throws for invalid format [pass] -bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers after sufficient delay [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers event when some throw [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers immediately without specified delay [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers multiple simultaneous timers [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › triggers simultaneous timers [fail] -bidi-chromium-library › library/page-clock.spec.ts › runFor › waits after setTimeout was called [fail] -bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › allows installing fake timers after settings time [fail] -bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › allows setting time multiple times [pass] -bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › does not fake methods [pass] -bidi-chromium-library › library/page-clock.spec.ts › setFixedTime › fixed time is not affected by clock manipulation [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › fakes Date constructor [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global clearInterval [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global clearTimeout [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global performance.now [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global performance.timeOrigin [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global setInterval [fail] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › replaces global setTimeout [fail] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › sets initial timestamp [pass] -bidi-chromium-library › library/page-clock.spec.ts › stubTimers › should throw for invalid date [pass] -bidi-chromium-library › library/page-clock.spec.ts › while on pause › fastForward should not run nested immediate [fail] -bidi-chromium-library › library/page-clock.spec.ts › while on pause › runFor should not run nested immediate [fail] -bidi-chromium-library › library/page-clock.spec.ts › while on pause › runFor should not run nested immediate from microtask [fail] -bidi-chromium-library › library/page-clock.spec.ts › while running › should fastForward [pass] -bidi-chromium-library › library/page-clock.spec.ts › while running › should fastForwardTo [pass] -bidi-chromium-library › library/page-clock.spec.ts › while running › should pause [pass] -bidi-chromium-library › library/page-clock.spec.ts › while running › should pause and fastForward [pass] -bidi-chromium-library › library/page-clock.spec.ts › while running › should progress time [pass] -bidi-chromium-library › library/page-clock.spec.ts › while running › should runFor [pass] -bidi-chromium-library › library/page-clock.spec.ts › while running › should set system time on pause [pass] -bidi-chromium-library › library/page-event-crash.spec.ts › should be able to close context when page crashes [timeout] -bidi-chromium-library › library/page-event-crash.spec.ts › should cancel navigation when page crashes [timeout] -bidi-chromium-library › library/page-event-crash.spec.ts › should cancel waitForEvent when page crashes [timeout] -bidi-chromium-library › library/page-event-crash.spec.ts › should emit crash event when page crashes [timeout] -bidi-chromium-library › library/page-event-crash.spec.ts › should throw on any action after page crashes [timeout] -bidi-chromium-library › library/pdf.spec.ts › should be able to generate outline [unknown] -bidi-chromium-library › library/pdf.spec.ts › should be able to save file [unknown] -bidi-chromium-library › library/permissions.spec.ts › permissions › should accumulate when adding [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should be prompt by default [pass] -bidi-chromium-library › library/permissions.spec.ts › permissions › should clear permissions [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should deny permission when not listed [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should fail when bad permission is given [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should grant geolocation permission when origin is listed [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should grant notifications permission when listed [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should grant permission when creating context [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should grant permission when listed for all domains [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should isolate permissions between browser contexts [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should prompt for geolocation permission when origin is not listed [pass] -bidi-chromium-library › library/permissions.spec.ts › permissions › should reset permissions [fail] -bidi-chromium-library › library/permissions.spec.ts › permissions › should trigger permission onchange [fail] -bidi-chromium-library › library/permissions.spec.ts › should support clipboard read [fail] -bidi-chromium-library › library/permissions.spec.ts › storage access [unknown] -bidi-chromium-library › library/popup.spec.ts › BrowserContext.addInitScript should apply to a cross-process popup [fail] -bidi-chromium-library › library/popup.spec.ts › BrowserContext.addInitScript should apply to an in-process popup [fail] -bidi-chromium-library › library/popup.spec.ts › should expose function from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should inherit extra headers from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should inherit http credentials from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should inherit offline from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should inherit touch support from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should inherit user agent from browser context @smoke [fail] -bidi-chromium-library › library/popup.spec.ts › should inherit viewport size from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should not dispatch binding on a closed page [fail] -bidi-chromium-library › library/popup.spec.ts › should not throttle rAF in the opener page [pass] -bidi-chromium-library › library/popup.spec.ts › should not throw when click closes popup [pass] -bidi-chromium-library › library/popup.spec.ts › should respect routes from browser context [fail] -bidi-chromium-library › library/popup.spec.ts › should respect routes from browser context when using window.open [fail] -bidi-chromium-library › library/popup.spec.ts › should use viewport size from window features [timeout] -bidi-chromium-library › library/proxy-pattern.spec.ts › socks proxy patter matcher [pass] -bidi-chromium-library › library/proxy.spec.ts › does launch without a port [pass] -bidi-chromium-library › library/proxy.spec.ts › should authenticate [fail] -bidi-chromium-library › library/proxy.spec.ts › should exclude patterns [pass] -bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › by default › link-local [pass] -bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › by default › localhost [pass] -bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › by default › loopback address [pass] -bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [pass] -bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [pass] -bidi-chromium-library › library/proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [pass] -bidi-chromium-library › library/proxy.spec.ts › should throw for bad server value [pass] -bidi-chromium-library › library/proxy.spec.ts › should use SOCKS proxy for websocket requests [pass] -bidi-chromium-library › library/proxy.spec.ts › should use proxy @smoke [pass] -bidi-chromium-library › library/proxy.spec.ts › should use proxy for second page [pass] -bidi-chromium-library › library/proxy.spec.ts › should use proxy with emulated user agent [unknown] -bidi-chromium-library › library/proxy.spec.ts › should use socks proxy [pass] -bidi-chromium-library › library/proxy.spec.ts › should use socks proxy in second page [pass] -bidi-chromium-library › library/proxy.spec.ts › should work with IP:PORT notion [pass] -bidi-chromium-library › library/proxy.spec.ts › should work with authenticate followed by redirect [fail] -bidi-chromium-library › library/resource-timing.spec.ts › should work @smoke [pass] -bidi-chromium-library › library/resource-timing.spec.ts › should work for SSL [fail] -bidi-chromium-library › library/resource-timing.spec.ts › should work for redirect [fail] -bidi-chromium-library › library/resource-timing.spec.ts › should work for subresource [fail] -bidi-chromium-library › library/resource-timing.spec.ts › should work when serving from memory cache [fail] -bidi-chromium-library › library/role-utils.spec.ts › accessible name nested treeitem [pass] -bidi-chromium-library › library/role-utils.spec.ts › accessible name with slots [pass] -bidi-chromium-library › library/role-utils.spec.ts › axe-core accessible-text [pass] -bidi-chromium-library › library/role-utils.spec.ts › axe-core implicit-role [pass] -bidi-chromium-library › library/role-utils.spec.ts › control embedded in a label [pass] -bidi-chromium-library › library/role-utils.spec.ts › control embedded in a target element [pass] -bidi-chromium-library › library/role-utils.spec.ts › display:contents should be visible when contents are visible [pass] -bidi-chromium-library › library/role-utils.spec.ts › label/labelled-by aria-hidden with descendants [pass] -bidi-chromium-library › library/role-utils.spec.ts › native controls [pass] -bidi-chromium-library › library/role-utils.spec.ts › native controls labelled-by [pass] -bidi-chromium-library › library/role-utils.spec.ts › own aria-label concatenated with aria-labelledby [pass] -bidi-chromium-library › library/role-utils.spec.ts › should ignore stylesheet from hidden aria-labelledby subtree [pass] -bidi-chromium-library › library/role-utils.spec.ts › should not include hidden pseudo into accessible name [pass] -bidi-chromium-library › library/role-utils.spec.ts › should work with form and tricky input names [pass] -bidi-chromium-library › library/role-utils.spec.ts › svg role=presentation [pass] -bidi-chromium-library › library/role-utils.spec.ts › svg title [pass] -bidi-chromium-library › library/role-utils.spec.ts › wpt accname #0 [pass] -bidi-chromium-library › library/role-utils.spec.ts › wpt accname #1 [pass] -bidi-chromium-library › library/role-utils.spec.ts › wpt accname #2 [pass] -bidi-chromium-library › library/role-utils.spec.ts › wpt accname #3 [pass] -bidi-chromium-library › library/role-utils.spec.ts › wpt accname non-manual [pass] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › element screenshot should work with a mobile viewport [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › element screenshot should work with device scale factor [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › element screenshots should handle vh units [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › page screenshot should capture css transform with device pixels [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor and scale:css [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore default viewport after fullPage screenshot [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore viewport after element screenshot and exception [pass] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and exception [pass] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and timeout [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should take element screenshot when default viewport is null and restore back [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should take fullPage screenshots when default viewport is null [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should take screenshots when default viewport is null [fail] -bidi-chromium-library › library/screenshot.spec.ts › element screenshot › should work if the main resource hangs [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should handle vh units [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should run in parallel in multiple pages [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should throw if screenshot size is too large with device scale factor [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and clip [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and fullPage [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor and clip [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor and scale:css [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with device scale factor, clip and scale:css [fail] -bidi-chromium-library › library/screenshot.spec.ts › page screenshot › should work with large size [fail] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should chain text after parent [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should escape text with quote [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should escape text with slash [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should find text in shadow dom [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate label selector [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate relative selector [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate text and normalize whitespace [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate text for [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should generate title selector [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should match in shadow dom [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not escape text with >> [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not improve guid text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use generated id [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use input[value] [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should not use text for select [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer button over inner span [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer data-testid [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should separate selectors by >> [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim long text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should trim text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve role name [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use nested ordinals [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use parent text [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use readable id [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work with tricky attributes [pass] -bidi-chromium-library › library/selector-generator.spec.ts › selector generator › should work without CSS.escape [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should handle errors [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should not rely on engines working from the root [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work in main and isolated world [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work when registered on global [pass] -bidi-chromium-library › library/selectors-register.spec.ts › should work with path [pass] -bidi-chromium-library › library/shared-worker.spec.ts › should survive shared worker restart [timeout] -bidi-chromium-library › library/signals.spec.ts › should close the browser when the node process closes [timeout] -bidi-chromium-library › library/signals.spec.ts › should remove temp dir on process.exit [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] -bidi-chromium-library › library/signals.spec.ts › signals › should report browser close signal 2 [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo check [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo click [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo fill [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo focus [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo goto [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo hover [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo press [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo type [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo check [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo click [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo fill [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo focus [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo goto [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo hover [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo press [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo reload [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [timeout] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo type [pass] -bidi-chromium-library › library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture frame [fail] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture iframe [fail] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [fail] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture resources [fail] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should capture snapshot target [timeout] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect multiple [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect on attribute change [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should collect snapshot [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should have a custom doctype [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect attr removal [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect node removal [pass] -bidi-chromium-library › library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] -bidi-chromium-library › library/tap.spec.ts › locators › should send all of the correct events [fail] -bidi-chromium-library › library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] -bidi-chromium-library › library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] -bidi-chromium-library › library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] -bidi-chromium-library › library/tap.spec.ts › should send all of the correct events @smoke [fail] -bidi-chromium-library › library/tap.spec.ts › should send well formed touch points [fail] -bidi-chromium-library › library/tap.spec.ts › should wait until an element is visible to tap it [fail] -bidi-chromium-library › library/tap.spec.ts › should work with modifiers [fail] -bidi-chromium-library › library/tap.spec.ts › trial run should not tap [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should allow hiding route actions [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should capture data-url svg iframe [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should contain action info [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should contain adopted style sheets [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should display language-specific locators [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should filter network requests by resource type [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should filter network requests by url [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should follow redirects [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should handle file URIs [unknown] -bidi-chromium-library › library/trace-viewer.spec.ts › should handle multiple headers [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should handle src=blob [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should have correct snapshot size [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should have correct stack trace [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should have network request overrides 2 [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should have network requests [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight expect failure [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should highlight target elements [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should ignore 304 responses [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should include metainfo [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.abort [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should not crash with broken locator [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open console errors on click [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should open simple trace viewer [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open snapshot in new browser context [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open trace viewer on specific host [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open trace-1.31 [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open trace-1.37 [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace files of the same test [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should open two trace viewers [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should pick locator in iframe [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should popup snapshot [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should preserve currentSrc [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should register custom elements [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should remove noscript by default [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should render console [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should render network bars [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should restore control values [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should restore scroll positions [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should serve css without content-type [timeout] -bidi-chromium-library › library/trace-viewer.spec.ts › should serve overridden request [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show action source [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show baseURL in metadata pane [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show correct request start time [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show empty trace viewer [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show font preview [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should show null as a param [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [unknown] -bidi-chromium-library › library/trace-viewer.spec.ts › should show params and return value [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show similar actions from library-only trace [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should show snapshot URL [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should update highlight when typing [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [fail] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with meta CSP [pass] -bidi-chromium-library › library/trace-viewer.spec.ts › should work with nesting CSS selectors [pass] -bidi-chromium-library › library/tracing.spec.ts › should collect sources [pass] -bidi-chromium-library › library/tracing.spec.ts › should collect trace with resources, but no js [timeout] -bidi-chromium-library › library/tracing.spec.ts › should collect two traces [pass] -bidi-chromium-library › library/tracing.spec.ts › should exclude internal pages [pass] -bidi-chromium-library › library/tracing.spec.ts › should export trace concurrently to second navigation [fail] -bidi-chromium-library › library/tracing.spec.ts › should flush console events on tracing stop [pass] -bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames [pass] -bidi-chromium-library › library/tracing.spec.ts › should hide internal stack frames in expect [pass] -bidi-chromium-library › library/tracing.spec.ts › should ignore iframes in head [pass] -bidi-chromium-library › library/tracing.spec.ts › should include context API requests [pass] -bidi-chromium-library › library/tracing.spec.ts › should include interrupted actions [pass] -bidi-chromium-library › library/tracing.spec.ts › should not collect snapshots by default [pass] -bidi-chromium-library › library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] -bidi-chromium-library › library/tracing.spec.ts › should not emit after w/o before [pass] -bidi-chromium-library › library/tracing.spec.ts › should not flush console events [pass] -bidi-chromium-library › library/tracing.spec.ts › should not hang for clicks that open dialogs [pass] -bidi-chromium-library › library/tracing.spec.ts › should not include buffers in the trace [fail] -bidi-chromium-library › library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] -bidi-chromium-library › library/tracing.spec.ts › should not stall on dialogs [pass] -bidi-chromium-library › library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] -bidi-chromium-library › library/tracing.spec.ts › should overwrite existing file [fail] -bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames crop [fail] -bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames fit [fail] -bidi-chromium-library › library/tracing.spec.ts › should produce screencast frames scale [fail] -bidi-chromium-library › library/tracing.spec.ts › should record global request trace [pass] -bidi-chromium-library › library/tracing.spec.ts › should record network failures [fail] -bidi-chromium-library › library/tracing.spec.ts › should respect tracesDir and name [fail] -bidi-chromium-library › library/tracing.spec.ts › should store global request traces separately [pass] -bidi-chromium-library › library/tracing.spec.ts › should store postData for global request [pass] -bidi-chromium-library › library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] -bidi-chromium-library › library/tracing.spec.ts › should throw when starting with different options [pass] -bidi-chromium-library › library/tracing.spec.ts › should throw when stopping without start [pass] -bidi-chromium-library › library/tracing.spec.ts › should use the correct apiName for event driven callbacks [fail] -bidi-chromium-library › library/tracing.spec.ts › should work with multiple chunks [pass] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [pass] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] -bidi-chromium-library › library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [fail] -bidi-chromium-library › library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [fail] -bidi-chromium-library › library/video.spec.ts › screencast › saveAs should throw when no video frames [pass] -bidi-chromium-library › library/video.spec.ts › screencast › should be 800x450 by default [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should be 800x600 with null viewport [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture css transformation [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture navigation [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture static page [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should delete video [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should emulate an iphone [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should expose video path [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should expose video path blank page [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should expose video path blank popup [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should not create video for internal pages [unknown] -bidi-chromium-library › library/video.spec.ts › screencast › should scale frames down to the requested size [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should throw if browser dies [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should throw on browser close [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] -bidi-chromium-library › library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should work for popups [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should work with old options [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › should work with video+trace [fail] -bidi-chromium-library › library/video.spec.ts › screencast › should work with weird screen resolution [timeout] -bidi-chromium-library › library/video.spec.ts › screencast › videoSize should require videosPath [pass] -bidi-chromium-library › library/video.spec.ts › should saveAs video [fail] -bidi-chromium-library › library/web-socket.spec.ts › should emit binary frame events [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should emit close events [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should emit error [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should emit frame events [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should not have stray error events [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should pass self as argument to close event [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] -bidi-chromium-library › library/web-socket.spec.ts › should turn off when offline [unknown] -bidi-chromium-library › library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file +library/beforeunload.spec.ts › should access page after beforeunload [timeout] +library/beforeunload.spec.ts › should be able to navigate away from page with beforeunload [pass] +library/beforeunload.spec.ts › should close browser with beforeunload page [pass] +library/beforeunload.spec.ts › should close browsercontext with beforeunload page [pass] +library/beforeunload.spec.ts › should close page with beforeunload listener [pass] +library/beforeunload.spec.ts › should not stall on evaluate when dismissing beforeunload [pass] +library/beforeunload.spec.ts › should run beforeunload if asked for @smoke [timeout] +library/browser.spec.ts › should create new page @smoke [pass] +library/browser.spec.ts › should dispatch page.on(close) upon browser.close and reject evaluate [fail] +library/browser.spec.ts › should return browserType [pass] +library/browser.spec.ts › should throw upon second create new page [pass] +library/browser.spec.ts › version should work [fail] +library/browsercontext-add-cookies.spec.ts › should add cookies with empty value [fail] +library/browsercontext-add-cookies.spec.ts › should allow unnamed cookies [fail] +library/browsercontext-add-cookies.spec.ts › should be able to set unsecure cookie for HTTP website [pass] +library/browsercontext-add-cookies.spec.ts › should default to setting secure cookie for HTTPS websites [pass] +library/browsercontext-add-cookies.spec.ts › should have |expires| set to |-1| for session cookies [pass] +library/browsercontext-add-cookies.spec.ts › should isolate cookies between launches [pass] +library/browsercontext-add-cookies.spec.ts › should isolate cookies in browser contexts [pass] +library/browsercontext-add-cookies.spec.ts › should isolate persistent cookies [pass] +library/browsercontext-add-cookies.spec.ts › should isolate send cookie header [pass] +library/browsercontext-add-cookies.spec.ts › should isolate session cookies [pass] +library/browsercontext-add-cookies.spec.ts › should not block third party SameSite=None cookies [fail] +library/browsercontext-add-cookies.spec.ts › should not set a cookie on a data URL page [pass] +library/browsercontext-add-cookies.spec.ts › should not set a cookie with blank page URL [pass] +library/browsercontext-add-cookies.spec.ts › should roundtrip cookie [fail] +library/browsercontext-add-cookies.spec.ts › should send cookie header [pass] +library/browsercontext-add-cookies.spec.ts › should set a cookie on a different domain [pass] +library/browsercontext-add-cookies.spec.ts › should set a cookie with a path [pass] +library/browsercontext-add-cookies.spec.ts › should set cookie with reasonable defaults [fail] +library/browsercontext-add-cookies.spec.ts › should set cookies for a frame [pass] +library/browsercontext-add-cookies.spec.ts › should set multiple cookies [pass] +library/browsercontext-add-cookies.spec.ts › should set secure cookies on secure WebSocket [fail] +library/browsercontext-add-cookies.spec.ts › should work @smoke [pass] +library/browsercontext-add-cookies.spec.ts › should work with expires=-1 [fail] +library/browsercontext-add-cookies.spec.ts › should(not) block third party cookies [pass] +library/browsercontext-add-init-script.spec.ts › should work with browser context scripts @smoke [pass] +library/browsercontext-add-init-script.spec.ts › should work with browser context scripts for already created pages [pass] +library/browsercontext-add-init-script.spec.ts › should work with browser context scripts with a path [pass] +library/browsercontext-add-init-script.spec.ts › should work without navigation in popup [fail] +library/browsercontext-add-init-script.spec.ts › should work without navigation, after all bindings [fail] +library/browsercontext-base-url.spec.ts › should be able to match a URL relative to its given URL with urlMatcher [fail] +library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newContext is passed to page.goto @smoke [pass] +library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newPage is passed to page.goto [pass] +library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browserType.launchPersistentContext is passed to page.goto [fail] +library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL with a trailing slash in browser.newPage is passed to page.goto [pass] +library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL without a trailing slash in browser.newPage is passed to page.goto [pass] +library/browsercontext-base-url.spec.ts › should not construct a new URL when valid URLs are passed [pass] +library/browsercontext-base-url.spec.ts › should not construct a new URL with baseURL when a glob was used [pass] +library/browsercontext-basic.spec.ts › close() should abort waitForEvent [pass] +library/browsercontext-basic.spec.ts › close() should be callable twice [pass] +library/browsercontext-basic.spec.ts › close() should work for empty context [pass] +library/browsercontext-basic.spec.ts › default user agent [pass] +library/browsercontext-basic.spec.ts › setContent should work after disabling javascript [pass] +library/browsercontext-basic.spec.ts › should be able to click across browser contexts [pass] +library/browsercontext-basic.spec.ts › should be able to navigate after disabling javascript [pass] +library/browsercontext-basic.spec.ts › should close all belonging pages once closing context [pass] +library/browsercontext-basic.spec.ts › should create new context @smoke [pass] +library/browsercontext-basic.spec.ts › should disable javascript [fail] +library/browsercontext-basic.spec.ts › should emulate media in cross-process iframe [fail] +library/browsercontext-basic.spec.ts › should emulate media in popup [fail] +library/browsercontext-basic.spec.ts › should emulate navigator.onLine [fail] +library/browsercontext-basic.spec.ts › should isolate localStorage and cookies @smoke [pass] +library/browsercontext-basic.spec.ts › should make a copy of default viewport [pass] +library/browsercontext-basic.spec.ts › should not allow deviceScaleFactor with null viewport [pass] +library/browsercontext-basic.spec.ts › should not allow isMobile with null viewport [pass] +library/browsercontext-basic.spec.ts › should not hang on promises after disabling javascript [pass] +library/browsercontext-basic.spec.ts › should not report frameless pages on error [pass] +library/browsercontext-basic.spec.ts › should pass self to close event [pass] +library/browsercontext-basic.spec.ts › should propagate default viewport to the page [pass] +library/browsercontext-basic.spec.ts › should respect deviceScaleFactor [pass] +library/browsercontext-basic.spec.ts › should return all of the pages [pass] +library/browsercontext-basic.spec.ts › should work with offline option [fail] +library/browsercontext-basic.spec.ts › window.open should use parent tab context [pass] +library/browsercontext-clearcookies.spec.ts › should clear cookies [pass] +library/browsercontext-clearcookies.spec.ts › should isolate cookies when clearing [pass] +library/browsercontext-clearcookies.spec.ts › should remove cookies by domain [fail] +library/browsercontext-clearcookies.spec.ts › should remove cookies by name [fail] +library/browsercontext-clearcookies.spec.ts › should remove cookies by name and domain [fail] +library/browsercontext-clearcookies.spec.ts › should remove cookies by name regex [fail] +library/browsercontext-clearcookies.spec.ts › should remove cookies by path [fail] +library/browsercontext-cookies.spec.ts › should add cookies with an expiration [pass] +library/browsercontext-cookies.spec.ts › should be able to send third party cookies via an iframe [fail] +library/browsercontext-cookies.spec.ts › should get a cookie @smoke [fail] +library/browsercontext-cookies.spec.ts › should get a non-session cookie [fail] +library/browsercontext-cookies.spec.ts › should get cookies from multiple urls [pass] +library/browsercontext-cookies.spec.ts › should get multiple cookies [fail] +library/browsercontext-cookies.spec.ts › should parse cookie with large Max-Age correctly [fail] +library/browsercontext-cookies.spec.ts › should properly report "Lax" sameSite cookie [pass] +library/browsercontext-cookies.spec.ts › should properly report "Strict" sameSite cookie [pass] +library/browsercontext-cookies.spec.ts › should properly report httpOnly cookie [pass] +library/browsercontext-cookies.spec.ts › should return cookies with empty value [pass] +library/browsercontext-cookies.spec.ts › should return no cookies in pristine browser context [pass] +library/browsercontext-cookies.spec.ts › should return secure cookies based on HTTP(S) protocol [pass] +library/browsercontext-cookies.spec.ts › should support requestStorageAccess [fail] +library/browsercontext-cookies.spec.ts › should work with subdomain cookie [pass] +library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching hostname [fail] +library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching port [fail] +library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching scheme [fail] +library/browsercontext-credentials.spec.ts › should fail with wrong credentials [fail] +library/browsercontext-credentials.spec.ts › should fail without credentials [pass] +library/browsercontext-credentials.spec.ts › should return resource body [fail] +library/browsercontext-credentials.spec.ts › should work with correct credentials @smoke [fail] +library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin [fail] +library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin case insensitive [fail] +library/browsercontext-credentials.spec.ts › should work with setHTTPCredentials [fail] +library/browsercontext-csp.spec.ts › should bypass CSP header [fail] +library/browsercontext-csp.spec.ts › should bypass CSP in iframes as well [fail] +library/browsercontext-csp.spec.ts › should bypass CSP meta tag @smoke [fail] +library/browsercontext-csp.spec.ts › should bypass after cross-process navigation [fail] +library/browsercontext-device.spec.ts › device › should emulate viewport and screen size [fail] +library/browsercontext-device.spec.ts › device › should emulate viewport without screen size [fail] +library/browsercontext-device.spec.ts › device › should reset scroll top after a navigation [pass] +library/browsercontext-device.spec.ts › device › should scroll to a precise position with mobile scale [pass] +library/browsercontext-device.spec.ts › device › should scroll to click [pass] +library/browsercontext-device.spec.ts › device › should scroll twice when emulated [pass] +library/browsercontext-device.spec.ts › device › should support clicking [pass] +library/browsercontext-device.spec.ts › device › should work @smoke [fail] +library/browsercontext-dsf.spec.ts › should fetch hidpi assets [pass] +library/browsercontext-dsf.spec.ts › should fetch lodpi assets @smoke [pass] +library/browsercontext-events.spec.ts › console event should work @smoke [pass] +library/browsercontext-events.spec.ts › console event should work in immediately closed popup [timeout] +library/browsercontext-events.spec.ts › console event should work in popup [pass] +library/browsercontext-events.spec.ts › console event should work in popup 2 [timeout] +library/browsercontext-events.spec.ts › dialog event should work @smoke [pass] +library/browsercontext-events.spec.ts › dialog event should work in immediately closed popup [timeout] +library/browsercontext-events.spec.ts › dialog event should work in popup [timeout] +library/browsercontext-events.spec.ts › dialog event should work in popup 2 [pass] +library/browsercontext-events.spec.ts › dialog event should work with inline script tag [timeout] +library/browsercontext-events.spec.ts › weberror event should work [timeout] +library/browsercontext-expose-function.spec.ts › expose binding should work [fail] +library/browsercontext-expose-function.spec.ts › exposeBindingHandle should work [fail] +library/browsercontext-expose-function.spec.ts › should be callable from-inside addInitScript [fail] +library/browsercontext-expose-function.spec.ts › should throw for duplicate registrations [pass] +library/browsercontext-expose-function.spec.ts › should work [fail] +library/browsercontext-expose-function.spec.ts › should work with CSP [fail] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail if response content-length header is missing (br) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with chunked responses (without Content-Length header) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should support decompression [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail if response content-length header is missing (deflate) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with chunked responses (without Content-Length header) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should support decompression [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail if response content-length header is missing (gzip) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with chunked responses (without Content-Length header) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should support decompression [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work on request fixture [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › https post should work with ignoreHTTPSErrors option [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › should work with ip6 and port as the host [pass] +library/browsercontext-fetch.spec.ts › context request should export same storage state as context [pass] +library/browsercontext-fetch.spec.ts › delete should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › delete should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › delete should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › delete should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › delete should support post data [pass] +library/browsercontext-fetch.spec.ts › deleteshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › fetch should not throw on long set-cookie value [pass] +library/browsercontext-fetch.spec.ts › fetch should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › fetch should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › fetch should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › fetch should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › fetch should work [pass] +library/browsercontext-fetch.spec.ts › fetchshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › get should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › get should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › get should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › get should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › get should support post data [pass] +library/browsercontext-fetch.spec.ts › get should work @smoke [pass] +library/browsercontext-fetch.spec.ts › getshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › head should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › head should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › head should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › head should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › head should support post data [pass] +library/browsercontext-fetch.spec.ts › headshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › patch should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › patch should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › patch should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › patch should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › patch should support post data [pass] +library/browsercontext-fetch.spec.ts › patchshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › post should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › post should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › post should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › post should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › post should support post data [pass] +library/browsercontext-fetch.spec.ts › postshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › put should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › put should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › put should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › put should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › put should support post data [pass] +library/browsercontext-fetch.spec.ts › putshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › should abort requests when browser context closes [pass] +library/browsercontext-fetch.spec.ts › should accept bool and numeric params [pass] +library/browsercontext-fetch.spec.ts › should add cookies from Set-Cookie header [pass] +library/browsercontext-fetch.spec.ts › should add default headers [pass] +library/browsercontext-fetch.spec.ts › should add default headers to redirects [pass] +library/browsercontext-fetch.spec.ts › should add session cookies to request [pass] +library/browsercontext-fetch.spec.ts › should allow to override default headers [pass] +library/browsercontext-fetch.spec.ts › should dispose [pass] +library/browsercontext-fetch.spec.ts › should dispose when context closes [pass] +library/browsercontext-fetch.spec.ts › should encode to application/json by default [pass] +library/browsercontext-fetch.spec.ts › should follow redirects [pass] +library/browsercontext-fetch.spec.ts › should follow redirects correctly when Location header contains UTF-8 characters [pass] +library/browsercontext-fetch.spec.ts › should handle cookies on redirects [pass] +library/browsercontext-fetch.spec.ts › should inherit ignoreHTTPSErrors from context [pass] +library/browsercontext-fetch.spec.ts › should not add context cookie if cookie header passed as a parameter [pass] +library/browsercontext-fetch.spec.ts › should not hang on a brotli encoded Range request [pass] +library/browsercontext-fetch.spec.ts › should not lose body while handling Set-Cookie header [pass] +library/browsercontext-fetch.spec.ts › should not work after context dispose [pass] +library/browsercontext-fetch.spec.ts › should not work after dispose [pass] +library/browsercontext-fetch.spec.ts › should override request parameters [pass] +library/browsercontext-fetch.spec.ts › should preserve cookie order from Set-Cookie header [pass] +library/browsercontext-fetch.spec.ts › should propagate custom headers with redirects [pass] +library/browsercontext-fetch.spec.ts › should propagate extra http headers with redirects [fail] +library/browsercontext-fetch.spec.ts › should remove cookie with expires far in the past [pass] +library/browsercontext-fetch.spec.ts › should remove cookie with negative max-age [pass] +library/browsercontext-fetch.spec.ts › should resolve url relative to baseURL [pass] +library/browsercontext-fetch.spec.ts › should respect timeout after redirects [pass] +library/browsercontext-fetch.spec.ts › should retry on ECONNRESET [pass] +library/browsercontext-fetch.spec.ts › should return error with wrong credentials [pass] +library/browsercontext-fetch.spec.ts › should return raw headers [pass] +library/browsercontext-fetch.spec.ts › should send content-length [pass] +library/browsercontext-fetch.spec.ts › should send secure cookie over http for localhost [pass] +library/browsercontext-fetch.spec.ts › should serialize data to json regardless of content-type [pass] +library/browsercontext-fetch.spec.ts › should set domain=localhost cookie [pass] +library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for browser.newPage [fail] +library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for newContext [pass] +library/browsercontext-fetch.spec.ts › should support SameSite cookie attribute over https [pass] +library/browsercontext-fetch.spec.ts › should support a timeout of 0 [pass] +library/browsercontext-fetch.spec.ts › should support application/x-www-form-urlencoded [pass] +library/browsercontext-fetch.spec.ts › should support brotli compression [pass] +library/browsercontext-fetch.spec.ts › should support cookie with empty value [pass] +library/browsercontext-fetch.spec.ts › should support deflate compression [pass] +library/browsercontext-fetch.spec.ts › should support gzip compression [pass] +library/browsercontext-fetch.spec.ts › should support https [pass] +library/browsercontext-fetch.spec.ts › should support multipart/form-data [pass] +library/browsercontext-fetch.spec.ts › should support multipart/form-data and keep the order [pass] +library/browsercontext-fetch.spec.ts › should support multipart/form-data with ReadStream values [pass] +library/browsercontext-fetch.spec.ts › should support repeating names in multipart/form-data [pass] +library/browsercontext-fetch.spec.ts › should support set-cookie with SameSite and without Secure attribute over HTTP [fail] +library/browsercontext-fetch.spec.ts › should support timeout option [pass] +library/browsercontext-fetch.spec.ts › should throw informative error on corrupted brotli body [pass] +library/browsercontext-fetch.spec.ts › should throw informative error on corrupted deflate body [pass] +library/browsercontext-fetch.spec.ts › should throw informative error on corrupted gzip body [pass] +library/browsercontext-fetch.spec.ts › should throw nice error on unsupported data type [pass] +library/browsercontext-fetch.spec.ts › should throw on invalid header value [pass] +library/browsercontext-fetch.spec.ts › should throw on network error [pass] +library/browsercontext-fetch.spec.ts › should throw on network error after redirect [pass] +library/browsercontext-fetch.spec.ts › should throw on network error when sending body [pass] +library/browsercontext-fetch.spec.ts › should throw on network error when sending body after redirect [pass] +library/browsercontext-fetch.spec.ts › should throw on non-http(s) protocol [pass] +library/browsercontext-fetch.spec.ts › should update host header on redirect [pass] +library/browsercontext-fetch.spec.ts › should work with connectOverCDP [unknown] +library/browsercontext-fetch.spec.ts › should work with http credentials [pass] +library/browsercontext-fetch.spec.ts › should work with setHTTPCredentials [pass] +library/browsercontext-har.spec.ts › by default should abort requests not found in har [fail] +library/browsercontext-har.spec.ts › context.unrouteAll should stop context.routeFromHAR [fail] +library/browsercontext-har.spec.ts › fallback:continue should continue requests on bad har [fail] +library/browsercontext-har.spec.ts › fallback:continue should continue when not found in har [fail] +library/browsercontext-har.spec.ts › newPage should fulfill from har, matching the method and following redirects [fail] +library/browsercontext-har.spec.ts › page.unrouteAll should stop page.routeFromHAR [fail] +library/browsercontext-har.spec.ts › should apply overrides before routing from har [fail] +library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] +library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [fail] +library/browsercontext-har.spec.ts › should context.routeFromHAR, matching the method and following redirects [fail] +library/browsercontext-har.spec.ts › should disambiguate by header [fail] +library/browsercontext-har.spec.ts › should fulfill from har with content in a file [fail] +library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] +library/browsercontext-har.spec.ts › should goForward to redirected navigation [fail] +library/browsercontext-har.spec.ts › should ignore aborted requests [fail] +library/browsercontext-har.spec.ts › should ignore boundary when matching multipart/form-data body [fail] +library/browsercontext-har.spec.ts › should only context.routeFromHAR requests matching url filter [fail] +library/browsercontext-har.spec.ts › should only handle requests matching url filter [fail] +library/browsercontext-har.spec.ts › should only page.routeFromHAR requests matching url filter [fail] +library/browsercontext-har.spec.ts › should page.routeFromHAR, matching the method and following redirects [fail] +library/browsercontext-har.spec.ts › should produce extracted zip [fail] +library/browsercontext-har.spec.ts › should record overridden requests to har [fail] +library/browsercontext-har.spec.ts › should reload redirected navigation [fail] +library/browsercontext-har.spec.ts › should round-trip extracted har.zip [fail] +library/browsercontext-har.spec.ts › should round-trip har with postData [fail] +library/browsercontext-har.spec.ts › should round-trip har.zip [fail] +library/browsercontext-har.spec.ts › should support regex filter [fail] +library/browsercontext-har.spec.ts › should update extracted har.zip for page [fail] +library/browsercontext-har.spec.ts › should update har.zip for context [fail] +library/browsercontext-har.spec.ts › should update har.zip for page [fail] +library/browsercontext-har.spec.ts › should update har.zip for page with different options [fail] +library/browsercontext-locale.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().locale [fail] +library/browsercontext-locale.spec.ts › should affect accept-language header @smoke [fail] +library/browsercontext-locale.spec.ts › should affect navigator.language [fail] +library/browsercontext-locale.spec.ts › should affect navigator.language in popups [fail] +library/browsercontext-locale.spec.ts › should be isolated between contexts [fail] +library/browsercontext-locale.spec.ts › should format date [fail] +library/browsercontext-locale.spec.ts › should format number [fail] +library/browsercontext-locale.spec.ts › should format number in popups [fail] +library/browsercontext-locale.spec.ts › should format number in workers [timeout] +library/browsercontext-locale.spec.ts › should not change default locale in another context [fail] +library/browsercontext-locale.spec.ts › should work for multiple pages sharing same process [pass] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.Request [pass] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFailed [fail] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFinished [pass] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.Response [pass] +library/browsercontext-network-event.spec.ts › should fire events in proper order [pass] +library/browsercontext-network-event.spec.ts › should not fire events for favicon or favicon redirects [unknown] +library/browsercontext-page-event.spec.ts › should fire page lifecycle events [fail] +library/browsercontext-page-event.spec.ts › should have about:blank for empty url with domcontentloaded [fail] +library/browsercontext-page-event.spec.ts › should have about:blank url with domcontentloaded [fail] +library/browsercontext-page-event.spec.ts › should have an opener [pass] +library/browsercontext-page-event.spec.ts › should have url [pass] +library/browsercontext-page-event.spec.ts › should have url after domcontentloaded [pass] +library/browsercontext-page-event.spec.ts › should not crash while redirecting of original request was missed [pass] +library/browsercontext-page-event.spec.ts › should not hang on ctrl-click during provisional load [timeout] +library/browsercontext-page-event.spec.ts › should report initialized pages [fail] +library/browsercontext-page-event.spec.ts › should report when a new page is created and closed [fail] +library/browsercontext-page-event.spec.ts › should work with Ctrl-clicking [pass] +library/browsercontext-page-event.spec.ts › should work with Shift-clicking [pass] +library/browsercontext-pages.spec.ts › frame.focus should work multiple times [pass] +library/browsercontext-pages.spec.ts › page.context should return the correct instance [pass] +library/browsercontext-pages.spec.ts › should click the button with deviceScaleFactor set [pass] +library/browsercontext-pages.spec.ts › should click the button with offset with page scale [pass] +library/browsercontext-pages.spec.ts › should click with disabled javascript [pass] +library/browsercontext-pages.spec.ts › should keep selection in multiple pages [pass] +library/browsercontext-pages.spec.ts › should not be visible in context.pages [pass] +library/browsercontext-pages.spec.ts › should not hang with touch-enabled viewports [pass] +library/browsercontext-pages.spec.ts › should not leak listeners during navigation of 20 pages [fail] +library/browsercontext-pages.spec.ts › should return bounding box with page scale [pass] +library/browsercontext-proxy.spec.ts › does launch without a port [pass] +library/browsercontext-proxy.spec.ts › should authenticate [fail] +library/browsercontext-proxy.spec.ts › should authenticate with empty password [fail] +library/browsercontext-proxy.spec.ts › should exclude patterns [fail] +library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts [fail] +library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts on navigation [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › link-local [timeout] +library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › localhost [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [timeout] +library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] +library/browsercontext-proxy.spec.ts › should set cookie for top-level domain [pass] +library/browsercontext-proxy.spec.ts › should throw for bad server value [pass] +library/browsercontext-proxy.spec.ts › should throw for socks4 authentication [pass] +library/browsercontext-proxy.spec.ts › should throw for socks5 authentication [pass] +library/browsercontext-proxy.spec.ts › should use ipv6 proxy [fail] +library/browsercontext-proxy.spec.ts › should use proxy [fail] +library/browsercontext-proxy.spec.ts › should use proxy for https urls [timeout] +library/browsercontext-proxy.spec.ts › should use proxy for second page [fail] +library/browsercontext-proxy.spec.ts › should use proxy twice [fail] +library/browsercontext-proxy.spec.ts › should use socks proxy [fail] +library/browsercontext-proxy.spec.ts › should use socks proxy in second page [fail] +library/browsercontext-proxy.spec.ts › should work when passing the proxy only on the context level [fail] +library/browsercontext-proxy.spec.ts › should work with IP:PORT notion [fail] +library/browsercontext-reuse.spec.ts › should continue issuing events after closing the reused page [fail] +library/browsercontext-reuse.spec.ts › should ignore binding from beforeunload [pass] +library/browsercontext-reuse.spec.ts › should not cache resources [fail] +library/browsercontext-reuse.spec.ts › should re-add binding after reset [fail] +library/browsercontext-reuse.spec.ts › should reset mouse position [pass] +library/browsercontext-reuse.spec.ts › should reset serviceworker [fail] +library/browsercontext-reuse.spec.ts › should reset serviceworker that hangs in importScripts [fail] +library/browsercontext-reuse.spec.ts › should reset tracing [pass] +library/browsercontext-reuse.spec.ts › should work with clock emulation [pass] +library/browsercontext-route.spec.ts › should chain fallback [fail] +library/browsercontext-route.spec.ts › should chain fallback into page [fail] +library/browsercontext-route.spec.ts › should chain fallback w/ dynamic URL [fail] +library/browsercontext-route.spec.ts › should fall back async [fail] +library/browsercontext-route.spec.ts › should fall back to context.route [fail] +library/browsercontext-route.spec.ts › should ignore secure Set-Cookie header for insecure requests [fail] +library/browsercontext-route.spec.ts › should intercept [fail] +library/browsercontext-route.spec.ts › should not chain abort [pass] +library/browsercontext-route.spec.ts › should not chain fulfill [fail] +library/browsercontext-route.spec.ts › should overwrite post body with empty string [fail] +library/browsercontext-route.spec.ts › should support Set-Cookie header [fail] +library/browsercontext-route.spec.ts › should support async handler w/ times [fail] +library/browsercontext-route.spec.ts › should support the times parameter with route matching [fail] +library/browsercontext-route.spec.ts › should unroute [fail] +library/browsercontext-route.spec.ts › should use Set-Cookie header in future requests [fail] +library/browsercontext-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] +library/browsercontext-route.spec.ts › should work with ignoreHTTPSErrors [fail] +library/browsercontext-route.spec.ts › should yield to page.route [fail] +library/browsercontext-service-worker-policy.spec.ts › block › blocks service worker registration [timeout] +library/browsercontext-service-worker-policy.spec.ts › block › should not throw error on about:blank [pass] +library/browsercontext-service-worker-policy.spec.ts › should allow service workers by default [pass] +library/browsercontext-set-extra-http-headers.spec.ts › should override extra headers from browser context [fail] +library/browsercontext-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] +library/browsercontext-storage-state.spec.ts › should capture cookies [fail] +library/browsercontext-storage-state.spec.ts › should capture local storage [fail] +library/browsercontext-storage-state.spec.ts › should handle malformed file [pass] +library/browsercontext-storage-state.spec.ts › should handle missing file [pass] +library/browsercontext-storage-state.spec.ts › should not emit events about internal page [fail] +library/browsercontext-storage-state.spec.ts › should not restore localStorage twice [fail] +library/browsercontext-storage-state.spec.ts › should round-trip through the file [fail] +library/browsercontext-storage-state.spec.ts › should serialize storageState with lone surrogates [pass] +library/browsercontext-storage-state.spec.ts › should set local storage [fail] +library/browsercontext-storage-state.spec.ts › should work when service worker is intefering [pass] +library/browsercontext-strict.spec.ts › should not fail page.textContent in non-strict mode [pass] +library/browsercontext-strict.spec.ts › strict context mode › should fail page.click in strict mode [fail] +library/browsercontext-strict.spec.ts › strict context mode › should fail page.textContent in strict mode [fail] +library/browsercontext-strict.spec.ts › strict context mode › should opt out of strict mode [pass] +library/browsercontext-timezone-id.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().timeZone [fail] +library/browsercontext-timezone-id.spec.ts › should not change default timezone in another context [fail] +library/browsercontext-timezone-id.spec.ts › should throw for invalid timezone IDs when creating pages [fail] +library/browsercontext-timezone-id.spec.ts › should work @smoke [fail] +library/browsercontext-timezone-id.spec.ts › should work for multiple pages sharing same process [pass] +library/browsercontext-user-agent.spec.ts › custom user agent for download [timeout] +library/browsercontext-user-agent.spec.ts › should emulate device user-agent [fail] +library/browsercontext-user-agent.spec.ts › should make a copy of default options [fail] +library/browsercontext-user-agent.spec.ts › should work [fail] +library/browsercontext-user-agent.spec.ts › should work for navigator.userAgentData and sec-ch-ua headers [unknown] +library/browsercontext-user-agent.spec.ts › should work for subframes [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › default mobile viewports to 980 width [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › mouse should work with mobile viewports and cross process navigations [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › respect meta viewport tag [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should be detectable [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should detect touch when applying viewport with touches [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should emulate the hover media feature [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should fire orientationchange event [timeout] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should scroll when emulating a mobile viewport [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support landscape emulation [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support mobile emulation [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support touch emulation [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support window.orientation emulation [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › view scale should reset after navigation [fail] +library/browsercontext-viewport.spec.ts › WebKit Windows headed should have a minimal viewport [unknown] +library/browsercontext-viewport.spec.ts › should be able to get correct orientation angle on non-mobile devices [pass] +library/browsercontext-viewport.spec.ts › should drag with high dpi [pass] +library/browsercontext-viewport.spec.ts › should emulate availWidth and availHeight [fail] +library/browsercontext-viewport.spec.ts › should emulate device height [fail] +library/browsercontext-viewport.spec.ts › should emulate device width [fail] +library/browsercontext-viewport.spec.ts › should get the proper default viewport size [pass] +library/browsercontext-viewport.spec.ts › should not have touch by default [pass] +library/browsercontext-viewport.spec.ts › should report null viewportSize when given null viewport [pass] +library/browsercontext-viewport.spec.ts › should return correct outerWidth and outerHeight [pass] +library/browsercontext-viewport.spec.ts › should set both screen and viewport options [fail] +library/browsercontext-viewport.spec.ts › should set the proper viewport size [pass] +library/browsercontext-viewport.spec.ts › should set window.screen.orientation.type for mobile devices [fail] +library/browsercontext-viewport.spec.ts › should support touch with null viewport [fail] +library/browsercontext-viewport.spec.ts › should throw on tap if hasTouch is not enabled [pass] +library/browsertype-basic.spec.ts › browserType.executablePath should work [unknown] +library/browsertype-basic.spec.ts › browserType.name should work [fail] +library/browsertype-basic.spec.ts › should throw when trying to connect with not-chromium [pass] +library/browsertype-connect.spec.ts › launchServer only › should be able to reconnect to a browser 12 times without warnings [timeout] +library/browsertype-connect.spec.ts › launchServer only › should properly disconnect when connection closes from the server side [timeout] +library/browsertype-connect.spec.ts › launchServer only › should work with cluster [timeout] +library/browsertype-connect.spec.ts › launchServer › disconnected event should be emitted when browser is closed or server is closed [timeout] +library/browsertype-connect.spec.ts › launchServer › disconnected event should have browser as argument [timeout] +library/browsertype-connect.spec.ts › launchServer › setInputFiles should preserve lastModified timestamp [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to connect 20 times to a single server without warnings [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to connect two browsers at the same time [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to connect when the wsEndpoint is passed as an option [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to reconnect to a browser [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 through localhost [timeout] +library/browsertype-connect.spec.ts › launchServer › should connect over http [timeout] +library/browsertype-connect.spec.ts › launchServer › should connect over wss [timeout] +library/browsertype-connect.spec.ts › launchServer › should emit close events on pages and contexts [timeout] +library/browsertype-connect.spec.ts › launchServer › should error when saving download after deletion [timeout] +library/browsertype-connect.spec.ts › launchServer › should filter launch options [timeout] +library/browsertype-connect.spec.ts › launchServer › should fulfill with global fetch result [timeout] +library/browsertype-connect.spec.ts › launchServer › should handle exceptions during connect [timeout] +library/browsertype-connect.spec.ts › launchServer › should ignore page.pause when headed [timeout] +library/browsertype-connect.spec.ts › launchServer › should not throw on close after disconnect [timeout] +library/browsertype-connect.spec.ts › launchServer › should print HTTP error [pass] +library/browsertype-connect.spec.ts › launchServer › should print custom ws close error [pass] +library/browsertype-connect.spec.ts › launchServer › should print ws error [pass] +library/browsertype-connect.spec.ts › launchServer › should properly disconnect when connection closes from the client side [timeout] +library/browsertype-connect.spec.ts › launchServer › should record trace with sources [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject navigation when browser closes [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.close finishes [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.onDisconnect fires [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject waitForSelector when browser closes [timeout] +library/browsertype-connect.spec.ts › launchServer › should respect selectors [timeout] +library/browsertype-connect.spec.ts › launchServer › should save download [timeout] +library/browsertype-connect.spec.ts › launchServer › should save har [timeout] +library/browsertype-connect.spec.ts › launchServer › should saveAs videos from remote browser [timeout] +library/browsertype-connect.spec.ts › launchServer › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +library/browsertype-connect.spec.ts › launchServer › should send extra headers with connect request [pass] +library/browsertype-connect.spec.ts › launchServer › should set the browser connected state [timeout] +library/browsertype-connect.spec.ts › launchServer › should support slowmo option [timeout] +library/browsertype-connect.spec.ts › launchServer › should terminate network waiters [timeout] +library/browsertype-connect.spec.ts › launchServer › should throw when calling waitForNavigation after disconnect [timeout] +library/browsertype-connect.spec.ts › launchServer › should throw when used after isConnected returns false [timeout] +library/browsertype-connect.spec.ts › launchServer › should timeout in connect while connecting [pass] +library/browsertype-connect.spec.ts › launchServer › should timeout in socket while connecting [pass] +library/browsertype-connect.spec.ts › launchServer › should upload large file [timeout] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should check proxy pattern on the client [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should forward non-forwarded requests [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should lead to the error page for forwarded requests when the connection is refused [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy based on the pattern [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy ipv6 localhost requests @smoke [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy local.playwright requests [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests @smoke [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests from fetch api [unknown] +library/browsertype-connect.spec.ts › run-server › disconnected event should be emitted when browser is closed or server is closed [fail] +library/browsertype-connect.spec.ts › run-server › disconnected event should have browser as argument [fail] +library/browsertype-connect.spec.ts › run-server › setInputFiles should preserve lastModified timestamp [fail] +library/browsertype-connect.spec.ts › run-server › should be able to connect 20 times to a single server without warnings [fail] +library/browsertype-connect.spec.ts › run-server › should be able to connect two browsers at the same time [fail] +library/browsertype-connect.spec.ts › run-server › should be able to connect when the wsEndpoint is passed as an option [fail] +library/browsertype-connect.spec.ts › run-server › should be able to reconnect to a browser [fail] +library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 [fail] +library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 through localhost [fail] +library/browsertype-connect.spec.ts › run-server › should connect over http [fail] +library/browsertype-connect.spec.ts › run-server › should connect over wss [fail] +library/browsertype-connect.spec.ts › run-server › should emit close events on pages and contexts [fail] +library/browsertype-connect.spec.ts › run-server › should error when saving download after deletion [fail] +library/browsertype-connect.spec.ts › run-server › should filter launch options [fail] +library/browsertype-connect.spec.ts › run-server › should fulfill with global fetch result [fail] +library/browsertype-connect.spec.ts › run-server › should handle exceptions during connect [pass] +library/browsertype-connect.spec.ts › run-server › should ignore page.pause when headed [fail] +library/browsertype-connect.spec.ts › run-server › should not throw on close after disconnect [fail] +library/browsertype-connect.spec.ts › run-server › should print HTTP error [pass] +library/browsertype-connect.spec.ts › run-server › should print custom ws close error [pass] +library/browsertype-connect.spec.ts › run-server › should print ws error [pass] +library/browsertype-connect.spec.ts › run-server › should properly disconnect when connection closes from the client side [fail] +library/browsertype-connect.spec.ts › run-server › should record trace with sources [fail] +library/browsertype-connect.spec.ts › run-server › should reject navigation when browser closes [fail] +library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.close finishes [fail] +library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.onDisconnect fires [fail] +library/browsertype-connect.spec.ts › run-server › should reject waitForSelector when browser closes [fail] +library/browsertype-connect.spec.ts › run-server › should respect selectors [fail] +library/browsertype-connect.spec.ts › run-server › should save download [fail] +library/browsertype-connect.spec.ts › run-server › should save har [fail] +library/browsertype-connect.spec.ts › run-server › should saveAs videos from remote browser [fail] +library/browsertype-connect.spec.ts › run-server › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +library/browsertype-connect.spec.ts › run-server › should send extra headers with connect request [pass] +library/browsertype-connect.spec.ts › run-server › should set the browser connected state [fail] +library/browsertype-connect.spec.ts › run-server › should support slowmo option [fail] +library/browsertype-connect.spec.ts › run-server › should terminate network waiters [fail] +library/browsertype-connect.spec.ts › run-server › should throw when calling waitForNavigation after disconnect [fail] +library/browsertype-connect.spec.ts › run-server › should throw when used after isConnected returns false [fail] +library/browsertype-connect.spec.ts › run-server › should timeout in connect while connecting [pass] +library/browsertype-connect.spec.ts › run-server › should timeout in socket while connecting [pass] +library/browsertype-connect.spec.ts › run-server › should upload large file [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should check proxy pattern on the client [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should forward non-forwarded requests [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should lead to the error page for forwarded requests when the connection is refused [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy based on the pattern [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy ipv6 localhost requests @smoke [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy local.playwright requests [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests @smoke [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests from fetch api [fail] +library/browsertype-connect.spec.ts › should refuse connecting when versions do not match [pass] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 hub + node chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium through run-driver [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone non-chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 hub + node chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium broken driver [unknown] +library/browsertype-launch-server.spec.ts › launch server › should default to random wsPath [fail] +library/browsertype-launch-server.spec.ts › launch server › should fire "close" event during kill [fail] +library/browsertype-launch-server.spec.ts › launch server › should fire close event [fail] +library/browsertype-launch-server.spec.ts › launch server › should log protocol [fail] +library/browsertype-launch-server.spec.ts › launch server › should provide an error when ws endpoint is incorrect [fail] +library/browsertype-launch-server.spec.ts › launch server › should return child_process instance [fail] +library/browsertype-launch-server.spec.ts › launch server › should work [fail] +library/browsertype-launch-server.spec.ts › launch server › should work when wsPath is missing leading slash [fail] +library/browsertype-launch-server.spec.ts › launch server › should work with host [fail] +library/browsertype-launch-server.spec.ts › launch server › should work with port [fail] +library/browsertype-launch-server.spec.ts › launch server › should work with wsPath [fail] +library/browsertype-launch.spec.ts › should accept objects as options [pass] +library/browsertype-launch.spec.ts › should allow await using [pass] +library/browsertype-launch.spec.ts › should be callable twice [pass] +library/browsertype-launch.spec.ts › should fire close event for all contexts [pass] +library/browsertype-launch.spec.ts › should handle exception [pass] +library/browsertype-launch.spec.ts › should handle timeout [pass] +library/browsertype-launch.spec.ts › should reject all promises when browser is closed [fail] +library/browsertype-launch.spec.ts › should reject if executable path is invalid [pass] +library/browsertype-launch.spec.ts › should reject if launched browser fails immediately [fail] +library/browsertype-launch.spec.ts › should report launch log [pass] +library/browsertype-launch.spec.ts › should throw if page argument is passed [pass] +library/browsertype-launch.spec.ts › should throw if port option is passed [pass] +library/browsertype-launch.spec.ts › should throw if port option is passed for persistent context [pass] +library/browsertype-launch.spec.ts › should throw if userDataDir is passed as an argument [pass] +library/browsertype-launch.spec.ts › should throw if userDataDir option is passed [pass] +library/capabilities.spec.ts › Intl.ListFormat should work [pass] +library/capabilities.spec.ts › SharedArrayBuffer should work @smoke [fail] +library/capabilities.spec.ts › Web Assembly should work @smoke [pass] +library/capabilities.spec.ts › WebSocket should work @smoke [pass] +library/capabilities.spec.ts › loading in HTMLImageElement.prototype [pass] +library/capabilities.spec.ts › make sure that XMLHttpRequest upload events are emitted correctly [pass] +library/capabilities.spec.ts › navigator.clipboard should be present [pass] +library/capabilities.spec.ts › requestFullscreen [pass] +library/capabilities.spec.ts › service worker should cover the iframe [pass] +library/capabilities.spec.ts › service worker should register in an iframe [pass] +library/capabilities.spec.ts › serviceWorker should intercept document request [pass] +library/capabilities.spec.ts › should not crash on page with mp4 @smoke [pass] +library/capabilities.spec.ts › should not crash on showDirectoryPicker [unknown] +library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] +library/capabilities.spec.ts › should play audio @smoke [pass] +library/capabilities.spec.ts › should play video @smoke [pass] +library/capabilities.spec.ts › should play webm video @smoke [pass] +library/capabilities.spec.ts › should respect CSP @smoke [pass] +library/capabilities.spec.ts › should send no Content-Length header for GET requests with a Content-Type [pass] +library/capabilities.spec.ts › should set CloseEvent.wasClean to false when the server terminates a WebSocket connection [pass] +library/capabilities.spec.ts › should support webgl 2 @smoke [pass] +library/capabilities.spec.ts › should support webgl @smoke [pass] +library/capabilities.spec.ts › webkit should define window.safari [unknown] +library/capabilities.spec.ts › window.GestureEvent in WebKit [pass] +library/channels.spec.ts › exposeFunction should not leak [fail] +library/channels.spec.ts › should not generate dispatchers for subresources w/o listeners [pass] +library/channels.spec.ts › should scope CDPSession handles [unknown] +library/channels.spec.ts › should scope browser handles [pass] +library/channels.spec.ts › should scope context handles [pass] +library/channels.spec.ts › should work with the domain module [timeout] +library/chromium/bfcache.spec.ts › bindings should work after restoring from bfcache [fail] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › serviceWorker(), and fromServiceWorker() work [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setExtraHTTPHeaders [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setOffline [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept only serviceworker request, not page [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker importScripts [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker requests (main and within) [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker update requests [unknown] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker [fail] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker (advanced) [fail] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to content-type) of main service worker request [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to redirect) of main service worker request [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report intercepted service worker requests in HAR [timeout] +library/chromium/chromium.spec.ts › Page.route should work with intervention headers [fail] +library/chromium/chromium.spec.ts › http credentials › httpCredentials [timeout] +library/chromium/chromium.spec.ts › serviceWorkers() should return current workers [timeout] +library/chromium/chromium.spec.ts › should close service worker together with the context [timeout] +library/chromium/chromium.spec.ts › should create a worker from a service worker [timeout] +library/chromium/chromium.spec.ts › should create a worker from service worker with noop routing [timeout] +library/chromium/chromium.spec.ts › should emit new service worker on update [timeout] +library/chromium/chromium.spec.ts › should not create a worker from a shared worker [pass] +library/chromium/chromium.spec.ts › should pass args with spaces [fail] +library/chromium/connect-over-cdp.spec.ts › emulate media should not be affected by second connectOverCDP [unknown] +library/chromium/connect-over-cdp.spec.ts › setInputFiles should preserve lastModified timestamp [fail] +library/chromium/connect-over-cdp.spec.ts › should allow tracing over cdp session [fail] +library/chromium/connect-over-cdp.spec.ts › should be able to connect via localhost [fail] +library/chromium/connect-over-cdp.spec.ts › should cleanup artifacts dir after connectOverCDP disconnects due to ws close [fail] +library/chromium/connect-over-cdp.spec.ts › should connect over a ws endpoint [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session twice [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session when passed as a first argument [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to existing page with iframe and navigate [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to existing service workers [fail] +library/chromium/connect-over-cdp.spec.ts › should connect via https [fail] +library/chromium/connect-over-cdp.spec.ts › should connectOverCDP and manage downloads in default context [fail] +library/chromium/connect-over-cdp.spec.ts › should print custom ws close error [fail] +library/chromium/connect-over-cdp.spec.ts › should report all pages in an existing browser [fail] +library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpoint URL JSON webSocketDebuggerUrl is undefined [fail] +library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpointURL returns a non-expected status code [fail] +library/chromium/connect-over-cdp.spec.ts › should return valid browser from context.browser() [fail] +library/chromium/connect-over-cdp.spec.ts › should send default User-Agent header with connect request [timeout] +library/chromium/connect-over-cdp.spec.ts › should send extra headers with connect request [timeout] +library/chromium/connect-over-cdp.spec.ts › should use logger in default context [fail] +library/chromium/connect-over-cdp.spec.ts › should use proxy with connectOverCDP [fail] +library/chromium/css-coverage.spec.ts › should NOT report scripts across navigations [fail] +library/chromium/css-coverage.spec.ts › should ignore injected stylesheets [fail] +library/chromium/css-coverage.spec.ts › should report multiple stylesheets [fail] +library/chromium/css-coverage.spec.ts › should report sourceURLs [fail] +library/chromium/css-coverage.spec.ts › should report stylesheets across navigations [fail] +library/chromium/css-coverage.spec.ts › should report stylesheets that have no coverage [fail] +library/chromium/css-coverage.spec.ts › should work [fail] +library/chromium/css-coverage.spec.ts › should work with a recently loaded stylesheet [fail] +library/chromium/css-coverage.spec.ts › should work with complicated usecases [fail] +library/chromium/css-coverage.spec.ts › should work with media queries [fail] +library/chromium/disable-web-security.spec.ts › test init script w/ --disable-web-security [fail] +library/chromium/disable-web-security.spec.ts › test utility world in popup w/ --disable-web-security [pass] +library/chromium/js-coverage.spec.ts › should NOT report scripts across navigations when enabled [fail] +library/chromium/js-coverage.spec.ts › should ignore eval() scripts by default [fail] +library/chromium/js-coverage.spec.ts › should not hang when there is a debugger statement [fail] +library/chromium/js-coverage.spec.ts › should report multiple scripts [fail] +library/chromium/js-coverage.spec.ts › should report scripts across navigations when disabled [fail] +library/chromium/js-coverage.spec.ts › should report sourceURLs [fail] +library/chromium/js-coverage.spec.ts › should work [fail] +library/chromium/js-coverage.spec.ts › shouldn't ignore eval() scripts if reportAnonymousScripts is true [fail] +library/chromium/launcher.spec.ts › should not create pages automatically [fail] +library/chromium/launcher.spec.ts › should not throw with remote-debugging-port argument [fail] +library/chromium/launcher.spec.ts › should open devtools when "devtools: true" option is given [unknown] +library/chromium/launcher.spec.ts › should return background pages [fail] +library/chromium/launcher.spec.ts › should return background pages when recording video [fail] +library/chromium/launcher.spec.ts › should support request/response events when using backgroundPage() [fail] +library/chromium/launcher.spec.ts › should throw with remote-debugging-pipe argument [fail] +library/chromium/oopif.spec.ts › ElementHandle.boundingBox() should work [fail] +library/chromium/oopif.spec.ts › contentFrame should work [pass] +library/chromium/oopif.spec.ts › should allow cdp sessions on oopifs [fail] +library/chromium/oopif.spec.ts › should be able to click in iframe [pass] +library/chromium/oopif.spec.ts › should click [pass] +library/chromium/oopif.spec.ts › should click a button when it overlays oopif [pass] +library/chromium/oopif.spec.ts › should emit filechooser event for iframe [timeout] +library/chromium/oopif.spec.ts › should emulate media [fail] +library/chromium/oopif.spec.ts › should emulate offline [fail] +library/chromium/oopif.spec.ts › should expose function [fail] +library/chromium/oopif.spec.ts › should get the proper viewport [unknown] +library/chromium/oopif.spec.ts › should handle oopif detach [pass] +library/chromium/oopif.spec.ts › should handle remote -> local -> remote transitions [fail] +library/chromium/oopif.spec.ts › should intercept response body from oopif [fail] +library/chromium/oopif.spec.ts › should load oopif iframes with subresources and route [fail] +library/chromium/oopif.spec.ts › should not throw on exposeFunction when oopif detaches [fail] +library/chromium/oopif.spec.ts › should report google.com frame with headed [fail] +library/chromium/oopif.spec.ts › should report main requests [pass] +library/chromium/oopif.spec.ts › should report oopif frames [pass] +library/chromium/oopif.spec.ts › should respect route [fail] +library/chromium/oopif.spec.ts › should support addInitScript [pass] +library/chromium/oopif.spec.ts › should support context options [fail] +library/chromium/oopif.spec.ts › should support exposeFunction [fail] +library/chromium/oopif.spec.ts › should take screenshot [fail] +library/chromium/session.spec.ts › should be able to detach session [fail] +library/chromium/session.spec.ts › should detach when page closes [fail] +library/chromium/session.spec.ts › should enable and disable domains independently [fail] +library/chromium/session.spec.ts › should not break page.close() [fail] +library/chromium/session.spec.ts › should only accept a page or frame [pass] +library/chromium/session.spec.ts › should reject protocol calls when page closes [fail] +library/chromium/session.spec.ts › should send events [fail] +library/chromium/session.spec.ts › should throw if target is part of main [fail] +library/chromium/session.spec.ts › should throw nice errors [fail] +library/chromium/session.spec.ts › should work [fail] +library/chromium/session.spec.ts › should work with main frame [fail] +library/chromium/session.spec.ts › should work with newBrowserCDPSession [fail] +library/chromium/tracing.spec.ts › should create directories as needed [fail] +library/chromium/tracing.spec.ts › should output a trace [fail] +library/chromium/tracing.spec.ts › should return a buffer [fail] +library/chromium/tracing.spec.ts › should run with custom categories if provided [fail] +library/chromium/tracing.spec.ts › should support a buffer without a path [fail] +library/chromium/tracing.spec.ts › should throw if tracing on two pages [fail] +library/chromium/tracing.spec.ts › should work without options [fail] +library/client-certificates.spec.ts › browser › persistentContext › should pass with matching certificates [fail] +library/client-certificates.spec.ts › browser › persistentContext › validate input [pass] +library/client-certificates.spec.ts › browser › should fail with matching certificates in legacy pfx format [pass] +library/client-certificates.spec.ts › browser › should fail with no client certificates [fail] +library/client-certificates.spec.ts › browser › should fail with self-signed client certificates [fail] +library/client-certificates.spec.ts › browser › should handle TLS renegotiation with client certificates [fail] +library/client-certificates.spec.ts › browser › should handle rejected certificate in handshake with HTTP/2 [pass] +library/client-certificates.spec.ts › browser › should have ignoreHTTPSErrors=false by default [fail] +library/client-certificates.spec.ts › browser › should keep supporting http [fail] +library/client-certificates.spec.ts › browser › should not hang on tls errors during TLS 1.2 handshake [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates and trailing slash [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format when passing as content [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates on context APIRequestContext instance [pass] +library/client-certificates.spec.ts › browser › should pass with matching certificates when passing as content [fail] +library/client-certificates.spec.ts › browser › should return target connection errors when using http2 [fail] +library/client-certificates.spec.ts › browser › should throw a http error if the pfx passphrase is incorect [pass] +library/client-certificates.spec.ts › browser › support http2 [fail] +library/client-certificates.spec.ts › browser › support http2 if the browser only supports http1.1 [unknown] +library/client-certificates.spec.ts › browser › validate input [pass] +library/client-certificates.spec.ts › fetch › pass with trusted client certificates [pass] +library/client-certificates.spec.ts › fetch › pass with trusted client certificates in pfx format [pass] +library/client-certificates.spec.ts › fetch › should fail with matching certificates in legacy pfx format [pass] +library/client-certificates.spec.ts › fetch › should fail with no client certificates provided [pass] +library/client-certificates.spec.ts › fetch › should keep supporting http [pass] +library/client-certificates.spec.ts › fetch › should throw a http error if the pfx passphrase is incorect [pass] +library/client-certificates.spec.ts › fetch › should throw with untrusted client certs [pass] +library/client-certificates.spec.ts › fetch › should work in the browser with request interception [fail] +library/client-certificates.spec.ts › fetch › validate input [pass] +library/clock.spec.ts › Intl API › Creates a RelativeTimeFormat like normal [pass] +library/clock.spec.ts › Intl API › Executes formatRange like normal [pass] +library/clock.spec.ts › Intl API › Executes formatRangeToParts like normal [pass] +library/clock.spec.ts › Intl API › Executes resolvedOptions like normal [pass] +library/clock.spec.ts › Intl API › Executes supportedLocalesOf like normal [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed a timestamp argument that is not first of the month [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed no timestamp and system time is not first of the month [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed a timestamp argument that is first of the month [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed no timestamp and system time is first of the month [pass] +library/clock.spec.ts › cancelAnimationFrame › does not remove interval [pass] +library/clock.spec.ts › cancelAnimationFrame › does not remove timeout [pass] +library/clock.spec.ts › cancelAnimationFrame › ignores null argument [pass] +library/clock.spec.ts › cancelAnimationFrame › removes animation frame [pass] +library/clock.spec.ts › cancelIdleCallback › removes idle callback [pass] +library/clock.spec.ts › clearInterval › ignores null argument [pass] +library/clock.spec.ts › clearInterval › removes interval [pass] +library/clock.spec.ts › clearInterval › removes interval with undefined interval [pass] +library/clock.spec.ts › clearInterval › removes timeout [pass] +library/clock.spec.ts › clearTimeout › ignores null argument [pass] +library/clock.spec.ts › clearTimeout › removes interval [pass] +library/clock.spec.ts › clearTimeout › removes interval with undefined interval [pass] +library/clock.spec.ts › clearTimeout › removes timeout [pass] +library/clock.spec.ts › date › creates Date objects representing clock time [pass] +library/clock.spec.ts › date › creates real Date objects [pass] +library/clock.spec.ts › date › creates regular date when passing a date as RFC 2822 string [pass] +library/clock.spec.ts › date › creates regular date when passing a date as string [pass] +library/clock.spec.ts › date › creates regular date when passing timestamp [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s, ms [pass] +library/clock.spec.ts › date › creates regular date when passing year, month [pass] +library/clock.spec.ts › date › listens to system clock changes [pass] +library/clock.spec.ts › date › listens to ticking clock [pass] +library/clock.spec.ts › date › mirrors UTC method [pass] +library/clock.spec.ts › date › mirrors native Date.prototype [pass] +library/clock.spec.ts › date › mirrors parse method [pass] +library/clock.spec.ts › date › mirrors toUTCString method [pass] +library/clock.spec.ts › date › provides date constructor [pass] +library/clock.spec.ts › date › returns clock.now() [pass] +library/clock.spec.ts › date › returns date as string representing clock time [pass] +library/clock.spec.ts › date › returns date as string when called as function [pass] +library/clock.spec.ts › date › returns date as string when calling with arguments [pass] +library/clock.spec.ts › date › returns date as string when calling with timestamp [pass] +library/clock.spec.ts › date › supports now method if present [pass] +library/clock.spec.ts › fastForward › handles multiple pending timers and types [pass] +library/clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +library/clock.spec.ts › fastForward › pushes back execution time for skipped timers [pass] +library/clock.spec.ts › pauseAt › fire target timers [pass] +library/clock.spec.ts › pauseAt › pause at target time [pass] +library/clock.spec.ts › pauseAt › returns consumed clicks [pass] +library/clock.spec.ts › performance.now() › should listen to multiple ticks in performance.now [pass] +library/clock.spec.ts › performance.now() › should run along with clock.tick [pass] +library/clock.spec.ts › performance.now() › should run with ticks with timers set [pass] +library/clock.spec.ts › performance.now() › should start at 0 [pass] +library/clock.spec.ts › requestAnimationFrame › returns numeric id or object with numeric id [pass] +library/clock.spec.ts › requestAnimationFrame › returns unique id [pass] +library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() even when performance unavailable [pass] +library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() when available [pass] +library/clock.spec.ts › requestAnimationFrame › should call callback once [pass] +library/clock.spec.ts › requestAnimationFrame › should properly schedule callback for 3rd frame [pass] +library/clock.spec.ts › requestAnimationFrame › should run every 16ms [pass] +library/clock.spec.ts › requestAnimationFrame › should schedule for next frame if on current frame [pass] +library/clock.spec.ts › requestAnimationFrame › should schedule two callbacks before the next frame at the same time [pass] +library/clock.spec.ts › requestAnimationFrame › throws if no arguments [pass] +library/clock.spec.ts › requestIdleCallback › doesn't runs if there are any timers and no timeout option [pass] +library/clock.spec.ts › requestIdleCallback › returns numeric id [pass] +library/clock.spec.ts › requestIdleCallback › returns unique id [pass] +library/clock.spec.ts › requestIdleCallback › runs after all timers [pass] +library/clock.spec.ts › requestIdleCallback › runs no later than timeout option even if there are any timers [pass] +library/clock.spec.ts › requestIdleCallback › throws if no arguments [pass] +library/clock.spec.ts › runFor › calls function with global object or null (strict mode) as this [pass] +library/clock.spec.ts › runFor › creates updated Date while ticking [pass] +library/clock.spec.ts › runFor › creates updated Date while ticking promises [pass] +library/clock.spec.ts › runFor › does not fire canceled intervals [pass] +library/clock.spec.ts › runFor › does not fire intervals canceled in a promise [pass] +library/clock.spec.ts › runFor › does not silently catch errors [pass] +library/clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +library/clock.spec.ts › runFor › fires nested setTimeout calls in user-created promises properly [pass] +library/clock.spec.ts › runFor › fires nested setTimeout calls properly [pass] +library/clock.spec.ts › runFor › fires promise timers in correct order [pass] +library/clock.spec.ts › runFor › fires timer in intervals of "13" [pass] +library/clock.spec.ts › runFor › fires timer in intervals of 13 [pass] +library/clock.spec.ts › runFor › fires timers in correct order [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes 2 [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes in promises [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown 2 [pass] +library/clock.spec.ts › runFor › mini integration test [pass] +library/clock.spec.ts › runFor › should settle chained user-created promises [pass] +library/clock.spec.ts › runFor › should settle local nested promises before calling timeouts [pass] +library/clock.spec.ts › runFor › should settle local promises before calling timeouts [pass] +library/clock.spec.ts › runFor › should settle multiple user-created promises [pass] +library/clock.spec.ts › runFor › should settle nested user-created promises [pass] +library/clock.spec.ts › runFor › should settle user-created promises [pass] +library/clock.spec.ts › runFor › should settle user-created promises before calling more timeouts [pass] +library/clock.spec.ts › runFor › should settle user-created promises even if some throw [pass] +library/clock.spec.ts › runFor › throws for negative minutes [pass] +library/clock.spec.ts › runFor › throws on negative ticks [pass] +library/clock.spec.ts › runFor › triggers after sufficient delay [pass] +library/clock.spec.ts › runFor › triggers even when some throw [pass] +library/clock.spec.ts › runFor › triggers immediately without specified delay [pass] +library/clock.spec.ts › runFor › triggers in the order scheduled [pass] +library/clock.spec.ts › runFor › triggers multiple simultaneous timers [pass] +library/clock.spec.ts › runFor › triggers multiple simultaneous timers with zero callAt [pass] +library/clock.spec.ts › runFor › triggers simultaneous timers [pass] +library/clock.spec.ts › runFor › triggers timeouts and intervals in the order scheduled [pass] +library/clock.spec.ts › runFor › waits after setTimeout was called [pass] +library/clock.spec.ts › setInterval › does not schedule recurring timeout when cleared [pass] +library/clock.spec.ts › setInterval › does not throw if |undefined| or |null| is passed as a callback [pass] +library/clock.spec.ts › setInterval › is not influenced by backward system clock changes [pass] +library/clock.spec.ts › setInterval › is not influenced by forward system clock changes [pass] +library/clock.spec.ts › setInterval › passes setTimeout parameters [pass] +library/clock.spec.ts › setInterval › returns numeric id or object with numeric id [pass] +library/clock.spec.ts › setInterval › returns unique id [pass] +library/clock.spec.ts › setInterval › schedules recurring timeout [pass] +library/clock.spec.ts › setInterval › throws if no arguments [pass] +library/clock.spec.ts › setTimeout › calls correct timeout on recursive tick [pass] +library/clock.spec.ts › setTimeout › does not depend on this [pass] +library/clock.spec.ts › setTimeout › does not throw if |undefined| or |null| is passed as a callback [pass] +library/clock.spec.ts › setTimeout › is not influenced by backward system clock changes [pass] +library/clock.spec.ts › setTimeout › is not influenced by forward system clock changes [pass] +library/clock.spec.ts › setTimeout › parses no-numeric string times [pass] +library/clock.spec.ts › setTimeout › parses numeric string times [pass] +library/clock.spec.ts › setTimeout › passes setTimeout parameters [pass] +library/clock.spec.ts › setTimeout › returns numeric id or object with numeric id [pass] +library/clock.spec.ts › setTimeout › returns unique id [pass] +library/clock.spec.ts › setTimeout › sets timers on instance [pass] +library/clock.spec.ts › setTimeout › starts id from a large number [pass] +library/clock.spec.ts › setTimeout › throws if no arguments [pass] +library/clock.spec.ts › setTimeout › use of eval when not in node › evals non-function callbacks [pass] +library/clock.spec.ts › setTimeout › use of eval when not in node › only evals on global scope [pass] +library/clock.spec.ts › stubTimers › deletes global property on uninstall if it was inherited onto the global object [unknown] +library/clock.spec.ts › stubTimers › does not fake methods not provided [pass] +library/clock.spec.ts › stubTimers › fake Date constructor should mirror Date's properties [pass] +library/clock.spec.ts › stubTimers › fakes Date constructor [pass] +library/clock.spec.ts › stubTimers › fakes provided methods [pass] +library/clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +library/clock.spec.ts › stubTimers › mirrors custom Date properties [pass] +library/clock.spec.ts › stubTimers › replace Event.prototype.timeStamp [pass] +library/clock.spec.ts › stubTimers › replaces global clearInterval [pass] +library/clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +library/clock.spec.ts › stubTimers › replaces global performance.now [pass] +library/clock.spec.ts › stubTimers › replaces global setInterval [pass] +library/clock.spec.ts › stubTimers › replaces global setTimeout [pass] +library/clock.spec.ts › stubTimers › resets faked methods [pass] +library/clock.spec.ts › stubTimers › returns clock object [pass] +library/clock.spec.ts › stubTimers › sets initial timestamp [pass] +library/clock.spec.ts › stubTimers › should let performance.mark still be callable after install() (#136) [pass] +library/clock.spec.ts › stubTimers › should not alter the global performance properties and methods [pass] +library/clock.spec.ts › stubTimers › should replace the getEntries, getEntriesByX methods with noops that return [] [pass] +library/clock.spec.ts › stubTimers › takes an object parameter [pass] +library/clock.spec.ts › stubTimers › uninstalls Date constructor [pass] +library/clock.spec.ts › stubTimers › uninstalls global performance.now [pass] +library/clock.spec.ts › works with concurrent runFor calls [pass] +library/clock.spec.ts › works with slow setTimeout in busy embedder [pass] +library/clock.spec.ts › works with slow setTimeout in busy embedder when not paused [pass] +library/component-parser.spec.ts › should escape [pass] +library/component-parser.spec.ts › should parse [pass] +library/component-parser.spec.ts › should parse all operators [pass] +library/component-parser.spec.ts › should parse bool [pass] +library/component-parser.spec.ts › should parse float values [pass] +library/component-parser.spec.ts › should parse identifiers [pass] +library/component-parser.spec.ts › should parse int values [pass] +library/component-parser.spec.ts › should parse regex [pass] +library/component-parser.spec.ts › should parse short attributes [pass] +library/component-parser.spec.ts › should parse unquoted string [pass] +library/component-parser.spec.ts › should throw on malformed selector [pass] +library/component-parser.spec.ts › should tolerate spacing [pass] +library/css-parser.spec.ts › should parse css [pass] +library/css-parser.spec.ts › should throw on malformed css [pass] +library/debug-controller.spec.ts › should highlight all [fail] +library/debug-controller.spec.ts › should navigate all [fail] +library/debug-controller.spec.ts › should pick element [fail] +library/debug-controller.spec.ts › should record [fail] +library/debug-controller.spec.ts › should record custom data-testid [fail] +library/debug-controller.spec.ts › should report pages [fail] +library/debug-controller.spec.ts › should reset for reuse [fail] +library/debug-controller.spec.ts › should reset routes before reuse [fail] +library/defaultbrowsercontext-1.spec.ts › context.addCookies() should work [fail] +library/defaultbrowsercontext-1.spec.ts › context.clearCookies() should work [fail] +library/defaultbrowsercontext-1.spec.ts › context.cookies() should work @smoke [fail] +library/defaultbrowsercontext-1.spec.ts › should support acceptDownloads option [fail] +library/defaultbrowsercontext-1.spec.ts › should support bypassCSP option [fail] +library/defaultbrowsercontext-1.spec.ts › should support deviceScaleFactor option [fail] +library/defaultbrowsercontext-1.spec.ts › should support httpCredentials option [fail] +library/defaultbrowsercontext-1.spec.ts › should support javascriptEnabled option [fail] +library/defaultbrowsercontext-1.spec.ts › should support offline option [fail] +library/defaultbrowsercontext-1.spec.ts › should support userAgent option [fail] +library/defaultbrowsercontext-1.spec.ts › should support viewport option [fail] +library/defaultbrowsercontext-1.spec.ts › should(not) block third party cookies [fail] +library/defaultbrowsercontext-2.spec.ts › coverage should work [unknown] +library/defaultbrowsercontext-2.spec.ts › should accept userDataDir [fail] +library/defaultbrowsercontext-2.spec.ts › should connect to a browser with the default page [fail] +library/defaultbrowsercontext-2.spec.ts › should create userDataDir if it does not exist [fail] +library/defaultbrowsercontext-2.spec.ts › should fire close event for a persistent context [fail] +library/defaultbrowsercontext-2.spec.ts › should handle exception [timeout] +library/defaultbrowsercontext-2.spec.ts › should handle timeout [pass] +library/defaultbrowsercontext-2.spec.ts › should have default URL when launching browser [fail] +library/defaultbrowsercontext-2.spec.ts › should have passed URL when launching with ignoreDefaultArgs: true [fail] +library/defaultbrowsercontext-2.spec.ts › should respect selectors [fail] +library/defaultbrowsercontext-2.spec.ts › should restore state from userDataDir [fail] +library/defaultbrowsercontext-2.spec.ts › should support colorScheme option [fail] +library/defaultbrowsercontext-2.spec.ts › should support extraHTTPHeaders option [fail] +library/defaultbrowsercontext-2.spec.ts › should support forcedColors option [fail] +library/defaultbrowsercontext-2.spec.ts › should support geolocation and permissions options [fail] +library/defaultbrowsercontext-2.spec.ts › should support har option [fail] +library/defaultbrowsercontext-2.spec.ts › should support hasTouch option [fail] +library/defaultbrowsercontext-2.spec.ts › should support ignoreHTTPSErrors option [fail] +library/defaultbrowsercontext-2.spec.ts › should support locale option [fail] +library/defaultbrowsercontext-2.spec.ts › should support reducedMotion option [fail] +library/defaultbrowsercontext-2.spec.ts › should support timezoneId option [fail] +library/defaultbrowsercontext-2.spec.ts › should throw if page argument is passed [pass] +library/defaultbrowsercontext-2.spec.ts › should work in persistent context [fail] +library/defaultbrowsercontext-2.spec.ts › user agent is up to date [fail] +library/download.spec.ts › download event › should be able to cancel pending downloads [timeout] +library/download.spec.ts › download event › should close the context without awaiting the download [timeout] +library/download.spec.ts › download event › should close the context without awaiting the failed download [unknown] +library/download.spec.ts › download event › should create subdirectories when saving to non-existent user-specified path [timeout] +library/download.spec.ts › download event › should delete downloads on browser gone [timeout] +library/download.spec.ts › download event › should delete downloads on context destruction [timeout] +library/download.spec.ts › download event › should delete file [timeout] +library/download.spec.ts › download event › should download large binary.zip [timeout] +library/download.spec.ts › download event › should emit download event from nested iframes [timeout] +library/download.spec.ts › download event › should error when saving after deletion [timeout] +library/download.spec.ts › download event › should error when saving with downloads disabled [timeout] +library/download.spec.ts › download event › should expose stream [timeout] +library/download.spec.ts › download event › should not fail explicitly to cancel a download even if that is already finished [timeout] +library/download.spec.ts › download event › should report alt-click downloads [timeout] +library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Blobs [timeout] +library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Files [timeout] +library/download.spec.ts › download event › should report download when navigation turns into download @smoke [timeout] +library/download.spec.ts › download event › should report downloads for download attribute [timeout] +library/download.spec.ts › download event › should report downloads with acceptDownloads: false [timeout] +library/download.spec.ts › download event › should report downloads with acceptDownloads: true [timeout] +library/download.spec.ts › download event › should report downloads with interception [fail] +library/download.spec.ts › download event › should report new window downloads [timeout] +library/download.spec.ts › download event › should report non-navigation downloads [timeout] +library/download.spec.ts › download event › should report proper download url when download is from download attribute [timeout] +library/download.spec.ts › download event › should save to overwritten filepath [timeout] +library/download.spec.ts › download event › should save to two different paths with multiple saveAs calls [timeout] +library/download.spec.ts › download event › should save to user-specified path without updating original path [timeout] +library/download.spec.ts › download event › should throw if browser dies [timeout] +library/download.spec.ts › download event › should work with Cross-Origin-Opener-Policy [timeout] +library/download.spec.ts › should be able to download a PDF file [timeout] +library/download.spec.ts › should be able to download a inline PDF file via navigation [timeout] +library/download.spec.ts › should be able to download a inline PDF file via response interception [fail] +library/download.spec.ts › should convert navigation to a resource with unsupported mime type into download [timeout] +library/download.spec.ts › should download even if there is no "attachment" value [timeout] +library/download.spec.ts › should download links with data url [timeout] +library/download.spec.ts › should download successfully when routing [timeout] +library/download.spec.ts › should save to user-specified path [timeout] +library/downloads-path.spec.ts › downloads path › should accept downloads in persistent context [fail] +library/downloads-path.spec.ts › downloads path › should delete downloads when context closes [timeout] +library/downloads-path.spec.ts › downloads path › should delete downloads when persistent context closes [fail] +library/downloads-path.spec.ts › downloads path › should keep downloadsPath folder [timeout] +library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder [timeout] +library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder with a relative path [timeout] +library/emulation-focus.spec.ts › should change document.activeElement [pass] +library/emulation-focus.spec.ts › should change focused iframe [pass] +library/emulation-focus.spec.ts › should focus popups by default [fail] +library/emulation-focus.spec.ts › should focus with more than one page/context [pass] +library/emulation-focus.spec.ts › should not affect mouse event target page [pass] +library/emulation-focus.spec.ts › should not affect screenshots [fail] +library/emulation-focus.spec.ts › should not fire blur events when interacting with more than one page/context [pass] +library/emulation-focus.spec.ts › should provide target for keyboard events [pass] +library/emulation-focus.spec.ts › should think that all pages are focused @smoke [pass] +library/emulation-focus.spec.ts › should think that it is focused by default [pass] +library/emulation-focus.spec.ts › should trigger hover state concurrently [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › Listener order [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › listener type check [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › set max listeners test [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › should work [pass] +library/events/check-listener-leaks.spec.ts › _maxListeners still has precedence over defaultMaxListeners [pass] +library/events/check-listener-leaks.spec.ts › defaultMaxListeners [pass] +library/events/check-listener-leaks.spec.ts › process-wide [pass] +library/events/events-list.spec.ts › EventEmitter › should maintain event names correctly [pass] +library/events/listener-count.spec.ts › Listener count test [pass] +library/events/listeners-side-effects.spec.ts › listeners empty check [pass] +library/events/listeners.spec.ts › Array copy modification does not modify orig [pass] +library/events/listeners.spec.ts › EventEmitter listeners with one listener [pass] +library/events/listeners.spec.ts › EventEmitter with no members [pass] +library/events/listeners.spec.ts › Modify array copy after multiple adds [pass] +library/events/listeners.spec.ts › listeners and once [pass] +library/events/listeners.spec.ts › listeners on prototype [pass] +library/events/listeners.spec.ts › listeners with conflicting types [pass] +library/events/listeners.spec.ts › raw listeners [pass] +library/events/listeners.spec.ts › raw listeners order [pass] +library/events/max-listeners.spec.ts › emit maxListeners on e [pass] +library/events/method-names.spec.ts › EventEmitter prototype test [pass] +library/events/modify-in-emit.spec.ts › add and remove listeners [pass] +library/events/modify-in-emit.spec.ts › removing callbacks in emit [pass] +library/events/num-args.spec.ts › should work [pass] +library/events/once.spec.ts › once() has different code paths based on the number of arguments being emitted [pass] +library/events/once.spec.ts › should work [pass] +library/events/prepend.spec.ts › EventEmitter functionality [pass] +library/events/prepend.spec.ts › Verify that the listener must be a function [pass] +library/events/remove-all-listeners-wait.spec.ts › should not throw with ignoreErrors [pass] +library/events/remove-all-listeners-wait.spec.ts › should wait [pass] +library/events/remove-all-listeners-wait.spec.ts › should wait all [pass] +library/events/remove-all-listeners-wait.spec.ts › wait should throw [pass] +library/events/remove-all-listeners.spec.ts › listener count after removeAllListeners [pass] +library/events/remove-all-listeners.spec.ts › listeners [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners on undefined _events [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners removes all listeners [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners returns EventEmitter [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners with no event type [pass] +library/events/remove-listeners.spec.ts › Eighth test [pass] +library/events/remove-listeners.spec.ts › Fifth test [pass] +library/events/remove-listeners.spec.ts › First test [pass] +library/events/remove-listeners.spec.ts › Fourth test [pass] +library/events/remove-listeners.spec.ts › Ninth test [pass] +library/events/remove-listeners.spec.ts › Second test [pass] +library/events/remove-listeners.spec.ts › Seventh test [pass] +library/events/remove-listeners.spec.ts › Sixth test [pass] +library/events/remove-listeners.spec.ts › Tenth test [pass] +library/events/remove-listeners.spec.ts › Third test [pass] +library/events/set-max-listeners-side-effects.spec.ts › set max listeners test [pass] +library/events/special-event-names.spec.ts › should support special event names [pass] +library/events/subclass.spec.ts › MyEE2 instance [pass] +library/events/subclass.spec.ts › myee instance [pass] +library/events/symbols.spec.ts › should support symbols [pass] +library/favicon.spec.ts › should load svg favicon with prefer-color-scheme [unknown] +library/fetch-proxy.spec.ts › context request should pick up proxy credentials [pass] +library/fetch-proxy.spec.ts › global request should pick up proxy credentials [pass] +library/fetch-proxy.spec.ts › should support proxy.bypass [pass] +library/fetch-proxy.spec.ts › should use socks proxy [pass] +library/fetch-proxy.spec.ts › should work with context level proxy [pass] +library/firefox/launcher.spec.ts › should pass firefox user preferences [fail] +library/firefox/launcher.spec.ts › should pass firefox user preferences in persistent [fail] +library/geolocation.spec.ts › should isolate contexts [timeout] +library/geolocation.spec.ts › should not modify passed default options object [pass] +library/geolocation.spec.ts › should throw when invalid longitude [fail] +library/geolocation.spec.ts › should throw with missing latitude [pass] +library/geolocation.spec.ts › should throw with missing longitude in default options [pass] +library/geolocation.spec.ts › should use context options [timeout] +library/geolocation.spec.ts › should use context options for popup [timeout] +library/geolocation.spec.ts › should work @smoke [timeout] +library/geolocation.spec.ts › watchPosition should be notified [timeout] +library/global-fetch-cookie.spec.ts › should do case-insensitive match of cookie domain [pass] +library/global-fetch-cookie.spec.ts › should do case-insensitive match of request domain [pass] +library/global-fetch-cookie.spec.ts › should export cookies to storage state [pass] +library/global-fetch-cookie.spec.ts › should filter outgoing cookies by domain [pass] +library/global-fetch-cookie.spec.ts › should filter outgoing cookies by path [pass] +library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header [pass] +library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header even if it expired [pass] +library/global-fetch-cookie.spec.ts › should preserve local storage on import/export of storage state [pass] +library/global-fetch-cookie.spec.ts › should remove cookie with expires far in the past [pass] +library/global-fetch-cookie.spec.ts › should remove cookie with negative max-age [pass] +library/global-fetch-cookie.spec.ts › should remove expired cookies [pass] +library/global-fetch-cookie.spec.ts › should send cookies from storage state [pass] +library/global-fetch-cookie.spec.ts › should send not expired cookies [pass] +library/global-fetch-cookie.spec.ts › should send secure cookie over http for localhost [pass] +library/global-fetch-cookie.spec.ts › should send secure cookie over https [pass] +library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header [pass] +library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header even if it contains equal signs [pass] +library/global-fetch-cookie.spec.ts › should work with empty storage state [pass] +library/global-fetch-cookie.spec.ts › storage state should round-trip through file [pass] +library/global-fetch.spec.ts › delete should work @smoke [pass] +library/global-fetch.spec.ts › fetch should work @smoke [pass] +library/global-fetch.spec.ts › get should work @smoke [pass] +library/global-fetch.spec.ts › head should work @smoke [pass] +library/global-fetch.spec.ts › patch should work @smoke [pass] +library/global-fetch.spec.ts › post should work @smoke [pass] +library/global-fetch.spec.ts › put should work @smoke [pass] +library/global-fetch.spec.ts › should abort redirected requests when context is disposed [pass] +library/global-fetch.spec.ts › should abort requests when context is disposed [pass] +library/global-fetch.spec.ts › should accept already serialized data as Buffer when content-type is application/json [pass] +library/global-fetch.spec.ts › should be able to construct with context options [pass] +library/global-fetch.spec.ts › should dispose global request [pass] +library/global-fetch.spec.ts › should have nice toString [pass] +library/global-fetch.spec.ts › should json stringify array body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify bool (false) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify bool body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify literal string undefined body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify null body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify number (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify number body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify object body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify string (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify string body when content-type is application/json [pass] +library/global-fetch.spec.ts › should keep headers capitalization [pass] +library/global-fetch.spec.ts › should not double stringify array body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify bool (false) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify bool body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify literal string undefined body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify null body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify number (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify number body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify object body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify string (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify string body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not fail on empty body with encoding [pass] +library/global-fetch.spec.ts › should not follow redirects when maxRedirects is set to 0 [pass] +library/global-fetch.spec.ts › should propagate extra http headers with redirects [pass] +library/global-fetch.spec.ts › should propagate ignoreHTTPSErrors on redirects [pass] +library/global-fetch.spec.ts › should remove content-length from redirected post requests [pass] +library/global-fetch.spec.ts › should resolve url relative to global baseURL option [pass] +library/global-fetch.spec.ts › should retry ECONNRESET [pass] +library/global-fetch.spec.ts › should return body for failing requests [pass] +library/global-fetch.spec.ts › should return empty body [pass] +library/global-fetch.spec.ts › should return error with correct credentials and mismatching hostname [pass] +library/global-fetch.spec.ts › should return error with correct credentials and mismatching port [pass] +library/global-fetch.spec.ts › should return error with correct credentials and mismatching scheme [pass] +library/global-fetch.spec.ts › should return error with wrong credentials [pass] +library/global-fetch.spec.ts › should serialize post data on the client [pass] +library/global-fetch.spec.ts › should set playwright as user-agent [pass] +library/global-fetch.spec.ts › should support HTTPCredentials.send [pass] +library/global-fetch.spec.ts › should support WWW-Authenticate: Basic [pass] +library/global-fetch.spec.ts › should support global httpCredentials option [pass] +library/global-fetch.spec.ts › should support global ignoreHTTPSErrors option [pass] +library/global-fetch.spec.ts › should support global timeout option [pass] +library/global-fetch.spec.ts › should support global userAgent option [pass] +library/global-fetch.spec.ts › should throw after dispose [pass] +library/global-fetch.spec.ts › should throw an error when maxRedirects is exceeded [pass] +library/global-fetch.spec.ts › should throw an error when maxRedirects is less than 0 [pass] +library/global-fetch.spec.ts › should work with correct credentials and matching origin [pass] +library/global-fetch.spec.ts › should work with correct credentials and matching origin case insensitive [pass] +library/har.spec.ts › should attach content [fail] +library/har.spec.ts › should calculate time [pass] +library/har.spec.ts › should contain http2 for http2 requests [fail] +library/har.spec.ts › should filter by glob [pass] +library/har.spec.ts › should filter by regexp [pass] +library/har.spec.ts › should filter favicon and favicon redirects [unknown] +library/har.spec.ts › should have -1 _transferSize when its a failed request [pass] +library/har.spec.ts › should have browser [fail] +library/har.spec.ts › should have connection details [fail] +library/har.spec.ts › should have connection details for failed requests [fail] +library/har.spec.ts › should have connection details for redirects [fail] +library/har.spec.ts › should have different hars for concurrent contexts [pass] +library/har.spec.ts › should have pages [pass] +library/har.spec.ts › should have pages in persistent context [fail] +library/har.spec.ts › should have popup requests [pass] +library/har.spec.ts › should have security details [fail] +library/har.spec.ts › should have version and creator [pass] +library/har.spec.ts › should include API request [pass] +library/har.spec.ts › should include binary postData [fail] +library/har.spec.ts › should include content @smoke [fail] +library/har.spec.ts › should include cookies [pass] +library/har.spec.ts › should include form params [fail] +library/har.spec.ts › should include postData [fail] +library/har.spec.ts › should include query params [pass] +library/har.spec.ts › should include redirectURL [pass] +library/har.spec.ts › should include request [pass] +library/har.spec.ts › should include response [pass] +library/har.spec.ts › should include secure set-cookies [fail] +library/har.spec.ts › should include set-cookies [fail] +library/har.spec.ts › should include set-cookies with comma [fail] +library/har.spec.ts › should include sizes [fail] +library/har.spec.ts › should not contain internal pages [pass] +library/har.spec.ts › should not hang on resources served from cache [pass] +library/har.spec.ts › should not hang on slow chunked response [fail] +library/har.spec.ts › should omit content [pass] +library/har.spec.ts › should omit content legacy [pass] +library/har.spec.ts › should record failed request headers [pass] +library/har.spec.ts › should record failed request overrides [fail] +library/har.spec.ts › should record request overrides [fail] +library/har.spec.ts › should report the correct _transferSize with PNG files [fail] +library/har.spec.ts › should report the correct request body size [pass] +library/har.spec.ts › should report the correct request body size when the bodySize is 0 [pass] +library/har.spec.ts › should report the correct response body size when the bodySize is 0 [pass] +library/har.spec.ts › should return receive time [fail] +library/har.spec.ts › should return security details directly from response [fail] +library/har.spec.ts › should return server address directly from response [fail] +library/har.spec.ts › should skip invalid Expires [pass] +library/har.spec.ts › should throw without path [pass] +library/har.spec.ts › should use attach mode for zip extension [fail] +library/har.spec.ts › should work with gzip compression [fail] +library/headful.spec.ts › Page.bringToFront should work [pass] +library/headful.spec.ts › headless and headful should use same default fonts [fail] +library/headful.spec.ts › should click background tab [timeout] +library/headful.spec.ts › should click bottom row w/ infobar in OOPIF [fail] +library/headful.spec.ts › should click in OOPIF [fail] +library/headful.spec.ts › should click when viewport size is larger than screen [pass] +library/headful.spec.ts › should close browser after context menu was triggered [pass] +library/headful.spec.ts › should close browser with beforeunload page [fail] +library/headful.spec.ts › should close browsercontext with pending beforeunload dialog [timeout] +library/headful.spec.ts › should dispatch click events to oversized viewports [pass] +library/headful.spec.ts › should have default url when launching browser @smoke [fail] +library/headful.spec.ts › should not block third party SameSite=None cookies [fail] +library/headful.spec.ts › should not crash when creating second context [pass] +library/headful.spec.ts › should not override viewport size when passed null [fail] +library/headful.spec.ts › should(not) block third party cookies [pass] +library/hit-target.spec.ts › should block all events when hit target is wrong [pass] +library/hit-target.spec.ts › should block all events when hit target is wrong and element detaches [pass] +library/hit-target.spec.ts › should block click when mousedown fails [pass] +library/hit-target.spec.ts › should click an element inside closed shadow root [pass] +library/hit-target.spec.ts › should click in custom element [pass] +library/hit-target.spec.ts › should click in iframe with padding [pass] +library/hit-target.spec.ts › should click in iframe with padding 2 [pass] +library/hit-target.spec.ts › should click into frame inside closed shadow root [fail] +library/hit-target.spec.ts › should click the button again after document.write [pass] +library/hit-target.spec.ts › should click when element detaches in mousedown [pass] +library/hit-target.spec.ts › should detect overlaid element in a transformed iframe [fail] +library/hit-target.spec.ts › should detect overlay from another shadow root [pass] +library/hit-target.spec.ts › should not block programmatic events [pass] +library/hit-target.spec.ts › should not click an element overlaying iframe with the target [pass] +library/hit-target.spec.ts › should not click iframe overlaying the target [pass] +library/hit-target.spec.ts › should work with block inside inline [pass] +library/hit-target.spec.ts › should work with block inside inline in shadow dom [pass] +library/hit-target.spec.ts › should work with block-block-block inside inline-inline [pass] +library/hit-target.spec.ts › should work with drag and drop that moves the element under cursor [pass] +library/hit-target.spec.ts › should work with mui select [pass] +library/ignorehttpserrors.spec.ts › serviceWorker should intercept document request [fail] +library/ignorehttpserrors.spec.ts › should fail with WebSocket if not ignored [pass] +library/ignorehttpserrors.spec.ts › should isolate contexts [fail] +library/ignorehttpserrors.spec.ts › should work @smoke [fail] +library/ignorehttpserrors.spec.ts › should work with WebSocket [fail] +library/ignorehttpserrors.spec.ts › should work with mixed content [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should assert navigation [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should await popup [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should check [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should check a radio button [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should check with keyboard [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should click [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should click after same-document navigation [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should click button with nested div [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should emit single keyup on ArrowDown [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [contentEditable] [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill japanese text [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea with new lines at the end [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore AltGraph [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore programmatic events [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should make a positioned click on a canvas [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should middle click [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should not target selector preview by text regexp [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should not throw csp directive violation errors [pass] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should press [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record ArrowDown [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after performAction [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after recordAction [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record slider [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should select [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should select with size attribute [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should uncheck [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should update selected element after pressing Tab [timeout] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should work with TrustedTypes [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › click should emit events in order [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should --save-trace [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should check input with chaining id [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should clear files [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain close page [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain open page [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain second page [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should download files [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should fill tricky characters [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle dialogs [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle history.postData [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should not clash pages [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should not lead to an error if html gets clicked [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should record navigations after identical pushState [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should record open in a new tab with url [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should reset hover model on action when element detaches [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should save assets via SIGINT [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should update active model on action [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should update hover model on action [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload a single file [timeout] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload multiple files [timeout] +library/inspector/cli-codegen-2.spec.ts › should --test-id-attribute [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled input [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled select [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert visibility [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.first [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.nth [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume contextmenu events, despite a custom context menu [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume pointer events [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with id attribute [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with name attribute [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with special characters in name attribute [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with testId [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with title attribute [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByAltText [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel without regex [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByPlaceholder [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByTestId [timeout] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate role locators undef frame locators [timeout] +library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in mstest if no options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in nunit if no options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in mstest [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in nunit [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in mstest if options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in nunit if options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print load/save storageState [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-csharp.spec.ts › should work with --save-har [fail] +library/inspector/cli-codegen-java.spec.ts › should print a valid basic program in junit [fail] +library/inspector/cli-codegen-java.spec.ts › should print load/save storage_state [fail] +library/inspector/cli-codegen-java.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-java.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-java.spec.ts › should print the correct imports in junit [fail] +library/inspector/cli-codegen-java.spec.ts › should work with --save-har [fail] +library/inspector/cli-codegen-javascript.spec.ts › should print load/save storageState [fail] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-javascript.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-pytest.spec.ts › should print the correct context options when using a device and lang [unknown] +library/inspector/cli-codegen-pytest.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-pytest.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-python-async.spec.ts › should print load/save storage_state [fail] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-python-async.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-python-async.spec.ts › should work with --save-har [fail] +library/inspector/cli-codegen-python.spec.ts › should print load/save storage_state [fail] +library/inspector/cli-codegen-python.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-python.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-python.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-test.spec.ts › should print load storageState [fail] +library/inspector/cli-codegen-test.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-test.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-test.spec.ts › should work with --save-har [fail] +library/inspector/console-api.spec.ts › expected properties on playwright object [pass] +library/inspector/console-api.spec.ts › should support locator.and() [pass] +library/inspector/console-api.spec.ts › should support locator.or() [pass] +library/inspector/console-api.spec.ts › should support playwright.$, playwright.$$ [pass] +library/inspector/console-api.spec.ts › should support playwright.getBy* [pass] +library/inspector/console-api.spec.ts › should support playwright.locator({ has }) [pass] +library/inspector/console-api.spec.ts › should support playwright.locator({ hasNot }) [pass] +library/inspector/console-api.spec.ts › should support playwright.locator.value [pass] +library/inspector/console-api.spec.ts › should support playwright.locator.values [pass] +library/inspector/console-api.spec.ts › should support playwright.selector [pass] +library/inspector/pause.spec.ts › pause › should hide internal calls [pass] +library/inspector/pause.spec.ts › pause › should highlight locators with custom testId [timeout] +library/inspector/pause.spec.ts › pause › should highlight on explore [timeout] +library/inspector/pause.spec.ts › pause › should highlight on explore (csharp) [timeout] +library/inspector/pause.spec.ts › pause › should highlight pointer, only in main frame [timeout] +library/inspector/pause.spec.ts › pause › should highlight waitForEvent [pass] +library/inspector/pause.spec.ts › pause › should not prevent key events [pass] +library/inspector/pause.spec.ts › pause › should pause after a navigation [pass] +library/inspector/pause.spec.ts › pause › should pause and resume the script [pass] +library/inspector/pause.spec.ts › pause › should pause and resume the script with keyboard shortcut [pass] +library/inspector/pause.spec.ts › pause › should pause on context close [pass] +library/inspector/pause.spec.ts › pause › should pause on next pause [pass] +library/inspector/pause.spec.ts › pause › should pause on page close [pass] +library/inspector/pause.spec.ts › pause › should populate log [pass] +library/inspector/pause.spec.ts › pause › should populate log with error [fail] +library/inspector/pause.spec.ts › pause › should populate log with error in waitForEvent [pass] +library/inspector/pause.spec.ts › pause › should populate log with waitForEvent [pass] +library/inspector/pause.spec.ts › pause › should resume from console [fail] +library/inspector/pause.spec.ts › pause › should show expect.toHaveText [pass] +library/inspector/pause.spec.ts › pause › should show source [pass] +library/inspector/pause.spec.ts › pause › should skip input when resuming [pass] +library/inspector/pause.spec.ts › pause › should step [pass] +library/inspector/pause.spec.ts › pause › should step with keyboard shortcut [pass] +library/inspector/pause.spec.ts › should not reset timeouts [pass] +library/inspector/pause.spec.ts › should resume when closing inspector [pass] +library/launcher.spec.ts › should have a devices object [pass] +library/launcher.spec.ts › should have an errors object [pass] +library/launcher.spec.ts › should kill browser process on timeout after close [pass] +library/launcher.spec.ts › should throw a friendly error if its headed and there is no xserver on linux running [fail] +library/locator-generator.spec.ts › asLocator internal:and [pass] +library/locator-generator.spec.ts › asLocator internal:chain [pass] +library/locator-generator.spec.ts › asLocator internal:or [pass] +library/locator-generator.spec.ts › asLocator xpath [pass] +library/locator-generator.spec.ts › generate multiple locators [pass] +library/locator-generator.spec.ts › parse locators strictly [pass] +library/locator-generator.spec.ts › parseLocator css [pass] +library/locator-generator.spec.ts › parseLocator quotes [pass] +library/locator-generator.spec.ts › reverse engineer frameLocator [pass] +library/locator-generator.spec.ts › reverse engineer getByRole [pass] +library/locator-generator.spec.ts › reverse engineer has [pass] +library/locator-generator.spec.ts › reverse engineer has + hasText [pass] +library/locator-generator.spec.ts › reverse engineer hasNot [pass] +library/locator-generator.spec.ts › reverse engineer hasNotText [pass] +library/locator-generator.spec.ts › reverse engineer hasText [pass] +library/locator-generator.spec.ts › reverse engineer ignore-case locators [pass] +library/locator-generator.spec.ts › reverse engineer internal:has-text locators [pass] +library/locator-generator.spec.ts › reverse engineer locators [pass] +library/locator-generator.spec.ts › reverse engineer locators with regex [pass] +library/locator-generator.spec.ts › reverse engineer ordered locators [pass] +library/logger.spec.ts › should log @smoke [pass] +library/logger.spec.ts › should log context-level [pass] +library/modernizr.spec.ts › Mobile Safari [unknown] +library/modernizr.spec.ts › Safari Desktop [unknown] +library/page-clock.frozen.spec.ts › clock should be frozen [unknown] +library/page-clock.frozen.spec.ts › clock should be realtime [unknown] +library/page-clock.spec.ts › Date.now › check Date.now is an integer [pass] +library/page-clock.spec.ts › Date.now › check Date.now is an integer (2) [pass] +library/page-clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +library/page-clock.spec.ts › fastForward › pushes back execution time for skipped timers [fail] +library/page-clock.spec.ts › fastForward › supports string time arguments [fail] +library/page-clock.spec.ts › popup › should not run time before popup on pause [fail] +library/page-clock.spec.ts › popup › should run time before popup [pass] +library/page-clock.spec.ts › popup › should tick after popup [fail] +library/page-clock.spec.ts › popup › should tick before popup [fail] +library/page-clock.spec.ts › runFor › creates updated Date while ticking [fail] +library/page-clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +library/page-clock.spec.ts › runFor › passes 1 minute [fail] +library/page-clock.spec.ts › runFor › passes 2 hours, 34 minutes and 10 seconds [fail] +library/page-clock.spec.ts › runFor › passes 8 seconds [fail] +library/page-clock.spec.ts › runFor › returns the current now value [pass] +library/page-clock.spec.ts › runFor › throws for invalid format [pass] +library/page-clock.spec.ts › runFor › triggers after sufficient delay [fail] +library/page-clock.spec.ts › runFor › triggers event when some throw [fail] +library/page-clock.spec.ts › runFor › triggers immediately without specified delay [fail] +library/page-clock.spec.ts › runFor › triggers multiple simultaneous timers [fail] +library/page-clock.spec.ts › runFor › triggers simultaneous timers [fail] +library/page-clock.spec.ts › runFor › waits after setTimeout was called [fail] +library/page-clock.spec.ts › setFixedTime › allows installing fake timers after settings time [fail] +library/page-clock.spec.ts › setFixedTime › allows setting time multiple times [pass] +library/page-clock.spec.ts › setFixedTime › does not fake methods [pass] +library/page-clock.spec.ts › setFixedTime › fixed time is not affected by clock manipulation [pass] +library/page-clock.spec.ts › stubTimers › fakes Date constructor [pass] +library/page-clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +library/page-clock.spec.ts › stubTimers › replaces global clearInterval [pass] +library/page-clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +library/page-clock.spec.ts › stubTimers › replaces global performance.now [pass] +library/page-clock.spec.ts › stubTimers › replaces global performance.timeOrigin [pass] +library/page-clock.spec.ts › stubTimers › replaces global setInterval [fail] +library/page-clock.spec.ts › stubTimers › replaces global setTimeout [fail] +library/page-clock.spec.ts › stubTimers › sets initial timestamp [pass] +library/page-clock.spec.ts › stubTimers › should throw for invalid date [pass] +library/page-clock.spec.ts › while on pause › fastForward should not run nested immediate [fail] +library/page-clock.spec.ts › while on pause › runFor should not run nested immediate [fail] +library/page-clock.spec.ts › while on pause › runFor should not run nested immediate from microtask [fail] +library/page-clock.spec.ts › while running › should fastForward [pass] +library/page-clock.spec.ts › while running › should fastForwardTo [pass] +library/page-clock.spec.ts › while running › should pause [pass] +library/page-clock.spec.ts › while running › should pause and fastForward [pass] +library/page-clock.spec.ts › while running › should progress time [pass] +library/page-clock.spec.ts › while running › should runFor [pass] +library/page-clock.spec.ts › while running › should set system time on pause [pass] +library/page-event-crash.spec.ts › should be able to close context when page crashes [timeout] +library/page-event-crash.spec.ts › should cancel navigation when page crashes [timeout] +library/page-event-crash.spec.ts › should cancel waitForEvent when page crashes [timeout] +library/page-event-crash.spec.ts › should emit crash event when page crashes [timeout] +library/page-event-crash.spec.ts › should throw on any action after page crashes [timeout] +library/pdf.spec.ts › should be able to generate outline [unknown] +library/pdf.spec.ts › should be able to save file [unknown] +library/permissions.spec.ts › permissions › should accumulate when adding [fail] +library/permissions.spec.ts › permissions › should be prompt by default [pass] +library/permissions.spec.ts › permissions › should clear permissions [fail] +library/permissions.spec.ts › permissions › should deny permission when not listed [fail] +library/permissions.spec.ts › permissions › should fail when bad permission is given [fail] +library/permissions.spec.ts › permissions › should grant geolocation permission when origin is listed [fail] +library/permissions.spec.ts › permissions › should grant notifications permission when listed [fail] +library/permissions.spec.ts › permissions › should grant permission when creating context [fail] +library/permissions.spec.ts › permissions › should grant permission when listed for all domains [fail] +library/permissions.spec.ts › permissions › should isolate permissions between browser contexts [fail] +library/permissions.spec.ts › permissions › should prompt for geolocation permission when origin is not listed [pass] +library/permissions.spec.ts › permissions › should reset permissions [fail] +library/permissions.spec.ts › permissions › should trigger permission onchange [fail] +library/permissions.spec.ts › should support clipboard read [fail] +library/permissions.spec.ts › storage access [unknown] +library/popup.spec.ts › BrowserContext.addInitScript should apply to a cross-process popup [fail] +library/popup.spec.ts › BrowserContext.addInitScript should apply to an in-process popup [fail] +library/popup.spec.ts › should expose function from browser context [fail] +library/popup.spec.ts › should inherit extra headers from browser context [fail] +library/popup.spec.ts › should inherit http credentials from browser context [fail] +library/popup.spec.ts › should inherit offline from browser context [fail] +library/popup.spec.ts › should inherit touch support from browser context [fail] +library/popup.spec.ts › should inherit user agent from browser context @smoke [fail] +library/popup.spec.ts › should inherit viewport size from browser context [fail] +library/popup.spec.ts › should not dispatch binding on a closed page [fail] +library/popup.spec.ts › should not throttle rAF in the opener page [pass] +library/popup.spec.ts › should not throw when click closes popup [pass] +library/popup.spec.ts › should respect routes from browser context [fail] +library/popup.spec.ts › should respect routes from browser context when using window.open [fail] +library/popup.spec.ts › should use viewport size from window features [timeout] +library/proxy-pattern.spec.ts › socks proxy patter matcher [pass] +library/proxy.spec.ts › does launch without a port [pass] +library/proxy.spec.ts › should authenticate [fail] +library/proxy.spec.ts › should exclude patterns [pass] +library/proxy.spec.ts › should proxy local network requests › by default › link-local [pass] +library/proxy.spec.ts › should proxy local network requests › by default › localhost [pass] +library/proxy.spec.ts › should proxy local network requests › by default › loopback address [pass] +library/proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [pass] +library/proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [pass] +library/proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [pass] +library/proxy.spec.ts › should throw for bad server value [pass] +library/proxy.spec.ts › should use SOCKS proxy for websocket requests [pass] +library/proxy.spec.ts › should use proxy @smoke [pass] +library/proxy.spec.ts › should use proxy for second page [pass] +library/proxy.spec.ts › should use proxy with emulated user agent [unknown] +library/proxy.spec.ts › should use socks proxy [pass] +library/proxy.spec.ts › should use socks proxy in second page [pass] +library/proxy.spec.ts › should work with IP:PORT notion [pass] +library/proxy.spec.ts › should work with authenticate followed by redirect [fail] +library/resource-timing.spec.ts › should work @smoke [pass] +library/resource-timing.spec.ts › should work for SSL [fail] +library/resource-timing.spec.ts › should work for redirect [fail] +library/resource-timing.spec.ts › should work for subresource [fail] +library/resource-timing.spec.ts › should work when serving from memory cache [fail] +library/role-utils.spec.ts › accessible name nested treeitem [pass] +library/role-utils.spec.ts › accessible name with slots [pass] +library/role-utils.spec.ts › axe-core accessible-text [pass] +library/role-utils.spec.ts › axe-core implicit-role [pass] +library/role-utils.spec.ts › control embedded in a label [pass] +library/role-utils.spec.ts › control embedded in a target element [pass] +library/role-utils.spec.ts › display:contents should be visible when contents are visible [pass] +library/role-utils.spec.ts › label/labelled-by aria-hidden with descendants [pass] +library/role-utils.spec.ts › native controls [pass] +library/role-utils.spec.ts › native controls labelled-by [pass] +library/role-utils.spec.ts › own aria-label concatenated with aria-labelledby [pass] +library/role-utils.spec.ts › should ignore stylesheet from hidden aria-labelledby subtree [pass] +library/role-utils.spec.ts › should not include hidden pseudo into accessible name [pass] +library/role-utils.spec.ts › should work with form and tricky input names [pass] +library/role-utils.spec.ts › svg role=presentation [pass] +library/role-utils.spec.ts › svg title [pass] +library/role-utils.spec.ts › wpt accname #0 [pass] +library/role-utils.spec.ts › wpt accname #1 [pass] +library/role-utils.spec.ts › wpt accname #2 [pass] +library/role-utils.spec.ts › wpt accname #3 [pass] +library/role-utils.spec.ts › wpt accname non-manual [pass] +library/screenshot.spec.ts › element screenshot › element screenshot should work with a mobile viewport [fail] +library/screenshot.spec.ts › element screenshot › element screenshot should work with device scale factor [fail] +library/screenshot.spec.ts › element screenshot › element screenshots should handle vh units [fail] +library/screenshot.spec.ts › element screenshot › page screenshot should capture css transform with device pixels [fail] +library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor [fail] +library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor and scale:css [fail] +library/screenshot.spec.ts › element screenshot › should restore default viewport after fullPage screenshot [fail] +library/screenshot.spec.ts › element screenshot › should restore viewport after element screenshot and exception [pass] +library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and exception [pass] +library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and timeout [fail] +library/screenshot.spec.ts › element screenshot › should take element screenshot when default viewport is null and restore back [fail] +library/screenshot.spec.ts › element screenshot › should take fullPage screenshots when default viewport is null [fail] +library/screenshot.spec.ts › element screenshot › should take screenshots when default viewport is null [fail] +library/screenshot.spec.ts › element screenshot › should work if the main resource hangs [fail] +library/screenshot.spec.ts › page screenshot › should handle vh units [fail] +library/screenshot.spec.ts › page screenshot › should run in parallel in multiple pages [fail] +library/screenshot.spec.ts › page screenshot › should throw if screenshot size is too large with device scale factor [fail] +library/screenshot.spec.ts › page screenshot › should work with a mobile viewport [fail] +library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and clip [fail] +library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and fullPage [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor and clip [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor and scale:css [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor, clip and scale:css [fail] +library/screenshot.spec.ts › page screenshot › should work with large size [fail] +library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [pass] +library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [pass] +library/selector-generator.spec.ts › selector generator › should chain text after parent [pass] +library/selector-generator.spec.ts › selector generator › should escape text with quote [pass] +library/selector-generator.spec.ts › selector generator › should escape text with slash [pass] +library/selector-generator.spec.ts › selector generator › should find text in shadow dom [pass] +library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [pass] +library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [pass] +library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [pass] +library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [pass] +library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [pass] +library/selector-generator.spec.ts › selector generator › should generate label selector [pass] +library/selector-generator.spec.ts › selector generator › should generate multiple: noId [pass] +library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [pass] +library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [pass] +library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [pass] +library/selector-generator.spec.ts › selector generator › should generate relative selector [pass] +library/selector-generator.spec.ts › selector generator › should generate text and normalize whitespace [pass] +library/selector-generator.spec.ts › selector generator › should generate text for [pass] +library/selector-generator.spec.ts › selector generator › should generate title selector [pass] +library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [pass] +library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [pass] +library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [pass] +library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [pass] +library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [pass] +library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [pass] +library/selector-generator.spec.ts › selector generator › should match in shadow dom [pass] +library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [pass] +library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [pass] +library/selector-generator.spec.ts › selector generator › should not escape text with >> [pass] +library/selector-generator.spec.ts › selector generator › should not improve guid text [pass] +library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [pass] +library/selector-generator.spec.ts › selector generator › should not use generated id [pass] +library/selector-generator.spec.ts › selector generator › should not use input[value] [pass] +library/selector-generator.spec.ts › selector generator › should not use text for select [pass] +library/selector-generator.spec.ts › selector generator › should prefer button over inner span [pass] +library/selector-generator.spec.ts › selector generator › should prefer data-testid [pass] +library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [pass] +library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [pass] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [pass] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [pass] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [pass] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [pass] +library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [pass] +library/selector-generator.spec.ts › selector generator › should separate selectors by >> [pass] +library/selector-generator.spec.ts › selector generator › should trim long text [pass] +library/selector-generator.spec.ts › selector generator › should trim text [pass] +library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [pass] +library/selector-generator.spec.ts › selector generator › should try to improve role name [pass] +library/selector-generator.spec.ts › selector generator › should try to improve text [pass] +library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [pass] +library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [pass] +library/selector-generator.spec.ts › selector generator › should use internal:has-text [pass] +library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [pass] +library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [pass] +library/selector-generator.spec.ts › selector generator › should use nested ordinals [pass] +library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [pass] +library/selector-generator.spec.ts › selector generator › should use parent text [pass] +library/selector-generator.spec.ts › selector generator › should use readable id [pass] +library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [pass] +library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] +library/selector-generator.spec.ts › selector generator › should work with tricky attributes [pass] +library/selector-generator.spec.ts › selector generator › should work without CSS.escape [pass] +library/selectors-register.spec.ts › should handle errors [pass] +library/selectors-register.spec.ts › should not rely on engines working from the root [pass] +library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] +library/selectors-register.spec.ts › should work [pass] +library/selectors-register.spec.ts › should work in main and isolated world [pass] +library/selectors-register.spec.ts › should work when registered on global [pass] +library/selectors-register.spec.ts › should work with path [pass] +library/shared-worker.spec.ts › should survive shared worker restart [timeout] +library/signals.spec.ts › should close the browser when the node process closes [timeout] +library/signals.spec.ts › should remove temp dir on process.exit [timeout] +library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] +library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] +library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] +library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] +library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] +library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] +library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] +library/signals.spec.ts › signals › should report browser close signal 2 [timeout] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo check [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo click [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo fill [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo focus [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo goto [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo hover [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo press [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [timeout] +library/slowmo.spec.ts › slowMo › Frame SlowMo type [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo check [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo click [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo fill [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo focus [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo goto [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo hover [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo press [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo reload [timeout] +library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [timeout] +library/slowmo.spec.ts › slowMo › Page SlowMo type [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [pass] +library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [pass] +library/snapshotter.spec.ts › snapshots › should capture frame [fail] +library/snapshotter.spec.ts › snapshots › should capture iframe [fail] +library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [fail] +library/snapshotter.spec.ts › snapshots › should capture resources [fail] +library/snapshotter.spec.ts › snapshots › should capture snapshot target [timeout] +library/snapshotter.spec.ts › snapshots › should collect multiple [pass] +library/snapshotter.spec.ts › snapshots › should collect on attribute change [pass] +library/snapshotter.spec.ts › snapshots › should collect snapshot [pass] +library/snapshotter.spec.ts › snapshots › should have a custom doctype [pass] +library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [pass] +library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] +library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [pass] +library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [pass] +library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [pass] +library/snapshotter.spec.ts › snapshots › should respect attr removal [pass] +library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [pass] +library/snapshotter.spec.ts › snapshots › should respect node removal [pass] +library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +library/tap.spec.ts › locators › should send all of the correct events [fail] +library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] +library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] +library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] +library/tap.spec.ts › should send all of the correct events @smoke [fail] +library/tap.spec.ts › should send well formed touch points [fail] +library/tap.spec.ts › should wait until an element is visible to tap it [fail] +library/tap.spec.ts › should work with modifiers [fail] +library/tap.spec.ts › trial run should not tap [fail] +library/trace-viewer.spec.ts › should allow hiding route actions [fail] +library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [fail] +library/trace-viewer.spec.ts › should capture data-url svg iframe [fail] +library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] +library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [pass] +library/trace-viewer.spec.ts › should contain action info [pass] +library/trace-viewer.spec.ts › should contain adopted style sheets [pass] +library/trace-viewer.spec.ts › should display language-specific locators [pass] +library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [pass] +library/trace-viewer.spec.ts › should filter network requests by resource type [pass] +library/trace-viewer.spec.ts › should filter network requests by url [pass] +library/trace-viewer.spec.ts › should follow redirects [fail] +library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [pass] +library/trace-viewer.spec.ts › should handle file URIs [unknown] +library/trace-viewer.spec.ts › should handle multiple headers [fail] +library/trace-viewer.spec.ts › should handle src=blob [fail] +library/trace-viewer.spec.ts › should have correct snapshot size [pass] +library/trace-viewer.spec.ts › should have correct stack trace [pass] +library/trace-viewer.spec.ts › should have network request overrides [fail] +library/trace-viewer.spec.ts › should have network request overrides 2 [fail] +library/trace-viewer.spec.ts › should have network requests [pass] +library/trace-viewer.spec.ts › should highlight expect failure [pass] +library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] +library/trace-viewer.spec.ts › should highlight target elements [fail] +library/trace-viewer.spec.ts › should ignore 304 responses [fail] +library/trace-viewer.spec.ts › should include metainfo [pass] +library/trace-viewer.spec.ts › should include requestUrl in route.abort [fail] +library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] +library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [fail] +library/trace-viewer.spec.ts › should not crash with broken locator [pass] +library/trace-viewer.spec.ts › should open console errors on click [fail] +library/trace-viewer.spec.ts › should open simple trace viewer [pass] +library/trace-viewer.spec.ts › should open snapshot in new browser context [pass] +library/trace-viewer.spec.ts › should open trace viewer on specific host [pass] +library/trace-viewer.spec.ts › should open trace-1.31 [pass] +library/trace-viewer.spec.ts › should open trace-1.37 [pass] +library/trace-viewer.spec.ts › should open two trace files [pass] +library/trace-viewer.spec.ts › should open two trace files of the same test [pass] +library/trace-viewer.spec.ts › should open two trace viewers [pass] +library/trace-viewer.spec.ts › should pick locator [pass] +library/trace-viewer.spec.ts › should pick locator in iframe [fail] +library/trace-viewer.spec.ts › should popup snapshot [pass] +library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] +library/trace-viewer.spec.ts › should preserve currentSrc [pass] +library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [pass] +library/trace-viewer.spec.ts › should register custom elements [pass] +library/trace-viewer.spec.ts › should remove noscript by default [pass] +library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [pass] +library/trace-viewer.spec.ts › should render console [fail] +library/trace-viewer.spec.ts › should render network bars [pass] +library/trace-viewer.spec.ts › should restore control values [fail] +library/trace-viewer.spec.ts › should restore scroll positions [pass] +library/trace-viewer.spec.ts › should serve css without content-type [timeout] +library/trace-viewer.spec.ts › should serve overridden request [fail] +library/trace-viewer.spec.ts › should show action source [pass] +library/trace-viewer.spec.ts › should show baseURL in metadata pane [pass] +library/trace-viewer.spec.ts › should show correct request start time [fail] +library/trace-viewer.spec.ts › should show empty trace viewer [pass] +library/trace-viewer.spec.ts › should show font preview [fail] +library/trace-viewer.spec.ts › should show null as a param [pass] +library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [unknown] +library/trace-viewer.spec.ts › should show params and return value [pass] +library/trace-viewer.spec.ts › should show similar actions from library-only trace [pass] +library/trace-viewer.spec.ts › should show snapshot URL [pass] +library/trace-viewer.spec.ts › should update highlight when typing [pass] +library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [fail] +library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [pass] +library/trace-viewer.spec.ts › should work with meta CSP [pass] +library/trace-viewer.spec.ts › should work with nesting CSS selectors [pass] +library/tracing.spec.ts › should collect sources [pass] +library/tracing.spec.ts › should collect trace with resources, but no js [timeout] +library/tracing.spec.ts › should collect two traces [pass] +library/tracing.spec.ts › should exclude internal pages [pass] +library/tracing.spec.ts › should export trace concurrently to second navigation [fail] +library/tracing.spec.ts › should flush console events on tracing stop [pass] +library/tracing.spec.ts › should hide internal stack frames [pass] +library/tracing.spec.ts › should hide internal stack frames in expect [pass] +library/tracing.spec.ts › should ignore iframes in head [pass] +library/tracing.spec.ts › should include context API requests [pass] +library/tracing.spec.ts › should include interrupted actions [pass] +library/tracing.spec.ts › should not collect snapshots by default [pass] +library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] +library/tracing.spec.ts › should not emit after w/o before [pass] +library/tracing.spec.ts › should not flush console events [pass] +library/tracing.spec.ts › should not hang for clicks that open dialogs [pass] +library/tracing.spec.ts › should not include buffers in the trace [fail] +library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] +library/tracing.spec.ts › should not stall on dialogs [pass] +library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] +library/tracing.spec.ts › should overwrite existing file [fail] +library/tracing.spec.ts › should produce screencast frames crop [fail] +library/tracing.spec.ts › should produce screencast frames fit [fail] +library/tracing.spec.ts › should produce screencast frames scale [fail] +library/tracing.spec.ts › should record global request trace [pass] +library/tracing.spec.ts › should record network failures [fail] +library/tracing.spec.ts › should respect tracesDir and name [fail] +library/tracing.spec.ts › should store global request traces separately [pass] +library/tracing.spec.ts › should store postData for global request [pass] +library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] +library/tracing.spec.ts › should throw when starting with different options [pass] +library/tracing.spec.ts › should throw when stopping without start [pass] +library/tracing.spec.ts › should use the correct apiName for event driven callbacks [fail] +library/tracing.spec.ts › should work with multiple chunks [pass] +library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [fail] +library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] +library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [pass] +library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] +library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] +library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] +library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [fail] +library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [fail] +library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [fail] +library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [fail] +library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] +library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [fail] +library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [fail] +library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [fail] +library/video.spec.ts › screencast › saveAs should throw when no video frames [pass] +library/video.spec.ts › screencast › should be 800x450 by default [fail] +library/video.spec.ts › screencast › should be 800x600 with null viewport [fail] +library/video.spec.ts › screencast › should capture css transformation [fail] +library/video.spec.ts › screencast › should capture full viewport [fail] +library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] +library/video.spec.ts › screencast › should capture navigation [fail] +library/video.spec.ts › screencast › should capture static page [fail] +library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] +library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] +library/video.spec.ts › screencast › should delete video [fail] +library/video.spec.ts › screencast › should emulate an iphone [fail] +library/video.spec.ts › screencast › should expose video path [timeout] +library/video.spec.ts › screencast › should expose video path blank page [timeout] +library/video.spec.ts › screencast › should expose video path blank popup [timeout] +library/video.spec.ts › screencast › should not create video for internal pages [unknown] +library/video.spec.ts › screencast › should scale frames down to the requested size [fail] +library/video.spec.ts › screencast › should throw if browser dies [fail] +library/video.spec.ts › screencast › should throw on browser close [fail] +library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] +library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [fail] +library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] +library/video.spec.ts › screencast › should work for popups [fail] +library/video.spec.ts › screencast › should work with old options [fail] +library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] +library/video.spec.ts › screencast › should work with video+trace [fail] +library/video.spec.ts › screencast › should work with weird screen resolution [timeout] +library/video.spec.ts › screencast › videoSize should require videosPath [pass] +library/video.spec.ts › should saveAs video [fail] +library/web-socket.spec.ts › should emit binary frame events [timeout] +library/web-socket.spec.ts › should emit close events [timeout] +library/web-socket.spec.ts › should emit error [timeout] +library/web-socket.spec.ts › should emit frame events [timeout] +library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] +library/web-socket.spec.ts › should not have stray error events [timeout] +library/web-socket.spec.ts › should pass self as argument to close event [timeout] +library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] +library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] +library/web-socket.spec.ts › should turn off when offline [unknown] +library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-chromium-page.txt b/tests/bidi/expectations/bidi-chromium-page.txt index 14d77dd0abfce..da2bee1fefd42 100644 --- a/tests/bidi/expectations/bidi-chromium-page.txt +++ b/tests/bidi/expectations/bidi-chromium-page.txt @@ -1,1966 +1,1966 @@ -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should force a layout [pass] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should get frame box [pass] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should handle nested frames [fail] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [pass] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should return null for invisible elements [fail] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should work [pass] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [pass] -bidi-chromium-page › page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should double click the button [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for
elements with force [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for detached nodes [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for hidden nodes with force [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should throw for recursively hidden nodes with force [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should work for Shadow DOM v1 [pass] -bidi-chromium-page › page/elementhandle-click.spec.ts › should work for TextNodes [fail] -bidi-chromium-page › page/elementhandle-click.spec.ts › should work with Node removed [pass] -bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should return null for document.documentElement [pass] -bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should return null for non-iframes [pass] -bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should work [pass] -bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should work for cross-frame evaluations [fail] -bidi-chromium-page › page/elementhandle-content-frame.spec.ts › should work for cross-process iframes [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › getAttribute should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › innerHTML should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › innerText should throw [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › innerText should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › inputValue should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › isChecked should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › isEditable should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work [pass] -bidi-chromium-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work with [fail] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect color value [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect date [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect month [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect range value [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect time [pass] -bidi-chromium-page › page/page-fill.spec.ts › should throw on incorrect week [unknown] -bidi-chromium-page › page/page-fill.spec.ts › should throw on unsupported inputs [pass] -bidi-chromium-page › page/page-focus.spec.ts › clicking checkbox should activate it [unknown] -bidi-chromium-page › page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [pass] -bidi-chromium-page › page/page-focus.spec.ts › should emit blur event [fail] -bidi-chromium-page › page/page-focus.spec.ts › should emit focus event [fail] -bidi-chromium-page › page/page-focus.spec.ts › should traverse focus [fail] -bidi-chromium-page › page/page-focus.spec.ts › should traverse focus in all directions [pass] -bidi-chromium-page › page/page-focus.spec.ts › should traverse only form elements [unknown] -bidi-chromium-page › page/page-focus.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [fail] -bidi-chromium-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] -bidi-chromium-page › page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] -bidi-chromium-page › page/page-goto.spec.ts › should capture iframe navigation request [pass] -bidi-chromium-page › page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when canceled by another navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding browser context timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when main resources failed to load [fail] -bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating and show the url at the error message [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] -bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] -bidi-chromium-page › page/page-goto.spec.ts › should fail when navigating to bad url [fail] -bidi-chromium-page › page/page-goto.spec.ts › should fail when replaced by another navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should fail when server returns 204 [fail] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to about:blank [pass] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] -bidi-chromium-page › page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not leak listeners during navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] -bidi-chromium-page › page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] -bidi-chromium-page › page/page-goto.spec.ts › should override referrer-policy [fail] -bidi-chromium-page › page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] -bidi-chromium-page › page/page-goto.spec.ts › should properly wait for load [pass] -bidi-chromium-page › page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] -bidi-chromium-page › page/page-goto.spec.ts › should report raw buffer for main resource [fail] -bidi-chromium-page › page/page-goto.spec.ts › should return from goto if new navigation is started [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return last response in redirect chain [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return response when page changes its URL after load [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return url with basic auth info [pass] -bidi-chromium-page › page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] -bidi-chromium-page › page/page-goto.spec.ts › should send referer [fail] -bidi-chromium-page › page/page-goto.spec.ts › should send referer of cross-origin URL [fail] -bidi-chromium-page › page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [pass] -bidi-chromium-page › page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] -bidi-chromium-page › page/page-goto.spec.ts › should use http for no protocol [pass] -bidi-chromium-page › page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work @smoke [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work cross-process [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to 404 [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to data url [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when navigating to valid url [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work when page calls history API in beforeunload [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [fail] -bidi-chromium-page › page/page-goto.spec.ts › should work with anchor navigation [timeout] -bidi-chromium-page › page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with file URL [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with file URL with subframes [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with lazy loading iframes [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with redirects [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with self requesting page [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 [pass] -bidi-chromium-page › page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] -bidi-chromium-page › page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] -bidi-chromium-page › page/page-history.spec.ts › page.goBack during renderer-initiated navigation [timeout] -bidi-chromium-page › page/page-history.spec.ts › page.goBack should work @smoke [fail] -bidi-chromium-page › page/page-history.spec.ts › page.goBack should work for file urls [fail] -bidi-chromium-page › page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] -bidi-chromium-page › page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] -bidi-chromium-page › page/page-history.spec.ts › page.reload during renderer-initiated navigation [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work on a page with a hash [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work with data url [timeout] -bidi-chromium-page › page/page-history.spec.ts › page.reload should work with same origin redirect [pass] -bidi-chromium-page › page/page-history.spec.ts › regression test for issue 20791 [pass] -bidi-chromium-page › page/page-history.spec.ts › should reload proper page [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › insertText should only emit input event [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] -bidi-chromium-page › page/page-keyboard.spec.ts › should handle selectAll [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should move around the selection in a contenteditable [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should move to the start of the document [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should move with the arrow keys [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should not type canceled events [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should press Enter [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should press plus [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should press shift plus [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should press the meta key [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should report multiple modifiers [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should report shiftKey [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should scroll with PageDown [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should send a character with insertText [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should send proper codes while typing [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should send proper codes while typing with shift [timeout] -bidi-chromium-page › page/page-keyboard.spec.ts › should shift raw codes [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should specify location [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should specify repeat property [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should support MacOS shortcuts [fail] -bidi-chromium-page › page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should support simple copy-pasting [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should support simple cut-pasting [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should support undo-redo [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should throw on unknown keys [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type after context menu was opened [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type all kinds of characters [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type emoji into an iframe [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] -bidi-chromium-page › page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [pass] -bidi-chromium-page › page/page-leaks.spec.ts › click should not leak [pass] -bidi-chromium-page › page/page-leaks.spec.ts › expect should not leak [pass] -bidi-chromium-page › page/page-leaks.spec.ts › fill should not leak [pass] -bidi-chromium-page › page/page-leaks.spec.ts › waitFor should not leak [pass] -bidi-chromium-page › page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] -bidi-chromium-page › page/page-listeners.spec.ts › should wait [pass] -bidi-chromium-page › page/page-listeners.spec.ts › wait should throw [pass] -bidi-chromium-page › page/page-mouse.spec.ts › down and up should generate click [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should always round down [fail] -bidi-chromium-page › page/page-mouse.spec.ts › should click the document @smoke [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should dblclick the div [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should pointerdown the div with a custom button [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should report correct buttons property [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should select the text with mouse [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should set modifier keys on click [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] -bidi-chromium-page › page/page-mouse.spec.ts › should tween mouse movement [pass] -bidi-chromium-page › page/page-navigation.spec.ts › should work with _blank target [pass] -bidi-chromium-page › page/page-navigation.spec.ts › should work with _blank target in form [pass] -bidi-chromium-page › page/page-navigation.spec.ts › should work with cross-process _blank target [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle from the popup [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] -bidi-chromium-page › page/page-network-idle.spec.ts › should work after repeated navigations in the same page [fail] -bidi-chromium-page › page/page-network-request.spec.ts › page.reload return 304 status code [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should get the same headers as the server [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] -bidi-chromium-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should not work for a redirect and interception [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should override post data content type [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should parse the json post data [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should report all cookies in one header [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should report raw headers [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should report raw response headers in redirects [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should return event source [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should return headers [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should return multipart/form-data [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should return navigation bit [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should return postData [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should work for a redirect [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work for main frame navigation request [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work for subframe navigation request [pass] -bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data [fail] -bidi-chromium-page › page/page-network-request.spec.ts › should work with binary post data and interception [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should provide a Response with a file URL [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if context closes [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should reject response.finished if page closes [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should report all headers [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return body [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return body for prefetch script [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return body with compression [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return headers after route.fulfill [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return json [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return multiple header value [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return status text [pass] -bidi-chromium-page › page/page-network-response.spec.ts › should return text [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should return uncompressed text [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] -bidi-chromium-page › page/page-network-response.spec.ts › should wait until response completes [fail] -bidi-chromium-page › page/page-network-response.spec.ts › should work @smoke [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should handle redirects [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should return sizes without hanging [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize and headersSize [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should throw for failed requests [pass] -bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 200 status code [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 401 status code [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 404 status code [fail] -bidi-chromium-page › page/page-network-sizes.spec.ts › should work with 500 status code [fail] -bidi-chromium-page › page/page-object-count.spec.ts › should count objects [unknown] -bidi-chromium-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend binary post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend longer post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend method and post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should amend utf8 post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › post data › should use content-type from original request [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should amend HTTP headers [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should amend method [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should amend method on main request [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should continue preload link requests [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should delete header with undefined value [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should delete the origin header [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should intercept css variable with background url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should not throw when continuing while page is closing [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should override method along with url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should override request url [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should work [fail] -bidi-chromium-page › page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend json post data [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › post data › should amend post data [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should amend HTTP headers [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should amend method [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should chain once [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should delete header with undefined value [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back after exception [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should fall back async [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain abort [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should not chain fulfill [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should override request url [fail] -bidi-chromium-page › page/page-request-fallback.spec.ts › should work [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fetch original request and fulfill [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill json [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill preload link requests [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with har response [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should include the origin header [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with buffer as body [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with file path [fail] -bidi-chromium-page › page/page-request-fulfill.spec.ts › should work with status code 422 [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should fulfill with any response [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should give access to the intercepted response body [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [unknown] -bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with post data override [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should intercept with url override [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] -bidi-chromium-page › page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] -bidi-chromium-page › page/page-route.spec.ts › route.abort should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › route.continue should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › route.fallback should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › route.fulfill should throw if called twice [fail] -bidi-chromium-page › page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] -bidi-chromium-page › page/page-route.spec.ts › should allow null origin for about:blank [fail] -bidi-chromium-page › page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [fail] -bidi-chromium-page › page/page-route.spec.ts › should be able to remove headers [fail] -bidi-chromium-page › page/page-route.spec.ts › should be abortable [fail] -bidi-chromium-page › page/page-route.spec.ts › should be abortable with custom error codes [fail] -bidi-chromium-page › page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain raw request header [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain raw response header [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain raw response header after fulfill [fail] -bidi-chromium-page › page/page-route.spec.ts › should contain referer header [fail] -bidi-chromium-page › page/page-route.spec.ts › should fail navigation when aborting main resource [fail] -bidi-chromium-page › page/page-route.spec.ts › should fulfill with redirect status [fail] -bidi-chromium-page › page/page-route.spec.ts › should intercept @smoke [fail] -bidi-chromium-page › page/page-route.spec.ts › should intercept main resource during cross-process navigation [fail] -bidi-chromium-page › page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] -bidi-chromium-page › page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [fail] -bidi-chromium-page › page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] -bidi-chromium-page › page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] -bidi-chromium-page › page/page-route.spec.ts › should not fulfill with redirect status [unknown] -bidi-chromium-page › page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] -bidi-chromium-page › page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] -bidi-chromium-page › page/page-route.spec.ts › should not work with redirects [fail] -bidi-chromium-page › page/page-route.spec.ts › should override cookie header [pass] -bidi-chromium-page › page/page-route.spec.ts › should pause intercepted XHR until continue [fail] -bidi-chromium-page › page/page-route.spec.ts › should pause intercepted fetch request until continue [fail] -bidi-chromium-page › page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] -bidi-chromium-page › page/page-route.spec.ts › should reject cors with disallowed credentials [fail] -bidi-chromium-page › page/page-route.spec.ts › should respect cors overrides [fail] -bidi-chromium-page › page/page-route.spec.ts › should send referer [fail] -bidi-chromium-page › page/page-route.spec.ts › should show custom HTTP headers [fail] -bidi-chromium-page › page/page-route.spec.ts › should support ? in glob pattern [fail] -bidi-chromium-page › page/page-route.spec.ts › should support async handler w/ times [fail] -bidi-chromium-page › page/page-route.spec.ts › should support cors for different methods [fail] -bidi-chromium-page › page/page-route.spec.ts › should support cors with GET [fail] -bidi-chromium-page › page/page-route.spec.ts › should support cors with POST [fail] -bidi-chromium-page › page/page-route.spec.ts › should support cors with credentials [fail] -bidi-chromium-page › page/page-route.spec.ts › should support the times parameter with route matching [fail] -bidi-chromium-page › page/page-route.spec.ts › should unroute [fail] -bidi-chromium-page › page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] -bidi-chromium-page › page/page-route.spec.ts › should work when POST is redirected with 302 [fail] -bidi-chromium-page › page/page-route.spec.ts › should work when header manipulation headers with redirect [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with badly encoded server [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with custom referer headers [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with encoded server [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with encoded server - 2 [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with equal requests [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with redirect inside sync XHR [fail] -bidi-chromium-page › page/page-route.spec.ts › should work with redirects for subresources [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [pass] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › path option should work [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] -bidi-chromium-page › page/page-screenshot.spec.ts › should capture css box-shadow [fail] -bidi-chromium-page › page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] -bidi-chromium-page › page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should fall back to selecting by label [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should not allow null items [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should not select single option when some attributes do not match [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should not throw when select causes navigation [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should respect event bubbling [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should return [] on no matched values [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should return [] on no values [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should return an array of matched values [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select multiple options [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select multiple options with attributes [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select only first option [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option @smoke [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by handle [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by index [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by label [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by multiple attributes [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should select single option by value [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should throw if passed wrong types [pass] -bidi-chromium-page › page/page-select-option.spec.ts › should throw when element is not a option/optgroup correctly [pass] +page/elementhandle-convenience.spec.ts › isVisible and isHidden should work [pass] +page/elementhandle-convenience.spec.ts › isVisible should not throw when the DOM element is not connected [pass] +page/elementhandle-convenience.spec.ts › should have a nice preview [pass] +page/elementhandle-convenience.spec.ts › should have a nice preview for non-ascii attributes/children [pass] +page/elementhandle-convenience.spec.ts › textContent should work [pass] +page/elementhandle-convenience.spec.ts › textContent should work on ShadowRoot [fail] +page/elementhandle-eval-on-selector.spec.ts › should not throw in case of missing selector for all [pass] +page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree [pass] +page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree for all [pass] +page/elementhandle-eval-on-selector.spec.ts › should throw in case of missing selector [pass] +page/elementhandle-eval-on-selector.spec.ts › should work [pass] +page/elementhandle-eval-on-selector.spec.ts › should work for all [pass] +page/elementhandle-misc.spec.ts › should allow disposing twice [pass] +page/elementhandle-misc.spec.ts › should check the box [pass] +page/elementhandle-misc.spec.ts › should check the box using setChecked [pass] +page/elementhandle-misc.spec.ts › should fill input [pass] +page/elementhandle-misc.spec.ts › should fill input when Node is removed [pass] +page/elementhandle-misc.spec.ts › should focus a button [pass] +page/elementhandle-misc.spec.ts › should hover [pass] +page/elementhandle-misc.spec.ts › should hover when Node is removed [pass] +page/elementhandle-misc.spec.ts › should select single option [pass] +page/elementhandle-misc.spec.ts › should uncheck the box [pass] +page/elementhandle-owner-frame.spec.ts › should work [fail] +page/elementhandle-owner-frame.spec.ts › should work for adopted elements [fail] +page/elementhandle-owner-frame.spec.ts › should work for cross-frame evaluations [fail] +page/elementhandle-owner-frame.spec.ts › should work for cross-process iframes [fail] +page/elementhandle-owner-frame.spec.ts › should work for detached elements [fail] +page/elementhandle-owner-frame.spec.ts › should work for document [fail] +page/elementhandle-owner-frame.spec.ts › should work for iframe elements [fail] +page/elementhandle-press.spec.ts › should not modify selection when focused [pass] +page/elementhandle-press.spec.ts › should not select existing value [pass] +page/elementhandle-press.spec.ts › should reset selection when not focused [pass] +page/elementhandle-press.spec.ts › should work [pass] +page/elementhandle-press.spec.ts › should work with number input [pass] +page/elementhandle-query-selector.spec.ts › should query existing element [pass] +page/elementhandle-query-selector.spec.ts › should query existing elements [fail] +page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [fail] +page/elementhandle-query-selector.spec.ts › should return null for non-existing element [pass] +page/elementhandle-query-selector.spec.ts › should work for adopted elements [fail] +page/elementhandle-query-selector.spec.ts › xpath should query existing element [fail] +page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport in parallel [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should fail to screenshot a detached element [pass] +page/elementhandle-screenshot.spec.ts › element screenshot › should not issue resize event [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should prefer type over extension [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should scroll 15000px into view [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should scroll element into view [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should take into account padding and border [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should take screenshot of disabled button [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should timeout waiting for visible [pass] +page/elementhandle-screenshot.spec.ts › element screenshot › should wait for element to stop moving [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should wait for visible [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with an offset [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with fractional dimensions [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work when main world busts JSON.stringify [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work with a rotated element [fail] +page/elementhandle-scroll-into-view.spec.ts › should scroll display:contents into view [fail] +page/elementhandle-scroll-into-view.spec.ts › should throw for detached element [fail] +page/elementhandle-scroll-into-view.spec.ts › should timeout waiting for visible [fail] +page/elementhandle-scroll-into-view.spec.ts › should wait for display:none to become visible [fail] +page/elementhandle-scroll-into-view.spec.ts › should wait for element to stop moving [pass] +page/elementhandle-scroll-into-view.spec.ts › should wait for nested display:none to become visible [fail] +page/elementhandle-scroll-into-view.spec.ts › should work @smoke [pass] +page/elementhandle-scroll-into-view.spec.ts › should work for visibility:hidden element [pass] +page/elementhandle-scroll-into-view.spec.ts › should work for zero-sized element [pass] +page/elementhandle-select-text.spec.ts › should select input [pass] +page/elementhandle-select-text.spec.ts › should select plain div [pass] +page/elementhandle-select-text.spec.ts › should select textarea [pass] +page/elementhandle-select-text.spec.ts › should timeout waiting for invisible element [pass] +page/elementhandle-select-text.spec.ts › should wait for visible [pass] +page/elementhandle-type.spec.ts › should not modify selection when focused [pass] +page/elementhandle-type.spec.ts › should not select existing value [pass] +page/elementhandle-type.spec.ts › should reset selection when not focused [pass] +page/elementhandle-type.spec.ts › should work [pass] +page/elementhandle-type.spec.ts › should work with number input [pass] +page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for enabled when detached [pass] +page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for visible when detached [pass] +page/elementhandle-wait-for-element-state.spec.ts › should timeout waiting for visible [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for already hidden [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for already visible [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for aria enabled button [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for button with an aria-disabled parent [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for editable input [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden when detached [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for stable position [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for visible [pass] +page/eval-on-selector-all.spec.ts › should auto-detect css selector [pass] +page/eval-on-selector-all.spec.ts › should return complex values [pass] +page/eval-on-selector-all.spec.ts › should support * capture [pass] +page/eval-on-selector-all.spec.ts › should support * capture when multiple paths match [pass] +page/eval-on-selector-all.spec.ts › should support >> syntax [pass] +page/eval-on-selector-all.spec.ts › should work with bogus Array.from [pass] +page/eval-on-selector-all.spec.ts › should work with css selector [pass] +page/eval-on-selector-all.spec.ts › should work with text selector [pass] +page/eval-on-selector-all.spec.ts › should work with xpath selector [pass] +page/eval-on-selector.spec.ts › should accept ElementHandles as arguments [pass] +page/eval-on-selector.spec.ts › should accept arguments [pass] +page/eval-on-selector.spec.ts › should auto-detect css selector [pass] +page/eval-on-selector.spec.ts › should auto-detect css selector with attributes [pass] +page/eval-on-selector.spec.ts › should auto-detect nested selectors [pass] +page/eval-on-selector.spec.ts › should not stop at first failure with >> syntax [pass] +page/eval-on-selector.spec.ts › should return complex values [pass] +page/eval-on-selector.spec.ts › should support * capture [pass] +page/eval-on-selector.spec.ts › should support >> syntax [pass] +page/eval-on-selector.spec.ts › should support >> syntax with different engines [pass] +page/eval-on-selector.spec.ts › should support spaces with >> syntax [pass] +page/eval-on-selector.spec.ts › should throw error if no element is found [pass] +page/eval-on-selector.spec.ts › should throw on malformed * capture [pass] +page/eval-on-selector.spec.ts › should throw on multiple * captures [pass] +page/eval-on-selector.spec.ts › should work with css selector [pass] +page/eval-on-selector.spec.ts › should work with data-test selector [pass] +page/eval-on-selector.spec.ts › should work with data-test-id selector [pass] +page/eval-on-selector.spec.ts › should work with data-testid selector [pass] +page/eval-on-selector.spec.ts › should work with id selector [pass] +page/eval-on-selector.spec.ts › should work with quotes in css attributes [pass] +page/eval-on-selector.spec.ts › should work with quotes in css attributes when missing [pass] +page/eval-on-selector.spec.ts › should work with spaces in css attributes [pass] +page/eval-on-selector.spec.ts › should work with spaces in css attributes when missing [pass] +page/eval-on-selector.spec.ts › should work with text selector [pass] +page/eval-on-selector.spec.ts › should work with text selector in quotes [pass] +page/eval-on-selector.spec.ts › should work with xpath selector [pass] +page/expect-boolean.spec.ts › not.toBeDisabled div [pass] +page/expect-boolean.spec.ts › not.toBeEmpty [pass] +page/expect-boolean.spec.ts › not.toBeOK [pass] +page/expect-boolean.spec.ts › should print selector syntax error [pass] +page/expect-boolean.spec.ts › should print unknown engine error [pass] +page/expect-boolean.spec.ts › toBeAttached › default [pass] +page/expect-boolean.spec.ts › toBeAttached › eventually [pass] +page/expect-boolean.spec.ts › toBeAttached › eventually with not [pass] +page/expect-boolean.spec.ts › toBeAttached › fail [pass] +page/expect-boolean.spec.ts › toBeAttached › fail with not [pass] +page/expect-boolean.spec.ts › toBeAttached › over navigation [pass] +page/expect-boolean.spec.ts › toBeAttached › with attached:false [pass] +page/expect-boolean.spec.ts › toBeAttached › with attached:true [pass] +page/expect-boolean.spec.ts › toBeAttached › with frameLocator [pass] +page/expect-boolean.spec.ts › toBeAttached › with hidden element [pass] +page/expect-boolean.spec.ts › toBeAttached › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeAttached › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeAttached › with not [pass] +page/expect-boolean.spec.ts › toBeAttached › with not and attached:false [pass] +page/expect-boolean.spec.ts › toBeChecked with value [pass] +page/expect-boolean.spec.ts › toBeChecked › default [pass] +page/expect-boolean.spec.ts › toBeChecked › fail [pass] +page/expect-boolean.spec.ts › toBeChecked › fail missing [pass] +page/expect-boolean.spec.ts › toBeChecked › fail with checked:false [pass] +page/expect-boolean.spec.ts › toBeChecked › fail with not [pass] +page/expect-boolean.spec.ts › toBeChecked › friendly log [pass] +page/expect-boolean.spec.ts › toBeChecked › with checked:false [pass] +page/expect-boolean.spec.ts › toBeChecked › with checked:true [pass] +page/expect-boolean.spec.ts › toBeChecked › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeChecked › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeChecked › with not [pass] +page/expect-boolean.spec.ts › toBeChecked › with not and checked:false [pass] +page/expect-boolean.spec.ts › toBeChecked › with role [pass] +page/expect-boolean.spec.ts › toBeDisabled with value [pass] +page/expect-boolean.spec.ts › toBeEditable › default [pass] +page/expect-boolean.spec.ts › toBeEditable › with editable:false [pass] +page/expect-boolean.spec.ts › toBeEditable › with editable:true [pass] +page/expect-boolean.spec.ts › toBeEditable › with not [pass] +page/expect-boolean.spec.ts › toBeEditable › with not and editable:false [pass] +page/expect-boolean.spec.ts › toBeEmpty div [pass] +page/expect-boolean.spec.ts › toBeEmpty input [pass] +page/expect-boolean.spec.ts › toBeEnabled › default [pass] +page/expect-boolean.spec.ts › toBeEnabled › eventually [pass] +page/expect-boolean.spec.ts › toBeEnabled › eventually with not [pass] +page/expect-boolean.spec.ts › toBeEnabled › failed [pass] +page/expect-boolean.spec.ts › toBeEnabled › toBeDisabled [pass] +page/expect-boolean.spec.ts › toBeEnabled › with enabled:false [pass] +page/expect-boolean.spec.ts › toBeEnabled › with enabled:true [pass] +page/expect-boolean.spec.ts › toBeEnabled › with not and enabled:false [pass] +page/expect-boolean.spec.ts › toBeFocused [pass] +page/expect-boolean.spec.ts › toBeFocused with shadow elements [pass] +page/expect-boolean.spec.ts › toBeHidden with value [pass] +page/expect-boolean.spec.ts › toBeHidden › default [pass] +page/expect-boolean.spec.ts › toBeHidden › eventually [pass] +page/expect-boolean.spec.ts › toBeHidden › eventually with not [pass] +page/expect-boolean.spec.ts › toBeHidden › fail [pass] +page/expect-boolean.spec.ts › toBeHidden › fail with not [pass] +page/expect-boolean.spec.ts › toBeHidden › fail with not when nothing matching [pass] +page/expect-boolean.spec.ts › toBeHidden › when nothing matches [pass] +page/expect-boolean.spec.ts › toBeHidden › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeHidden › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeHidden › with not [pass] +page/expect-boolean.spec.ts › toBeOK [pass] +page/expect-boolean.spec.ts › toBeOK fail with invalid argument [pass] +page/expect-boolean.spec.ts › toBeOK fail with promise [pass] +page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › image content type [pass] +page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › no content type [pass] +page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › text content type [pass] +page/expect-boolean.spec.ts › toBeVisible › default [pass] +page/expect-boolean.spec.ts › toBeVisible › eventually [pass] +page/expect-boolean.spec.ts › toBeVisible › eventually with not [pass] +page/expect-boolean.spec.ts › toBeVisible › fail [pass] +page/expect-boolean.spec.ts › toBeVisible › fail with not [pass] +page/expect-boolean.spec.ts › toBeVisible › over navigation [pass] +page/expect-boolean.spec.ts › toBeVisible › with frameLocator [pass] +page/expect-boolean.spec.ts › toBeVisible › with frameLocator 2 [pass] +page/expect-boolean.spec.ts › toBeVisible › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeVisible › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeVisible › with not [pass] +page/expect-boolean.spec.ts › toBeVisible › with not and visible:false [pass] +page/expect-boolean.spec.ts › toBeVisible › with visible:false [pass] +page/expect-boolean.spec.ts › toBeVisible › with visible:true [pass] +page/expect-matcher-result.spec.ts › toBeChecked({ checked: false }) should have expected: false [pass] +page/expect-matcher-result.spec.ts › toBeTruthy-based assertions should have matcher result [pass] +page/expect-matcher-result.spec.ts › toEqual-based assertions should have matcher result [pass] +page/expect-matcher-result.spec.ts › toHaveScreenshot should populate matcherResult [fail] +page/expect-matcher-result.spec.ts › toMatchText-based assertions should have matcher result [pass] +page/expect-misc.spec.ts › toBeInViewport › should have good stack [pass] +page/expect-misc.spec.ts › toBeInViewport › should report intersection even if fully covered by other element [pass] +page/expect-misc.spec.ts › toBeInViewport › should respect ratio option [pass] +page/expect-misc.spec.ts › toBeInViewport › should work [pass] +page/expect-misc.spec.ts › toHaveAccessibleDescription [pass] +page/expect-misc.spec.ts › toHaveAccessibleName [pass] +page/expect-misc.spec.ts › toHaveAttribute › pass [pass] +page/expect-misc.spec.ts › toHaveAttribute › should match attribute without value [pass] +page/expect-misc.spec.ts › toHaveAttribute › should match boolean attribute [pass] +page/expect-misc.spec.ts › toHaveAttribute › should not match missing attribute [pass] +page/expect-misc.spec.ts › toHaveAttribute › should support boolean attribute with options [pass] +page/expect-misc.spec.ts › toHaveAttribute › support ignoreCase [pass] +page/expect-misc.spec.ts › toHaveCSS › custom css properties [pass] +page/expect-misc.spec.ts › toHaveCSS › pass [pass] +page/expect-misc.spec.ts › toHaveClass › fail [pass] +page/expect-misc.spec.ts › toHaveClass › fail with array [pass] +page/expect-misc.spec.ts › toHaveClass › pass [pass] +page/expect-misc.spec.ts › toHaveClass › pass with SVGs [pass] +page/expect-misc.spec.ts › toHaveClass › pass with array [pass] +page/expect-misc.spec.ts › toHaveCount should not produce logs twice [pass] +page/expect-misc.spec.ts › toHaveCount › eventually pass non-zero [pass] +page/expect-misc.spec.ts › toHaveCount › eventually pass not non-zero [pass] +page/expect-misc.spec.ts › toHaveCount › eventually pass zero [pass] +page/expect-misc.spec.ts › toHaveCount › fail zero [pass] +page/expect-misc.spec.ts › toHaveCount › fail zero 2 [pass] +page/expect-misc.spec.ts › toHaveCount › pass zero [pass] +page/expect-misc.spec.ts › toHaveCount › toHaveCount pass [pass] +page/expect-misc.spec.ts › toHaveId › pass [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail boolean [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail boolean 2 [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail nested [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail number [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail string [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass boolean [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass boolean 2 [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass nested [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass null [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass number [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass string [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass undefined [pass] +page/expect-misc.spec.ts › toHaveRole [pass] +page/expect-misc.spec.ts › toHaveText should not produce logs twice [pass] +page/expect-misc.spec.ts › toHaveText that does not match should not produce logs twice [pass] +page/expect-misc.spec.ts › toHaveTitle › fail [pass] +page/expect-misc.spec.ts › toHaveTitle › pass [pass] +page/expect-misc.spec.ts › toHaveURL › fail [pass] +page/expect-misc.spec.ts › toHaveURL › pass [pass] +page/expect-misc.spec.ts › toHaveURL › support ignoreCase [pass] +page/expect-timeout.spec.ts › should have timeout error name [pass] +page/expect-timeout.spec.ts › should not print timed out error message when page closes [timeout] +page/expect-timeout.spec.ts › should not throw when navigating during first locator handler check [pass] +page/expect-timeout.spec.ts › should not throw when navigating during one-shot check [pass] +page/expect-timeout.spec.ts › should print timed out error message [pass] +page/expect-timeout.spec.ts › should print timed out error message when value does not match [pass] +page/expect-timeout.spec.ts › should print timed out error message when value does not match with impossible timeout [pass] +page/expect-timeout.spec.ts › should print timed out error message with impossible timeout [pass] +page/expect-timeout.spec.ts › should timeout during first locator handler check [pass] +page/expect-to-have-text.spec.ts › not.toHaveText › fail [pass] +page/expect-to-have-text.spec.ts › not.toHaveText › pass [pass] +page/expect-to-have-text.spec.ts › not.toHaveText › should work when selector does not match [pass] +page/expect-to-have-text.spec.ts › toContainText with array › fail [pass] +page/expect-to-have-text.spec.ts › toContainText with array › pass [pass] +page/expect-to-have-text.spec.ts › toContainText with regex › fail [pass] +page/expect-to-have-text.spec.ts › toContainText with regex › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › fail [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › fail on not+empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › fail on repeating array matchers [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass eventually empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass lazy [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass not empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass on empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with regex › fail [pass] +page/expect-to-have-text.spec.ts › toHaveText with regex › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › fail [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › fail with impossible timeout [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › in shadow dom [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › pass contain [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › pass eventually [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › with userInnerText [pass] +page/expect-to-have-value.spec.ts › should support failure [pass] +page/expect-to-have-value.spec.ts › should work [pass] +page/expect-to-have-value.spec.ts › should work with label [pass] +page/expect-to-have-value.spec.ts › should work with regex [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › exact match with text failure [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when items not selected [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when multiple not specified [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when not a select element [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › follows labels [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with regex [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with text [pass] +page/frame-evaluate.spec.ts › evaluateHandle should work [pass] +page/frame-evaluate.spec.ts › should allow cross-frame element handles [fail] +page/frame-evaluate.spec.ts › should be isolated between frames [pass] +page/frame-evaluate.spec.ts › should dispose context on cross-origin navigation [fail] +page/frame-evaluate.spec.ts › should dispose context on navigation [fail] +page/frame-evaluate.spec.ts › should execute after cross-site navigation [pass] +page/frame-evaluate.spec.ts › should have correct execution contexts @smoke [pass] +page/frame-evaluate.spec.ts › should have different execution contexts [pass] +page/frame-evaluate.spec.ts › should not allow cross-frame element handles when frames do not script each other [fail] +page/frame-evaluate.spec.ts › should not allow cross-frame js handles [pass] +page/frame-evaluate.spec.ts › should throw for detached frames [pass] +page/frame-evaluate.spec.ts › should work in iframes that failed initial navigation [fail] +page/frame-evaluate.spec.ts › should work in iframes that interrupted initial javascript url navigation [pass] +page/frame-frame-element.spec.ts › should throw when detached [pass] +page/frame-frame-element.spec.ts › should work @smoke [pass] +page/frame-frame-element.spec.ts › should work inside closed shadow root [fail] +page/frame-frame-element.spec.ts › should work inside declarative shadow root [fail] +page/frame-frame-element.spec.ts › should work with contentFrame [pass] +page/frame-frame-element.spec.ts › should work with frameset [pass] +page/frame-goto.spec.ts › should continue after client redirect [pass] +page/frame-goto.spec.ts › should navigate subframes @smoke [pass] +page/frame-goto.spec.ts › should reject when frame detaches [pass] +page/frame-goto.spec.ts › should return matching responses [fail] +page/frame-hierarchy.spec.ts › should detach child frames on navigation [pass] +page/frame-hierarchy.spec.ts › should handle nested frames @smoke [fail] +page/frame-hierarchy.spec.ts › should not send attach/detach events for main frame [pass] +page/frame-hierarchy.spec.ts › should persist mainFrame on cross-process navigation [pass] +page/frame-hierarchy.spec.ts › should refuse to display x-frame-options:deny iframe [timeout] +page/frame-hierarchy.spec.ts › should report different frame instance when frame re-attaches [pass] +page/frame-hierarchy.spec.ts › should report frame from-inside shadow DOM [pass] +page/frame-hierarchy.spec.ts › should report frame.name() [fail] +page/frame-hierarchy.spec.ts › should report frame.parent() [pass] +page/frame-hierarchy.spec.ts › should return frame.page() [pass] +page/frame-hierarchy.spec.ts › should send "framenavigated" when navigating on anchor URLs [timeout] +page/frame-hierarchy.spec.ts › should send events when frames are manipulated dynamically [pass] +page/frame-hierarchy.spec.ts › should support framesets [fail] +page/interception.spec.ts › should disable memory cache when intercepting [fail] +page/interception.spec.ts › should intercept after a service worker [fail] +page/interception.spec.ts › should intercept blob url requests [unknown] +page/interception.spec.ts › should intercept network activity from worker [fail] +page/interception.spec.ts › should intercept network activity from worker 2 [fail] +page/interception.spec.ts › should intercept worker requests when enabled after worker creation [fail] +page/interception.spec.ts › should not break remote worker importScripts [fail] +page/interception.spec.ts › should work with glob [pass] +page/interception.spec.ts › should work with navigation @smoke [fail] +page/interception.spec.ts › should work with regular expression passed from a different context [fail] +page/jshandle-as-element.spec.ts › should return ElementHandle for TextNodes [pass] +page/jshandle-as-element.spec.ts › should return null for non-elements [pass] +page/jshandle-as-element.spec.ts › should work @smoke [pass] +page/jshandle-as-element.spec.ts › should work with nullified Node [pass] +page/jshandle-evaluate.spec.ts › should work with expression [pass] +page/jshandle-evaluate.spec.ts › should work with function @smoke [pass] +page/jshandle-json-value.spec.ts › should handle circular objects [pass] +page/jshandle-json-value.spec.ts › should work @smoke [pass] +page/jshandle-json-value.spec.ts › should work with dates [pass] +page/jshandle-properties.spec.ts › getProperties should return empty map for non-objects [pass] +page/jshandle-properties.spec.ts › getProperties should return even non-own properties [fail] +page/jshandle-properties.spec.ts › getProperties should work [fail] +page/jshandle-properties.spec.ts › getProperties should work with elements [fail] +page/jshandle-properties.spec.ts › should work @smoke [fail] +page/jshandle-properties.spec.ts › should work with undefined, null, and empty [fail] +page/jshandle-properties.spec.ts › should work with unserializable values [fail] +page/jshandle-to-string.spec.ts › should beautifully render sparse arrays [fail] +page/jshandle-to-string.spec.ts › should work for complicated objects [fail] +page/jshandle-to-string.spec.ts › should work for primitives [pass] +page/jshandle-to-string.spec.ts › should work for promises [fail] +page/jshandle-to-string.spec.ts › should work with different subtypes @smoke [fail] +page/jshandle-to-string.spec.ts › should work with previewable subtypes [fail] +page/locator-click.spec.ts › should click if the target element is removed in pointerdown event [pass] +page/locator-click.spec.ts › should click if the target element is removed in pointerup event [pass] +page/locator-click.spec.ts › should double click the button [pass] +page/locator-click.spec.ts › should work @smoke [pass] +page/locator-click.spec.ts › should work for TextNodes [fail] +page/locator-click.spec.ts › should work with Node removed [pass] +page/locator-convenience.spec.ts › allInnerTexts should work [pass] +page/locator-convenience.spec.ts › allTextContents should work [pass] +page/locator-convenience.spec.ts › getAttribute should work [pass] +page/locator-convenience.spec.ts › innerHTML should work [pass] +page/locator-convenience.spec.ts › innerText should produce log [pass] +page/locator-convenience.spec.ts › innerText should throw [pass] +page/locator-convenience.spec.ts › innerText should work [pass] +page/locator-convenience.spec.ts › inputValue should work [pass] +page/locator-convenience.spec.ts › isChecked should work [pass] +page/locator-convenience.spec.ts › isChecked should work for indeterminate input [pass] +page/locator-convenience.spec.ts › isEditable should work [pass] +page/locator-convenience.spec.ts › isEnabled and isDisabled should work [pass] +page/locator-convenience.spec.ts › should have a nice preview [pass] +page/locator-convenience.spec.ts › should return page [pass] +page/locator-convenience.spec.ts › textContent should work [pass] +page/locator-element-handle.spec.ts › should query existing element @smoke [pass] +page/locator-element-handle.spec.ts › should query existing elements [fail] +page/locator-element-handle.spec.ts › should return empty array for non-existing elements [fail] +page/locator-element-handle.spec.ts › xpath should query existing element [pass] +page/locator-element-handle.spec.ts › xpath should return null for non-existing element [fail] +page/locator-evaluate.spec.ts › should not throw in case of missing selector for all [pass] +page/locator-evaluate.spec.ts › should retrieve content from subtree [pass] +page/locator-evaluate.spec.ts › should retrieve content from subtree for all [pass] +page/locator-evaluate.spec.ts › should work @smoke [pass] +page/locator-evaluate.spec.ts › should work for all [pass] +page/locator-frame.spec.ts › click should survive frame reattach [fail] +page/locator-frame.spec.ts › click should survive iframe navigation [fail] +page/locator-frame.spec.ts › frameLocator.owner should work [fail] +page/locator-frame.spec.ts › getBy coverage [fail] +page/locator-frame.spec.ts › locator.contentFrame should work [fail] +page/locator-frame.spec.ts › locator.frameLocator should not throw on first/last/nth [fail] +page/locator-frame.spec.ts › locator.frameLocator should throw on ambiguity [fail] +page/locator-frame.spec.ts › locator.frameLocator should work for iframe [fail] +page/locator-frame.spec.ts › should click in lazy iframe [fail] +page/locator-frame.spec.ts › should non work for non-frame [fail] +page/locator-frame.spec.ts › should not wait for frame [pass] +page/locator-frame.spec.ts › should not wait for frame 2 [pass] +page/locator-frame.spec.ts › should not wait for frame 3 [pass] +page/locator-frame.spec.ts › should wait for frame [pass] +page/locator-frame.spec.ts › should wait for frame 2 [fail] +page/locator-frame.spec.ts › should wait for frame to go [fail] +page/locator-frame.spec.ts › should work for $ and $$ [fail] +page/locator-frame.spec.ts › should work for iframe @smoke [fail] +page/locator-frame.spec.ts › should work for nested iframe [fail] +page/locator-frame.spec.ts › should work with COEP/COOP/CORP isolated iframe [fail] +page/locator-frame.spec.ts › wait for hidden should succeed when frame is not in dom [pass] +page/locator-frame.spec.ts › waitFor should survive frame reattach [fail] +page/locator-highlight.spec.ts › should highlight locator [pass] +page/locator-is-visible.spec.ts › isVisible and isHidden should work [pass] +page/locator-is-visible.spec.ts › isVisible and isHidden should work with details [pass] +page/locator-is-visible.spec.ts › isVisible during navigation should not throw [timeout] +page/locator-is-visible.spec.ts › isVisible inside a button [pass] +page/locator-is-visible.spec.ts › isVisible inside a role=button [pass] +page/locator-is-visible.spec.ts › isVisible should be true for element outside view [pass] +page/locator-is-visible.spec.ts › isVisible should be true for opacity:0 [pass] +page/locator-is-visible.spec.ts › isVisible with invalid selector should throw [pass] +page/locator-list.spec.ts › locator.all should work [pass] +page/locator-misc-1.spec.ts › focus should respect strictness [pass] +page/locator-misc-1.spec.ts › should check the box [pass] +page/locator-misc-1.spec.ts › should check the box using setChecked [pass] +page/locator-misc-1.spec.ts › should clear input [pass] +page/locator-misc-1.spec.ts › should dispatch click event via ElementHandles [pass] +page/locator-misc-1.spec.ts › should fill input [pass] +page/locator-misc-1.spec.ts › should fill input when Node is removed [pass] +page/locator-misc-1.spec.ts › should focus and blur a button [fail] +page/locator-misc-1.spec.ts › should hover @smoke [pass] +page/locator-misc-1.spec.ts › should hover when Node is removed [pass] +page/locator-misc-1.spec.ts › should select single option [pass] +page/locator-misc-1.spec.ts › should uncheck the box [pass] +page/locator-misc-1.spec.ts › should upload the file [timeout] +page/locator-misc-2.spec.ts › Locator.locator() and FrameLocator.locator() should accept locator [pass] +page/locator-misc-2.spec.ts › locator.count should work with deleted Map in main world [pass] +page/locator-misc-2.spec.ts › should combine visible with other selectors [pass] +page/locator-misc-2.spec.ts › should press @smoke [pass] +page/locator-misc-2.spec.ts › should pressSequentially [pass] +page/locator-misc-2.spec.ts › should return bounding box [pass] +page/locator-misc-2.spec.ts › should scroll into view [pass] +page/locator-misc-2.spec.ts › should scroll zero-sized element into view [pass] +page/locator-misc-2.spec.ts › should select textarea [pass] +page/locator-misc-2.spec.ts › should take screenshot [fail] +page/locator-misc-2.spec.ts › should type [pass] +page/locator-misc-2.spec.ts › should waitFor [pass] +page/locator-misc-2.spec.ts › should waitFor hidden [pass] +page/locator-query.spec.ts › alias methods coverage [pass] +page/locator-query.spec.ts › should allow some, but not all nested frameLocators [pass] +page/locator-query.spec.ts › should enforce same frame for has/leftOf/rightOf/above/below/near [pass] +page/locator-query.spec.ts › should filter by case-insensitive regex in a child [pass] +page/locator-query.spec.ts › should filter by case-insensitive regex in multiple children [pass] +page/locator-query.spec.ts › should filter by regex [pass] +page/locator-query.spec.ts › should filter by regex and regexp flags [pass] +page/locator-query.spec.ts › should filter by regex with a single quote [pass] +page/locator-query.spec.ts › should filter by regex with quotes [pass] +page/locator-query.spec.ts › should filter by regex with special symbols [pass] +page/locator-query.spec.ts › should filter by text [pass] +page/locator-query.spec.ts › should filter by text 2 [pass] +page/locator-query.spec.ts › should filter by text with quotes [pass] +page/locator-query.spec.ts › should respect first() and last() @smoke [pass] +page/locator-query.spec.ts › should respect nth() [pass] +page/locator-query.spec.ts › should support has:locator [pass] +page/locator-query.spec.ts › should support locator.and [pass] +page/locator-query.spec.ts › should support locator.filter [pass] +page/locator-query.spec.ts › should support locator.locator with and/or [pass] +page/locator-query.spec.ts › should support locator.or [pass] +page/locator-query.spec.ts › should throw on capture w/ nth() [pass] +page/locator-query.spec.ts › should throw on due to strictness [pass] +page/locator-query.spec.ts › should throw on due to strictness 2 [pass] +page/matchers.misc.spec.ts › should outlive frame navigation [pass] +page/matchers.misc.spec.ts › should print no-locator-resolved error when locator matcher did not resolve to any element [pass] +page/network-post-data.spec.ts › should get post data for file/blob [fail] +page/network-post-data.spec.ts › should get post data for navigator.sendBeacon api calls [fail] +page/network-post-data.spec.ts › should return correct postData buffer for utf-8 body [fail] +page/network-post-data.spec.ts › should return post data for PUT requests [fail] +page/network-post-data.spec.ts › should return post data w/o content-type @smoke [fail] +page/network-post-data.spec.ts › should throw on invalid JSON in post data [fail] +page/page-accessibility.spec.ts › autocomplete [fail] +page/page-accessibility.spec.ts › checkbox with and tabIndex and label should not have children [fail] +page/page-accessibility.spec.ts › checkbox without label should not have children [fail] +page/page-accessibility.spec.ts › keyshortcuts [fail] +page/page-accessibility.spec.ts › multiselectable [fail] +page/page-accessibility.spec.ts › non editable textbox with role and tabIndex and label should not have children [fail] +page/page-accessibility.spec.ts › orientation [fail] +page/page-accessibility.spec.ts › rich text editable fields should have children [fail] +page/page-accessibility.spec.ts › rich text editable fields with role should have children [fail] +page/page-accessibility.spec.ts › roledescription [fail] +page/page-accessibility.spec.ts › should not report text nodes inside controls [fail] +page/page-accessibility.spec.ts › should return null when the element is no longer in DOM [fail] +page/page-accessibility.spec.ts › should show uninteresting nodes [fail] +page/page-accessibility.spec.ts › should work @smoke [fail] +page/page-accessibility.spec.ts › should work a button [fail] +page/page-accessibility.spec.ts › should work an input [fail] +page/page-accessibility.spec.ts › should work on a menu [fail] +page/page-accessibility.spec.ts › should work when there is a title [fail] +page/page-accessibility.spec.ts › should work with aria-invalid accessibility tree [fail] +page/page-accessibility.spec.ts › should work with regular text [fail] +page/page-add-init-script.spec.ts › init script should run only once in iframe [pass] +page/page-add-init-script.spec.ts › init script should run only once in popup [fail] +page/page-add-init-script.spec.ts › should evaluate before anything else on the page [pass] +page/page-add-init-script.spec.ts › should support multiple scripts [pass] +page/page-add-init-script.spec.ts › should throw without path and content [pass] +page/page-add-init-script.spec.ts › should work after a cross origin navigation [pass] +page/page-add-init-script.spec.ts › should work with CSP [pass] +page/page-add-init-script.spec.ts › should work with a path [pass] +page/page-add-init-script.spec.ts › should work with content @smoke [pass] +page/page-add-init-script.spec.ts › should work with trailing comments [pass] +page/page-add-locator-handler.spec.ts › should not work with force:true [pass] +page/page-add-locator-handler.spec.ts › should removeLocatorHandler [pass] +page/page-add-locator-handler.spec.ts › should throw when handler times out [pass] +page/page-add-locator-handler.spec.ts › should throw when page closes [pass] +page/page-add-locator-handler.spec.ts › should wait for hidden by default [pass] +page/page-add-locator-handler.spec.ts › should wait for hidden by default 2 [pass] +page/page-add-locator-handler.spec.ts › should work [pass] +page/page-add-locator-handler.spec.ts › should work when owner frame detaches [pass] +page/page-add-locator-handler.spec.ts › should work with a custom check [pass] +page/page-add-locator-handler.spec.ts › should work with locator.hover() [pass] +page/page-add-locator-handler.spec.ts › should work with noWaitAfter [pass] +page/page-add-locator-handler.spec.ts › should work with times: option [pass] +page/page-add-locator-handler.spec.ts › should work with toBeVisible [pass] +page/page-add-locator-handler.spec.ts › should work with toHaveScreenshot [fail] +page/page-add-script-tag.spec.ts › should include sourceURL when path is provided [pass] +page/page-add-script-tag.spec.ts › should throw a nice error when the request fails [pass] +page/page-add-script-tag.spec.ts › should throw an error if loading from url fail [pass] +page/page-add-script-tag.spec.ts › should throw an error if no options are provided [pass] +page/page-add-script-tag.spec.ts › should throw when added with URL to the CSP page [pass] +page/page-add-script-tag.spec.ts › should throw when added with content to the CSP page [fail] +page/page-add-script-tag.spec.ts › should work with a content and type=module [pass] +page/page-add-script-tag.spec.ts › should work with a path [pass] +page/page-add-script-tag.spec.ts › should work with a path and type=module [pass] +page/page-add-script-tag.spec.ts › should work with a url [pass] +page/page-add-script-tag.spec.ts › should work with a url and type=module [pass] +page/page-add-script-tag.spec.ts › should work with content [pass] +page/page-add-style-tag.spec.ts › should include sourceURL when path is provided [pass] +page/page-add-style-tag.spec.ts › should throw an error if loading from url fail [pass] +page/page-add-style-tag.spec.ts › should throw an error if no options are provided [pass] +page/page-add-style-tag.spec.ts › should throw when added with URL to the CSP page [pass] +page/page-add-style-tag.spec.ts › should throw when added with content to the CSP page [pass] +page/page-add-style-tag.spec.ts › should work with a path [pass] +page/page-add-style-tag.spec.ts › should work with a url @smoke [pass] +page/page-add-style-tag.spec.ts › should work with content [pass] +page/page-autowaiting-basic.spec.ts › should await cross-process navigation when clicking anchor [pass] +page/page-autowaiting-basic.spec.ts › should await form-get on click [pass] +page/page-autowaiting-basic.spec.ts › should await form-post on click [pass] +page/page-autowaiting-basic.spec.ts › should await navigation when clicking anchor [pass] +page/page-autowaiting-basic.spec.ts › should not stall on JS navigation link [pass] +page/page-autowaiting-basic.spec.ts › should report navigation in the log when clicking anchor [pass] +page/page-autowaiting-basic.spec.ts › should work with dblclick without noWaitAfter when navigation is stalled [pass] +page/page-autowaiting-basic.spec.ts › should work with goto following click [pass] +page/page-autowaiting-basic.spec.ts › should work with noWaitAfter: true [pass] +page/page-autowaiting-basic.spec.ts › should work with waitForLoadState(load) [pass] +page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank [pass] +page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank after non-about:blank [pass] +page/page-autowaiting-no-hang.spec.ts › calling window.open and window.close [pass] +page/page-autowaiting-no-hang.spec.ts › calling window.stop async [pass] +page/page-autowaiting-no-hang.spec.ts › calling window.stop sync [pass] +page/page-autowaiting-no-hang.spec.ts › clicking on links which do not commit navigation [pass] +page/page-autowaiting-no-hang.spec.ts › opening a popup [pass] +page/page-basic.spec.ts › async stacks should work [pass] +page/page-basic.spec.ts › frame.press should work [fail] +page/page-basic.spec.ts › has navigator.webdriver set to true [pass] +page/page-basic.spec.ts › page.close should work with page.close [pass] +page/page-basic.spec.ts › page.close should work with window.close [pass] +page/page-basic.spec.ts › page.frame should respect name [fail] +page/page-basic.spec.ts › page.frame should respect url [pass] +page/page-basic.spec.ts › page.press should work [pass] +page/page-basic.spec.ts › page.press should work for Enter [pass] +page/page-basic.spec.ts › page.title should return the page title [pass] +page/page-basic.spec.ts › page.url should include hashes [pass] +page/page-basic.spec.ts › page.url should work [fail] +page/page-basic.spec.ts › should be callable twice [pass] +page/page-basic.spec.ts › should fail with error upon disconnect [pass] +page/page-basic.spec.ts › should fire domcontentloaded when expected [pass] +page/page-basic.spec.ts › should fire load when expected [pass] +page/page-basic.spec.ts › should have sane user agent [fail] +page/page-basic.spec.ts › should iterate over page properties [pass] +page/page-basic.spec.ts › should pass page to close event [pass] +page/page-basic.spec.ts › should pass self as argument to domcontentloaded event [pass] +page/page-basic.spec.ts › should pass self as argument to load event [pass] +page/page-basic.spec.ts › should provide access to the opener page [pass] +page/page-basic.spec.ts › should reject all promises when page is closed [fail] +page/page-basic.spec.ts › should return null if parent page has been closed [pass] +page/page-basic.spec.ts › should set the page close state [pass] +page/page-basic.spec.ts › should terminate network waiters [pass] +page/page-check.spec.ts › should check radio [pass] +page/page-check.spec.ts › should check radio by aria role [pass] +page/page-check.spec.ts › should check the box @smoke [pass] +page/page-check.spec.ts › should check the box by aria role [pass] +page/page-check.spec.ts › should check the box inside a button [pass] +page/page-check.spec.ts › should check the box using setChecked [pass] +page/page-check.spec.ts › should check the label with position [pass] +page/page-check.spec.ts › should not check the checked box [pass] +page/page-check.spec.ts › should not uncheck the unchecked box [pass] +page/page-check.spec.ts › should throw when not a checkbox [pass] +page/page-check.spec.ts › should throw when not a checkbox 2 [pass] +page/page-check.spec.ts › should uncheck radio by aria role [pass] +page/page-check.spec.ts › should uncheck the box [pass] +page/page-check.spec.ts › should uncheck the box by aria role [pass] +page/page-check.spec.ts › trial run should not check [pass] +page/page-check.spec.ts › trial run should not uncheck [pass] +page/page-click-during-navigation.spec.ts › should not fail with internal error upon navigation [pass] +page/page-click-react.spec.ts › should not retarget the handle when element is recycled [unknown] +page/page-click-react.spec.ts › should not retarget when element changes on hover [pass] +page/page-click-react.spec.ts › should not retarget when element is recycled on hover [pass] +page/page-click-react.spec.ts › should report that selector does not match anymore [unknown] +page/page-click-react.spec.ts › should retarget when element is recycled before enabled check [unknown] +page/page-click-react.spec.ts › should retarget when element is recycled during hit testing [unknown] +page/page-click-react.spec.ts › should timeout when click opens alert [pass] +page/page-click-scroll.spec.ts › should not crash when force-clicking hidden input [pass] +page/page-click-scroll.spec.ts › should not hit scroll bar [pass] +page/page-click-scroll.spec.ts › should scroll into view display:contents [fail] +page/page-click-scroll.spec.ts › should scroll into view display:contents with a child [pass] +page/page-click-scroll.spec.ts › should scroll into view display:contents with position [fail] +page/page-click-scroll.spec.ts › should scroll into view element in iframe [pass] +page/page-click-scroll.spec.ts › should scroll into view span element [pass] +page/page-click-timeout-1.spec.ts › should avoid side effects after timeout [pass] +page/page-click-timeout-1.spec.ts › should timeout waiting for button to be enabled [pass] +page/page-click-timeout-2.spec.ts › should timeout waiting for display:none to be gone [pass] +page/page-click-timeout-2.spec.ts › should timeout waiting for visibility:hidden to be gone [pass] +page/page-click-timeout-3.spec.ts › should fail when element jumps during hit testing [pass] +page/page-click-timeout-3.spec.ts › should report wrong hit target subtree [pass] +page/page-click-timeout-3.spec.ts › should still click when force but hit target is obscured [pass] +page/page-click-timeout-3.spec.ts › should timeout waiting for hit target [pass] +page/page-click-timeout-4.spec.ts › should click for the second time after first timeout [pass] +page/page-click-timeout-4.spec.ts › should timeout waiting for stable position [pass] +page/page-click.spec.ts › ensure events are dispatched in the individual tasks [pass] +page/page-click.spec.ts › should click a button in scrolling container with offset [pass] +page/page-click.spec.ts › should click a button that is overlaid by a permission popup [pass] +page/page-click.spec.ts › should click a partially obscured button [pass] +page/page-click.spec.ts › should click a rotated button [pass] +page/page-click.spec.ts › should click a very large button with offset [pass] +page/page-click.spec.ts › should click an offscreen element when scroll-behavior is smooth [pass] +page/page-click.spec.ts › should click button inside frameset [pass] +page/page-click.spec.ts › should click disabled div [pass] +page/page-click.spec.ts › should click if opened select covers the button [pass] +page/page-click.spec.ts › should click in a nested transformed iframe [timeout] +page/page-click.spec.ts › should click in a transformed iframe [timeout] +page/page-click.spec.ts › should click in a transformed iframe with force [fail] +page/page-click.spec.ts › should click in an iframe with border [pass] +page/page-click.spec.ts › should click in an iframe with border 2 [pass] +page/page-click.spec.ts › should click links which cause navigation [pass] +page/page-click.spec.ts › should click offscreen buttons [pass] +page/page-click.spec.ts › should click on a span with an inline element inside [pass] +page/page-click.spec.ts › should click on checkbox input and toggle [pass] +page/page-click.spec.ts › should click on checkbox label and toggle [pass] +page/page-click.spec.ts › should click svg [pass] +page/page-click.spec.ts › should click the 1x1 div [pass] +page/page-click.spec.ts › should click the button @smoke [pass] +page/page-click.spec.ts › should click the button after a cross origin navigation [pass] +page/page-click.spec.ts › should click the button after navigation [pass] +page/page-click.spec.ts › should click the button behind sticky header [pass] +page/page-click.spec.ts › should click the button if window.Node is removed [pass] +page/page-click.spec.ts › should click the button inside an iframe [pass] +page/page-click.spec.ts › should click the button when window.innerWidth is corrupted [pass] +page/page-click.spec.ts › should click the button with em border with offset [pass] +page/page-click.spec.ts › should click the button with fixed position inside an iframe [timeout] +page/page-click.spec.ts › should click the button with px border with offset [pass] +page/page-click.spec.ts › should click when one of inline box children is outside of viewport [pass] +page/page-click.spec.ts › should click wrapped links [pass] +page/page-click.spec.ts › should click zero-sized input by label [pass] +page/page-click.spec.ts › should climb dom for inner label with pointer-events:none [pass] +page/page-click.spec.ts › should climb up to [role=button] [pass] +page/page-click.spec.ts › should climb up to a [role=link] [pass] +page/page-click.spec.ts › should climb up to a anchor [pass] +page/page-click.spec.ts › should dispatch microtasks in order [pass] +page/page-click.spec.ts › should double click the button [pass] +page/page-click.spec.ts › should fail when element detaches after animation [pass] +page/page-click.spec.ts › should fail when element is animating from outside the viewport with force [pass] +page/page-click.spec.ts › should fail when obscured and not waiting for hit target [pass] +page/page-click.spec.ts › should fire contextmenu event on right click [pass] +page/page-click.spec.ts › should fire contextmenu event on right click in correct order [fail] +page/page-click.spec.ts › should issue clicks in parallel in page and popup [pass] +page/page-click.spec.ts › should not hang when frame is detached [pass] +page/page-click.spec.ts › should not throw UnhandledPromiseRejection when page closes [pass] +page/page-click.spec.ts › should not throw protocol error when navigating during the click [pass] +page/page-click.spec.ts › should not wait with force [pass] +page/page-click.spec.ts › should report nice error when element is detached and force-clicked [pass] +page/page-click.spec.ts › should retry when element detaches after animation [pass] +page/page-click.spec.ts › should retry when element is animating from outside the viewport [pass] +page/page-click.spec.ts › should retry when navigating during the click [pass] +page/page-click.spec.ts › should scroll and click the button [pass] +page/page-click.spec.ts › should scroll and click the button with smooth scroll behavior [pass] +page/page-click.spec.ts › should select the text by triple clicking [pass] +page/page-click.spec.ts › should update modifiers correctly [pass] +page/page-click.spec.ts › should wait for BUTTON to be clickable when it has pointer-events:none [pass] +page/page-click.spec.ts › should wait for LABEL to be clickable when it has pointer-events:none [pass] +page/page-click.spec.ts › should wait for becoming hit target [pass] +page/page-click.spec.ts › should wait for becoming hit target with trial run [pass] +page/page-click.spec.ts › should wait for button to be enabled [pass] +page/page-click.spec.ts › should wait for input to be enabled [pass] +page/page-click.spec.ts › should wait for select to be enabled [pass] +page/page-click.spec.ts › should wait for stable position [pass] +page/page-click.spec.ts › should waitFor display:none to be gone [pass] +page/page-click.spec.ts › should waitFor visibility:hidden to be gone [pass] +page/page-click.spec.ts › should waitFor visible when already visible [pass] +page/page-click.spec.ts › should waitFor visible when parent is hidden [pass] +page/page-click.spec.ts › trial run should not click [pass] +page/page-click.spec.ts › trial run should not double click [pass] +page/page-click.spec.ts › trial run should work with short timeout [pass] +page/page-close.spec.ts › should close page with active dialog [pass] +page/page-close.spec.ts › should not accept dialog after close [pass] +page/page-dialog.spec.ts › should accept the confirm prompt [pass] +page/page-dialog.spec.ts › should allow accepting prompts @smoke [pass] +page/page-dialog.spec.ts › should auto-dismiss the alert without listeners [pass] +page/page-dialog.spec.ts › should auto-dismiss the prompt without listeners [pass] +page/page-dialog.spec.ts › should be able to close context with open alert [pass] +page/page-dialog.spec.ts › should dismiss the confirm prompt [pass] +page/page-dialog.spec.ts › should dismiss the prompt [pass] +page/page-dialog.spec.ts › should fire [pass] +page/page-dialog.spec.ts › should handle multiple alerts [timeout] +page/page-dialog.spec.ts › should handle multiple confirms [timeout] +page/page-dispatchevent.spec.ts › should be atomic [pass] +page/page-dispatchevent.spec.ts › should dispatch absolute device orientation event [pass] +page/page-dispatchevent.spec.ts › should dispatch click after a cross origin navigation [pass] +page/page-dispatchevent.spec.ts › should dispatch click after navigation [pass] +page/page-dispatchevent.spec.ts › should dispatch click event @smoke [pass] +page/page-dispatchevent.spec.ts › should dispatch click event properties [pass] +page/page-dispatchevent.spec.ts › should dispatch click event via ElementHandles [pass] +page/page-dispatchevent.spec.ts › should dispatch click on a span with an inline element inside [pass] +page/page-dispatchevent.spec.ts › should dispatch click svg [pass] +page/page-dispatchevent.spec.ts › should dispatch click when node is added in shadow dom [pass] +page/page-dispatchevent.spec.ts › should dispatch device motion event [pass] +page/page-dispatchevent.spec.ts › should dispatch device orientation event [pass] +page/page-dispatchevent.spec.ts › should dispatch drag drop events [pass] +page/page-dispatchevent.spec.ts › should dispatch drag drop events via ElementHandles [pass] +page/page-dispatchevent.spec.ts › should dispatch wheel event [pass] +page/page-dispatchevent.spec.ts › should not fail when element is blocked on hover [pass] +page/page-dispatchevent.spec.ts › should throw if argument is from different frame [pass] +page/page-drag.spec.ts › Drag and drop › iframe › should drag into an iframe [unknown] +page/page-drag.spec.ts › Drag and drop › iframe › should drag out of an iframe [unknown] +page/page-drag.spec.ts › Drag and drop › should allow specifying the position [pass] +page/page-drag.spec.ts › Drag and drop › should be able to drag the mouse in a frame [pass] +page/page-drag.spec.ts › Drag and drop › should cancel on escape [fail] +page/page-drag.spec.ts › Drag and drop › should not send dragover on the first mousemove [unknown] +page/page-drag.spec.ts › Drag and drop › should respect the drop effect [fail] +page/page-drag.spec.ts › Drag and drop › should send the right events [pass] +page/page-drag.spec.ts › Drag and drop › should work @smoke [pass] +page/page-drag.spec.ts › Drag and drop › should work if a frame is stalled [fail] +page/page-drag.spec.ts › Drag and drop › should work if the drag event is captured but not canceled [pass] +page/page-drag.spec.ts › Drag and drop › should work if the drag is canceled [pass] +page/page-drag.spec.ts › Drag and drop › should work inside iframe [pass] +page/page-drag.spec.ts › Drag and drop › should work with locators [pass] +page/page-drag.spec.ts › Drag and drop › should work with the helper method [pass] +page/page-drag.spec.ts › should handle custom dataTransfer [pass] +page/page-drag.spec.ts › should report event.buttons [pass] +page/page-drag.spec.ts › should work if not doing a drag [pass] +page/page-drag.spec.ts › what happens when dragging element is destroyed [pass] +page/page-emulate-media.spec.ts › should change the actual colors in css [fail] +page/page-emulate-media.spec.ts › should default to light [fail] +page/page-emulate-media.spec.ts › should emulate colorScheme should work @smoke [fail] +page/page-emulate-media.spec.ts › should emulate forcedColors [fail] +page/page-emulate-media.spec.ts › should emulate reduced motion [fail] +page/page-emulate-media.spec.ts › should emulate type @smoke [fail] +page/page-emulate-media.spec.ts › should keep reduced motion and color emulation after reload [fail] +page/page-emulate-media.spec.ts › should throw in case of bad colorScheme argument [pass] +page/page-emulate-media.spec.ts › should throw in case of bad media argument [pass] +page/page-emulate-media.spec.ts › should work during navigation [fail] +page/page-evaluate-handle.spec.ts › should accept multiple nested handles [pass] +page/page-evaluate-handle.spec.ts › should accept nested handle [pass] +page/page-evaluate-handle.spec.ts › should accept nested window handle [pass] +page/page-evaluate-handle.spec.ts › should accept object handle as an argument [pass] +page/page-evaluate-handle.spec.ts › should accept object handle to primitive types [pass] +page/page-evaluate-handle.spec.ts › should accept object handle to unserializable value [pass] +page/page-evaluate-handle.spec.ts › should accept same handle multiple times [pass] +page/page-evaluate-handle.spec.ts › should accept same nested object multiple times [pass] +page/page-evaluate-handle.spec.ts › should pass configurable args [pass] +page/page-evaluate-handle.spec.ts › should work [pass] +page/page-evaluate-handle.spec.ts › should work with primitives [pass] +page/page-evaluate-no-stall.spec.ts › should throw when no main execution context [pass] +page/page-evaluate-no-stall.spec.ts › should throw while pending navigation [fail] +page/page-evaluate-no-stall.spec.ts › should work [pass] +page/page-evaluate.spec.ts › should accept "undefined" as one of multiple parameters [pass] +page/page-evaluate.spec.ts › should accept a string [pass] +page/page-evaluate.spec.ts › should accept a string with comments [pass] +page/page-evaluate.spec.ts › should accept a string with semi colons [pass] +page/page-evaluate.spec.ts › should accept element handle as an argument [pass] +page/page-evaluate.spec.ts › should alias Window, Document and Node [pass] +page/page-evaluate.spec.ts › should await promise [pass] +page/page-evaluate.spec.ts › should await promise from popup [pass] +page/page-evaluate.spec.ts › should be able to throw a tricky error [pass] +page/page-evaluate.spec.ts › should evaluate date [pass] +page/page-evaluate.spec.ts › should evaluate exception [pass] +page/page-evaluate.spec.ts › should evaluate exception with a function on the stack [pass] +page/page-evaluate.spec.ts › should evaluate in the page context [pass] +page/page-evaluate.spec.ts › should evaluate url [pass] +page/page-evaluate.spec.ts › should ignore buggy toJSON [pass] +page/page-evaluate.spec.ts › should jsonValue() date [pass] +page/page-evaluate.spec.ts › should jsonValue() url [pass] +page/page-evaluate.spec.ts › should modify global environment [pass] +page/page-evaluate.spec.ts › should not add a toJSON property to newly created Arrays after evaluation [pass] +page/page-evaluate.spec.ts › should not expose the injected script export [pass] +page/page-evaluate.spec.ts › should not leak handles [pass] +page/page-evaluate.spec.ts › should not leak utility script [pass] +page/page-evaluate.spec.ts › should not throw an error when evaluation does a navigation [pass] +page/page-evaluate.spec.ts › should not throw an error when evaluation does a synchronous navigation and returns an object [pass] +page/page-evaluate.spec.ts › should not throw an error when evaluation does a synchronous navigation and returns undefined [pass] +page/page-evaluate.spec.ts › should not use Array.prototype.toJSON when evaluating [pass] +page/page-evaluate.spec.ts › should not use toJSON in jsonValue [pass] +page/page-evaluate.spec.ts › should not use toJSON when evaluating [pass] +page/page-evaluate.spec.ts › should pass exception argument [pass] +page/page-evaluate.spec.ts › should properly serialize PerformanceMeasure object [pass] +page/page-evaluate.spec.ts › should properly serialize null arguments [pass] +page/page-evaluate.spec.ts › should properly serialize null fields [pass] +page/page-evaluate.spec.ts › should properly serialize undefined arguments [pass] +page/page-evaluate.spec.ts › should properly serialize undefined fields [pass] +page/page-evaluate.spec.ts › should properly serialize window.performance object [pass] +page/page-evaluate.spec.ts › should reject promise with exception [pass] +page/page-evaluate.spec.ts › should respect use strict expression [pass] +page/page-evaluate.spec.ts › should return -0 [pass] +page/page-evaluate.spec.ts › should return -Infinity [pass] +page/page-evaluate.spec.ts › should return Infinity [pass] +page/page-evaluate.spec.ts › should return NaN [pass] +page/page-evaluate.spec.ts › should return complex objects [pass] +page/page-evaluate.spec.ts › should return undefined for non-serializable objects [pass] +page/page-evaluate.spec.ts › should return undefined for objects with symbols [pass] +page/page-evaluate.spec.ts › should return undefined properties [pass] +page/page-evaluate.spec.ts › should roundtrip date [pass] +page/page-evaluate.spec.ts › should roundtrip promise to unserializable values [pass] +page/page-evaluate.spec.ts › should roundtrip promise to value [pass] +page/page-evaluate.spec.ts › should roundtrip regex [pass] +page/page-evaluate.spec.ts › should roundtrip unserializable values [pass] +page/page-evaluate.spec.ts › should roundtrip url [pass] +page/page-evaluate.spec.ts › should simulate a user gesture [pass] +page/page-evaluate.spec.ts › should support thrown numbers as error messages [pass] +page/page-evaluate.spec.ts › should support thrown strings as error messages [pass] +page/page-evaluate.spec.ts › should throw a nice error after a navigation [fail] +page/page-evaluate.spec.ts › should throw error with detailed information on exception inside promise [pass] +page/page-evaluate.spec.ts › should throw if underlying element was disposed [pass] +page/page-evaluate.spec.ts › should throw when evaluation triggers reload [fail] +page/page-evaluate.spec.ts › should throw when frame is detached [pass] +page/page-evaluate.spec.ts › should throw when passed more than one parameter [pass] +page/page-evaluate.spec.ts › should transfer -0 [pass] +page/page-evaluate.spec.ts › should transfer -Infinity [pass] +page/page-evaluate.spec.ts › should transfer 100Mb of data from page to node.js [pass] +page/page-evaluate.spec.ts › should transfer Infinity [pass] +page/page-evaluate.spec.ts › should transfer NaN [pass] +page/page-evaluate.spec.ts › should transfer arrays [pass] +page/page-evaluate.spec.ts › should transfer arrays as arrays, not objects [pass] +page/page-evaluate.spec.ts › should transfer bigint [pass] +page/page-evaluate.spec.ts › should transfer maps as empty objects [pass] +page/page-evaluate.spec.ts › should work @smoke [pass] +page/page-evaluate.spec.ts › should work even when JSON is set to null [pass] +page/page-evaluate.spec.ts › should work for circular object [pass] +page/page-evaluate.spec.ts › should work from-inside an exposed function [fail] +page/page-evaluate.spec.ts › should work right after a cross-origin navigation [fail] +page/page-evaluate.spec.ts › should work right after framenavigated [fail] +page/page-evaluate.spec.ts › should work with Array.from/map [pass] +page/page-evaluate.spec.ts › should work with CSP [pass] +page/page-evaluate.spec.ts › should work with busted Array.prototype.map/push [pass] +page/page-evaluate.spec.ts › should work with function shorthands [pass] +page/page-evaluate.spec.ts › should work with large strings [pass] +page/page-evaluate.spec.ts › should work with large unicode strings [pass] +page/page-evaluate.spec.ts › should work with new Function() and CSP [pass] +page/page-evaluate.spec.ts › should work with non-strict expressions [pass] +page/page-evaluate.spec.ts › should work with overridden Object.defineProperty [pass] +page/page-evaluate.spec.ts › should work with overridden URL/Date/RegExp [pass] +page/page-evaluate.spec.ts › should work with overridden globalThis.Window/Document/Node [pass] +page/page-evaluate.spec.ts › should work with overwritten Promise [pass] +page/page-evaluate.spec.ts › should work with unicode chars [pass] +page/page-event-console.spec.ts › do not update console count on unhandled rejections [pass] +page/page-event-console.spec.ts › should emit same log twice [pass] +page/page-event-console.spec.ts › should format the message correctly with time/timeLog/timeEnd [pass] +page/page-event-console.spec.ts › should have location for console API calls [pass] +page/page-event-console.spec.ts › should not fail for window object [fail] +page/page-event-console.spec.ts › should not throw when there are console messages in detached iframes [pass] +page/page-event-console.spec.ts › should trigger correct Log [timeout] +page/page-event-console.spec.ts › should use object previews for arrays and objects [fail] +page/page-event-console.spec.ts › should use object previews for errors [pass] +page/page-event-console.spec.ts › should use text() for inspection [pass] +page/page-event-console.spec.ts › should work @smoke [fail] +page/page-event-console.spec.ts › should work for different console API calls [fail] +page/page-event-load.spec.ts › should fire once [pass] +page/page-event-load.spec.ts › should fire once with iframe navigation [pass] +page/page-event-network.spec.ts › Page.Events.Request @smoke [fail] +page/page-event-network.spec.ts › Page.Events.RequestFailed @smoke [fail] +page/page-event-network.spec.ts › Page.Events.RequestFinished @smoke [pass] +page/page-event-network.spec.ts › Page.Events.Response @smoke [pass] +page/page-event-network.spec.ts › interrupt request.response() and request.allHeaders() on page.close [fail] +page/page-event-network.spec.ts › should fire events in proper order [pass] +page/page-event-network.spec.ts › should resolve responses after a navigation [timeout] +page/page-event-network.spec.ts › should support redirects [pass] +page/page-event-pageerror.spec.ts › should contain sourceURL [timeout] +page/page-event-pageerror.spec.ts › should contain the Error.name property [timeout] +page/page-event-pageerror.spec.ts › should emit error from unhandled rejects [timeout] +page/page-event-pageerror.spec.ts › should fire [timeout] +page/page-event-pageerror.spec.ts › should handle object [timeout] +page/page-event-pageerror.spec.ts › should handle odd values [timeout] +page/page-event-pageerror.spec.ts › should handle window [timeout] +page/page-event-pageerror.spec.ts › should not receive console message for pageError [timeout] +page/page-event-pageerror.spec.ts › should remove a listener of a non-existing event handler [pass] +page/page-event-pageerror.spec.ts › should support an empty Error.name property [timeout] +page/page-event-popup.spec.ts › should be able to capture alert [timeout] +page/page-event-popup.spec.ts › should emit for immediately closed popups [pass] +page/page-event-popup.spec.ts › should emit for immediately closed popups 2 [pass] +page/page-event-popup.spec.ts › should not treat navigations as new popups [pass] +page/page-event-popup.spec.ts › should report popup opened from iframes [fail] +page/page-event-popup.spec.ts › should work @smoke [pass] +page/page-event-popup.spec.ts › should work with clicking target=_blank [pass] +page/page-event-popup.spec.ts › should work with clicking target=_blank and rel=noopener [pass] +page/page-event-popup.spec.ts › should work with empty url [pass] +page/page-event-popup.spec.ts › should work with fake-clicking target=_blank and rel=noopener [pass] +page/page-event-popup.spec.ts › should work with noopener and about:blank [pass] +page/page-event-popup.spec.ts › should work with noopener and no url [fail] +page/page-event-popup.spec.ts › should work with noopener and url [pass] +page/page-event-popup.spec.ts › should work with window features [pass] +page/page-event-request.spec.ts › main resource xhr should have type xhr [fail] +page/page-event-request.spec.ts › should fire for fetches [pass] +page/page-event-request.spec.ts › should fire for iframes [pass] +page/page-event-request.spec.ts › should fire for navigation requests [pass] +page/page-event-request.spec.ts › should fire requestfailed when intercepting race [unknown] +page/page-event-request.spec.ts › should report navigation requests and responses handled by service worker [fail] +page/page-event-request.spec.ts › should report navigation requests and responses handled by service worker with routing [fail] +page/page-event-request.spec.ts › should report requests and responses handled by service worker [fail] +page/page-event-request.spec.ts › should report requests and responses handled by service worker with routing [fail] +page/page-event-request.spec.ts › should return response body when Cross-Origin-Opener-Policy is set [fail] +page/page-expose-function.spec.ts › exposeBinding should work @smoke [fail] +page/page-expose-function.spec.ts › exposeBinding(handle) should work with element handles [timeout] +page/page-expose-function.spec.ts › exposeBindingHandle should not throw during navigation [fail] +page/page-expose-function.spec.ts › exposeBindingHandle should throw for multiple arguments [fail] +page/page-expose-function.spec.ts › exposeBindingHandle should work [fail] +page/page-expose-function.spec.ts › should alias Window, Document and Node [fail] +page/page-expose-function.spec.ts › should await returned promise [fail] +page/page-expose-function.spec.ts › should be callable from-inside addInitScript [timeout] +page/page-expose-function.spec.ts › should fail with busted Array.prototype.toJSON [fail] +page/page-expose-function.spec.ts › should not result in unhandled rejection [timeout] +page/page-expose-function.spec.ts › should serialize cycles [fail] +page/page-expose-function.spec.ts › should support throwing "null" [fail] +page/page-expose-function.spec.ts › should survive navigation [fail] +page/page-expose-function.spec.ts › should throw exception in page context [fail] +page/page-expose-function.spec.ts › should throw for duplicate registrations [pass] +page/page-expose-function.spec.ts › should work [fail] +page/page-expose-function.spec.ts › should work after cross origin navigation [fail] +page/page-expose-function.spec.ts › should work on frames [fail] +page/page-expose-function.spec.ts › should work on frames before navigation [fail] +page/page-expose-function.spec.ts › should work with busted Array.prototype.map/push [fail] +page/page-expose-function.spec.ts › should work with complex objects [fail] +page/page-expose-function.spec.ts › should work with handles and complex objects [fail] +page/page-expose-function.spec.ts › should work with overridden console object [fail] +page/page-expose-function.spec.ts › should work with setContent [fail] +page/page-fill.spec.ts › fill back to back [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - color [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - date [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - datetime-local [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - month [unknown] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - range [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - time [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - week [unknown] +page/page-fill.spec.ts › should be able to clear using fill() [pass] +page/page-fill.spec.ts › should be able to fill exponent into the input[type=number] [pass] +page/page-fill.spec.ts › should be able to fill input[type=number] with empty string [pass] +page/page-fill.spec.ts › should be able to fill the body [pass] +page/page-fill.spec.ts › should be able to fill the input[type=number] [pass] +page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [pass] +page/page-fill.spec.ts › should fill color input [pass] +page/page-fill.spec.ts › should fill contenteditable [pass] +page/page-fill.spec.ts › should fill contenteditable with new lines [pass] +page/page-fill.spec.ts › should fill date input after clicking [pass] +page/page-fill.spec.ts › should fill datetime-local input [pass] +page/page-fill.spec.ts › should fill different input types [pass] +page/page-fill.spec.ts › should fill elements with existing value and selection [pass] +page/page-fill.spec.ts › should fill fixed position input [pass] +page/page-fill.spec.ts › should fill input [pass] +page/page-fill.spec.ts › should fill month input [pass] +page/page-fill.spec.ts › should fill range input [pass] +page/page-fill.spec.ts › should fill textarea @smoke [pass] +page/page-fill.spec.ts › should fill time input [pass] +page/page-fill.spec.ts › should fill week input [pass] +page/page-fill.spec.ts › should not be able to fill text into the input[type=number] [pass] +page/page-fill.spec.ts › should not throw when fill causes navigation [pass] +page/page-fill.spec.ts › should retry on disabled element [pass] +page/page-fill.spec.ts › should retry on invisible element [pass] +page/page-fill.spec.ts › should retry on readonly element [pass] +page/page-fill.spec.ts › should throw if passed a non-string value [pass] +page/page-fill.spec.ts › should throw nice error without injected script stack when element is not an [fail] +page/page-fill.spec.ts › should throw on incorrect color value [pass] +page/page-fill.spec.ts › should throw on incorrect date [pass] +page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] +page/page-fill.spec.ts › should throw on incorrect month [unknown] +page/page-fill.spec.ts › should throw on incorrect range value [pass] +page/page-fill.spec.ts › should throw on incorrect time [pass] +page/page-fill.spec.ts › should throw on incorrect week [unknown] +page/page-fill.spec.ts › should throw on unsupported inputs [pass] +page/page-focus.spec.ts › clicking checkbox should activate it [unknown] +page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [pass] +page/page-focus.spec.ts › should emit blur event [fail] +page/page-focus.spec.ts › should emit focus event [fail] +page/page-focus.spec.ts › should traverse focus [fail] +page/page-focus.spec.ts › should traverse focus in all directions [pass] +page/page-focus.spec.ts › should traverse only form elements [unknown] +page/page-focus.spec.ts › should work @smoke [pass] +page/page-goto.spec.ts › js redirect overrides url bar navigation [fail] +page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] +page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] +page/page-goto.spec.ts › should capture iframe navigation request [pass] +page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] +page/page-goto.spec.ts › should fail when canceled by another navigation [pass] +page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] +page/page-goto.spec.ts › should fail when exceeding browser context timeout [pass] +page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] +page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] +page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] +page/page-goto.spec.ts › should fail when main resources failed to load [fail] +page/page-goto.spec.ts › should fail when navigating and show the url at the error message [pass] +page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] +page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] +page/page-goto.spec.ts › should fail when navigating to bad url [fail] +page/page-goto.spec.ts › should fail when replaced by another navigation [pass] +page/page-goto.spec.ts › should fail when server returns 204 [fail] +page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] +page/page-goto.spec.ts › should navigate to about:blank [pass] +page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] +page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] +page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] +page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] +page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] +page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] +page/page-goto.spec.ts › should not leak listeners during navigation [pass] +page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] +page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] +page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] +page/page-goto.spec.ts › should override referrer-policy [fail] +page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] +page/page-goto.spec.ts › should properly wait for load [pass] +page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] +page/page-goto.spec.ts › should report raw buffer for main resource [fail] +page/page-goto.spec.ts › should return from goto if new navigation is started [pass] +page/page-goto.spec.ts › should return last response in redirect chain [pass] +page/page-goto.spec.ts › should return response when page changes its URL after load [pass] +page/page-goto.spec.ts › should return url with basic auth info [pass] +page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] +page/page-goto.spec.ts › should send referer [fail] +page/page-goto.spec.ts › should send referer of cross-origin URL [fail] +page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [pass] +page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] +page/page-goto.spec.ts › should use http for no protocol [pass] +page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] +page/page-goto.spec.ts › should work @smoke [pass] +page/page-goto.spec.ts › should work cross-process [pass] +page/page-goto.spec.ts › should work when navigating to 404 [pass] +page/page-goto.spec.ts › should work when navigating to data url [pass] +page/page-goto.spec.ts › should work when navigating to valid url [pass] +page/page-goto.spec.ts › should work when page calls history API in beforeunload [pass] +page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] +page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] +page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [fail] +page/page-goto.spec.ts › should work with anchor navigation [timeout] +page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] +page/page-goto.spec.ts › should work with file URL [pass] +page/page-goto.spec.ts › should work with file URL with subframes [pass] +page/page-goto.spec.ts › should work with lazy loading iframes [pass] +page/page-goto.spec.ts › should work with redirects [pass] +page/page-goto.spec.ts › should work with self requesting page [pass] +page/page-goto.spec.ts › should work with subframes return 204 [pass] +page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] +page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] +page/page-history.spec.ts › page.goBack during renderer-initiated navigation [timeout] +page/page-history.spec.ts › page.goBack should work @smoke [fail] +page/page-history.spec.ts › page.goBack should work for file urls [fail] +page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] +page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] +page/page-history.spec.ts › page.reload during renderer-initiated navigation [pass] +page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] +page/page-history.spec.ts › page.reload should work [pass] +page/page-history.spec.ts › page.reload should work on a page with a hash [pass] +page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] +page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] +page/page-history.spec.ts › page.reload should work with data url [timeout] +page/page-history.spec.ts › page.reload should work with same origin redirect [pass] +page/page-history.spec.ts › regression test for issue 20791 [pass] +page/page-history.spec.ts › should reload proper page [pass] +page/page-keyboard.spec.ts › insertText should only emit input event [fail] +page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [pass] +page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] +page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [pass] +page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [pass] +page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] +page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] +page/page-keyboard.spec.ts › should handle selectAll [pass] +page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] +page/page-keyboard.spec.ts › should move around the selection in a contenteditable [pass] +page/page-keyboard.spec.ts › should move to the start of the document [fail] +page/page-keyboard.spec.ts › should move with the arrow keys [pass] +page/page-keyboard.spec.ts › should not type canceled events [pass] +page/page-keyboard.spec.ts › should press Enter [fail] +page/page-keyboard.spec.ts › should press plus [fail] +page/page-keyboard.spec.ts › should press shift plus [fail] +page/page-keyboard.spec.ts › should press the meta key [pass] +page/page-keyboard.spec.ts › should report multiple modifiers [pass] +page/page-keyboard.spec.ts › should report shiftKey [pass] +page/page-keyboard.spec.ts › should scroll with PageDown [pass] +page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] +page/page-keyboard.spec.ts › should send a character with insertText [fail] +page/page-keyboard.spec.ts › should send proper codes while typing [pass] +page/page-keyboard.spec.ts › should send proper codes while typing with shift [timeout] +page/page-keyboard.spec.ts › should shift raw codes [pass] +page/page-keyboard.spec.ts › should specify location [fail] +page/page-keyboard.spec.ts › should specify repeat property [pass] +page/page-keyboard.spec.ts › should support MacOS shortcuts [fail] +page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] +page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] +page/page-keyboard.spec.ts › should support simple copy-pasting [pass] +page/page-keyboard.spec.ts › should support simple cut-pasting [pass] +page/page-keyboard.spec.ts › should support undo-redo [pass] +page/page-keyboard.spec.ts › should throw on unknown keys [pass] +page/page-keyboard.spec.ts › should type after context menu was opened [pass] +page/page-keyboard.spec.ts › should type all kinds of characters [pass] +page/page-keyboard.spec.ts › should type emoji [pass] +page/page-keyboard.spec.ts › should type emoji into an iframe [pass] +page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] +page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [pass] +page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [pass] +page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [pass] +page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] +page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] +page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [pass] +page/page-leaks.spec.ts › click should not leak [pass] +page/page-leaks.spec.ts › expect should not leak [pass] +page/page-leaks.spec.ts › fill should not leak [pass] +page/page-leaks.spec.ts › waitFor should not leak [pass] +page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] +page/page-listeners.spec.ts › should wait [pass] +page/page-listeners.spec.ts › wait should throw [pass] +page/page-mouse.spec.ts › down and up should generate click [pass] +page/page-mouse.spec.ts › should always round down [fail] +page/page-mouse.spec.ts › should click the document @smoke [pass] +page/page-mouse.spec.ts › should dblclick the div [pass] +page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] +page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] +page/page-mouse.spec.ts › should pointerdown the div with a custom button [pass] +page/page-mouse.spec.ts › should report correct buttons property [pass] +page/page-mouse.spec.ts › should select the text with mouse [pass] +page/page-mouse.spec.ts › should set modifier keys on click [pass] +page/page-mouse.spec.ts › should trigger hover state [pass] +page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] +page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] +page/page-mouse.spec.ts › should tween mouse movement [pass] +page/page-navigation.spec.ts › should work with _blank target [pass] +page/page-navigation.spec.ts › should work with _blank target in form [pass] +page/page-navigation.spec.ts › should work with cross-process _blank target [pass] +page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] +page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] +page/page-network-idle.spec.ts › should wait for networkidle from the popup [pass] +page/page-network-idle.spec.ts › should wait for networkidle in setContent [pass] +page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [pass] +page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [pass] +page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] +page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] +page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [pass] +page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [pass] +page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] +page/page-network-idle.spec.ts › should work after repeated navigations in the same page [fail] +page/page-network-request.spec.ts › page.reload return 304 status code [fail] +page/page-network-request.spec.ts › should get the same headers as the server [fail] +page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] +page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] +page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] +page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] +page/page-network-request.spec.ts › should not allow to access frame on popup main request [pass] +page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] +page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] +page/page-network-request.spec.ts › should not work for a redirect and interception [fail] +page/page-network-request.spec.ts › should override post data content type [fail] +page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] +page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] +page/page-network-request.spec.ts › should parse the json post data [fail] +page/page-network-request.spec.ts › should report all cookies in one header [pass] +page/page-network-request.spec.ts › should report raw headers [fail] +page/page-network-request.spec.ts › should report raw response headers in redirects [fail] +page/page-network-request.spec.ts › should return event source [fail] +page/page-network-request.spec.ts › should return headers [pass] +page/page-network-request.spec.ts › should return multipart/form-data [fail] +page/page-network-request.spec.ts › should return navigation bit [pass] +page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] +page/page-network-request.spec.ts › should return postData [fail] +page/page-network-request.spec.ts › should work for a redirect [pass] +page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] +page/page-network-request.spec.ts › should work for main frame navigation request [pass] +page/page-network-request.spec.ts › should work for subframe navigation request [pass] +page/page-network-request.spec.ts › should work with binary post data [fail] +page/page-network-request.spec.ts › should work with binary post data and interception [fail] +page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [fail] +page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] +page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [fail] +page/page-network-response.spec.ts › should provide a Response with a file URL [fail] +page/page-network-response.spec.ts › should reject response.finished if context closes [fail] +page/page-network-response.spec.ts › should reject response.finished if page closes [fail] +page/page-network-response.spec.ts › should report all headers [fail] +page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] +page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] +page/page-network-response.spec.ts › should return body [fail] +page/page-network-response.spec.ts › should return body for prefetch script [fail] +page/page-network-response.spec.ts › should return body with compression [fail] +page/page-network-response.spec.ts › should return headers after route.fulfill [fail] +page/page-network-response.spec.ts › should return json [fail] +page/page-network-response.spec.ts › should return multiple header value [fail] +page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [fail] +page/page-network-response.spec.ts › should return status text [pass] +page/page-network-response.spec.ts › should return text [fail] +page/page-network-response.spec.ts › should return uncompressed text [fail] +page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] +page/page-network-response.spec.ts › should wait until response completes [fail] +page/page-network-response.spec.ts › should work @smoke [fail] +page/page-network-sizes.spec.ts › should handle redirects [fail] +page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] +page/page-network-sizes.spec.ts › should have the correct responseBodySize [fail] +page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] +page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [fail] +page/page-network-sizes.spec.ts › should return sizes without hanging [pass] +page/page-network-sizes.spec.ts › should set bodySize and headersSize [pass] +page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] +page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] +page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [fail] +page/page-network-sizes.spec.ts › should throw for failed requests [pass] +page/page-network-sizes.spec.ts › should work with 200 status code [fail] +page/page-network-sizes.spec.ts › should work with 401 status code [fail] +page/page-network-sizes.spec.ts › should work with 404 status code [fail] +page/page-network-sizes.spec.ts › should work with 500 status code [fail] +page/page-object-count.spec.ts › should count objects [unknown] +page/page-request-continue.spec.ts › continue should delete headers on redirects [fail] +page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] +page/page-request-continue.spec.ts › continue should propagate headers to redirects [fail] +page/page-request-continue.spec.ts › post data › should amend binary post data [fail] +page/page-request-continue.spec.ts › post data › should amend longer post data [fail] +page/page-request-continue.spec.ts › post data › should amend method and post data [fail] +page/page-request-continue.spec.ts › post data › should amend post data [fail] +page/page-request-continue.spec.ts › post data › should amend utf8 post data [fail] +page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] +page/page-request-continue.spec.ts › post data › should use content-type from original request [fail] +page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] +page/page-request-continue.spec.ts › should amend HTTP headers [fail] +page/page-request-continue.spec.ts › should amend method [fail] +page/page-request-continue.spec.ts › should amend method on main request [fail] +page/page-request-continue.spec.ts › should continue preload link requests [fail] +page/page-request-continue.spec.ts › should delete header with undefined value [fail] +page/page-request-continue.spec.ts › should delete the origin header [fail] +page/page-request-continue.spec.ts › should intercept css variable with background url [fail] +page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [fail] +page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [fail] +page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] +page/page-request-continue.spec.ts › should not throw when continuing while page is closing [fail] +page/page-request-continue.spec.ts › should override method along with url [fail] +page/page-request-continue.spec.ts › should override request url [fail] +page/page-request-continue.spec.ts › should work [fail] +page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] +page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] +page/page-request-fallback.spec.ts › post data › should amend json post data [fail] +page/page-request-fallback.spec.ts › post data › should amend post data [fail] +page/page-request-fallback.spec.ts › should amend HTTP headers [fail] +page/page-request-fallback.spec.ts › should amend method [fail] +page/page-request-fallback.spec.ts › should chain once [fail] +page/page-request-fallback.spec.ts › should delete header with undefined value [fail] +page/page-request-fallback.spec.ts › should fall back [fail] +page/page-request-fallback.spec.ts › should fall back after exception [fail] +page/page-request-fallback.spec.ts › should fall back async [fail] +page/page-request-fallback.spec.ts › should not chain abort [fail] +page/page-request-fallback.spec.ts › should not chain fulfill [fail] +page/page-request-fallback.spec.ts › should override request url [fail] +page/page-request-fallback.spec.ts › should work [fail] +page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [fail] +page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] +page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] +page/page-request-fulfill.spec.ts › should fetch original request and fulfill [fail] +page/page-request-fulfill.spec.ts › should fulfill json [fail] +page/page-request-fulfill.spec.ts › should fulfill preload link requests [fail] +page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [fail] +page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] +page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] +page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] +page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [fail] +page/page-request-fulfill.spec.ts › should fulfill with har response [fail] +page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] +page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [fail] +page/page-request-fulfill.spec.ts › should include the origin header [fail] +page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] +page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [fail] +page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [fail] +page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [fail] +page/page-request-fulfill.spec.ts › should work [fail] +page/page-request-fulfill.spec.ts › should work with buffer as body [fail] +page/page-request-fulfill.spec.ts › should work with file path [fail] +page/page-request-fulfill.spec.ts › should work with status code 422 [fail] +page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] +page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] +page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [fail] +page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] +page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] +page/page-request-intercept.spec.ts › should fulfill with any response [fail] +page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] +page/page-request-intercept.spec.ts › should give access to the intercepted response body [fail] +page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [unknown] +page/page-request-intercept.spec.ts › should intercept with post data override [fail] +page/page-request-intercept.spec.ts › should intercept with url override [fail] +page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [fail] +page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] +page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] +page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] +page/page-route.spec.ts › route.abort should throw if called twice [fail] +page/page-route.spec.ts › route.continue should throw if called twice [fail] +page/page-route.spec.ts › route.fallback should throw if called twice [fail] +page/page-route.spec.ts › route.fulfill should throw if called twice [fail] +page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] +page/page-route.spec.ts › should allow null origin for about:blank [fail] +page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [fail] +page/page-route.spec.ts › should be able to remove headers [fail] +page/page-route.spec.ts › should be abortable [fail] +page/page-route.spec.ts › should be abortable with custom error codes [fail] +page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] +page/page-route.spec.ts › should contain raw request header [fail] +page/page-route.spec.ts › should contain raw response header [fail] +page/page-route.spec.ts › should contain raw response header after fulfill [fail] +page/page-route.spec.ts › should contain referer header [fail] +page/page-route.spec.ts › should fail navigation when aborting main resource [fail] +page/page-route.spec.ts › should fulfill with redirect status [fail] +page/page-route.spec.ts › should intercept @smoke [fail] +page/page-route.spec.ts › should intercept main resource during cross-process navigation [fail] +page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] +page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [fail] +page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] +page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] +page/page-route.spec.ts › should not fulfill with redirect status [unknown] +page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] +page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] +page/page-route.spec.ts › should not work with redirects [fail] +page/page-route.spec.ts › should override cookie header [pass] +page/page-route.spec.ts › should pause intercepted XHR until continue [fail] +page/page-route.spec.ts › should pause intercepted fetch request until continue [fail] +page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] +page/page-route.spec.ts › should reject cors with disallowed credentials [fail] +page/page-route.spec.ts › should respect cors overrides [fail] +page/page-route.spec.ts › should send referer [fail] +page/page-route.spec.ts › should show custom HTTP headers [fail] +page/page-route.spec.ts › should support ? in glob pattern [fail] +page/page-route.spec.ts › should support async handler w/ times [fail] +page/page-route.spec.ts › should support cors for different methods [fail] +page/page-route.spec.ts › should support cors with GET [fail] +page/page-route.spec.ts › should support cors with POST [fail] +page/page-route.spec.ts › should support cors with credentials [fail] +page/page-route.spec.ts › should support the times parameter with route matching [fail] +page/page-route.spec.ts › should unroute [fail] +page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] +page/page-route.spec.ts › should work when POST is redirected with 302 [fail] +page/page-route.spec.ts › should work when header manipulation headers with redirect [fail] +page/page-route.spec.ts › should work with badly encoded server [fail] +page/page-route.spec.ts › should work with custom referer headers [fail] +page/page-route.spec.ts › should work with encoded server [fail] +page/page-route.spec.ts › should work with encoded server - 2 [fail] +page/page-route.spec.ts › should work with equal requests [fail] +page/page-route.spec.ts › should work with redirect inside sync XHR [fail] +page/page-route.spec.ts › should work with redirects for subresources [fail] +page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] +page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] +page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] +page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] +page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] +page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] +page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] +page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] +page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] +page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [pass] +page/page-screenshot.spec.ts › page screenshot › path option should work [fail] +page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] +page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] +page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] +page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] +page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] +page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] +page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] +page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] +page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] +page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] +page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] +page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] +page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] +page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] +page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] +page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] +page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] +page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] +page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] +page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] +page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] +page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] +page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] +page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] +page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] +page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] +page/page-screenshot.spec.ts › should capture css box-shadow [fail] +page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] +page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [pass] +page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] +page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] +page/page-select-option.spec.ts › should fall back to selecting by label [pass] +page/page-select-option.spec.ts › should not allow null items [pass] +page/page-select-option.spec.ts › should not select single option when some attributes do not match [pass] +page/page-select-option.spec.ts › should not throw when select causes navigation [pass] +page/page-select-option.spec.ts › should respect event bubbling [pass] +page/page-select-option.spec.ts › should return [] on no matched values [pass] +page/page-select-option.spec.ts › should return [] on no values [pass] +page/page-select-option.spec.ts › should return an array of matched values [pass] +page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] +page/page-select-option.spec.ts › should select multiple options [pass] +page/page-select-option.spec.ts › should select multiple options with attributes [pass] +page/page-select-option.spec.ts › should select only first option [pass] +page/page-select-option.spec.ts › should select single option @smoke [pass] +page/page-select-option.spec.ts › should select single option by handle [pass] +page/page-select-option.spec.ts › should select single option by index [pass] +page/page-select-option.spec.ts › should select single option by label [pass] +page/page-select-option.spec.ts › should select single option by multiple attributes [pass] +page/page-select-option.spec.ts › should select single option by value [pass] +page/page-select-option.spec.ts › should throw if passed wrong types [pass] +page/page-select-option.spec.ts › should throw when element is not a [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should generate title selector [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should match in shadow dom [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not escape text with >> [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not improve guid text [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not use generated id [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not use input[value] [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should not use text for select [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer button over inner span [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer data-testid [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should separate selectors by >> [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should trim long text [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should trim text [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve role name [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve text [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use nested ordinals [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use parent text [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use readable id [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should work with tricky attributes [fail] -bidi-firefox-beta-library › library/selector-generator.spec.ts › selector generator › should work without CSS.escape [fail] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should handle errors [pass] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should not rely on engines working from the root [fail] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should work [fail] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should work in main and isolated world [fail] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should work when registered on global [fail] -bidi-firefox-beta-library › library/selectors-register.spec.ts › should work with path [fail] -bidi-firefox-beta-library › library/shared-worker.spec.ts › should survive shared worker restart [pass] -bidi-firefox-beta-library › library/signals.spec.ts › should close the browser when the node process closes [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › should remove temp dir on process.exit [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] -bidi-firefox-beta-library › library/signals.spec.ts › signals › should report browser close signal 2 [timeout] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo check [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo click [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo fill [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo focus [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo goto [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo hover [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo press [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo type [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo check [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo click [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo fill [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo focus [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo goto [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo hover [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo press [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo reload [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo type [fail] -bidi-firefox-beta-library › library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture frame [pass] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture iframe [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [pass] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture resources [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should capture snapshot target [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should collect multiple [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should collect on attribute change [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should collect snapshot [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should have a custom doctype [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect attr removal [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect node removal [fail] -bidi-firefox-beta-library › library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] -bidi-firefox-beta-library › library/tap.spec.ts › locators › should send all of the correct events [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should send all of the correct events @smoke [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should send well formed touch points [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should wait until an element is visible to tap it [fail] -bidi-firefox-beta-library › library/tap.spec.ts › should work with modifiers [fail] -bidi-firefox-beta-library › library/tap.spec.ts › trial run should not tap [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should allow hiding route actions [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should capture data-url svg iframe [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should contain action info [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should contain adopted style sheets [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should display language-specific locators [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should filter network requests by resource type [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should filter network requests by url [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should follow redirects [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle file URIs [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle multiple headers [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should handle src=blob [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have correct snapshot size [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have correct stack trace [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have network request overrides [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have network request overrides 2 [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should have network requests [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight expect failure [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should highlight target elements [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should ignore 304 responses [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include metainfo [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include requestUrl in route.abort [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should not crash with broken locator [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open console errors on click [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open simple trace viewer [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open snapshot in new browser context [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open trace viewer on specific host [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open trace-1.31 [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open trace-1.37 [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open two trace files [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open two trace files of the same test [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should open two trace viewers [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should pick locator [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should pick locator in iframe [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should popup snapshot [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should preserve currentSrc [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should register custom elements [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should remove noscript by default [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should render console [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should render network bars [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should restore control values [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should restore scroll positions [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should serve css without content-type [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should serve overridden request [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show action source [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show baseURL in metadata pane [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show correct request start time [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show empty trace viewer [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show font preview [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show null as a param [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show params and return value [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show similar actions from library-only trace [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should show snapshot URL [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should update highlight when typing [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [fail] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with meta CSP [unknown] -bidi-firefox-beta-library › library/trace-viewer.spec.ts › should work with nesting CSS selectors [unknown] -bidi-firefox-beta-library › library/tracing.spec.ts › should collect sources [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should collect trace with resources, but no js [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should collect two traces [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should exclude internal pages [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should export trace concurrently to second navigation [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should flush console events on tracing stop [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should hide internal stack frames [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should hide internal stack frames in expect [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should ignore iframes in head [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should include context API requests [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should include interrupted actions [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should not collect snapshots by default [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should not emit after w/o before [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should not flush console events [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should not hang for clicks that open dialogs [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should not include buffers in the trace [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should not stall on dialogs [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should overwrite existing file [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should produce screencast frames crop [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should produce screencast frames fit [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should produce screencast frames scale [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should record global request trace [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should record network failures [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should respect tracesDir and name [fail] -bidi-firefox-beta-library › library/tracing.spec.ts › should store global request traces separately [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should store postData for global request [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should throw when starting with different options [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should throw when stopping without start [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should use the correct apiName for event driven callbacks [pass] -bidi-firefox-beta-library › library/tracing.spec.ts › should work with multiple chunks [fail] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [fail] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [pass] -bidi-firefox-beta-library › library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [pass] -bidi-firefox-beta-library › library/video.spec.ts › screencast › saveAs should throw when no video frames [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should be 800x450 by default [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should be 800x600 with null viewport [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture css transformation [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture full viewport [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture navigation [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture static page [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should delete video [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should emulate an iphone [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should expose video path [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should expose video path blank page [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should expose video path blank popup [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should not create video for internal pages [unknown] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should scale frames down to the requested size [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should throw if browser dies [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should throw on browser close [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should work for popups [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with old options [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with video+trace [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › should work with weird screen resolution [timeout] -bidi-firefox-beta-library › library/video.spec.ts › screencast › videoSize should require videosPath [pass] -bidi-firefox-beta-library › library/video.spec.ts › should saveAs video [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should emit binary frame events [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should emit close events [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should emit error [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should emit frame events [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should not have stray error events [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should pass self as argument to close event [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] -bidi-firefox-beta-library › library/web-socket.spec.ts › should turn off when offline [unknown] -bidi-firefox-beta-library › library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file +library/beforeunload.spec.ts › should access page after beforeunload [fail] +library/beforeunload.spec.ts › should be able to navigate away from page with beforeunload [fail] +library/beforeunload.spec.ts › should close browser with beforeunload page [fail] +library/beforeunload.spec.ts › should close browsercontext with beforeunload page [pass] +library/beforeunload.spec.ts › should close page with beforeunload listener [pass] +library/beforeunload.spec.ts › should not stall on evaluate when dismissing beforeunload [fail] +library/beforeunload.spec.ts › should run beforeunload if asked for @smoke [fail] +library/browser.spec.ts › should create new page @smoke [pass] +library/browser.spec.ts › should dispatch page.on(close) upon browser.close and reject evaluate [pass] +library/browser.spec.ts › should return browserType [pass] +library/browser.spec.ts › should throw upon second create new page [pass] +library/browser.spec.ts › version should work [pass] +library/browsercontext-add-cookies.spec.ts › should add cookies with empty value [pass] +library/browsercontext-add-cookies.spec.ts › should allow unnamed cookies [fail] +library/browsercontext-add-cookies.spec.ts › should be able to set unsecure cookie for HTTP website [pass] +library/browsercontext-add-cookies.spec.ts › should default to setting secure cookie for HTTPS websites [pass] +library/browsercontext-add-cookies.spec.ts › should have |expires| set to |-1| for session cookies [pass] +library/browsercontext-add-cookies.spec.ts › should isolate cookies between launches [pass] +library/browsercontext-add-cookies.spec.ts › should isolate cookies in browser contexts [pass] +library/browsercontext-add-cookies.spec.ts › should isolate persistent cookies [pass] +library/browsercontext-add-cookies.spec.ts › should isolate send cookie header [fail] +library/browsercontext-add-cookies.spec.ts › should isolate session cookies [pass] +library/browsercontext-add-cookies.spec.ts › should not block third party SameSite=None cookies [fail] +library/browsercontext-add-cookies.spec.ts › should not set a cookie on a data URL page [pass] +library/browsercontext-add-cookies.spec.ts › should not set a cookie with blank page URL [pass] +library/browsercontext-add-cookies.spec.ts › should roundtrip cookie [pass] +library/browsercontext-add-cookies.spec.ts › should send cookie header [pass] +library/browsercontext-add-cookies.spec.ts › should set a cookie on a different domain [pass] +library/browsercontext-add-cookies.spec.ts › should set a cookie with a path [pass] +library/browsercontext-add-cookies.spec.ts › should set cookie with reasonable defaults [fail] +library/browsercontext-add-cookies.spec.ts › should set cookies for a frame [pass] +library/browsercontext-add-cookies.spec.ts › should set multiple cookies [pass] +library/browsercontext-add-cookies.spec.ts › should set secure cookies on secure WebSocket [fail] +library/browsercontext-add-cookies.spec.ts › should work @smoke [pass] +library/browsercontext-add-cookies.spec.ts › should work with expires=-1 [fail] +library/browsercontext-add-cookies.spec.ts › should(not) block third party cookies [fail] +library/browsercontext-add-init-script.spec.ts › should work with browser context scripts @smoke [pass] +library/browsercontext-add-init-script.spec.ts › should work with browser context scripts for already created pages [pass] +library/browsercontext-add-init-script.spec.ts › should work with browser context scripts with a path [pass] +library/browsercontext-add-init-script.spec.ts › should work without navigation in popup [fail] +library/browsercontext-add-init-script.spec.ts › should work without navigation, after all bindings [fail] +library/browsercontext-base-url.spec.ts › should be able to match a URL relative to its given URL with urlMatcher [fail] +library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newContext is passed to page.goto @smoke [pass] +library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newPage is passed to page.goto [pass] +library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browserType.launchPersistentContext is passed to page.goto [fail] +library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL with a trailing slash in browser.newPage is passed to page.goto [pass] +library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL without a trailing slash in browser.newPage is passed to page.goto [pass] +library/browsercontext-base-url.spec.ts › should not construct a new URL when valid URLs are passed [pass] +library/browsercontext-base-url.spec.ts › should not construct a new URL with baseURL when a glob was used [pass] +library/browsercontext-basic.spec.ts › close() should abort waitForEvent [fail] +library/browsercontext-basic.spec.ts › close() should be callable twice [pass] +library/browsercontext-basic.spec.ts › close() should work for empty context [pass] +library/browsercontext-basic.spec.ts › default user agent [pass] +library/browsercontext-basic.spec.ts › setContent should work after disabling javascript [fail] +library/browsercontext-basic.spec.ts › should be able to click across browser contexts [fail] +library/browsercontext-basic.spec.ts › should be able to navigate after disabling javascript [pass] +library/browsercontext-basic.spec.ts › should close all belonging pages once closing context [fail] +library/browsercontext-basic.spec.ts › should create new context @smoke [pass] +library/browsercontext-basic.spec.ts › should disable javascript [fail] +library/browsercontext-basic.spec.ts › should emulate media in cross-process iframe [fail] +library/browsercontext-basic.spec.ts › should emulate media in popup [fail] +library/browsercontext-basic.spec.ts › should emulate navigator.onLine [fail] +library/browsercontext-basic.spec.ts › should isolate localStorage and cookies @smoke [pass] +library/browsercontext-basic.spec.ts › should make a copy of default viewport [pass] +library/browsercontext-basic.spec.ts › should not allow deviceScaleFactor with null viewport [pass] +library/browsercontext-basic.spec.ts › should not allow isMobile with null viewport [pass] +library/browsercontext-basic.spec.ts › should not hang on promises after disabling javascript [pass] +library/browsercontext-basic.spec.ts › should not report frameless pages on error [pass] +library/browsercontext-basic.spec.ts › should pass self to close event [pass] +library/browsercontext-basic.spec.ts › should propagate default viewport to the page [pass] +library/browsercontext-basic.spec.ts › should respect deviceScaleFactor [pass] +library/browsercontext-basic.spec.ts › should return all of the pages [pass] +library/browsercontext-basic.spec.ts › should work with offline option [fail] +library/browsercontext-basic.spec.ts › window.open should use parent tab context [pass] +library/browsercontext-clearcookies.spec.ts › should clear cookies [pass] +library/browsercontext-clearcookies.spec.ts › should isolate cookies when clearing [pass] +library/browsercontext-clearcookies.spec.ts › should remove cookies by domain [pass] +library/browsercontext-clearcookies.spec.ts › should remove cookies by name [pass] +library/browsercontext-clearcookies.spec.ts › should remove cookies by name and domain [pass] +library/browsercontext-clearcookies.spec.ts › should remove cookies by name regex [pass] +library/browsercontext-clearcookies.spec.ts › should remove cookies by path [pass] +library/browsercontext-cookies.spec.ts › should add cookies with an expiration [pass] +library/browsercontext-cookies.spec.ts › should be able to send third party cookies via an iframe [fail] +library/browsercontext-cookies.spec.ts › should get a cookie @smoke [fail] +library/browsercontext-cookies.spec.ts › should get a non-session cookie [fail] +library/browsercontext-cookies.spec.ts › should get cookies from multiple urls [pass] +library/browsercontext-cookies.spec.ts › should get multiple cookies [fail] +library/browsercontext-cookies.spec.ts › should parse cookie with large Max-Age correctly [fail] +library/browsercontext-cookies.spec.ts › should properly report "Lax" sameSite cookie [pass] +library/browsercontext-cookies.spec.ts › should properly report "Strict" sameSite cookie [pass] +library/browsercontext-cookies.spec.ts › should properly report httpOnly cookie [pass] +library/browsercontext-cookies.spec.ts › should return cookies with empty value [pass] +library/browsercontext-cookies.spec.ts › should return no cookies in pristine browser context [pass] +library/browsercontext-cookies.spec.ts › should return secure cookies based on HTTP(S) protocol [pass] +library/browsercontext-cookies.spec.ts › should support requestStorageAccess [fail] +library/browsercontext-cookies.spec.ts › should work with subdomain cookie [pass] +library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching hostname [pass] +library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching port [pass] +library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching scheme [pass] +library/browsercontext-credentials.spec.ts › should fail with wrong credentials [timeout] +library/browsercontext-credentials.spec.ts › should fail without credentials [timeout] +library/browsercontext-credentials.spec.ts › should return resource body [fail] +library/browsercontext-credentials.spec.ts › should work with correct credentials @smoke [fail] +library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin [fail] +library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin case insensitive [fail] +library/browsercontext-credentials.spec.ts › should work with setHTTPCredentials [timeout] +library/browsercontext-csp.spec.ts › should bypass CSP header [fail] +library/browsercontext-csp.spec.ts › should bypass CSP in iframes as well [fail] +library/browsercontext-csp.spec.ts › should bypass CSP meta tag @smoke [fail] +library/browsercontext-csp.spec.ts › should bypass after cross-process navigation [fail] +library/browsercontext-device.spec.ts › device › should emulate viewport and screen size [fail] +library/browsercontext-device.spec.ts › device › should emulate viewport without screen size [fail] +library/browsercontext-device.spec.ts › device › should reset scroll top after a navigation [pass] +library/browsercontext-device.spec.ts › device › should scroll to a precise position with mobile scale [pass] +library/browsercontext-device.spec.ts › device › should scroll to click [pass] +library/browsercontext-device.spec.ts › device › should scroll twice when emulated [fail] +library/browsercontext-device.spec.ts › device › should support clicking [pass] +library/browsercontext-device.spec.ts › device › should work @smoke [fail] +library/browsercontext-dsf.spec.ts › should fetch hidpi assets [fail] +library/browsercontext-dsf.spec.ts › should fetch lodpi assets @smoke [pass] +library/browsercontext-events.spec.ts › console event should work @smoke [pass] +library/browsercontext-events.spec.ts › console event should work in immediately closed popup [fail] +library/browsercontext-events.spec.ts › console event should work in popup [pass] +library/browsercontext-events.spec.ts › console event should work in popup 2 [fail] +library/browsercontext-events.spec.ts › dialog event should work @smoke [pass] +library/browsercontext-events.spec.ts › dialog event should work in immediately closed popup [pass] +library/browsercontext-events.spec.ts › dialog event should work in popup [pass] +library/browsercontext-events.spec.ts › dialog event should work in popup 2 [fail] +library/browsercontext-events.spec.ts › dialog event should work with inline script tag [fail] +library/browsercontext-events.spec.ts › weberror event should work [fail] +library/browsercontext-expose-function.spec.ts › expose binding should work [fail] +library/browsercontext-expose-function.spec.ts › exposeBindingHandle should work [fail] +library/browsercontext-expose-function.spec.ts › should be callable from-inside addInitScript [fail] +library/browsercontext-expose-function.spec.ts › should throw for duplicate registrations [pass] +library/browsercontext-expose-function.spec.ts › should work [fail] +library/browsercontext-expose-function.spec.ts › should work with CSP [fail] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail if response content-length header is missing (br) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with chunked responses (without Content-Length header) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should support decompression [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail if response content-length header is missing (deflate) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with chunked responses (without Content-Length header) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should support decompression [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail if response content-length header is missing (gzip) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with chunked responses (without Content-Length header) [pass] +library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should support decompression [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work on request fixture [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › https post should work with ignoreHTTPSErrors option [pass] +library/browsercontext-fetch-happy-eyeballs.spec.ts › should work with ip6 and port as the host [pass] +library/browsercontext-fetch.spec.ts › context request should export same storage state as context [pass] +library/browsercontext-fetch.spec.ts › delete should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › delete should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › delete should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › delete should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › delete should support post data [pass] +library/browsercontext-fetch.spec.ts › deleteshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › fetch should not throw on long set-cookie value [pass] +library/browsercontext-fetch.spec.ts › fetch should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › fetch should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › fetch should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › fetch should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › fetch should work [pass] +library/browsercontext-fetch.spec.ts › fetchshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › get should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › get should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › get should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › get should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › get should support post data [pass] +library/browsercontext-fetch.spec.ts › get should work @smoke [pass] +library/browsercontext-fetch.spec.ts › getshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › head should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › head should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › head should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › head should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › head should support post data [pass] +library/browsercontext-fetch.spec.ts › headshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › patch should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › patch should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › patch should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › patch should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › patch should support post data [pass] +library/browsercontext-fetch.spec.ts › patchshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › post should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › post should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › post should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › post should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › post should support post data [pass] +library/browsercontext-fetch.spec.ts › postshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › put should support failOnStatusCode [pass] +library/browsercontext-fetch.spec.ts › put should support params passed as URLSearchParams [pass] +library/browsercontext-fetch.spec.ts › put should support params passed as object [pass] +library/browsercontext-fetch.spec.ts › put should support params passed as string [pass] +library/browsercontext-fetch.spec.ts › put should support post data [pass] +library/browsercontext-fetch.spec.ts › putshould support ignoreHTTPSErrors option [pass] +library/browsercontext-fetch.spec.ts › should abort requests when browser context closes [pass] +library/browsercontext-fetch.spec.ts › should accept bool and numeric params [pass] +library/browsercontext-fetch.spec.ts › should add cookies from Set-Cookie header [pass] +library/browsercontext-fetch.spec.ts › should add default headers [fail] +library/browsercontext-fetch.spec.ts › should add default headers to redirects [pass] +library/browsercontext-fetch.spec.ts › should add session cookies to request [pass] +library/browsercontext-fetch.spec.ts › should allow to override default headers [pass] +library/browsercontext-fetch.spec.ts › should dispose [pass] +library/browsercontext-fetch.spec.ts › should dispose when context closes [pass] +library/browsercontext-fetch.spec.ts › should encode to application/json by default [pass] +library/browsercontext-fetch.spec.ts › should follow redirects [pass] +library/browsercontext-fetch.spec.ts › should follow redirects correctly when Location header contains UTF-8 characters [pass] +library/browsercontext-fetch.spec.ts › should handle cookies on redirects [pass] +library/browsercontext-fetch.spec.ts › should inherit ignoreHTTPSErrors from context [pass] +library/browsercontext-fetch.spec.ts › should not add context cookie if cookie header passed as a parameter [pass] +library/browsercontext-fetch.spec.ts › should not hang on a brotli encoded Range request [pass] +library/browsercontext-fetch.spec.ts › should not lose body while handling Set-Cookie header [pass] +library/browsercontext-fetch.spec.ts › should not work after context dispose [pass] +library/browsercontext-fetch.spec.ts › should not work after dispose [pass] +library/browsercontext-fetch.spec.ts › should override request parameters [pass] +library/browsercontext-fetch.spec.ts › should preserve cookie order from Set-Cookie header [pass] +library/browsercontext-fetch.spec.ts › should propagate custom headers with redirects [pass] +library/browsercontext-fetch.spec.ts › should propagate extra http headers with redirects [fail] +library/browsercontext-fetch.spec.ts › should remove cookie with expires far in the past [pass] +library/browsercontext-fetch.spec.ts › should remove cookie with negative max-age [pass] +library/browsercontext-fetch.spec.ts › should resolve url relative to baseURL [pass] +library/browsercontext-fetch.spec.ts › should respect timeout after redirects [pass] +library/browsercontext-fetch.spec.ts › should retry on ECONNRESET [pass] +library/browsercontext-fetch.spec.ts › should return error with wrong credentials [pass] +library/browsercontext-fetch.spec.ts › should return raw headers [pass] +library/browsercontext-fetch.spec.ts › should send content-length [pass] +library/browsercontext-fetch.spec.ts › should send secure cookie over http for localhost [pass] +library/browsercontext-fetch.spec.ts › should serialize data to json regardless of content-type [pass] +library/browsercontext-fetch.spec.ts › should set domain=localhost cookie [pass] +library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for browser.newPage [pass] +library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for newContext [pass] +library/browsercontext-fetch.spec.ts › should support SameSite cookie attribute over https [pass] +library/browsercontext-fetch.spec.ts › should support a timeout of 0 [pass] +library/browsercontext-fetch.spec.ts › should support application/x-www-form-urlencoded [pass] +library/browsercontext-fetch.spec.ts › should support brotli compression [pass] +library/browsercontext-fetch.spec.ts › should support cookie with empty value [pass] +library/browsercontext-fetch.spec.ts › should support deflate compression [pass] +library/browsercontext-fetch.spec.ts › should support gzip compression [pass] +library/browsercontext-fetch.spec.ts › should support https [pass] +library/browsercontext-fetch.spec.ts › should support multipart/form-data [pass] +library/browsercontext-fetch.spec.ts › should support multipart/form-data and keep the order [pass] +library/browsercontext-fetch.spec.ts › should support multipart/form-data with ReadStream values [pass] +library/browsercontext-fetch.spec.ts › should support repeating names in multipart/form-data [unknown] +library/browsercontext-fetch.spec.ts › should support set-cookie with SameSite and without Secure attribute over HTTP [pass] +library/browsercontext-fetch.spec.ts › should support timeout option [pass] +library/browsercontext-fetch.spec.ts › should throw informative error on corrupted brotli body [pass] +library/browsercontext-fetch.spec.ts › should throw informative error on corrupted deflate body [pass] +library/browsercontext-fetch.spec.ts › should throw informative error on corrupted gzip body [pass] +library/browsercontext-fetch.spec.ts › should throw nice error on unsupported data type [pass] +library/browsercontext-fetch.spec.ts › should throw on invalid header value [pass] +library/browsercontext-fetch.spec.ts › should throw on network error [pass] +library/browsercontext-fetch.spec.ts › should throw on network error after redirect [pass] +library/browsercontext-fetch.spec.ts › should throw on network error when sending body [pass] +library/browsercontext-fetch.spec.ts › should throw on network error when sending body after redirect [pass] +library/browsercontext-fetch.spec.ts › should throw on non-http(s) protocol [pass] +library/browsercontext-fetch.spec.ts › should update host header on redirect [pass] +library/browsercontext-fetch.spec.ts › should work with connectOverCDP [unknown] +library/browsercontext-fetch.spec.ts › should work with http credentials [pass] +library/browsercontext-fetch.spec.ts › should work with setHTTPCredentials [pass] +library/browsercontext-har.spec.ts › by default should abort requests not found in har [pass] +library/browsercontext-har.spec.ts › context.unrouteAll should stop context.routeFromHAR [fail] +library/browsercontext-har.spec.ts › fallback:continue should continue requests on bad har [pass] +library/browsercontext-har.spec.ts › fallback:continue should continue when not found in har [pass] +library/browsercontext-har.spec.ts › newPage should fulfill from har, matching the method and following redirects [pass] +library/browsercontext-har.spec.ts › page.unrouteAll should stop page.routeFromHAR [pass] +library/browsercontext-har.spec.ts › should apply overrides before routing from har [pass] +library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] +library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [fail] +library/browsercontext-har.spec.ts › should context.routeFromHAR, matching the method and following redirects [pass] +library/browsercontext-har.spec.ts › should disambiguate by header [fail] +library/browsercontext-har.spec.ts › should fulfill from har with content in a file [pass] +library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] +library/browsercontext-har.spec.ts › should goForward to redirected navigation [timeout] +library/browsercontext-har.spec.ts › should ignore aborted requests [pass] +library/browsercontext-har.spec.ts › should ignore boundary when matching multipart/form-data body [timeout] +library/browsercontext-har.spec.ts › should only context.routeFromHAR requests matching url filter [pass] +library/browsercontext-har.spec.ts › should only handle requests matching url filter [pass] +library/browsercontext-har.spec.ts › should only page.routeFromHAR requests matching url filter [fail] +library/browsercontext-har.spec.ts › should page.routeFromHAR, matching the method and following redirects [pass] +library/browsercontext-har.spec.ts › should produce extracted zip [fail] +library/browsercontext-har.spec.ts › should record overridden requests to har [timeout] +library/browsercontext-har.spec.ts › should reload redirected navigation [fail] +library/browsercontext-har.spec.ts › should round-trip extracted har.zip [fail] +library/browsercontext-har.spec.ts › should round-trip har with postData [fail] +library/browsercontext-har.spec.ts › should round-trip har.zip [fail] +library/browsercontext-har.spec.ts › should support regex filter [pass] +library/browsercontext-har.spec.ts › should update extracted har.zip for page [fail] +library/browsercontext-har.spec.ts › should update har.zip for context [fail] +library/browsercontext-har.spec.ts › should update har.zip for page [fail] +library/browsercontext-har.spec.ts › should update har.zip for page with different options [fail] +library/browsercontext-locale.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().locale [fail] +library/browsercontext-locale.spec.ts › should affect accept-language header @smoke [fail] +library/browsercontext-locale.spec.ts › should affect navigator.language [fail] +library/browsercontext-locale.spec.ts › should affect navigator.language in popups [fail] +library/browsercontext-locale.spec.ts › should be isolated between contexts [fail] +library/browsercontext-locale.spec.ts › should format date [fail] +library/browsercontext-locale.spec.ts › should format number [fail] +library/browsercontext-locale.spec.ts › should format number in popups [fail] +library/browsercontext-locale.spec.ts › should format number in workers [fail] +library/browsercontext-locale.spec.ts › should not change default locale in another context [fail] +library/browsercontext-locale.spec.ts › should work for multiple pages sharing same process [timeout] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.Request [fail] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFailed [fail] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFinished [pass] +library/browsercontext-network-event.spec.ts › BrowserContext.Events.Response [fail] +library/browsercontext-network-event.spec.ts › should fire events in proper order [pass] +library/browsercontext-network-event.spec.ts › should not fire events for favicon or favicon redirects [unknown] +library/browsercontext-page-event.spec.ts › should fire page lifecycle events [fail] +library/browsercontext-page-event.spec.ts › should have about:blank for empty url with domcontentloaded [timeout] +library/browsercontext-page-event.spec.ts › should have about:blank url with domcontentloaded [pass] +library/browsercontext-page-event.spec.ts › should have an opener [fail] +library/browsercontext-page-event.spec.ts › should have url [fail] +library/browsercontext-page-event.spec.ts › should have url after domcontentloaded [pass] +library/browsercontext-page-event.spec.ts › should not crash while redirecting of original request was missed [pass] +library/browsercontext-page-event.spec.ts › should not hang on ctrl-click during provisional load [fail] +library/browsercontext-page-event.spec.ts › should report initialized pages [fail] +library/browsercontext-page-event.spec.ts › should report when a new page is created and closed [fail] +library/browsercontext-page-event.spec.ts › should work with Ctrl-clicking [fail] +library/browsercontext-page-event.spec.ts › should work with Shift-clicking [fail] +library/browsercontext-pages.spec.ts › frame.focus should work multiple times [fail] +library/browsercontext-pages.spec.ts › page.context should return the correct instance [pass] +library/browsercontext-pages.spec.ts › should click the button with deviceScaleFactor set [fail] +library/browsercontext-pages.spec.ts › should click the button with offset with page scale [pass] +library/browsercontext-pages.spec.ts › should click with disabled javascript [pass] +library/browsercontext-pages.spec.ts › should keep selection in multiple pages [fail] +library/browsercontext-pages.spec.ts › should not be visible in context.pages [fail] +library/browsercontext-pages.spec.ts › should not hang with touch-enabled viewports [pass] +library/browsercontext-pages.spec.ts › should not leak listeners during navigation of 20 pages [pass] +library/browsercontext-pages.spec.ts › should return bounding box with page scale [pass] +library/browsercontext-proxy.spec.ts › does launch without a port [pass] +library/browsercontext-proxy.spec.ts › should authenticate [fail] +library/browsercontext-proxy.spec.ts › should authenticate with empty password [fail] +library/browsercontext-proxy.spec.ts › should exclude patterns [fail] +library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts [fail] +library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts on navigation [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › link-local [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › localhost [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] +library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] +library/browsercontext-proxy.spec.ts › should set cookie for top-level domain [pass] +library/browsercontext-proxy.spec.ts › should throw for bad server value [pass] +library/browsercontext-proxy.spec.ts › should throw for socks4 authentication [pass] +library/browsercontext-proxy.spec.ts › should throw for socks5 authentication [pass] +library/browsercontext-proxy.spec.ts › should use ipv6 proxy [fail] +library/browsercontext-proxy.spec.ts › should use proxy [fail] +library/browsercontext-proxy.spec.ts › should use proxy for https urls [timeout] +library/browsercontext-proxy.spec.ts › should use proxy for second page [fail] +library/browsercontext-proxy.spec.ts › should use proxy twice [fail] +library/browsercontext-proxy.spec.ts › should use socks proxy [fail] +library/browsercontext-proxy.spec.ts › should use socks proxy in second page [fail] +library/browsercontext-proxy.spec.ts › should work when passing the proxy only on the context level [fail] +library/browsercontext-proxy.spec.ts › should work with IP:PORT notion [fail] +library/browsercontext-reuse.spec.ts › should continue issuing events after closing the reused page [pass] +library/browsercontext-reuse.spec.ts › should ignore binding from beforeunload [fail] +library/browsercontext-reuse.spec.ts › should not cache resources [timeout] +library/browsercontext-reuse.spec.ts › should re-add binding after reset [fail] +library/browsercontext-reuse.spec.ts › should reset mouse position [fail] +library/browsercontext-reuse.spec.ts › should reset serviceworker [pass] +library/browsercontext-reuse.spec.ts › should reset serviceworker that hangs in importScripts [pass] +library/browsercontext-reuse.spec.ts › should reset tracing [pass] +library/browsercontext-reuse.spec.ts › should work with clock emulation [pass] +library/browsercontext-route.spec.ts › should chain fallback [fail] +library/browsercontext-route.spec.ts › should chain fallback into page [pass] +library/browsercontext-route.spec.ts › should chain fallback w/ dynamic URL [fail] +library/browsercontext-route.spec.ts › should fall back async [fail] +library/browsercontext-route.spec.ts › should fall back to context.route [fail] +library/browsercontext-route.spec.ts › should ignore secure Set-Cookie header for insecure requests [pass] +library/browsercontext-route.spec.ts › should intercept [fail] +library/browsercontext-route.spec.ts › should not chain abort [pass] +library/browsercontext-route.spec.ts › should not chain fulfill [fail] +library/browsercontext-route.spec.ts › should overwrite post body with empty string [fail] +library/browsercontext-route.spec.ts › should support Set-Cookie header [fail] +library/browsercontext-route.spec.ts › should support async handler w/ times [fail] +library/browsercontext-route.spec.ts › should support the times parameter with route matching [fail] +library/browsercontext-route.spec.ts › should unroute [fail] +library/browsercontext-route.spec.ts › should use Set-Cookie header in future requests [fail] +library/browsercontext-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] +library/browsercontext-route.spec.ts › should work with ignoreHTTPSErrors [fail] +library/browsercontext-route.spec.ts › should yield to page.route [fail] +library/browsercontext-service-worker-policy.spec.ts › block › blocks service worker registration [timeout] +library/browsercontext-service-worker-policy.spec.ts › block › should not throw error on about:blank [pass] +library/browsercontext-service-worker-policy.spec.ts › should allow service workers by default [pass] +library/browsercontext-set-extra-http-headers.spec.ts › should override extra headers from browser context [fail] +library/browsercontext-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] +library/browsercontext-storage-state.spec.ts › should capture cookies [pass] +library/browsercontext-storage-state.spec.ts › should capture local storage [fail] +library/browsercontext-storage-state.spec.ts › should handle malformed file [pass] +library/browsercontext-storage-state.spec.ts › should handle missing file [pass] +library/browsercontext-storage-state.spec.ts › should not emit events about internal page [fail] +library/browsercontext-storage-state.spec.ts › should not restore localStorage twice [pass] +library/browsercontext-storage-state.spec.ts › should round-trip through the file [pass] +library/browsercontext-storage-state.spec.ts › should serialize storageState with lone surrogates [pass] +library/browsercontext-storage-state.spec.ts › should set local storage [fail] +library/browsercontext-storage-state.spec.ts › should work when service worker is intefering [pass] +library/browsercontext-strict.spec.ts › should not fail page.textContent in non-strict mode [fail] +library/browsercontext-strict.spec.ts › strict context mode › should fail page.click in strict mode [fail] +library/browsercontext-strict.spec.ts › strict context mode › should fail page.textContent in strict mode [fail] +library/browsercontext-strict.spec.ts › strict context mode › should opt out of strict mode [fail] +library/browsercontext-timezone-id.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().timeZone [fail] +library/browsercontext-timezone-id.spec.ts › should not change default timezone in another context [fail] +library/browsercontext-timezone-id.spec.ts › should throw for invalid timezone IDs when creating pages [fail] +library/browsercontext-timezone-id.spec.ts › should work @smoke [fail] +library/browsercontext-timezone-id.spec.ts › should work for multiple pages sharing same process [timeout] +library/browsercontext-user-agent.spec.ts › custom user agent for download [fail] +library/browsercontext-user-agent.spec.ts › should emulate device user-agent [fail] +library/browsercontext-user-agent.spec.ts › should make a copy of default options [fail] +library/browsercontext-user-agent.spec.ts › should work [fail] +library/browsercontext-user-agent.spec.ts › should work for navigator.userAgentData and sec-ch-ua headers [unknown] +library/browsercontext-user-agent.spec.ts › should work for subframes [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › default mobile viewports to 980 width [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › mouse should work with mobile viewports and cross process navigations [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › respect meta viewport tag [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should be detectable [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should detect touch when applying viewport with touches [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should emulate the hover media feature [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should fire orientationchange event [timeout] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should scroll when emulating a mobile viewport [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support landscape emulation [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support mobile emulation [pass] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support touch emulation [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support window.orientation emulation [fail] +library/browsercontext-viewport-mobile.spec.ts › mobile viewport › view scale should reset after navigation [pass] +library/browsercontext-viewport.spec.ts › WebKit Windows headed should have a minimal viewport [unknown] +library/browsercontext-viewport.spec.ts › should be able to get correct orientation angle on non-mobile devices [fail] +library/browsercontext-viewport.spec.ts › should drag with high dpi [fail] +library/browsercontext-viewport.spec.ts › should emulate availWidth and availHeight [fail] +library/browsercontext-viewport.spec.ts › should emulate device height [fail] +library/browsercontext-viewport.spec.ts › should emulate device width [fail] +library/browsercontext-viewport.spec.ts › should get the proper default viewport size [pass] +library/browsercontext-viewport.spec.ts › should not have touch by default [pass] +library/browsercontext-viewport.spec.ts › should report null viewportSize when given null viewport [pass] +library/browsercontext-viewport.spec.ts › should return correct outerWidth and outerHeight [pass] +library/browsercontext-viewport.spec.ts › should set both screen and viewport options [fail] +library/browsercontext-viewport.spec.ts › should set the proper viewport size [pass] +library/browsercontext-viewport.spec.ts › should set window.screen.orientation.type for mobile devices [fail] +library/browsercontext-viewport.spec.ts › should support touch with null viewport [fail] +library/browsercontext-viewport.spec.ts › should throw on tap if hasTouch is not enabled [fail] +library/browsertype-basic.spec.ts › browserType.executablePath should work [unknown] +library/browsertype-basic.spec.ts › browserType.name should work [fail] +library/browsertype-basic.spec.ts › should throw when trying to connect with not-chromium [pass] +library/browsertype-connect.spec.ts › launchServer only › should be able to reconnect to a browser 12 times without warnings [timeout] +library/browsertype-connect.spec.ts › launchServer only › should properly disconnect when connection closes from the server side [timeout] +library/browsertype-connect.spec.ts › launchServer only › should work with cluster [timeout] +library/browsertype-connect.spec.ts › launchServer › disconnected event should be emitted when browser is closed or server is closed [timeout] +library/browsertype-connect.spec.ts › launchServer › disconnected event should have browser as argument [timeout] +library/browsertype-connect.spec.ts › launchServer › setInputFiles should preserve lastModified timestamp [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to connect 20 times to a single server without warnings [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to connect two browsers at the same time [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to connect when the wsEndpoint is passed as an option [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to reconnect to a browser [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 [timeout] +library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 through localhost [timeout] +library/browsertype-connect.spec.ts › launchServer › should connect over http [timeout] +library/browsertype-connect.spec.ts › launchServer › should connect over wss [timeout] +library/browsertype-connect.spec.ts › launchServer › should emit close events on pages and contexts [timeout] +library/browsertype-connect.spec.ts › launchServer › should error when saving download after deletion [timeout] +library/browsertype-connect.spec.ts › launchServer › should filter launch options [timeout] +library/browsertype-connect.spec.ts › launchServer › should fulfill with global fetch result [timeout] +library/browsertype-connect.spec.ts › launchServer › should handle exceptions during connect [timeout] +library/browsertype-connect.spec.ts › launchServer › should ignore page.pause when headed [timeout] +library/browsertype-connect.spec.ts › launchServer › should not throw on close after disconnect [timeout] +library/browsertype-connect.spec.ts › launchServer › should print HTTP error [pass] +library/browsertype-connect.spec.ts › launchServer › should print custom ws close error [pass] +library/browsertype-connect.spec.ts › launchServer › should print ws error [pass] +library/browsertype-connect.spec.ts › launchServer › should properly disconnect when connection closes from the client side [timeout] +library/browsertype-connect.spec.ts › launchServer › should record trace with sources [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject navigation when browser closes [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.close finishes [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.onDisconnect fires [timeout] +library/browsertype-connect.spec.ts › launchServer › should reject waitForSelector when browser closes [timeout] +library/browsertype-connect.spec.ts › launchServer › should respect selectors [timeout] +library/browsertype-connect.spec.ts › launchServer › should save download [timeout] +library/browsertype-connect.spec.ts › launchServer › should save har [timeout] +library/browsertype-connect.spec.ts › launchServer › should saveAs videos from remote browser [timeout] +library/browsertype-connect.spec.ts › launchServer › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +library/browsertype-connect.spec.ts › launchServer › should send extra headers with connect request [pass] +library/browsertype-connect.spec.ts › launchServer › should set the browser connected state [timeout] +library/browsertype-connect.spec.ts › launchServer › should support slowmo option [timeout] +library/browsertype-connect.spec.ts › launchServer › should terminate network waiters [timeout] +library/browsertype-connect.spec.ts › launchServer › should throw when calling waitForNavigation after disconnect [timeout] +library/browsertype-connect.spec.ts › launchServer › should throw when used after isConnected returns false [timeout] +library/browsertype-connect.spec.ts › launchServer › should timeout in connect while connecting [pass] +library/browsertype-connect.spec.ts › launchServer › should timeout in socket while connecting [pass] +library/browsertype-connect.spec.ts › launchServer › should upload large file [timeout] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should check proxy pattern on the client [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should forward non-forwarded requests [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should lead to the error page for forwarded requests when the connection is refused [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy based on the pattern [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy ipv6 localhost requests @smoke [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy local.playwright requests [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests @smoke [unknown] +library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests from fetch api [unknown] +library/browsertype-connect.spec.ts › run-server › disconnected event should be emitted when browser is closed or server is closed [fail] +library/browsertype-connect.spec.ts › run-server › disconnected event should have browser as argument [fail] +library/browsertype-connect.spec.ts › run-server › setInputFiles should preserve lastModified timestamp [fail] +library/browsertype-connect.spec.ts › run-server › should be able to connect 20 times to a single server without warnings [fail] +library/browsertype-connect.spec.ts › run-server › should be able to connect two browsers at the same time [fail] +library/browsertype-connect.spec.ts › run-server › should be able to connect when the wsEndpoint is passed as an option [fail] +library/browsertype-connect.spec.ts › run-server › should be able to reconnect to a browser [fail] +library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 [fail] +library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 through localhost [fail] +library/browsertype-connect.spec.ts › run-server › should connect over http [fail] +library/browsertype-connect.spec.ts › run-server › should connect over wss [fail] +library/browsertype-connect.spec.ts › run-server › should emit close events on pages and contexts [fail] +library/browsertype-connect.spec.ts › run-server › should error when saving download after deletion [fail] +library/browsertype-connect.spec.ts › run-server › should filter launch options [fail] +library/browsertype-connect.spec.ts › run-server › should fulfill with global fetch result [fail] +library/browsertype-connect.spec.ts › run-server › should handle exceptions during connect [pass] +library/browsertype-connect.spec.ts › run-server › should ignore page.pause when headed [fail] +library/browsertype-connect.spec.ts › run-server › should not throw on close after disconnect [fail] +library/browsertype-connect.spec.ts › run-server › should print HTTP error [pass] +library/browsertype-connect.spec.ts › run-server › should print custom ws close error [pass] +library/browsertype-connect.spec.ts › run-server › should print ws error [pass] +library/browsertype-connect.spec.ts › run-server › should properly disconnect when connection closes from the client side [fail] +library/browsertype-connect.spec.ts › run-server › should record trace with sources [fail] +library/browsertype-connect.spec.ts › run-server › should reject navigation when browser closes [fail] +library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.close finishes [fail] +library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.onDisconnect fires [fail] +library/browsertype-connect.spec.ts › run-server › should reject waitForSelector when browser closes [fail] +library/browsertype-connect.spec.ts › run-server › should respect selectors [fail] +library/browsertype-connect.spec.ts › run-server › should save download [fail] +library/browsertype-connect.spec.ts › run-server › should save har [fail] +library/browsertype-connect.spec.ts › run-server › should saveAs videos from remote browser [fail] +library/browsertype-connect.spec.ts › run-server › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] +library/browsertype-connect.spec.ts › run-server › should send extra headers with connect request [pass] +library/browsertype-connect.spec.ts › run-server › should set the browser connected state [fail] +library/browsertype-connect.spec.ts › run-server › should support slowmo option [fail] +library/browsertype-connect.spec.ts › run-server › should terminate network waiters [fail] +library/browsertype-connect.spec.ts › run-server › should throw when calling waitForNavigation after disconnect [fail] +library/browsertype-connect.spec.ts › run-server › should throw when used after isConnected returns false [fail] +library/browsertype-connect.spec.ts › run-server › should timeout in connect while connecting [pass] +library/browsertype-connect.spec.ts › run-server › should timeout in socket while connecting [pass] +library/browsertype-connect.spec.ts › run-server › should upload large file [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should check proxy pattern on the client [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should forward non-forwarded requests [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should lead to the error page for forwarded requests when the connection is refused [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy based on the pattern [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy ipv6 localhost requests @smoke [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy local.playwright requests [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests @smoke [fail] +library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests from fetch api [fail] +library/browsertype-connect.spec.ts › should refuse connecting when versions do not match [pass] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 hub + node chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium through run-driver [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone non-chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 hub + node chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium [unknown] +library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium broken driver [unknown] +library/browsertype-launch-server.spec.ts › launch server › should default to random wsPath [fail] +library/browsertype-launch-server.spec.ts › launch server › should fire "close" event during kill [fail] +library/browsertype-launch-server.spec.ts › launch server › should fire close event [fail] +library/browsertype-launch-server.spec.ts › launch server › should log protocol [fail] +library/browsertype-launch-server.spec.ts › launch server › should provide an error when ws endpoint is incorrect [fail] +library/browsertype-launch-server.spec.ts › launch server › should return child_process instance [fail] +library/browsertype-launch-server.spec.ts › launch server › should work [fail] +library/browsertype-launch-server.spec.ts › launch server › should work when wsPath is missing leading slash [fail] +library/browsertype-launch-server.spec.ts › launch server › should work with host [fail] +library/browsertype-launch-server.spec.ts › launch server › should work with port [fail] +library/browsertype-launch-server.spec.ts › launch server › should work with wsPath [fail] +library/browsertype-launch.spec.ts › should accept objects as options [pass] +library/browsertype-launch.spec.ts › should allow await using [pass] +library/browsertype-launch.spec.ts › should be callable twice [pass] +library/browsertype-launch.spec.ts › should fire close event for all contexts [pass] +library/browsertype-launch.spec.ts › should handle exception [pass] +library/browsertype-launch.spec.ts › should handle timeout [pass] +library/browsertype-launch.spec.ts › should reject all promises when browser is closed [pass] +library/browsertype-launch.spec.ts › should reject if executable path is invalid [pass] +library/browsertype-launch.spec.ts › should reject if launched browser fails immediately [fail] +library/browsertype-launch.spec.ts › should report launch log [pass] +library/browsertype-launch.spec.ts › should throw if page argument is passed [fail] +library/browsertype-launch.spec.ts › should throw if port option is passed [pass] +library/browsertype-launch.spec.ts › should throw if port option is passed for persistent context [pass] +library/browsertype-launch.spec.ts › should throw if userDataDir is passed as an argument [pass] +library/browsertype-launch.spec.ts › should throw if userDataDir option is passed [pass] +library/capabilities.spec.ts › Intl.ListFormat should work [pass] +library/capabilities.spec.ts › SharedArrayBuffer should work @smoke [fail] +library/capabilities.spec.ts › Web Assembly should work @smoke [pass] +library/capabilities.spec.ts › WebSocket should work @smoke [pass] +library/capabilities.spec.ts › loading in HTMLImageElement.prototype [pass] +library/capabilities.spec.ts › make sure that XMLHttpRequest upload events are emitted correctly [pass] +library/capabilities.spec.ts › navigator.clipboard should be present [pass] +library/capabilities.spec.ts › requestFullscreen [fail] +library/capabilities.spec.ts › service worker should cover the iframe [pass] +library/capabilities.spec.ts › service worker should register in an iframe [pass] +library/capabilities.spec.ts › serviceWorker should intercept document request [pass] +library/capabilities.spec.ts › should not crash on page with mp4 @smoke [fail] +library/capabilities.spec.ts › should not crash on showDirectoryPicker [flaky] +library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] +library/capabilities.spec.ts › should play audio @smoke [fail] +library/capabilities.spec.ts › should play video @smoke [pass] +library/capabilities.spec.ts › should play webm video @smoke [pass] +library/capabilities.spec.ts › should respect CSP @smoke [fail] +library/capabilities.spec.ts › should send no Content-Length header for GET requests with a Content-Type [pass] +library/capabilities.spec.ts › should set CloseEvent.wasClean to false when the server terminates a WebSocket connection [fail] +library/capabilities.spec.ts › should support webgl 2 @smoke [pass] +library/capabilities.spec.ts › should support webgl @smoke [fail] +library/capabilities.spec.ts › webkit should define window.safari [unknown] +library/capabilities.spec.ts › window.GestureEvent in WebKit [pass] +library/channels.spec.ts › exposeFunction should not leak [fail] +library/channels.spec.ts › should not generate dispatchers for subresources w/o listeners [pass] +library/channels.spec.ts › should scope CDPSession handles [unknown] +library/channels.spec.ts › should scope browser handles [pass] +library/channels.spec.ts › should scope context handles [pass] +library/channels.spec.ts › should work with the domain module [timeout] +library/chromium/bfcache.spec.ts › bindings should work after restoring from bfcache [fail] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › serviceWorker(), and fromServiceWorker() work [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setExtraHTTPHeaders [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setOffline [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept only serviceworker request, not page [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker importScripts [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker requests (main and within) [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker update requests [unknown] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker (advanced) [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to content-type) of main service worker request [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to redirect) of main service worker request [timeout] +library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report intercepted service worker requests in HAR [timeout] +library/chromium/chromium.spec.ts › Page.route should work with intervention headers [fail] +library/chromium/chromium.spec.ts › http credentials › httpCredentials [timeout] +library/chromium/chromium.spec.ts › serviceWorkers() should return current workers [timeout] +library/chromium/chromium.spec.ts › should close service worker together with the context [timeout] +library/chromium/chromium.spec.ts › should create a worker from a service worker [timeout] +library/chromium/chromium.spec.ts › should create a worker from service worker with noop routing [timeout] +library/chromium/chromium.spec.ts › should emit new service worker on update [timeout] +library/chromium/chromium.spec.ts › should not create a worker from a shared worker [pass] +library/chromium/chromium.spec.ts › should pass args with spaces [fail] +library/chromium/connect-over-cdp.spec.ts › emulate media should not be affected by second connectOverCDP [unknown] +library/chromium/connect-over-cdp.spec.ts › setInputFiles should preserve lastModified timestamp [fail] +library/chromium/connect-over-cdp.spec.ts › should allow tracing over cdp session [fail] +library/chromium/connect-over-cdp.spec.ts › should be able to connect via localhost [fail] +library/chromium/connect-over-cdp.spec.ts › should cleanup artifacts dir after connectOverCDP disconnects due to ws close [fail] +library/chromium/connect-over-cdp.spec.ts › should connect over a ws endpoint [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session twice [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session when passed as a first argument [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to existing page with iframe and navigate [fail] +library/chromium/connect-over-cdp.spec.ts › should connect to existing service workers [fail] +library/chromium/connect-over-cdp.spec.ts › should connect via https [fail] +library/chromium/connect-over-cdp.spec.ts › should connectOverCDP and manage downloads in default context [fail] +library/chromium/connect-over-cdp.spec.ts › should print custom ws close error [fail] +library/chromium/connect-over-cdp.spec.ts › should report all pages in an existing browser [fail] +library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpoint URL JSON webSocketDebuggerUrl is undefined [fail] +library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpointURL returns a non-expected status code [fail] +library/chromium/connect-over-cdp.spec.ts › should return valid browser from context.browser() [fail] +library/chromium/connect-over-cdp.spec.ts › should send default User-Agent header with connect request [timeout] +library/chromium/connect-over-cdp.spec.ts › should send extra headers with connect request [timeout] +library/chromium/connect-over-cdp.spec.ts › should use logger in default context [fail] +library/chromium/connect-over-cdp.spec.ts › should use proxy with connectOverCDP [fail] +library/chromium/css-coverage.spec.ts › should NOT report scripts across navigations [fail] +library/chromium/css-coverage.spec.ts › should ignore injected stylesheets [fail] +library/chromium/css-coverage.spec.ts › should report multiple stylesheets [fail] +library/chromium/css-coverage.spec.ts › should report sourceURLs [fail] +library/chromium/css-coverage.spec.ts › should report stylesheets across navigations [fail] +library/chromium/css-coverage.spec.ts › should report stylesheets that have no coverage [fail] +library/chromium/css-coverage.spec.ts › should work [fail] +library/chromium/css-coverage.spec.ts › should work with a recently loaded stylesheet [fail] +library/chromium/css-coverage.spec.ts › should work with complicated usecases [fail] +library/chromium/css-coverage.spec.ts › should work with media queries [fail] +library/chromium/disable-web-security.spec.ts › test init script w/ --disable-web-security [pass] +library/chromium/disable-web-security.spec.ts › test utility world in popup w/ --disable-web-security [pass] +library/chromium/js-coverage.spec.ts › should NOT report scripts across navigations when enabled [fail] +library/chromium/js-coverage.spec.ts › should ignore eval() scripts by default [fail] +library/chromium/js-coverage.spec.ts › should not hang when there is a debugger statement [fail] +library/chromium/js-coverage.spec.ts › should report multiple scripts [fail] +library/chromium/js-coverage.spec.ts › should report scripts across navigations when disabled [fail] +library/chromium/js-coverage.spec.ts › should report sourceURLs [fail] +library/chromium/js-coverage.spec.ts › should work [fail] +library/chromium/js-coverage.spec.ts › shouldn't ignore eval() scripts if reportAnonymousScripts is true [fail] +library/chromium/launcher.spec.ts › should not create pages automatically [fail] +library/chromium/launcher.spec.ts › should not throw with remote-debugging-port argument [fail] +library/chromium/launcher.spec.ts › should open devtools when "devtools: true" option is given [unknown] +library/chromium/launcher.spec.ts › should return background pages [fail] +library/chromium/launcher.spec.ts › should return background pages when recording video [fail] +library/chromium/launcher.spec.ts › should support request/response events when using backgroundPage() [fail] +library/chromium/launcher.spec.ts › should throw with remote-debugging-pipe argument [fail] +library/chromium/oopif.spec.ts › ElementHandle.boundingBox() should work [pass] +library/chromium/oopif.spec.ts › contentFrame should work [pass] +library/chromium/oopif.spec.ts › should allow cdp sessions on oopifs [fail] +library/chromium/oopif.spec.ts › should be able to click in iframe [fail] +library/chromium/oopif.spec.ts › should click [fail] +library/chromium/oopif.spec.ts › should click a button when it overlays oopif [fail] +library/chromium/oopif.spec.ts › should emit filechooser event for iframe [fail] +library/chromium/oopif.spec.ts › should emulate media [fail] +library/chromium/oopif.spec.ts › should emulate offline [fail] +library/chromium/oopif.spec.ts › should expose function [fail] +library/chromium/oopif.spec.ts › should get the proper viewport [unknown] +library/chromium/oopif.spec.ts › should handle oopif detach [pass] +library/chromium/oopif.spec.ts › should handle remote -> local -> remote transitions [pass] +library/chromium/oopif.spec.ts › should intercept response body from oopif [fail] +library/chromium/oopif.spec.ts › should load oopif iframes with subresources and route [pass] +library/chromium/oopif.spec.ts › should not throw on exposeFunction when oopif detaches [fail] +library/chromium/oopif.spec.ts › should report google.com frame with headed [pass] +library/chromium/oopif.spec.ts › should report main requests [pass] +library/chromium/oopif.spec.ts › should report oopif frames [pass] +library/chromium/oopif.spec.ts › should respect route [pass] +library/chromium/oopif.spec.ts › should support addInitScript [pass] +library/chromium/oopif.spec.ts › should support context options [fail] +library/chromium/oopif.spec.ts › should support exposeFunction [fail] +library/chromium/oopif.spec.ts › should take screenshot [fail] +library/chromium/session.spec.ts › should be able to detach session [fail] +library/chromium/session.spec.ts › should detach when page closes [fail] +library/chromium/session.spec.ts › should enable and disable domains independently [fail] +library/chromium/session.spec.ts › should not break page.close() [fail] +library/chromium/session.spec.ts › should only accept a page or frame [pass] +library/chromium/session.spec.ts › should reject protocol calls when page closes [fail] +library/chromium/session.spec.ts › should send events [fail] +library/chromium/session.spec.ts › should throw if target is part of main [fail] +library/chromium/session.spec.ts › should throw nice errors [fail] +library/chromium/session.spec.ts › should work [fail] +library/chromium/session.spec.ts › should work with main frame [fail] +library/chromium/session.spec.ts › should work with newBrowserCDPSession [fail] +library/chromium/tracing.spec.ts › should create directories as needed [fail] +library/chromium/tracing.spec.ts › should output a trace [fail] +library/chromium/tracing.spec.ts › should return a buffer [fail] +library/chromium/tracing.spec.ts › should run with custom categories if provided [fail] +library/chromium/tracing.spec.ts › should support a buffer without a path [fail] +library/chromium/tracing.spec.ts › should throw if tracing on two pages [fail] +library/chromium/tracing.spec.ts › should work without options [fail] +library/client-certificates.spec.ts › browser › persistentContext › should pass with matching certificates [fail] +library/client-certificates.spec.ts › browser › persistentContext › validate input [pass] +library/client-certificates.spec.ts › browser › should fail with matching certificates in legacy pfx format [pass] +library/client-certificates.spec.ts › browser › should fail with no client certificates [fail] +library/client-certificates.spec.ts › browser › should fail with self-signed client certificates [fail] +library/client-certificates.spec.ts › browser › should handle TLS renegotiation with client certificates [fail] +library/client-certificates.spec.ts › browser › should handle rejected certificate in handshake with HTTP/2 [pass] +library/client-certificates.spec.ts › browser › should have ignoreHTTPSErrors=false by default [fail] +library/client-certificates.spec.ts › browser › should keep supporting http [pass] +library/client-certificates.spec.ts › browser › should not hang on tls errors during TLS 1.2 handshake [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates and trailing slash [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format when passing as content [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates on context APIRequestContext instance [fail] +library/client-certificates.spec.ts › browser › should pass with matching certificates when passing as content [fail] +library/client-certificates.spec.ts › browser › should return target connection errors when using http2 [unknown] +library/client-certificates.spec.ts › browser › should throw a http error if the pfx passphrase is incorect [pass] +library/client-certificates.spec.ts › browser › support http2 [fail] +library/client-certificates.spec.ts › browser › support http2 if the browser only supports http1.1 [unknown] +library/client-certificates.spec.ts › browser › validate input [pass] +library/client-certificates.spec.ts › fetch › pass with trusted client certificates [pass] +library/client-certificates.spec.ts › fetch › pass with trusted client certificates in pfx format [pass] +library/client-certificates.spec.ts › fetch › should fail with matching certificates in legacy pfx format [pass] +library/client-certificates.spec.ts › fetch › should fail with no client certificates provided [pass] +library/client-certificates.spec.ts › fetch › should keep supporting http [pass] +library/client-certificates.spec.ts › fetch › should throw a http error if the pfx passphrase is incorect [pass] +library/client-certificates.spec.ts › fetch › should throw with untrusted client certs [pass] +library/client-certificates.spec.ts › fetch › should work in the browser with request interception [pass] +library/client-certificates.spec.ts › fetch › validate input [pass] +library/clock.spec.ts › Intl API › Creates a RelativeTimeFormat like normal [pass] +library/clock.spec.ts › Intl API › Executes formatRange like normal [pass] +library/clock.spec.ts › Intl API › Executes formatRangeToParts like normal [pass] +library/clock.spec.ts › Intl API › Executes resolvedOptions like normal [pass] +library/clock.spec.ts › Intl API › Executes supportedLocalesOf like normal [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed a timestamp argument that is not first of the month [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed no timestamp and system time is not first of the month [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed a timestamp argument that is first of the month [pass] +library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed no timestamp and system time is first of the month [pass] +library/clock.spec.ts › cancelAnimationFrame › does not remove interval [pass] +library/clock.spec.ts › cancelAnimationFrame › does not remove timeout [pass] +library/clock.spec.ts › cancelAnimationFrame › ignores null argument [pass] +library/clock.spec.ts › cancelAnimationFrame › removes animation frame [pass] +library/clock.spec.ts › cancelIdleCallback › removes idle callback [pass] +library/clock.spec.ts › clearInterval › ignores null argument [pass] +library/clock.spec.ts › clearInterval › removes interval [pass] +library/clock.spec.ts › clearInterval › removes interval with undefined interval [pass] +library/clock.spec.ts › clearInterval › removes timeout [pass] +library/clock.spec.ts › clearTimeout › ignores null argument [pass] +library/clock.spec.ts › clearTimeout › removes interval [pass] +library/clock.spec.ts › clearTimeout › removes interval with undefined interval [pass] +library/clock.spec.ts › clearTimeout › removes timeout [pass] +library/clock.spec.ts › date › creates Date objects representing clock time [pass] +library/clock.spec.ts › date › creates real Date objects [pass] +library/clock.spec.ts › date › creates regular date when passing a date as RFC 2822 string [pass] +library/clock.spec.ts › date › creates regular date when passing a date as string [pass] +library/clock.spec.ts › date › creates regular date when passing timestamp [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s [pass] +library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s, ms [pass] +library/clock.spec.ts › date › creates regular date when passing year, month [pass] +library/clock.spec.ts › date › listens to system clock changes [pass] +library/clock.spec.ts › date › listens to ticking clock [pass] +library/clock.spec.ts › date › mirrors UTC method [pass] +library/clock.spec.ts › date › mirrors native Date.prototype [pass] +library/clock.spec.ts › date › mirrors parse method [pass] +library/clock.spec.ts › date › mirrors toUTCString method [pass] +library/clock.spec.ts › date › provides date constructor [pass] +library/clock.spec.ts › date › returns clock.now() [pass] +library/clock.spec.ts › date › returns date as string representing clock time [pass] +library/clock.spec.ts › date › returns date as string when called as function [pass] +library/clock.spec.ts › date › returns date as string when calling with arguments [pass] +library/clock.spec.ts › date › returns date as string when calling with timestamp [pass] +library/clock.spec.ts › date › supports now method if present [pass] +library/clock.spec.ts › fastForward › handles multiple pending timers and types [pass] +library/clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +library/clock.spec.ts › fastForward › pushes back execution time for skipped timers [pass] +library/clock.spec.ts › pauseAt › fire target timers [pass] +library/clock.spec.ts › pauseAt › pause at target time [pass] +library/clock.spec.ts › pauseAt › returns consumed clicks [pass] +library/clock.spec.ts › performance.now() › should listen to multiple ticks in performance.now [pass] +library/clock.spec.ts › performance.now() › should run along with clock.tick [pass] +library/clock.spec.ts › performance.now() › should run with ticks with timers set [pass] +library/clock.spec.ts › performance.now() › should start at 0 [pass] +library/clock.spec.ts › requestAnimationFrame › returns numeric id or object with numeric id [pass] +library/clock.spec.ts › requestAnimationFrame › returns unique id [pass] +library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() even when performance unavailable [pass] +library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() when available [pass] +library/clock.spec.ts › requestAnimationFrame › should call callback once [pass] +library/clock.spec.ts › requestAnimationFrame › should properly schedule callback for 3rd frame [pass] +library/clock.spec.ts › requestAnimationFrame › should run every 16ms [pass] +library/clock.spec.ts › requestAnimationFrame › should schedule for next frame if on current frame [pass] +library/clock.spec.ts › requestAnimationFrame › should schedule two callbacks before the next frame at the same time [pass] +library/clock.spec.ts › requestAnimationFrame › throws if no arguments [pass] +library/clock.spec.ts › requestIdleCallback › doesn't runs if there are any timers and no timeout option [pass] +library/clock.spec.ts › requestIdleCallback › returns numeric id [pass] +library/clock.spec.ts › requestIdleCallback › returns unique id [pass] +library/clock.spec.ts › requestIdleCallback › runs after all timers [pass] +library/clock.spec.ts › requestIdleCallback › runs no later than timeout option even if there are any timers [pass] +library/clock.spec.ts › requestIdleCallback › throws if no arguments [pass] +library/clock.spec.ts › runFor › calls function with global object or null (strict mode) as this [pass] +library/clock.spec.ts › runFor › creates updated Date while ticking [pass] +library/clock.spec.ts › runFor › creates updated Date while ticking promises [pass] +library/clock.spec.ts › runFor › does not fire canceled intervals [pass] +library/clock.spec.ts › runFor › does not fire intervals canceled in a promise [pass] +library/clock.spec.ts › runFor › does not silently catch errors [pass] +library/clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +library/clock.spec.ts › runFor › fires nested setTimeout calls in user-created promises properly [pass] +library/clock.spec.ts › runFor › fires nested setTimeout calls properly [pass] +library/clock.spec.ts › runFor › fires promise timers in correct order [pass] +library/clock.spec.ts › runFor › fires timer in intervals of "13" [pass] +library/clock.spec.ts › runFor › fires timer in intervals of 13 [pass] +library/clock.spec.ts › runFor › fires timers in correct order [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes 2 [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes in promises [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown [pass] +library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown 2 [pass] +library/clock.spec.ts › runFor › mini integration test [pass] +library/clock.spec.ts › runFor › should settle chained user-created promises [pass] +library/clock.spec.ts › runFor › should settle local nested promises before calling timeouts [pass] +library/clock.spec.ts › runFor › should settle local promises before calling timeouts [pass] +library/clock.spec.ts › runFor › should settle multiple user-created promises [pass] +library/clock.spec.ts › runFor › should settle nested user-created promises [pass] +library/clock.spec.ts › runFor › should settle user-created promises [pass] +library/clock.spec.ts › runFor › should settle user-created promises before calling more timeouts [pass] +library/clock.spec.ts › runFor › should settle user-created promises even if some throw [pass] +library/clock.spec.ts › runFor › throws for negative minutes [pass] +library/clock.spec.ts › runFor › throws on negative ticks [pass] +library/clock.spec.ts › runFor › triggers after sufficient delay [pass] +library/clock.spec.ts › runFor › triggers even when some throw [pass] +library/clock.spec.ts › runFor › triggers immediately without specified delay [pass] +library/clock.spec.ts › runFor › triggers in the order scheduled [pass] +library/clock.spec.ts › runFor › triggers multiple simultaneous timers [pass] +library/clock.spec.ts › runFor › triggers multiple simultaneous timers with zero callAt [pass] +library/clock.spec.ts › runFor › triggers simultaneous timers [pass] +library/clock.spec.ts › runFor › triggers timeouts and intervals in the order scheduled [pass] +library/clock.spec.ts › runFor › waits after setTimeout was called [pass] +library/clock.spec.ts › setInterval › does not schedule recurring timeout when cleared [pass] +library/clock.spec.ts › setInterval › does not throw if |undefined| or |null| is passed as a callback [pass] +library/clock.spec.ts › setInterval › is not influenced by backward system clock changes [pass] +library/clock.spec.ts › setInterval › is not influenced by forward system clock changes [pass] +library/clock.spec.ts › setInterval › passes setTimeout parameters [pass] +library/clock.spec.ts › setInterval › returns numeric id or object with numeric id [pass] +library/clock.spec.ts › setInterval › returns unique id [pass] +library/clock.spec.ts › setInterval › schedules recurring timeout [pass] +library/clock.spec.ts › setInterval › throws if no arguments [pass] +library/clock.spec.ts › setTimeout › calls correct timeout on recursive tick [pass] +library/clock.spec.ts › setTimeout › does not depend on this [pass] +library/clock.spec.ts › setTimeout › does not throw if |undefined| or |null| is passed as a callback [pass] +library/clock.spec.ts › setTimeout › is not influenced by backward system clock changes [pass] +library/clock.spec.ts › setTimeout › is not influenced by forward system clock changes [pass] +library/clock.spec.ts › setTimeout › parses no-numeric string times [pass] +library/clock.spec.ts › setTimeout › parses numeric string times [pass] +library/clock.spec.ts › setTimeout › passes setTimeout parameters [pass] +library/clock.spec.ts › setTimeout › returns numeric id or object with numeric id [pass] +library/clock.spec.ts › setTimeout › returns unique id [pass] +library/clock.spec.ts › setTimeout › sets timers on instance [pass] +library/clock.spec.ts › setTimeout › starts id from a large number [pass] +library/clock.spec.ts › setTimeout › throws if no arguments [pass] +library/clock.spec.ts › setTimeout › use of eval when not in node › evals non-function callbacks [pass] +library/clock.spec.ts › setTimeout › use of eval when not in node › only evals on global scope [pass] +library/clock.spec.ts › stubTimers › deletes global property on uninstall if it was inherited onto the global object [unknown] +library/clock.spec.ts › stubTimers › does not fake methods not provided [pass] +library/clock.spec.ts › stubTimers › fake Date constructor should mirror Date's properties [pass] +library/clock.spec.ts › stubTimers › fakes Date constructor [pass] +library/clock.spec.ts › stubTimers › fakes provided methods [pass] +library/clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +library/clock.spec.ts › stubTimers › mirrors custom Date properties [pass] +library/clock.spec.ts › stubTimers › replace Event.prototype.timeStamp [pass] +library/clock.spec.ts › stubTimers › replaces global clearInterval [pass] +library/clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +library/clock.spec.ts › stubTimers › replaces global performance.now [pass] +library/clock.spec.ts › stubTimers › replaces global setInterval [pass] +library/clock.spec.ts › stubTimers › replaces global setTimeout [pass] +library/clock.spec.ts › stubTimers › resets faked methods [pass] +library/clock.spec.ts › stubTimers › returns clock object [pass] +library/clock.spec.ts › stubTimers › sets initial timestamp [pass] +library/clock.spec.ts › stubTimers › should let performance.mark still be callable after install() (#136) [unknown] +library/clock.spec.ts › stubTimers › should not alter the global performance properties and methods [unknown] +library/clock.spec.ts › stubTimers › should replace the getEntries, getEntriesByX methods with noops that return [] [unknown] +library/clock.spec.ts › stubTimers › takes an object parameter [pass] +library/clock.spec.ts › stubTimers › uninstalls Date constructor [pass] +library/clock.spec.ts › stubTimers › uninstalls global performance.now [pass] +library/clock.spec.ts › works with concurrent runFor calls [pass] +library/clock.spec.ts › works with slow setTimeout in busy embedder [pass] +library/clock.spec.ts › works with slow setTimeout in busy embedder when not paused [pass] +library/component-parser.spec.ts › should escape [pass] +library/component-parser.spec.ts › should parse [pass] +library/component-parser.spec.ts › should parse all operators [pass] +library/component-parser.spec.ts › should parse bool [pass] +library/component-parser.spec.ts › should parse float values [pass] +library/component-parser.spec.ts › should parse identifiers [pass] +library/component-parser.spec.ts › should parse int values [pass] +library/component-parser.spec.ts › should parse regex [pass] +library/component-parser.spec.ts › should parse short attributes [pass] +library/component-parser.spec.ts › should parse unquoted string [pass] +library/component-parser.spec.ts › should throw on malformed selector [pass] +library/component-parser.spec.ts › should tolerate spacing [pass] +library/css-parser.spec.ts › should parse css [pass] +library/css-parser.spec.ts › should throw on malformed css [pass] +library/debug-controller.spec.ts › should highlight all [fail] +library/debug-controller.spec.ts › should navigate all [fail] +library/debug-controller.spec.ts › should pick element [fail] +library/debug-controller.spec.ts › should record [fail] +library/debug-controller.spec.ts › should record custom data-testid [fail] +library/debug-controller.spec.ts › should report pages [fail] +library/debug-controller.spec.ts › should reset for reuse [fail] +library/debug-controller.spec.ts › should reset routes before reuse [fail] +library/defaultbrowsercontext-1.spec.ts › context.addCookies() should work [fail] +library/defaultbrowsercontext-1.spec.ts › context.clearCookies() should work [fail] +library/defaultbrowsercontext-1.spec.ts › context.cookies() should work @smoke [fail] +library/defaultbrowsercontext-1.spec.ts › should support acceptDownloads option [fail] +library/defaultbrowsercontext-1.spec.ts › should support bypassCSP option [fail] +library/defaultbrowsercontext-1.spec.ts › should support deviceScaleFactor option [fail] +library/defaultbrowsercontext-1.spec.ts › should support httpCredentials option [fail] +library/defaultbrowsercontext-1.spec.ts › should support javascriptEnabled option [fail] +library/defaultbrowsercontext-1.spec.ts › should support offline option [fail] +library/defaultbrowsercontext-1.spec.ts › should support userAgent option [fail] +library/defaultbrowsercontext-1.spec.ts › should support viewport option [fail] +library/defaultbrowsercontext-1.spec.ts › should(not) block third party cookies [fail] +library/defaultbrowsercontext-2.spec.ts › coverage should work [unknown] +library/defaultbrowsercontext-2.spec.ts › should accept userDataDir [fail] +library/defaultbrowsercontext-2.spec.ts › should connect to a browser with the default page [fail] +library/defaultbrowsercontext-2.spec.ts › should create userDataDir if it does not exist [fail] +library/defaultbrowsercontext-2.spec.ts › should fire close event for a persistent context [fail] +library/defaultbrowsercontext-2.spec.ts › should handle exception [timeout] +library/defaultbrowsercontext-2.spec.ts › should handle timeout [pass] +library/defaultbrowsercontext-2.spec.ts › should have default URL when launching browser [fail] +library/defaultbrowsercontext-2.spec.ts › should have passed URL when launching with ignoreDefaultArgs: true [fail] +library/defaultbrowsercontext-2.spec.ts › should respect selectors [fail] +library/defaultbrowsercontext-2.spec.ts › should restore state from userDataDir [fail] +library/defaultbrowsercontext-2.spec.ts › should support colorScheme option [fail] +library/defaultbrowsercontext-2.spec.ts › should support extraHTTPHeaders option [fail] +library/defaultbrowsercontext-2.spec.ts › should support forcedColors option [fail] +library/defaultbrowsercontext-2.spec.ts › should support geolocation and permissions options [fail] +library/defaultbrowsercontext-2.spec.ts › should support har option [fail] +library/defaultbrowsercontext-2.spec.ts › should support hasTouch option [fail] +library/defaultbrowsercontext-2.spec.ts › should support ignoreHTTPSErrors option [fail] +library/defaultbrowsercontext-2.spec.ts › should support locale option [fail] +library/defaultbrowsercontext-2.spec.ts › should support reducedMotion option [fail] +library/defaultbrowsercontext-2.spec.ts › should support timezoneId option [fail] +library/defaultbrowsercontext-2.spec.ts › should throw if page argument is passed [fail] +library/defaultbrowsercontext-2.spec.ts › should work in persistent context [fail] +library/defaultbrowsercontext-2.spec.ts › user agent is up to date [fail] +library/download.spec.ts › download event › should be able to cancel pending downloads [fail] +library/download.spec.ts › download event › should close the context without awaiting the download [fail] +library/download.spec.ts › download event › should close the context without awaiting the failed download [unknown] +library/download.spec.ts › download event › should create subdirectories when saving to non-existent user-specified path [fail] +library/download.spec.ts › download event › should delete downloads on browser gone [fail] +library/download.spec.ts › download event › should delete downloads on context destruction [fail] +library/download.spec.ts › download event › should delete file [fail] +library/download.spec.ts › download event › should download large binary.zip [fail] +library/download.spec.ts › download event › should emit download event from nested iframes [timeout] +library/download.spec.ts › download event › should error when saving after deletion [fail] +library/download.spec.ts › download event › should error when saving with downloads disabled [fail] +library/download.spec.ts › download event › should expose stream [fail] +library/download.spec.ts › download event › should not fail explicitly to cancel a download even if that is already finished [fail] +library/download.spec.ts › download event › should report alt-click downloads [fail] +library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Blobs [timeout] +library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Files [fail] +library/download.spec.ts › download event › should report download when navigation turns into download @smoke [timeout] +library/download.spec.ts › download event › should report downloads for download attribute [fail] +library/download.spec.ts › download event › should report downloads with acceptDownloads: false [fail] +library/download.spec.ts › download event › should report downloads with acceptDownloads: true [fail] +library/download.spec.ts › download event › should report downloads with interception [fail] +library/download.spec.ts › download event › should report new window downloads [fail] +library/download.spec.ts › download event › should report non-navigation downloads [fail] +library/download.spec.ts › download event › should report proper download url when download is from download attribute [fail] +library/download.spec.ts › download event › should save to overwritten filepath [fail] +library/download.spec.ts › download event › should save to two different paths with multiple saveAs calls [fail] +library/download.spec.ts › download event › should save to user-specified path without updating original path [fail] +library/download.spec.ts › download event › should throw if browser dies [fail] +library/download.spec.ts › download event › should work with Cross-Origin-Opener-Policy [timeout] +library/download.spec.ts › should be able to download a PDF file [fail] +library/download.spec.ts › should be able to download a inline PDF file via navigation [fail] +library/download.spec.ts › should be able to download a inline PDF file via response interception [fail] +library/download.spec.ts › should convert navigation to a resource with unsupported mime type into download [timeout] +library/download.spec.ts › should download even if there is no "attachment" value [fail] +library/download.spec.ts › should download links with data url [fail] +library/download.spec.ts › should download successfully when routing [fail] +library/download.spec.ts › should save to user-specified path [fail] +library/downloads-path.spec.ts › downloads path › should accept downloads in persistent context [fail] +library/downloads-path.spec.ts › downloads path › should delete downloads when context closes [fail] +library/downloads-path.spec.ts › downloads path › should delete downloads when persistent context closes [fail] +library/downloads-path.spec.ts › downloads path › should keep downloadsPath folder [fail] +library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder [fail] +library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder with a relative path [fail] +library/emulation-focus.spec.ts › should change document.activeElement [pass] +library/emulation-focus.spec.ts › should change focused iframe [pass] +library/emulation-focus.spec.ts › should focus popups by default [fail] +library/emulation-focus.spec.ts › should focus with more than one page/context [fail] +library/emulation-focus.spec.ts › should not affect mouse event target page [pass] +library/emulation-focus.spec.ts › should not affect screenshots [fail] +library/emulation-focus.spec.ts › should not fire blur events when interacting with more than one page/context [fail] +library/emulation-focus.spec.ts › should provide target for keyboard events [pass] +library/emulation-focus.spec.ts › should think that all pages are focused @smoke [fail] +library/emulation-focus.spec.ts › should think that it is focused by default [pass] +library/emulation-focus.spec.ts › should trigger hover state concurrently [fail] +library/events/add-listeners.spec.ts › EventEmitter tests › Listener order [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › listener type check [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › set max listeners test [pass] +library/events/add-listeners.spec.ts › EventEmitter tests › should work [pass] +library/events/check-listener-leaks.spec.ts › _maxListeners still has precedence over defaultMaxListeners [pass] +library/events/check-listener-leaks.spec.ts › defaultMaxListeners [pass] +library/events/check-listener-leaks.spec.ts › process-wide [pass] +library/events/events-list.spec.ts › EventEmitter › should maintain event names correctly [pass] +library/events/listener-count.spec.ts › Listener count test [pass] +library/events/listeners-side-effects.spec.ts › listeners empty check [pass] +library/events/listeners.spec.ts › Array copy modification does not modify orig [pass] +library/events/listeners.spec.ts › EventEmitter listeners with one listener [pass] +library/events/listeners.spec.ts › EventEmitter with no members [pass] +library/events/listeners.spec.ts › Modify array copy after multiple adds [pass] +library/events/listeners.spec.ts › listeners and once [pass] +library/events/listeners.spec.ts › listeners on prototype [pass] +library/events/listeners.spec.ts › listeners with conflicting types [pass] +library/events/listeners.spec.ts › raw listeners [pass] +library/events/listeners.spec.ts › raw listeners order [pass] +library/events/max-listeners.spec.ts › emit maxListeners on e [pass] +library/events/method-names.spec.ts › EventEmitter prototype test [pass] +library/events/modify-in-emit.spec.ts › add and remove listeners [pass] +library/events/modify-in-emit.spec.ts › removing callbacks in emit [pass] +library/events/num-args.spec.ts › should work [pass] +library/events/once.spec.ts › once() has different code paths based on the number of arguments being emitted [pass] +library/events/once.spec.ts › should work [pass] +library/events/prepend.spec.ts › EventEmitter functionality [pass] +library/events/prepend.spec.ts › Verify that the listener must be a function [pass] +library/events/remove-all-listeners-wait.spec.ts › should not throw with ignoreErrors [pass] +library/events/remove-all-listeners-wait.spec.ts › should wait [pass] +library/events/remove-all-listeners-wait.spec.ts › should wait all [pass] +library/events/remove-all-listeners-wait.spec.ts › wait should throw [pass] +library/events/remove-all-listeners.spec.ts › listener count after removeAllListeners [pass] +library/events/remove-all-listeners.spec.ts › listeners [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners on undefined _events [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners removes all listeners [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners returns EventEmitter [pass] +library/events/remove-all-listeners.spec.ts › removeAllListeners with no event type [pass] +library/events/remove-listeners.spec.ts › Eighth test [pass] +library/events/remove-listeners.spec.ts › Fifth test [pass] +library/events/remove-listeners.spec.ts › First test [pass] +library/events/remove-listeners.spec.ts › Fourth test [pass] +library/events/remove-listeners.spec.ts › Ninth test [pass] +library/events/remove-listeners.spec.ts › Second test [pass] +library/events/remove-listeners.spec.ts › Seventh test [pass] +library/events/remove-listeners.spec.ts › Sixth test [pass] +library/events/remove-listeners.spec.ts › Tenth test [pass] +library/events/remove-listeners.spec.ts › Third test [pass] +library/events/set-max-listeners-side-effects.spec.ts › set max listeners test [pass] +library/events/special-event-names.spec.ts › should support special event names [pass] +library/events/subclass.spec.ts › MyEE2 instance [pass] +library/events/subclass.spec.ts › myee instance [pass] +library/events/symbols.spec.ts › should support symbols [pass] +library/favicon.spec.ts › should load svg favicon with prefer-color-scheme [unknown] +library/fetch-proxy.spec.ts › context request should pick up proxy credentials [timeout] +library/fetch-proxy.spec.ts › global request should pick up proxy credentials [pass] +library/fetch-proxy.spec.ts › should support proxy.bypass [pass] +library/fetch-proxy.spec.ts › should use socks proxy [pass] +library/fetch-proxy.spec.ts › should work with context level proxy [pass] +library/firefox/launcher.spec.ts › should pass firefox user preferences [fail] +library/firefox/launcher.spec.ts › should pass firefox user preferences in persistent [fail] +library/geolocation.spec.ts › should isolate contexts [fail] +library/geolocation.spec.ts › should not modify passed default options object [pass] +library/geolocation.spec.ts › should throw when invalid longitude [fail] +library/geolocation.spec.ts › should throw with missing latitude [pass] +library/geolocation.spec.ts › should throw with missing longitude in default options [pass] +library/geolocation.spec.ts › should use context options [timeout] +library/geolocation.spec.ts › should use context options for popup [timeout] +library/geolocation.spec.ts › should work @smoke [timeout] +library/geolocation.spec.ts › watchPosition should be notified [timeout] +library/global-fetch-cookie.spec.ts › should do case-insensitive match of cookie domain [pass] +library/global-fetch-cookie.spec.ts › should do case-insensitive match of request domain [pass] +library/global-fetch-cookie.spec.ts › should export cookies to storage state [pass] +library/global-fetch-cookie.spec.ts › should filter outgoing cookies by domain [pass] +library/global-fetch-cookie.spec.ts › should filter outgoing cookies by path [pass] +library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header [pass] +library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header even if it expired [pass] +library/global-fetch-cookie.spec.ts › should preserve local storage on import/export of storage state [pass] +library/global-fetch-cookie.spec.ts › should remove cookie with expires far in the past [pass] +library/global-fetch-cookie.spec.ts › should remove cookie with negative max-age [pass] +library/global-fetch-cookie.spec.ts › should remove expired cookies [pass] +library/global-fetch-cookie.spec.ts › should send cookies from storage state [pass] +library/global-fetch-cookie.spec.ts › should send not expired cookies [pass] +library/global-fetch-cookie.spec.ts › should send secure cookie over http for localhost [pass] +library/global-fetch-cookie.spec.ts › should send secure cookie over https [pass] +library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header [pass] +library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header even if it contains equal signs [pass] +library/global-fetch-cookie.spec.ts › should work with empty storage state [pass] +library/global-fetch-cookie.spec.ts › storage state should round-trip through file [pass] +library/global-fetch.spec.ts › delete should work @smoke [pass] +library/global-fetch.spec.ts › fetch should work @smoke [pass] +library/global-fetch.spec.ts › get should work @smoke [pass] +library/global-fetch.spec.ts › head should work @smoke [pass] +library/global-fetch.spec.ts › patch should work @smoke [pass] +library/global-fetch.spec.ts › post should work @smoke [pass] +library/global-fetch.spec.ts › put should work @smoke [pass] +library/global-fetch.spec.ts › should abort redirected requests when context is disposed [pass] +library/global-fetch.spec.ts › should abort requests when context is disposed [pass] +library/global-fetch.spec.ts › should accept already serialized data as Buffer when content-type is application/json [pass] +library/global-fetch.spec.ts › should be able to construct with context options [pass] +library/global-fetch.spec.ts › should dispose global request [pass] +library/global-fetch.spec.ts › should have nice toString [pass] +library/global-fetch.spec.ts › should json stringify array body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify bool (false) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify bool body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify literal string undefined body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify null body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify number (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify number body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify object body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify string (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should json stringify string body when content-type is application/json [pass] +library/global-fetch.spec.ts › should keep headers capitalization [pass] +library/global-fetch.spec.ts › should not double stringify array body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify bool (false) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify bool body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify literal string undefined body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify null body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify number (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify number body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify object body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify string (falsey) body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not double stringify string body when content-type is application/json [pass] +library/global-fetch.spec.ts › should not fail on empty body with encoding [pass] +library/global-fetch.spec.ts › should not follow redirects when maxRedirects is set to 0 [pass] +library/global-fetch.spec.ts › should propagate extra http headers with redirects [pass] +library/global-fetch.spec.ts › should propagate ignoreHTTPSErrors on redirects [pass] +library/global-fetch.spec.ts › should remove content-length from redirected post requests [pass] +library/global-fetch.spec.ts › should resolve url relative to global baseURL option [pass] +library/global-fetch.spec.ts › should retry ECONNRESET [pass] +library/global-fetch.spec.ts › should return body for failing requests [pass] +library/global-fetch.spec.ts › should return empty body [pass] +library/global-fetch.spec.ts › should return error with correct credentials and mismatching hostname [pass] +library/global-fetch.spec.ts › should return error with correct credentials and mismatching port [pass] +library/global-fetch.spec.ts › should return error with correct credentials and mismatching scheme [pass] +library/global-fetch.spec.ts › should return error with wrong credentials [pass] +library/global-fetch.spec.ts › should serialize post data on the client [pass] +library/global-fetch.spec.ts › should set playwright as user-agent [pass] +library/global-fetch.spec.ts › should support HTTPCredentials.send [pass] +library/global-fetch.spec.ts › should support WWW-Authenticate: Basic [pass] +library/global-fetch.spec.ts › should support global httpCredentials option [pass] +library/global-fetch.spec.ts › should support global ignoreHTTPSErrors option [pass] +library/global-fetch.spec.ts › should support global timeout option [pass] +library/global-fetch.spec.ts › should support global userAgent option [pass] +library/global-fetch.spec.ts › should throw after dispose [pass] +library/global-fetch.spec.ts › should throw an error when maxRedirects is exceeded [pass] +library/global-fetch.spec.ts › should throw an error when maxRedirects is less than 0 [pass] +library/global-fetch.spec.ts › should work with correct credentials and matching origin [pass] +library/global-fetch.spec.ts › should work with correct credentials and matching origin case insensitive [pass] +library/har.spec.ts › should attach content [fail] +library/har.spec.ts › should calculate time [pass] +library/har.spec.ts › should contain http2 for http2 requests [fail] +library/har.spec.ts › should filter by glob [pass] +library/har.spec.ts › should filter by regexp [pass] +library/har.spec.ts › should filter favicon and favicon redirects [unknown] +library/har.spec.ts › should have -1 _transferSize when its a failed request [pass] +library/har.spec.ts › should have browser [fail] +library/har.spec.ts › should have connection details [fail] +library/har.spec.ts › should have connection details for failed requests [fail] +library/har.spec.ts › should have connection details for redirects [fail] +library/har.spec.ts › should have different hars for concurrent contexts [fail] +library/har.spec.ts › should have pages [pass] +library/har.spec.ts › should have pages in persistent context [fail] +library/har.spec.ts › should have popup requests [fail] +library/har.spec.ts › should have security details [fail] +library/har.spec.ts › should have version and creator [pass] +library/har.spec.ts › should include API request [pass] +library/har.spec.ts › should include binary postData [fail] +library/har.spec.ts › should include content @smoke [fail] +library/har.spec.ts › should include cookies [pass] +library/har.spec.ts › should include form params [fail] +library/har.spec.ts › should include postData [fail] +library/har.spec.ts › should include query params [pass] +library/har.spec.ts › should include redirectURL [pass] +library/har.spec.ts › should include request [pass] +library/har.spec.ts › should include response [pass] +library/har.spec.ts › should include secure set-cookies [fail] +library/har.spec.ts › should include set-cookies [fail] +library/har.spec.ts › should include set-cookies with comma [fail] +library/har.spec.ts › should include sizes [fail] +library/har.spec.ts › should not contain internal pages [pass] +library/har.spec.ts › should not hang on resources served from cache [fail] +library/har.spec.ts › should not hang on slow chunked response [fail] +library/har.spec.ts › should omit content [pass] +library/har.spec.ts › should omit content legacy [pass] +library/har.spec.ts › should record failed request headers [pass] +library/har.spec.ts › should record failed request overrides [timeout] +library/har.spec.ts › should record request overrides [timeout] +library/har.spec.ts › should report the correct _transferSize with PNG files [fail] +library/har.spec.ts › should report the correct request body size [pass] +library/har.spec.ts › should report the correct request body size when the bodySize is 0 [pass] +library/har.spec.ts › should report the correct response body size when the bodySize is 0 [pass] +library/har.spec.ts › should return receive time [pass] +library/har.spec.ts › should return security details directly from response [fail] +library/har.spec.ts › should return server address directly from response [fail] +library/har.spec.ts › should skip invalid Expires [pass] +library/har.spec.ts › should throw without path [pass] +library/har.spec.ts › should use attach mode for zip extension [fail] +library/har.spec.ts › should work with gzip compression [fail] +library/headful.spec.ts › Page.bringToFront should work [fail] +library/headful.spec.ts › headless and headful should use same default fonts [fail] +library/headful.spec.ts › should click background tab [fail] +library/headful.spec.ts › should click bottom row w/ infobar in OOPIF [fail] +library/headful.spec.ts › should click in OOPIF [fail] +library/headful.spec.ts › should click when viewport size is larger than screen [fail] +library/headful.spec.ts › should close browser after context menu was triggered [pass] +library/headful.spec.ts › should close browser with beforeunload page [fail] +library/headful.spec.ts › should close browsercontext with pending beforeunload dialog [fail] +library/headful.spec.ts › should dispatch click events to oversized viewports [pass] +library/headful.spec.ts › should have default url when launching browser @smoke [fail] +library/headful.spec.ts › should not block third party SameSite=None cookies [fail] +library/headful.spec.ts › should not crash when creating second context [pass] +library/headful.spec.ts › should not override viewport size when passed null [pass] +library/headful.spec.ts › should(not) block third party cookies [fail] +library/hit-target.spec.ts › should block all events when hit target is wrong [pass] +library/hit-target.spec.ts › should block all events when hit target is wrong and element detaches [pass] +library/hit-target.spec.ts › should block click when mousedown fails [pass] +library/hit-target.spec.ts › should click an element inside closed shadow root [fail] +library/hit-target.spec.ts › should click in custom element [fail] +library/hit-target.spec.ts › should click in iframe with padding [fail] +library/hit-target.spec.ts › should click in iframe with padding 2 [fail] +library/hit-target.spec.ts › should click into frame inside closed shadow root [fail] +library/hit-target.spec.ts › should click the button again after document.write [pass] +library/hit-target.spec.ts › should click when element detaches in mousedown [pass] +library/hit-target.spec.ts › should detect overlaid element in a transformed iframe [fail] +library/hit-target.spec.ts › should detect overlay from another shadow root [fail] +library/hit-target.spec.ts › should not block programmatic events [pass] +library/hit-target.spec.ts › should not click an element overlaying iframe with the target [fail] +library/hit-target.spec.ts › should not click iframe overlaying the target [fail] +library/hit-target.spec.ts › should work with block inside inline [fail] +library/hit-target.spec.ts › should work with block inside inline in shadow dom [fail] +library/hit-target.spec.ts › should work with block-block-block inside inline-inline [fail] +library/hit-target.spec.ts › should work with drag and drop that moves the element under cursor [pass] +library/hit-target.spec.ts › should work with mui select [pass] +library/ignorehttpserrors.spec.ts › serviceWorker should intercept document request [fail] +library/ignorehttpserrors.spec.ts › should fail with WebSocket if not ignored [pass] +library/ignorehttpserrors.spec.ts › should isolate contexts [fail] +library/ignorehttpserrors.spec.ts › should work @smoke [fail] +library/ignorehttpserrors.spec.ts › should work with WebSocket [fail] +library/ignorehttpserrors.spec.ts › should work with mixed content [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should assert navigation [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should await popup [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should check [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should check a radio button [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should check with keyboard [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should click [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should click after same-document navigation [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should click button with nested div [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should emit single keyup on ArrowDown [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [contentEditable] [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill japanese text [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea with new lines at the end [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore AltGraph [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore programmatic events [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should make a positioned click on a canvas [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should middle click [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should not target selector preview by text regexp [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should not throw csp directive violation errors [pass] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should press [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record ArrowDown [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after performAction [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after recordAction [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should record slider [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should select [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should select with size attribute [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should uncheck [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should update selected element after pressing Tab [fail] +library/inspector/cli-codegen-1.spec.ts › cli codegen › should work with TrustedTypes [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › click should emit events in order [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should --save-trace [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should check input with chaining id [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should clear files [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain close page [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain open page [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain second page [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should download files [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should fill tricky characters [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle dialogs [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle history.postData [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should not clash pages [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should not lead to an error if html gets clicked [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should record navigations after identical pushState [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should record open in a new tab with url [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should reset hover model on action when element detaches [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should save assets via SIGINT [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should update active model on action [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should update hover model on action [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload a single file [fail] +library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload multiple files [fail] +library/inspector/cli-codegen-2.spec.ts › should --test-id-attribute [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled input [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled select [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert visibility [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.first [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.nth [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume contextmenu events, despite a custom context menu [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume pointer events [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with id attribute [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with name attribute [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with special characters in name attribute [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with testId [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with title attribute [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByAltText [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel without regex [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByPlaceholder [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByTestId [fail] +library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate role locators undef frame locators [fail] +library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in mstest if no options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in nunit if no options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in mstest [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in nunit [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in mstest if options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in nunit if options were passed [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print load/save storageState [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-csharp.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-csharp.spec.ts › should work with --save-har [fail] +library/inspector/cli-codegen-java.spec.ts › should print a valid basic program in junit [fail] +library/inspector/cli-codegen-java.spec.ts › should print load/save storage_state [fail] +library/inspector/cli-codegen-java.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-java.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-java.spec.ts › should print the correct imports in junit [fail] +library/inspector/cli-codegen-java.spec.ts › should work with --save-har [fail] +library/inspector/cli-codegen-javascript.spec.ts › should print load/save storageState [fail] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-javascript.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-javascript.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-pytest.spec.ts › should print the correct context options when using a device and lang [unknown] +library/inspector/cli-codegen-pytest.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-pytest.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-python-async.spec.ts › should print load/save storage_state [fail] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-python-async.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-python-async.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-python-async.spec.ts › should work with --save-har [fail] +library/inspector/cli-codegen-python.spec.ts › should print load/save storage_state [fail] +library/inspector/cli-codegen-python.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-python.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-python.spec.ts › should save the codegen output to a file if specified [fail] +library/inspector/cli-codegen-test.spec.ts › should print load storageState [fail] +library/inspector/cli-codegen-test.spec.ts › should print the correct context options for custom settings [fail] +library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device [unknown] +library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device and additional options [unknown] +library/inspector/cli-codegen-test.spec.ts › should print the correct imports and context options [fail] +library/inspector/cli-codegen-test.spec.ts › should work with --save-har [fail] +library/inspector/console-api.spec.ts › expected properties on playwright object [pass] +library/inspector/console-api.spec.ts › should support locator.and() [fail] +library/inspector/console-api.spec.ts › should support locator.or() [fail] +library/inspector/console-api.spec.ts › should support playwright.$, playwright.$$ [pass] +library/inspector/console-api.spec.ts › should support playwright.getBy* [fail] +library/inspector/console-api.spec.ts › should support playwright.locator({ has }) [fail] +library/inspector/console-api.spec.ts › should support playwright.locator({ hasNot }) [fail] +library/inspector/console-api.spec.ts › should support playwright.locator.value [fail] +library/inspector/console-api.spec.ts › should support playwright.locator.values [fail] +library/inspector/console-api.spec.ts › should support playwright.selector [pass] +library/inspector/pause.spec.ts › pause › should hide internal calls [pass] +library/inspector/pause.spec.ts › pause › should highlight locators with custom testId [fail] +library/inspector/pause.spec.ts › pause › should highlight on explore [fail] +library/inspector/pause.spec.ts › pause › should highlight on explore (csharp) [fail] +library/inspector/pause.spec.ts › pause › should highlight pointer, only in main frame [fail] +library/inspector/pause.spec.ts › pause › should highlight waitForEvent [fail] +library/inspector/pause.spec.ts › pause › should not prevent key events [fail] +library/inspector/pause.spec.ts › pause › should pause after a navigation [pass] +library/inspector/pause.spec.ts › pause › should pause and resume the script [pass] +library/inspector/pause.spec.ts › pause › should pause and resume the script with keyboard shortcut [pass] +library/inspector/pause.spec.ts › pause › should pause on context close [pass] +library/inspector/pause.spec.ts › pause › should pause on next pause [pass] +library/inspector/pause.spec.ts › pause › should pause on page close [pass] +library/inspector/pause.spec.ts › pause › should populate log [fail] +library/inspector/pause.spec.ts › pause › should populate log with error [fail] +library/inspector/pause.spec.ts › pause › should populate log with error in waitForEvent [fail] +library/inspector/pause.spec.ts › pause › should populate log with waitForEvent [fail] +library/inspector/pause.spec.ts › pause › should resume from console [fail] +library/inspector/pause.spec.ts › pause › should show expect.toHaveText [fail] +library/inspector/pause.spec.ts › pause › should show source [pass] +library/inspector/pause.spec.ts › pause › should skip input when resuming [fail] +library/inspector/pause.spec.ts › pause › should step [fail] +library/inspector/pause.spec.ts › pause › should step with keyboard shortcut [fail] +library/inspector/pause.spec.ts › should not reset timeouts [pass] +library/inspector/pause.spec.ts › should resume when closing inspector [pass] +library/launcher.spec.ts › should have a devices object [pass] +library/launcher.spec.ts › should have an errors object [pass] +library/launcher.spec.ts › should kill browser process on timeout after close [pass] +library/launcher.spec.ts › should throw a friendly error if its headed and there is no xserver on linux running [fail] +library/locator-generator.spec.ts › asLocator internal:and [pass] +library/locator-generator.spec.ts › asLocator internal:chain [pass] +library/locator-generator.spec.ts › asLocator internal:or [pass] +library/locator-generator.spec.ts › asLocator xpath [pass] +library/locator-generator.spec.ts › generate multiple locators [pass] +library/locator-generator.spec.ts › parse locators strictly [pass] +library/locator-generator.spec.ts › parseLocator css [pass] +library/locator-generator.spec.ts › parseLocator quotes [pass] +library/locator-generator.spec.ts › reverse engineer frameLocator [pass] +library/locator-generator.spec.ts › reverse engineer getByRole [pass] +library/locator-generator.spec.ts › reverse engineer has [pass] +library/locator-generator.spec.ts › reverse engineer has + hasText [pass] +library/locator-generator.spec.ts › reverse engineer hasNot [pass] +library/locator-generator.spec.ts › reverse engineer hasNotText [pass] +library/locator-generator.spec.ts › reverse engineer hasText [pass] +library/locator-generator.spec.ts › reverse engineer ignore-case locators [pass] +library/locator-generator.spec.ts › reverse engineer internal:has-text locators [fail] +library/locator-generator.spec.ts › reverse engineer locators [pass] +library/locator-generator.spec.ts › reverse engineer locators with regex [pass] +library/locator-generator.spec.ts › reverse engineer ordered locators [pass] +library/logger.spec.ts › should log @smoke [pass] +library/logger.spec.ts › should log context-level [fail] +library/modernizr.spec.ts › Mobile Safari [unknown] +library/modernizr.spec.ts › Safari Desktop [unknown] +library/page-clock.frozen.spec.ts › clock should be frozen [unknown] +library/page-clock.frozen.spec.ts › clock should be realtime [unknown] +library/page-clock.spec.ts › Date.now › check Date.now is an integer [pass] +library/page-clock.spec.ts › Date.now › check Date.now is an integer (2) [pass] +library/page-clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] +library/page-clock.spec.ts › fastForward › pushes back execution time for skipped timers [fail] +library/page-clock.spec.ts › fastForward › supports string time arguments [fail] +library/page-clock.spec.ts › popup › should not run time before popup on pause [fail] +library/page-clock.spec.ts › popup › should run time before popup [pass] +library/page-clock.spec.ts › popup › should tick after popup [fail] +library/page-clock.spec.ts › popup › should tick before popup [fail] +library/page-clock.spec.ts › runFor › creates updated Date while ticking [fail] +library/page-clock.spec.ts › runFor › does not trigger without sufficient delay [pass] +library/page-clock.spec.ts › runFor › passes 1 minute [fail] +library/page-clock.spec.ts › runFor › passes 2 hours, 34 minutes and 10 seconds [fail] +library/page-clock.spec.ts › runFor › passes 8 seconds [fail] +library/page-clock.spec.ts › runFor › returns the current now value [pass] +library/page-clock.spec.ts › runFor › throws for invalid format [pass] +library/page-clock.spec.ts › runFor › triggers after sufficient delay [fail] +library/page-clock.spec.ts › runFor › triggers event when some throw [fail] +library/page-clock.spec.ts › runFor › triggers immediately without specified delay [fail] +library/page-clock.spec.ts › runFor › triggers multiple simultaneous timers [fail] +library/page-clock.spec.ts › runFor › triggers simultaneous timers [fail] +library/page-clock.spec.ts › runFor › waits after setTimeout was called [fail] +library/page-clock.spec.ts › setFixedTime › allows installing fake timers after settings time [fail] +library/page-clock.spec.ts › setFixedTime › allows setting time multiple times [pass] +library/page-clock.spec.ts › setFixedTime › does not fake methods [pass] +library/page-clock.spec.ts › setFixedTime › fixed time is not affected by clock manipulation [pass] +library/page-clock.spec.ts › stubTimers › fakes Date constructor [pass] +library/page-clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] +library/page-clock.spec.ts › stubTimers › replaces global clearInterval [pass] +library/page-clock.spec.ts › stubTimers › replaces global clearTimeout [pass] +library/page-clock.spec.ts › stubTimers › replaces global performance.now [pass] +library/page-clock.spec.ts › stubTimers › replaces global performance.timeOrigin [pass] +library/page-clock.spec.ts › stubTimers › replaces global setInterval [fail] +library/page-clock.spec.ts › stubTimers › replaces global setTimeout [fail] +library/page-clock.spec.ts › stubTimers › sets initial timestamp [pass] +library/page-clock.spec.ts › stubTimers › should throw for invalid date [pass] +library/page-clock.spec.ts › while on pause › fastForward should not run nested immediate [fail] +library/page-clock.spec.ts › while on pause › runFor should not run nested immediate [fail] +library/page-clock.spec.ts › while on pause › runFor should not run nested immediate from microtask [fail] +library/page-clock.spec.ts › while running › should fastForward [pass] +library/page-clock.spec.ts › while running › should fastForwardTo [pass] +library/page-clock.spec.ts › while running › should pause [pass] +library/page-clock.spec.ts › while running › should pause and fastForward [pass] +library/page-clock.spec.ts › while running › should progress time [pass] +library/page-clock.spec.ts › while running › should runFor [pass] +library/page-clock.spec.ts › while running › should set system time on pause [pass] +library/page-event-crash.spec.ts › should be able to close context when page crashes [fail] +library/page-event-crash.spec.ts › should cancel navigation when page crashes [fail] +library/page-event-crash.spec.ts › should cancel waitForEvent when page crashes [fail] +library/page-event-crash.spec.ts › should emit crash event when page crashes [fail] +library/page-event-crash.spec.ts › should throw on any action after page crashes [fail] +library/pdf.spec.ts › should be able to generate outline [unknown] +library/pdf.spec.ts › should be able to save file [unknown] +library/permissions.spec.ts › permissions › should accumulate when adding [fail] +library/permissions.spec.ts › permissions › should be prompt by default [pass] +library/permissions.spec.ts › permissions › should clear permissions [fail] +library/permissions.spec.ts › permissions › should deny permission when not listed [fail] +library/permissions.spec.ts › permissions › should fail when bad permission is given [fail] +library/permissions.spec.ts › permissions › should grant geolocation permission when origin is listed [fail] +library/permissions.spec.ts › permissions › should grant notifications permission when listed [fail] +library/permissions.spec.ts › permissions › should grant permission when creating context [fail] +library/permissions.spec.ts › permissions › should grant permission when listed for all domains [fail] +library/permissions.spec.ts › permissions › should isolate permissions between browser contexts [fail] +library/permissions.spec.ts › permissions › should prompt for geolocation permission when origin is not listed [pass] +library/permissions.spec.ts › permissions › should reset permissions [fail] +library/permissions.spec.ts › permissions › should trigger permission onchange [fail] +library/permissions.spec.ts › should support clipboard read [fail] +library/permissions.spec.ts › storage access [unknown] +library/popup.spec.ts › BrowserContext.addInitScript should apply to a cross-process popup [fail] +library/popup.spec.ts › BrowserContext.addInitScript should apply to an in-process popup [fail] +library/popup.spec.ts › should expose function from browser context [fail] +library/popup.spec.ts › should inherit extra headers from browser context [fail] +library/popup.spec.ts › should inherit http credentials from browser context [pass] +library/popup.spec.ts › should inherit offline from browser context [fail] +library/popup.spec.ts › should inherit touch support from browser context [fail] +library/popup.spec.ts › should inherit user agent from browser context @smoke [fail] +library/popup.spec.ts › should inherit viewport size from browser context [fail] +library/popup.spec.ts › should not dispatch binding on a closed page [fail] +library/popup.spec.ts › should not throttle rAF in the opener page [timeout] +library/popup.spec.ts › should not throw when click closes popup [timeout] +library/popup.spec.ts › should respect routes from browser context [fail] +library/popup.spec.ts › should respect routes from browser context when using window.open [fail] +library/popup.spec.ts › should use viewport size from window features [timeout] +library/proxy-pattern.spec.ts › socks proxy patter matcher [pass] +library/proxy.spec.ts › does launch without a port [pass] +library/proxy.spec.ts › should authenticate [pass] +library/proxy.spec.ts › should exclude patterns [fail] +library/proxy.spec.ts › should proxy local network requests › by default › link-local [pass] +library/proxy.spec.ts › should proxy local network requests › by default › localhost [fail] +library/proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] +library/proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [pass] +library/proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] +library/proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] +library/proxy.spec.ts › should throw for bad server value [pass] +library/proxy.spec.ts › should use SOCKS proxy for websocket requests [pass] +library/proxy.spec.ts › should use proxy @smoke [pass] +library/proxy.spec.ts › should use proxy for second page [pass] +library/proxy.spec.ts › should use proxy with emulated user agent [unknown] +library/proxy.spec.ts › should use socks proxy [pass] +library/proxy.spec.ts › should use socks proxy in second page [pass] +library/proxy.spec.ts › should work with IP:PORT notion [pass] +library/proxy.spec.ts › should work with authenticate followed by redirect [pass] +library/resource-timing.spec.ts › should work @smoke [pass] +library/resource-timing.spec.ts › should work for SSL [fail] +library/resource-timing.spec.ts › should work for redirect [pass] +library/resource-timing.spec.ts › should work for subresource [pass] +library/resource-timing.spec.ts › should work when serving from memory cache [fail] +library/role-utils.spec.ts › accessible name nested treeitem [fail] +library/role-utils.spec.ts › accessible name with slots [fail] +library/role-utils.spec.ts › axe-core accessible-text [fail] +library/role-utils.spec.ts › axe-core implicit-role [fail] +library/role-utils.spec.ts › control embedded in a label [fail] +library/role-utils.spec.ts › control embedded in a target element [fail] +library/role-utils.spec.ts › display:contents should be visible when contents are visible [fail] +library/role-utils.spec.ts › label/labelled-by aria-hidden with descendants [fail] +library/role-utils.spec.ts › native controls [fail] +library/role-utils.spec.ts › native controls labelled-by [fail] +library/role-utils.spec.ts › own aria-label concatenated with aria-labelledby [fail] +library/role-utils.spec.ts › should ignore stylesheet from hidden aria-labelledby subtree [fail] +library/role-utils.spec.ts › should not include hidden pseudo into accessible name [fail] +library/role-utils.spec.ts › should work with form and tricky input names [fail] +library/role-utils.spec.ts › svg role=presentation [fail] +library/role-utils.spec.ts › svg title [fail] +library/role-utils.spec.ts › wpt accname #0 [pass] +library/role-utils.spec.ts › wpt accname #1 [pass] +library/role-utils.spec.ts › wpt accname #2 [fail] +library/role-utils.spec.ts › wpt accname #3 [pass] +library/role-utils.spec.ts › wpt accname non-manual [pass] +library/screenshot.spec.ts › element screenshot › element screenshot should work with a mobile viewport [fail] +library/screenshot.spec.ts › element screenshot › element screenshot should work with device scale factor [fail] +library/screenshot.spec.ts › element screenshot › element screenshots should handle vh units [fail] +library/screenshot.spec.ts › element screenshot › page screenshot should capture css transform with device pixels [fail] +library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor [fail] +library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor and scale:css [fail] +library/screenshot.spec.ts › element screenshot › should restore default viewport after fullPage screenshot [fail] +library/screenshot.spec.ts › element screenshot › should restore viewport after element screenshot and exception [fail] +library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and exception [pass] +library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and timeout [fail] +library/screenshot.spec.ts › element screenshot › should take element screenshot when default viewport is null and restore back [fail] +library/screenshot.spec.ts › element screenshot › should take fullPage screenshots when default viewport is null [fail] +library/screenshot.spec.ts › element screenshot › should take screenshots when default viewport is null [fail] +library/screenshot.spec.ts › element screenshot › should work if the main resource hangs [fail] +library/screenshot.spec.ts › page screenshot › should handle vh units [fail] +library/screenshot.spec.ts › page screenshot › should run in parallel in multiple pages [fail] +library/screenshot.spec.ts › page screenshot › should throw if screenshot size is too large with device scale factor [fail] +library/screenshot.spec.ts › page screenshot › should work with a mobile viewport [fail] +library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and clip [fail] +library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and fullPage [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor and clip [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor and scale:css [fail] +library/screenshot.spec.ts › page screenshot › should work with device scale factor, clip and scale:css [fail] +library/screenshot.spec.ts › page screenshot › should work with large size [fail] +library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [fail] +library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [fail] +library/selector-generator.spec.ts › selector generator › should chain text after parent [fail] +library/selector-generator.spec.ts › selector generator › should escape text with quote [fail] +library/selector-generator.spec.ts › selector generator › should escape text with slash [fail] +library/selector-generator.spec.ts › selector generator › should find text in shadow dom [fail] +library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [fail] +library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [fail] +library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [fail] +library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [fail] +library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [fail] +library/selector-generator.spec.ts › selector generator › should generate label selector [fail] +library/selector-generator.spec.ts › selector generator › should generate multiple: noId [fail] +library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [fail] +library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [fail] +library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [fail] +library/selector-generator.spec.ts › selector generator › should generate relative selector [fail] +library/selector-generator.spec.ts › selector generator › should generate text and normalize whitespace [fail] +library/selector-generator.spec.ts › selector generator › should generate text for [fail] +library/selector-generator.spec.ts › selector generator › should generate title selector [fail] +library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [fail] +library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [fail] +library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [fail] +library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [fail] +library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [fail] +library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [fail] +library/selector-generator.spec.ts › selector generator › should match in shadow dom [fail] +library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [fail] +library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [fail] +library/selector-generator.spec.ts › selector generator › should not escape text with >> [fail] +library/selector-generator.spec.ts › selector generator › should not improve guid text [fail] +library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [fail] +library/selector-generator.spec.ts › selector generator › should not use generated id [fail] +library/selector-generator.spec.ts › selector generator › should not use input[value] [fail] +library/selector-generator.spec.ts › selector generator › should not use text for select [fail] +library/selector-generator.spec.ts › selector generator › should prefer button over inner span [fail] +library/selector-generator.spec.ts › selector generator › should prefer data-testid [fail] +library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [fail] +library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [fail] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [fail] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [fail] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [fail] +library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [fail] +library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [fail] +library/selector-generator.spec.ts › selector generator › should separate selectors by >> [fail] +library/selector-generator.spec.ts › selector generator › should trim long text [fail] +library/selector-generator.spec.ts › selector generator › should trim text [fail] +library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [fail] +library/selector-generator.spec.ts › selector generator › should try to improve role name [fail] +library/selector-generator.spec.ts › selector generator › should try to improve text [fail] +library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [fail] +library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [fail] +library/selector-generator.spec.ts › selector generator › should use internal:has-text [fail] +library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [fail] +library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [fail] +library/selector-generator.spec.ts › selector generator › should use nested ordinals [fail] +library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [fail] +library/selector-generator.spec.ts › selector generator › should use parent text [fail] +library/selector-generator.spec.ts › selector generator › should use readable id [fail] +library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [fail] +library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] +library/selector-generator.spec.ts › selector generator › should work with tricky attributes [fail] +library/selector-generator.spec.ts › selector generator › should work without CSS.escape [fail] +library/selectors-register.spec.ts › should handle errors [pass] +library/selectors-register.spec.ts › should not rely on engines working from the root [fail] +library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] +library/selectors-register.spec.ts › should work [fail] +library/selectors-register.spec.ts › should work in main and isolated world [fail] +library/selectors-register.spec.ts › should work when registered on global [fail] +library/selectors-register.spec.ts › should work with path [fail] +library/shared-worker.spec.ts › should survive shared worker restart [pass] +library/signals.spec.ts › should close the browser when the node process closes [timeout] +library/signals.spec.ts › should remove temp dir on process.exit [timeout] +library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] +library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] +library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] +library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] +library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] +library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] +library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] +library/signals.spec.ts › signals › should report browser close signal 2 [timeout] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo check [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo click [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo fill [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo focus [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo goto [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo hover [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo press [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo type [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo check [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo click [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo fill [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo focus [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo goto [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo hover [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo press [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo reload [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo type [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [fail] +library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [fail] +library/snapshotter.spec.ts › snapshots › should capture frame [pass] +library/snapshotter.spec.ts › snapshots › should capture iframe [fail] +library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [pass] +library/snapshotter.spec.ts › snapshots › should capture resources [fail] +library/snapshotter.spec.ts › snapshots › should capture snapshot target [fail] +library/snapshotter.spec.ts › snapshots › should collect multiple [fail] +library/snapshotter.spec.ts › snapshots › should collect on attribute change [fail] +library/snapshotter.spec.ts › snapshots › should collect snapshot [fail] +library/snapshotter.spec.ts › snapshots › should have a custom doctype [fail] +library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [fail] +library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] +library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [fail] +library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [fail] +library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [fail] +library/snapshotter.spec.ts › snapshots › should respect attr removal [fail] +library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [fail] +library/snapshotter.spec.ts › snapshots › should respect node removal [fail] +library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +library/tap.spec.ts › locators › should send all of the correct events [fail] +library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] +library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] +library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] +library/tap.spec.ts › should send all of the correct events @smoke [fail] +library/tap.spec.ts › should send well formed touch points [fail] +library/tap.spec.ts › should wait until an element is visible to tap it [fail] +library/tap.spec.ts › should work with modifiers [fail] +library/tap.spec.ts › trial run should not tap [fail] +library/trace-viewer.spec.ts › should allow hiding route actions [unknown] +library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [unknown] +library/trace-viewer.spec.ts › should capture data-url svg iframe [unknown] +library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] +library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [unknown] +library/trace-viewer.spec.ts › should contain action info [unknown] +library/trace-viewer.spec.ts › should contain adopted style sheets [unknown] +library/trace-viewer.spec.ts › should display language-specific locators [unknown] +library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [fail] +library/trace-viewer.spec.ts › should filter network requests by resource type [unknown] +library/trace-viewer.spec.ts › should filter network requests by url [unknown] +library/trace-viewer.spec.ts › should follow redirects [fail] +library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [unknown] +library/trace-viewer.spec.ts › should handle file URIs [unknown] +library/trace-viewer.spec.ts › should handle multiple headers [fail] +library/trace-viewer.spec.ts › should handle src=blob [unknown] +library/trace-viewer.spec.ts › should have correct snapshot size [unknown] +library/trace-viewer.spec.ts › should have correct stack trace [fail] +library/trace-viewer.spec.ts › should have network request overrides [unknown] +library/trace-viewer.spec.ts › should have network request overrides 2 [fail] +library/trace-viewer.spec.ts › should have network requests [unknown] +library/trace-viewer.spec.ts › should highlight expect failure [unknown] +library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] +library/trace-viewer.spec.ts › should highlight target elements [unknown] +library/trace-viewer.spec.ts › should ignore 304 responses [unknown] +library/trace-viewer.spec.ts › should include metainfo [unknown] +library/trace-viewer.spec.ts › should include requestUrl in route.abort [unknown] +library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] +library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [unknown] +library/trace-viewer.spec.ts › should not crash with broken locator [unknown] +library/trace-viewer.spec.ts › should open console errors on click [unknown] +library/trace-viewer.spec.ts › should open simple trace viewer [fail] +library/trace-viewer.spec.ts › should open snapshot in new browser context [unknown] +library/trace-viewer.spec.ts › should open trace viewer on specific host [unknown] +library/trace-viewer.spec.ts › should open trace-1.31 [unknown] +library/trace-viewer.spec.ts › should open trace-1.37 [unknown] +library/trace-viewer.spec.ts › should open two trace files [unknown] +library/trace-viewer.spec.ts › should open two trace files of the same test [fail] +library/trace-viewer.spec.ts › should open two trace viewers [unknown] +library/trace-viewer.spec.ts › should pick locator [unknown] +library/trace-viewer.spec.ts › should pick locator in iframe [unknown] +library/trace-viewer.spec.ts › should popup snapshot [unknown] +library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] +library/trace-viewer.spec.ts › should preserve currentSrc [fail] +library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [unknown] +library/trace-viewer.spec.ts › should register custom elements [unknown] +library/trace-viewer.spec.ts › should remove noscript by default [unknown] +library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [fail] +library/trace-viewer.spec.ts › should render console [unknown] +library/trace-viewer.spec.ts › should render network bars [fail] +library/trace-viewer.spec.ts › should restore control values [unknown] +library/trace-viewer.spec.ts › should restore scroll positions [fail] +library/trace-viewer.spec.ts › should serve css without content-type [fail] +library/trace-viewer.spec.ts › should serve overridden request [unknown] +library/trace-viewer.spec.ts › should show action source [unknown] +library/trace-viewer.spec.ts › should show baseURL in metadata pane [unknown] +library/trace-viewer.spec.ts › should show correct request start time [fail] +library/trace-viewer.spec.ts › should show empty trace viewer [fail] +library/trace-viewer.spec.ts › should show font preview [fail] +library/trace-viewer.spec.ts › should show null as a param [unknown] +library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [fail] +library/trace-viewer.spec.ts › should show params and return value [fail] +library/trace-viewer.spec.ts › should show similar actions from library-only trace [unknown] +library/trace-viewer.spec.ts › should show snapshot URL [unknown] +library/trace-viewer.spec.ts › should update highlight when typing [fail] +library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [unknown] +library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [fail] +library/trace-viewer.spec.ts › should work with meta CSP [unknown] +library/trace-viewer.spec.ts › should work with nesting CSS selectors [unknown] +library/tracing.spec.ts › should collect sources [fail] +library/tracing.spec.ts › should collect trace with resources, but no js [fail] +library/tracing.spec.ts › should collect two traces [fail] +library/tracing.spec.ts › should exclude internal pages [pass] +library/tracing.spec.ts › should export trace concurrently to second navigation [pass] +library/tracing.spec.ts › should flush console events on tracing stop [pass] +library/tracing.spec.ts › should hide internal stack frames [fail] +library/tracing.spec.ts › should hide internal stack frames in expect [fail] +library/tracing.spec.ts › should ignore iframes in head [pass] +library/tracing.spec.ts › should include context API requests [pass] +library/tracing.spec.ts › should include interrupted actions [fail] +library/tracing.spec.ts › should not collect snapshots by default [fail] +library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] +library/tracing.spec.ts › should not emit after w/o before [pass] +library/tracing.spec.ts › should not flush console events [pass] +library/tracing.spec.ts › should not hang for clicks that open dialogs [fail] +library/tracing.spec.ts › should not include buffers in the trace [fail] +library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] +library/tracing.spec.ts › should not stall on dialogs [pass] +library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] +library/tracing.spec.ts › should overwrite existing file [fail] +library/tracing.spec.ts › should produce screencast frames crop [fail] +library/tracing.spec.ts › should produce screencast frames fit [fail] +library/tracing.spec.ts › should produce screencast frames scale [fail] +library/tracing.spec.ts › should record global request trace [pass] +library/tracing.spec.ts › should record network failures [pass] +library/tracing.spec.ts › should respect tracesDir and name [fail] +library/tracing.spec.ts › should store global request traces separately [pass] +library/tracing.spec.ts › should store postData for global request [pass] +library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] +library/tracing.spec.ts › should throw when starting with different options [pass] +library/tracing.spec.ts › should throw when stopping without start [pass] +library/tracing.spec.ts › should use the correct apiName for event driven callbacks [pass] +library/tracing.spec.ts › should work with multiple chunks [fail] +library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [pass] +library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] +library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [fail] +library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] +library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] +library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] +library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [pass] +library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [pass] +library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [pass] +library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [pass] +library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] +library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [pass] +library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [pass] +library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [pass] +library/video.spec.ts › screencast › saveAs should throw when no video frames [timeout] +library/video.spec.ts › screencast › should be 800x450 by default [timeout] +library/video.spec.ts › screencast › should be 800x600 with null viewport [timeout] +library/video.spec.ts › screencast › should capture css transformation [timeout] +library/video.spec.ts › screencast › should capture full viewport [fail] +library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] +library/video.spec.ts › screencast › should capture navigation [timeout] +library/video.spec.ts › screencast › should capture static page [timeout] +library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] +library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] +library/video.spec.ts › screencast › should delete video [timeout] +library/video.spec.ts › screencast › should emulate an iphone [timeout] +library/video.spec.ts › screencast › should expose video path [timeout] +library/video.spec.ts › screencast › should expose video path blank page [fail] +library/video.spec.ts › screencast › should expose video path blank popup [timeout] +library/video.spec.ts › screencast › should not create video for internal pages [unknown] +library/video.spec.ts › screencast › should scale frames down to the requested size [timeout] +library/video.spec.ts › screencast › should throw if browser dies [fail] +library/video.spec.ts › screencast › should throw on browser close [fail] +library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] +library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [timeout] +library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] +library/video.spec.ts › screencast › should work for popups [timeout] +library/video.spec.ts › screencast › should work with old options [timeout] +library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] +library/video.spec.ts › screencast › should work with video+trace [timeout] +library/video.spec.ts › screencast › should work with weird screen resolution [timeout] +library/video.spec.ts › screencast › videoSize should require videosPath [pass] +library/video.spec.ts › should saveAs video [timeout] +library/web-socket.spec.ts › should emit binary frame events [timeout] +library/web-socket.spec.ts › should emit close events [timeout] +library/web-socket.spec.ts › should emit error [timeout] +library/web-socket.spec.ts › should emit frame events [timeout] +library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] +library/web-socket.spec.ts › should not have stray error events [timeout] +library/web-socket.spec.ts › should pass self as argument to close event [timeout] +library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] +library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] +library/web-socket.spec.ts › should turn off when offline [unknown] +library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-firefox-beta-page.txt b/tests/bidi/expectations/bidi-firefox-beta-page.txt index b9e4bd9bd7ea2..85489527fa98c 100644 --- a/tests/bidi/expectations/bidi-firefox-beta-page.txt +++ b/tests/bidi/expectations/bidi-firefox-beta-page.txt @@ -1,1971 +1,1971 @@ -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should force a layout [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should get frame box [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should handle nested frames [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should return null for invisible elements [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should work [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [fail] -bidi-firefox-beta-page › page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [fail] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should double click the button [fail] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for
elements with force [fail] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for detached nodes [pass] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for hidden nodes with force [pass] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should throw for recursively hidden nodes with force [pass] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work @smoke [pass] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work for Shadow DOM v1 [pass] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work for TextNodes [fail] -bidi-firefox-beta-page › page/elementhandle-click.spec.ts › should work with Node removed [pass] -bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should return null for document.documentElement [pass] -bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should return null for non-iframes [pass] -bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should work [pass] -bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should work for cross-frame evaluations [fail] -bidi-firefox-beta-page › page/elementhandle-content-frame.spec.ts › should work for cross-process iframes [pass] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › getAttribute should work [pass] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › innerHTML should work [pass] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › innerText should throw [fail] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › innerText should work [pass] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › inputValue should work [fail] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isChecked should work [fail] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isEditable should work [fail] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work [fail] -bidi-firefox-beta-page › page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work with [fail] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect color value [fail] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect date [fail] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect month [unknown] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect range value [fail] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect time [fail] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on incorrect week [unknown] -bidi-firefox-beta-page › page/page-fill.spec.ts › should throw on unsupported inputs [pass] -bidi-firefox-beta-page › page/page-focus.spec.ts › clicking checkbox should activate it [unknown] -bidi-firefox-beta-page › page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [fail] -bidi-firefox-beta-page › page/page-focus.spec.ts › should emit blur event [fail] -bidi-firefox-beta-page › page/page-focus.spec.ts › should emit focus event [fail] -bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse focus [fail] -bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse focus in all directions [fail] -bidi-firefox-beta-page › page/page-focus.spec.ts › should traverse only form elements [flaky] -bidi-firefox-beta-page › page/page-focus.spec.ts › should work @smoke [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › js redirect overrides url bar navigation [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should capture iframe navigation request [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when canceled by another navigation [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding browser context timeout [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when main resources failed to load [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating and show the url at the error message [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when navigating to bad url [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when replaced by another navigation [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should fail when server returns 204 [timeout] -bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to about:blank [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not leak listeners during navigation [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should override referrer-policy [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should properly wait for load [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should report raw buffer for main resource [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should return from goto if new navigation is started [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should return last response in redirect chain [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should return response when page changes its URL after load [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should return url with basic auth info [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should send referer [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should send referer of cross-origin URL [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should use http for no protocol [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work @smoke [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work cross-process [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work when navigating to 404 [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work when navigating to data url [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work when navigating to valid url [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work when page calls history API in beforeunload [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with anchor navigation [timeout] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with file URL [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with file URL with subframes [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with lazy loading iframes [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with redirects [fail] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with self requesting page [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with subframes return 204 [pass] -bidi-firefox-beta-page › page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack during renderer-initiated navigation [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack should work @smoke [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack should work for file urls [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload during renderer-initiated navigation [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work on a page with a hash [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work with data url [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › page.reload should work with same origin redirect [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › regression test for issue 20791 [pass] -bidi-firefox-beta-page › page/page-history.spec.ts › should reload proper page [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › insertText should only emit input event [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should handle selectAll [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should move around the selection in a contenteditable [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should move to the start of the document [unknown] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should move with the arrow keys [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should not type canceled events [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press Enter [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press plus [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press shift plus [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should press the meta key [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should report multiple modifiers [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should report shiftKey [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should scroll with PageDown [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send a character with insertText [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send proper codes while typing [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should send proper codes while typing with shift [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should shift raw codes [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should specify location [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should specify repeat property [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support MacOS shortcuts [unknown] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support simple copy-pasting [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support simple cut-pasting [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should support undo-redo [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should throw on unknown keys [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type after context menu was opened [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type all kinds of characters [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type emoji [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type emoji into an iframe [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [fail] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] -bidi-firefox-beta-page › page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [fail] -bidi-firefox-beta-page › page/page-leaks.spec.ts › click should not leak [fail] -bidi-firefox-beta-page › page/page-leaks.spec.ts › expect should not leak [fail] -bidi-firefox-beta-page › page/page-leaks.spec.ts › fill should not leak [fail] -bidi-firefox-beta-page › page/page-leaks.spec.ts › waitFor should not leak [fail] -bidi-firefox-beta-page › page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] -bidi-firefox-beta-page › page/page-listeners.spec.ts › should wait [pass] -bidi-firefox-beta-page › page/page-listeners.spec.ts › wait should throw [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › down and up should generate click [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should always round down [fail] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should click the document @smoke [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should dblclick the div [fail] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should pointerdown the div with a custom button [fail] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should report correct buttons property [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should select the text with mouse [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should set modifier keys on click [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should trigger hover state [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] -bidi-firefox-beta-page › page/page-mouse.spec.ts › should tween mouse movement [pass] -bidi-firefox-beta-page › page/page-navigation.spec.ts › should work with _blank target [pass] -bidi-firefox-beta-page › page/page-navigation.spec.ts › should work with _blank target in form [fail] -bidi-firefox-beta-page › page/page-navigation.spec.ts › should work with cross-process _blank target [pass] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle from the popup [fail] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent [fail] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [fail] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [fail] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [fail] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [fail] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] -bidi-firefox-beta-page › page/page-network-idle.spec.ts › should work after repeated navigations in the same page [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › page.reload return 304 status code [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should get the same headers as the server [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should handle mixed-content blocked requests [flaky] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should not allow to access frame on popup main request [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should not work for a redirect and interception [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should override post data content type [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should parse the json post data [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should report all cookies in one header [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should report raw headers [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should report raw response headers in redirects [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should return event source [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should return headers [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should return multipart/form-data [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should return navigation bit [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should return postData [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for a redirect [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for main frame navigation request [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should work for subframe navigation request [pass] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should work with binary post data [fail] -bidi-firefox-beta-page › page/page-network-request.spec.ts › should work with binary post data and interception [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should provide a Response with a file URL [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should reject response.finished if context closes [timeout] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should reject response.finished if page closes [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should report all headers [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return body [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return body for prefetch script [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return body with compression [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return headers after route.fulfill [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return json [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return multiple header value [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return status text [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return text [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should return uncompressed text [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should wait until response completes [fail] -bidi-firefox-beta-page › page/page-network-response.spec.ts › should work @smoke [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should handle redirects [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should return sizes without hanging [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize and headersSize [fail] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should throw for failed requests [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 200 status code [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 401 status code [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 404 status code [pass] -bidi-firefox-beta-page › page/page-network-sizes.spec.ts › should work with 500 status code [fail] -bidi-firefox-beta-page › page/page-object-count.spec.ts › should count objects [flaky] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should delete headers on redirects [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › continue should propagate headers to redirects [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend binary post data [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend longer post data [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend method and post data [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend post data [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should amend utf8 post data [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › post data › should use content-type from original request [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should amend HTTP headers [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should amend method [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should amend method on main request [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should continue preload link requests [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should delete header with undefined value [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should delete the origin header [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should intercept css variable with background url [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [timeout] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should not throw when continuing while page is closing [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should override method along with url [fail] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should override request url [timeout] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should work [pass] -bidi-firefox-beta-page › page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › post data › should amend json post data [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › post data › should amend post data [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should amend HTTP headers [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should amend method [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should chain once [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should delete header with undefined value [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should fall back [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should fall back after exception [pass] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should fall back async [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should not chain abort [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should not chain fulfill [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should override request url [fail] -bidi-firefox-beta-page › page/page-request-fallback.spec.ts › should work [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fetch original request and fulfill [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill json [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill preload link requests [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [timeout] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [timeout] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with har response [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should include the origin header [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [timeout] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work [pass] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work with buffer as body [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work with file path [fail] -bidi-firefox-beta-page › page/page-request-fulfill.spec.ts › should work with status code 422 [pass] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [pass] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should fulfill with any response [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should give access to the intercepted response body [pass] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should intercept with post data override [pass] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should intercept with url override [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [pass] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] -bidi-firefox-beta-page › page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › route.abort should throw if called twice [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › route.continue should throw if called twice [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › route.fallback should throw if called twice [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › route.fulfill should throw if called twice [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should allow null origin for about:blank [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should be able to remove headers [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should be abortable [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should be abortable with custom error codes [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should contain raw request header [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should contain raw response header [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should contain raw response header after fulfill [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should contain referer header [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should fail navigation when aborting main resource [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should fulfill with redirect status [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should intercept @smoke [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should intercept main resource during cross-process navigation [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should not fulfill with redirect status [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should not work with redirects [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should override cookie header [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should pause intercepted XHR until continue [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should pause intercepted fetch request until continue [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should reject cors with disallowed credentials [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should respect cors overrides [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should send referer [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should show custom HTTP headers [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should support ? in glob pattern [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should support async handler w/ times [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should support cors for different methods [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should support cors with GET [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should support cors with POST [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should support cors with credentials [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should support the times parameter with route matching [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should unroute [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should work when POST is redirected with 302 [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should work when header manipulation headers with redirect [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with badly encoded server [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with custom referer headers [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with encoded server [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with encoded server - 2 [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with equal requests [pass] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with redirect inside sync XHR [fail] -bidi-firefox-beta-page › page/page-route.spec.ts › should work with redirects for subresources [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › path option should work [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › should capture css box-shadow [fail] -bidi-firefox-beta-page › page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] -bidi-firefox-beta-page › page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [fail] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should fall back to selecting by label [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should not allow null items [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should not select single option when some attributes do not match [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should not throw when select causes navigation [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should respect event bubbling [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should return [] on no matched values [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should return [] on no values [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should return an array of matched values [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select multiple options [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select multiple options with attributes [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select only first option [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option @smoke [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by handle [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by index [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by label [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by multiple attributes [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should select single option by value [pass] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should throw if passed wrong types [fail] -bidi-firefox-beta-page › page/page-select-option.spec.ts › should throw when element is not a option/optgroup correctly [fail] +page/elementhandle-convenience.spec.ts › isVisible and isHidden should work [fail] +page/elementhandle-convenience.spec.ts › isVisible should not throw when the DOM element is not connected [fail] +page/elementhandle-convenience.spec.ts › should have a nice preview [pass] +page/elementhandle-convenience.spec.ts › should have a nice preview for non-ascii attributes/children [fail] +page/elementhandle-convenience.spec.ts › textContent should work [pass] +page/elementhandle-convenience.spec.ts › textContent should work on ShadowRoot [fail] +page/elementhandle-eval-on-selector.spec.ts › should not throw in case of missing selector for all [fail] +page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree [fail] +page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree for all [fail] +page/elementhandle-eval-on-selector.spec.ts › should throw in case of missing selector [fail] +page/elementhandle-eval-on-selector.spec.ts › should work [fail] +page/elementhandle-eval-on-selector.spec.ts › should work for all [fail] +page/elementhandle-misc.spec.ts › should allow disposing twice [fail] +page/elementhandle-misc.spec.ts › should check the box [fail] +page/elementhandle-misc.spec.ts › should check the box using setChecked [fail] +page/elementhandle-misc.spec.ts › should fill input [pass] +page/elementhandle-misc.spec.ts › should fill input when Node is removed [pass] +page/elementhandle-misc.spec.ts › should focus a button [pass] +page/elementhandle-misc.spec.ts › should hover [pass] +page/elementhandle-misc.spec.ts › should hover when Node is removed [pass] +page/elementhandle-misc.spec.ts › should select single option [pass] +page/elementhandle-misc.spec.ts › should uncheck the box [fail] +page/elementhandle-owner-frame.spec.ts › should work [fail] +page/elementhandle-owner-frame.spec.ts › should work for adopted elements [fail] +page/elementhandle-owner-frame.spec.ts › should work for cross-frame evaluations [fail] +page/elementhandle-owner-frame.spec.ts › should work for cross-process iframes [fail] +page/elementhandle-owner-frame.spec.ts › should work for detached elements [fail] +page/elementhandle-owner-frame.spec.ts › should work for document [fail] +page/elementhandle-owner-frame.spec.ts › should work for iframe elements [fail] +page/elementhandle-press.spec.ts › should not modify selection when focused [fail] +page/elementhandle-press.spec.ts › should not select existing value [fail] +page/elementhandle-press.spec.ts › should reset selection when not focused [fail] +page/elementhandle-press.spec.ts › should work [fail] +page/elementhandle-press.spec.ts › should work with number input [fail] +page/elementhandle-query-selector.spec.ts › should query existing element [fail] +page/elementhandle-query-selector.spec.ts › should query existing elements [fail] +page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [fail] +page/elementhandle-query-selector.spec.ts › should return null for non-existing element [fail] +page/elementhandle-query-selector.spec.ts › should work for adopted elements [pass] +page/elementhandle-query-selector.spec.ts › xpath should query existing element [fail] +page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport in parallel [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should fail to screenshot a detached element [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should not issue resize event [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should prefer type over extension [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should scroll 15000px into view [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should scroll element into view [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should take into account padding and border [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should take screenshot of disabled button [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should timeout waiting for visible [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should wait for element to stop moving [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should wait for visible [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with an offset [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work for an element with fractional dimensions [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work when main world busts JSON.stringify [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should work with a rotated element [fail] +page/elementhandle-scroll-into-view.spec.ts › should scroll display:contents into view [fail] +page/elementhandle-scroll-into-view.spec.ts › should throw for detached element [fail] +page/elementhandle-scroll-into-view.spec.ts › should timeout waiting for visible [fail] +page/elementhandle-scroll-into-view.spec.ts › should wait for display:none to become visible [fail] +page/elementhandle-scroll-into-view.spec.ts › should wait for element to stop moving [fail] +page/elementhandle-scroll-into-view.spec.ts › should wait for nested display:none to become visible [fail] +page/elementhandle-scroll-into-view.spec.ts › should work @smoke [pass] +page/elementhandle-scroll-into-view.spec.ts › should work for visibility:hidden element [fail] +page/elementhandle-scroll-into-view.spec.ts › should work for zero-sized element [fail] +page/elementhandle-select-text.spec.ts › should select input [fail] +page/elementhandle-select-text.spec.ts › should select plain div [pass] +page/elementhandle-select-text.spec.ts › should select textarea [fail] +page/elementhandle-select-text.spec.ts › should timeout waiting for invisible element [pass] +page/elementhandle-select-text.spec.ts › should wait for visible [pass] +page/elementhandle-type.spec.ts › should not modify selection when focused [fail] +page/elementhandle-type.spec.ts › should not select existing value [fail] +page/elementhandle-type.spec.ts › should reset selection when not focused [fail] +page/elementhandle-type.spec.ts › should work [fail] +page/elementhandle-type.spec.ts › should work with number input [fail] +page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for enabled when detached [fail] +page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for visible when detached [fail] +page/elementhandle-wait-for-element-state.spec.ts › should timeout waiting for visible [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for already hidden [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for already visible [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for aria enabled button [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for button with an aria-disabled parent [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for editable input [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden when detached [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for stable position [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for visible [fail] +page/eval-on-selector-all.spec.ts › should auto-detect css selector [fail] +page/eval-on-selector-all.spec.ts › should return complex values [fail] +page/eval-on-selector-all.spec.ts › should support * capture [fail] +page/eval-on-selector-all.spec.ts › should support * capture when multiple paths match [fail] +page/eval-on-selector-all.spec.ts › should support >> syntax [fail] +page/eval-on-selector-all.spec.ts › should work with bogus Array.from [fail] +page/eval-on-selector-all.spec.ts › should work with css selector [fail] +page/eval-on-selector-all.spec.ts › should work with text selector [fail] +page/eval-on-selector-all.spec.ts › should work with xpath selector [fail] +page/eval-on-selector.spec.ts › should accept ElementHandles as arguments [fail] +page/eval-on-selector.spec.ts › should accept arguments [fail] +page/eval-on-selector.spec.ts › should auto-detect css selector [fail] +page/eval-on-selector.spec.ts › should auto-detect css selector with attributes [fail] +page/eval-on-selector.spec.ts › should auto-detect nested selectors [fail] +page/eval-on-selector.spec.ts › should not stop at first failure with >> syntax [fail] +page/eval-on-selector.spec.ts › should return complex values [fail] +page/eval-on-selector.spec.ts › should support * capture [fail] +page/eval-on-selector.spec.ts › should support >> syntax [fail] +page/eval-on-selector.spec.ts › should support >> syntax with different engines [fail] +page/eval-on-selector.spec.ts › should support spaces with >> syntax [fail] +page/eval-on-selector.spec.ts › should throw error if no element is found [pass] +page/eval-on-selector.spec.ts › should throw on malformed * capture [pass] +page/eval-on-selector.spec.ts › should throw on multiple * captures [pass] +page/eval-on-selector.spec.ts › should work with css selector [fail] +page/eval-on-selector.spec.ts › should work with data-test selector [fail] +page/eval-on-selector.spec.ts › should work with data-test-id selector [fail] +page/eval-on-selector.spec.ts › should work with data-testid selector [fail] +page/eval-on-selector.spec.ts › should work with id selector [fail] +page/eval-on-selector.spec.ts › should work with quotes in css attributes [fail] +page/eval-on-selector.spec.ts › should work with quotes in css attributes when missing [fail] +page/eval-on-selector.spec.ts › should work with spaces in css attributes [fail] +page/eval-on-selector.spec.ts › should work with spaces in css attributes when missing [fail] +page/eval-on-selector.spec.ts › should work with text selector [fail] +page/eval-on-selector.spec.ts › should work with text selector in quotes [fail] +page/eval-on-selector.spec.ts › should work with xpath selector [fail] +page/expect-boolean.spec.ts › not.toBeDisabled div [fail] +page/expect-boolean.spec.ts › not.toBeEmpty [fail] +page/expect-boolean.spec.ts › not.toBeOK [pass] +page/expect-boolean.spec.ts › should print selector syntax error [pass] +page/expect-boolean.spec.ts › should print unknown engine error [pass] +page/expect-boolean.spec.ts › toBeAttached › default [fail] +page/expect-boolean.spec.ts › toBeAttached › eventually [fail] +page/expect-boolean.spec.ts › toBeAttached › eventually with not [fail] +page/expect-boolean.spec.ts › toBeAttached › fail [fail] +page/expect-boolean.spec.ts › toBeAttached › fail with not [fail] +page/expect-boolean.spec.ts › toBeAttached › over navigation [pass] +page/expect-boolean.spec.ts › toBeAttached › with attached:false [fail] +page/expect-boolean.spec.ts › toBeAttached › with attached:true [fail] +page/expect-boolean.spec.ts › toBeAttached › with frameLocator [fail] +page/expect-boolean.spec.ts › toBeAttached › with hidden element [fail] +page/expect-boolean.spec.ts › toBeAttached › with impossible timeout [fail] +page/expect-boolean.spec.ts › toBeAttached › with impossible timeout .not [fail] +page/expect-boolean.spec.ts › toBeAttached › with not [fail] +page/expect-boolean.spec.ts › toBeAttached › with not and attached:false [fail] +page/expect-boolean.spec.ts › toBeChecked with value [fail] +page/expect-boolean.spec.ts › toBeChecked › default [fail] +page/expect-boolean.spec.ts › toBeChecked › fail [fail] +page/expect-boolean.spec.ts › toBeChecked › fail missing [fail] +page/expect-boolean.spec.ts › toBeChecked › fail with checked:false [fail] +page/expect-boolean.spec.ts › toBeChecked › fail with not [fail] +page/expect-boolean.spec.ts › toBeChecked › friendly log [fail] +page/expect-boolean.spec.ts › toBeChecked › with checked:false [fail] +page/expect-boolean.spec.ts › toBeChecked › with checked:true [fail] +page/expect-boolean.spec.ts › toBeChecked › with impossible timeout [fail] +page/expect-boolean.spec.ts › toBeChecked › with impossible timeout .not [fail] +page/expect-boolean.spec.ts › toBeChecked › with not [fail] +page/expect-boolean.spec.ts › toBeChecked › with not and checked:false [fail] +page/expect-boolean.spec.ts › toBeChecked › with role [fail] +page/expect-boolean.spec.ts › toBeDisabled with value [fail] +page/expect-boolean.spec.ts › toBeEditable › default [fail] +page/expect-boolean.spec.ts › toBeEditable › with editable:false [fail] +page/expect-boolean.spec.ts › toBeEditable › with editable:true [fail] +page/expect-boolean.spec.ts › toBeEditable › with not [fail] +page/expect-boolean.spec.ts › toBeEditable › with not and editable:false [fail] +page/expect-boolean.spec.ts › toBeEmpty div [fail] +page/expect-boolean.spec.ts › toBeEmpty input [fail] +page/expect-boolean.spec.ts › toBeEnabled › default [fail] +page/expect-boolean.spec.ts › toBeEnabled › eventually [fail] +page/expect-boolean.spec.ts › toBeEnabled › eventually with not [fail] +page/expect-boolean.spec.ts › toBeEnabled › failed [fail] +page/expect-boolean.spec.ts › toBeEnabled › toBeDisabled [fail] +page/expect-boolean.spec.ts › toBeEnabled › with enabled:false [fail] +page/expect-boolean.spec.ts › toBeEnabled › with enabled:true [fail] +page/expect-boolean.spec.ts › toBeEnabled › with not and enabled:false [fail] +page/expect-boolean.spec.ts › toBeFocused [fail] +page/expect-boolean.spec.ts › toBeFocused with shadow elements [fail] +page/expect-boolean.spec.ts › toBeHidden with value [fail] +page/expect-boolean.spec.ts › toBeHidden › default [fail] +page/expect-boolean.spec.ts › toBeHidden › eventually [fail] +page/expect-boolean.spec.ts › toBeHidden › eventually with not [fail] +page/expect-boolean.spec.ts › toBeHidden › fail [fail] +page/expect-boolean.spec.ts › toBeHidden › fail with not [fail] +page/expect-boolean.spec.ts › toBeHidden › fail with not when nothing matching [fail] +page/expect-boolean.spec.ts › toBeHidden › when nothing matches [fail] +page/expect-boolean.spec.ts › toBeHidden › with impossible timeout [fail] +page/expect-boolean.spec.ts › toBeHidden › with impossible timeout .not [fail] +page/expect-boolean.spec.ts › toBeHidden › with not [fail] +page/expect-boolean.spec.ts › toBeOK [pass] +page/expect-boolean.spec.ts › toBeOK fail with invalid argument [pass] +page/expect-boolean.spec.ts › toBeOK fail with promise [pass] +page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › image content type [pass] +page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › no content type [pass] +page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › text content type [pass] +page/expect-boolean.spec.ts › toBeVisible › default [fail] +page/expect-boolean.spec.ts › toBeVisible › eventually [fail] +page/expect-boolean.spec.ts › toBeVisible › eventually with not [fail] +page/expect-boolean.spec.ts › toBeVisible › fail [fail] +page/expect-boolean.spec.ts › toBeVisible › fail with not [fail] +page/expect-boolean.spec.ts › toBeVisible › over navigation [pass] +page/expect-boolean.spec.ts › toBeVisible › with frameLocator [fail] +page/expect-boolean.spec.ts › toBeVisible › with frameLocator 2 [fail] +page/expect-boolean.spec.ts › toBeVisible › with impossible timeout [fail] +page/expect-boolean.spec.ts › toBeVisible › with impossible timeout .not [fail] +page/expect-boolean.spec.ts › toBeVisible › with not [fail] +page/expect-boolean.spec.ts › toBeVisible › with not and visible:false [fail] +page/expect-boolean.spec.ts › toBeVisible › with visible:false [fail] +page/expect-boolean.spec.ts › toBeVisible › with visible:true [fail] +page/expect-matcher-result.spec.ts › toBeChecked({ checked: false }) should have expected: false [fail] +page/expect-matcher-result.spec.ts › toBeTruthy-based assertions should have matcher result [fail] +page/expect-matcher-result.spec.ts › toEqual-based assertions should have matcher result [fail] +page/expect-matcher-result.spec.ts › toHaveScreenshot should populate matcherResult [fail] +page/expect-matcher-result.spec.ts › toMatchText-based assertions should have matcher result [fail] +page/expect-misc.spec.ts › toBeInViewport › should have good stack [pass] +page/expect-misc.spec.ts › toBeInViewport › should report intersection even if fully covered by other element [fail] +page/expect-misc.spec.ts › toBeInViewport › should respect ratio option [fail] +page/expect-misc.spec.ts › toBeInViewport › should work [fail] +page/expect-misc.spec.ts › toHaveAccessibleDescription [fail] +page/expect-misc.spec.ts › toHaveAccessibleName [fail] +page/expect-misc.spec.ts › toHaveAttribute › pass [fail] +page/expect-misc.spec.ts › toHaveAttribute › should match attribute without value [fail] +page/expect-misc.spec.ts › toHaveAttribute › should match boolean attribute [fail] +page/expect-misc.spec.ts › toHaveAttribute › should not match missing attribute [fail] +page/expect-misc.spec.ts › toHaveAttribute › should support boolean attribute with options [fail] +page/expect-misc.spec.ts › toHaveAttribute › support ignoreCase [fail] +page/expect-misc.spec.ts › toHaveCSS › custom css properties [fail] +page/expect-misc.spec.ts › toHaveCSS › pass [fail] +page/expect-misc.spec.ts › toHaveClass › fail [fail] +page/expect-misc.spec.ts › toHaveClass › fail with array [fail] +page/expect-misc.spec.ts › toHaveClass › pass [fail] +page/expect-misc.spec.ts › toHaveClass › pass with SVGs [fail] +page/expect-misc.spec.ts › toHaveClass › pass with array [fail] +page/expect-misc.spec.ts › toHaveCount should not produce logs twice [fail] +page/expect-misc.spec.ts › toHaveCount › eventually pass non-zero [fail] +page/expect-misc.spec.ts › toHaveCount › eventually pass not non-zero [fail] +page/expect-misc.spec.ts › toHaveCount › eventually pass zero [fail] +page/expect-misc.spec.ts › toHaveCount › fail zero [fail] +page/expect-misc.spec.ts › toHaveCount › fail zero 2 [fail] +page/expect-misc.spec.ts › toHaveCount › pass zero [fail] +page/expect-misc.spec.ts › toHaveCount › toHaveCount pass [fail] +page/expect-misc.spec.ts › toHaveId › pass [fail] +page/expect-misc.spec.ts › toHaveJSProperty › fail [fail] +page/expect-misc.spec.ts › toHaveJSProperty › fail boolean [fail] +page/expect-misc.spec.ts › toHaveJSProperty › fail boolean 2 [fail] +page/expect-misc.spec.ts › toHaveJSProperty › fail nested [fail] +page/expect-misc.spec.ts › toHaveJSProperty › fail number [fail] +page/expect-misc.spec.ts › toHaveJSProperty › fail string [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass boolean [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass boolean 2 [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass nested [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass null [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass number [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass string [fail] +page/expect-misc.spec.ts › toHaveJSProperty › pass undefined [fail] +page/expect-misc.spec.ts › toHaveRole [fail] +page/expect-misc.spec.ts › toHaveText should not produce logs twice [fail] +page/expect-misc.spec.ts › toHaveText that does not match should not produce logs twice [fail] +page/expect-misc.spec.ts › toHaveTitle › fail [fail] +page/expect-misc.spec.ts › toHaveTitle › pass [fail] +page/expect-misc.spec.ts › toHaveURL › fail [pass] +page/expect-misc.spec.ts › toHaveURL › pass [pass] +page/expect-misc.spec.ts › toHaveURL › support ignoreCase [pass] +page/expect-timeout.spec.ts › should have timeout error name [pass] +page/expect-timeout.spec.ts › should not print timed out error message when page closes [fail] +page/expect-timeout.spec.ts › should not throw when navigating during first locator handler check [fail] +page/expect-timeout.spec.ts › should not throw when navigating during one-shot check [fail] +page/expect-timeout.spec.ts › should print timed out error message [fail] +page/expect-timeout.spec.ts › should print timed out error message when value does not match [fail] +page/expect-timeout.spec.ts › should print timed out error message when value does not match with impossible timeout [fail] +page/expect-timeout.spec.ts › should print timed out error message with impossible timeout [fail] +page/expect-timeout.spec.ts › should timeout during first locator handler check [fail] +page/expect-to-have-text.spec.ts › not.toHaveText › fail [fail] +page/expect-to-have-text.spec.ts › not.toHaveText › pass [fail] +page/expect-to-have-text.spec.ts › not.toHaveText › should work when selector does not match [fail] +page/expect-to-have-text.spec.ts › toContainText with array › fail [fail] +page/expect-to-have-text.spec.ts › toContainText with array › pass [fail] +page/expect-to-have-text.spec.ts › toContainText with regex › fail [fail] +page/expect-to-have-text.spec.ts › toContainText with regex › pass [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › fail [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › fail on not+empty [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › fail on repeating array matchers [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › pass [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › pass empty [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › pass eventually empty [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › pass lazy [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › pass not empty [fail] +page/expect-to-have-text.spec.ts › toHaveText with array › pass on empty [fail] +page/expect-to-have-text.spec.ts › toHaveText with regex › fail [fail] +page/expect-to-have-text.spec.ts › toHaveText with regex › pass [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › fail [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › fail with impossible timeout [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › in shadow dom [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › pass [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › pass contain [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › pass eventually [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › with userInnerText [fail] +page/expect-to-have-value.spec.ts › should support failure [fail] +page/expect-to-have-value.spec.ts › should work [fail] +page/expect-to-have-value.spec.ts › should work with label [fail] +page/expect-to-have-value.spec.ts › should work with regex [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › exact match with text failure [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when items not selected [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when multiple not specified [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when not a select element [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › follows labels [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with regex [fail] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with text [fail] +page/frame-evaluate.spec.ts › evaluateHandle should work [pass] +page/frame-evaluate.spec.ts › should allow cross-frame element handles [fail] +page/frame-evaluate.spec.ts › should be isolated between frames [pass] +page/frame-evaluate.spec.ts › should dispose context on cross-origin navigation [fail] +page/frame-evaluate.spec.ts › should dispose context on navigation [fail] +page/frame-evaluate.spec.ts › should execute after cross-site navigation [pass] +page/frame-evaluate.spec.ts › should have correct execution contexts @smoke [pass] +page/frame-evaluate.spec.ts › should have different execution contexts [pass] +page/frame-evaluate.spec.ts › should not allow cross-frame element handles when frames do not script each other [fail] +page/frame-evaluate.spec.ts › should not allow cross-frame js handles [pass] +page/frame-evaluate.spec.ts › should throw for detached frames [pass] +page/frame-evaluate.spec.ts › should work in iframes that failed initial navigation [fail] +page/frame-evaluate.spec.ts › should work in iframes that interrupted initial javascript url navigation [pass] +page/frame-frame-element.spec.ts › should throw when detached [pass] +page/frame-frame-element.spec.ts › should work @smoke [pass] +page/frame-frame-element.spec.ts › should work inside closed shadow root [fail] +page/frame-frame-element.spec.ts › should work inside declarative shadow root [fail] +page/frame-frame-element.spec.ts › should work with contentFrame [pass] +page/frame-frame-element.spec.ts › should work with frameset [pass] +page/frame-goto.spec.ts › should continue after client redirect [pass] +page/frame-goto.spec.ts › should navigate subframes @smoke [pass] +page/frame-goto.spec.ts › should reject when frame detaches [pass] +page/frame-goto.spec.ts › should return matching responses [fail] +page/frame-hierarchy.spec.ts › should detach child frames on navigation [pass] +page/frame-hierarchy.spec.ts › should handle nested frames @smoke [fail] +page/frame-hierarchy.spec.ts › should not send attach/detach events for main frame [pass] +page/frame-hierarchy.spec.ts › should persist mainFrame on cross-process navigation [pass] +page/frame-hierarchy.spec.ts › should refuse to display x-frame-options:deny iframe [fail] +page/frame-hierarchy.spec.ts › should report different frame instance when frame re-attaches [pass] +page/frame-hierarchy.spec.ts › should report frame from-inside shadow DOM [pass] +page/frame-hierarchy.spec.ts › should report frame.name() [fail] +page/frame-hierarchy.spec.ts › should report frame.parent() [pass] +page/frame-hierarchy.spec.ts › should return frame.page() [pass] +page/frame-hierarchy.spec.ts › should send "framenavigated" when navigating on anchor URLs [timeout] +page/frame-hierarchy.spec.ts › should send events when frames are manipulated dynamically [pass] +page/frame-hierarchy.spec.ts › should support framesets [pass] +page/interception.spec.ts › should disable memory cache when intercepting [fail] +page/interception.spec.ts › should intercept after a service worker [pass] +page/interception.spec.ts › should intercept blob url requests [fail] +page/interception.spec.ts › should intercept network activity from worker [pass] +page/interception.spec.ts › should intercept network activity from worker 2 [pass] +page/interception.spec.ts › should intercept worker requests when enabled after worker creation [pass] +page/interception.spec.ts › should not break remote worker importScripts [pass] +page/interception.spec.ts › should work with glob [pass] +page/interception.spec.ts › should work with navigation @smoke [pass] +page/interception.spec.ts › should work with regular expression passed from a different context [fail] +page/jshandle-as-element.spec.ts › should return ElementHandle for TextNodes [fail] +page/jshandle-as-element.spec.ts › should return null for non-elements [pass] +page/jshandle-as-element.spec.ts › should work @smoke [fail] +page/jshandle-as-element.spec.ts › should work with nullified Node [fail] +page/jshandle-evaluate.spec.ts › should work with expression [pass] +page/jshandle-evaluate.spec.ts › should work with function @smoke [pass] +page/jshandle-json-value.spec.ts › should handle circular objects [pass] +page/jshandle-json-value.spec.ts › should work @smoke [pass] +page/jshandle-json-value.spec.ts › should work with dates [pass] +page/jshandle-properties.spec.ts › getProperties should return empty map for non-objects [pass] +page/jshandle-properties.spec.ts › getProperties should return even non-own properties [fail] +page/jshandle-properties.spec.ts › getProperties should work [fail] +page/jshandle-properties.spec.ts › getProperties should work with elements [fail] +page/jshandle-properties.spec.ts › should work @smoke [fail] +page/jshandle-properties.spec.ts › should work with undefined, null, and empty [fail] +page/jshandle-properties.spec.ts › should work with unserializable values [fail] +page/jshandle-to-string.spec.ts › should beautifully render sparse arrays [fail] +page/jshandle-to-string.spec.ts › should work for complicated objects [fail] +page/jshandle-to-string.spec.ts › should work for primitives [pass] +page/jshandle-to-string.spec.ts › should work for promises [fail] +page/jshandle-to-string.spec.ts › should work with different subtypes @smoke [fail] +page/jshandle-to-string.spec.ts › should work with previewable subtypes [fail] +page/locator-click.spec.ts › should click if the target element is removed in pointerdown event [fail] +page/locator-click.spec.ts › should click if the target element is removed in pointerup event [fail] +page/locator-click.spec.ts › should double click the button [fail] +page/locator-click.spec.ts › should work @smoke [pass] +page/locator-click.spec.ts › should work for TextNodes [fail] +page/locator-click.spec.ts › should work with Node removed [pass] +page/locator-convenience.spec.ts › allInnerTexts should work [fail] +page/locator-convenience.spec.ts › allTextContents should work [fail] +page/locator-convenience.spec.ts › getAttribute should work [pass] +page/locator-convenience.spec.ts › innerHTML should work [pass] +page/locator-convenience.spec.ts › innerText should produce log [fail] +page/locator-convenience.spec.ts › innerText should throw [fail] +page/locator-convenience.spec.ts › innerText should work [pass] +page/locator-convenience.spec.ts › inputValue should work [pass] +page/locator-convenience.spec.ts › isChecked should work [fail] +page/locator-convenience.spec.ts › isChecked should work for indeterminate input [fail] +page/locator-convenience.spec.ts › isEditable should work [fail] +page/locator-convenience.spec.ts › isEnabled and isDisabled should work [fail] +page/locator-convenience.spec.ts › should have a nice preview [pass] +page/locator-convenience.spec.ts › should return page [pass] +page/locator-convenience.spec.ts › textContent should work [pass] +page/locator-element-handle.spec.ts › should query existing element @smoke [fail] +page/locator-element-handle.spec.ts › should query existing elements [fail] +page/locator-element-handle.spec.ts › should return empty array for non-existing elements [fail] +page/locator-element-handle.spec.ts › xpath should query existing element [fail] +page/locator-element-handle.spec.ts › xpath should return null for non-existing element [fail] +page/locator-evaluate.spec.ts › should not throw in case of missing selector for all [fail] +page/locator-evaluate.spec.ts › should retrieve content from subtree [fail] +page/locator-evaluate.spec.ts › should retrieve content from subtree for all [fail] +page/locator-evaluate.spec.ts › should work @smoke [fail] +page/locator-evaluate.spec.ts › should work for all [fail] +page/locator-frame.spec.ts › click should survive frame reattach [pass] +page/locator-frame.spec.ts › click should survive iframe navigation [fail] +page/locator-frame.spec.ts › frameLocator.owner should work [pass] +page/locator-frame.spec.ts › getBy coverage [pass] +page/locator-frame.spec.ts › locator.contentFrame should work [pass] +page/locator-frame.spec.ts › locator.frameLocator should not throw on first/last/nth [pass] +page/locator-frame.spec.ts › locator.frameLocator should throw on ambiguity [pass] +page/locator-frame.spec.ts › locator.frameLocator should work for iframe [pass] +page/locator-frame.spec.ts › should click in lazy iframe [pass] +page/locator-frame.spec.ts › should non work for non-frame [fail] +page/locator-frame.spec.ts › should not wait for frame [fail] +page/locator-frame.spec.ts › should not wait for frame 2 [pass] +page/locator-frame.spec.ts › should not wait for frame 3 [fail] +page/locator-frame.spec.ts › should wait for frame [pass] +page/locator-frame.spec.ts › should wait for frame 2 [pass] +page/locator-frame.spec.ts › should wait for frame to go [pass] +page/locator-frame.spec.ts › should work for $ and $$ [pass] +page/locator-frame.spec.ts › should work for iframe @smoke [pass] +page/locator-frame.spec.ts › should work for nested iframe [pass] +page/locator-frame.spec.ts › should work with COEP/COOP/CORP isolated iframe [fail] +page/locator-frame.spec.ts › wait for hidden should succeed when frame is not in dom [pass] +page/locator-frame.spec.ts › waitFor should survive frame reattach [pass] +page/locator-highlight.spec.ts › should highlight locator [fail] +page/locator-is-visible.spec.ts › isVisible and isHidden should work [fail] +page/locator-is-visible.spec.ts › isVisible and isHidden should work with details [fail] +page/locator-is-visible.spec.ts › isVisible during navigation should not throw [pass] +page/locator-is-visible.spec.ts › isVisible inside a button [fail] +page/locator-is-visible.spec.ts › isVisible inside a role=button [fail] +page/locator-is-visible.spec.ts › isVisible should be true for element outside view [fail] +page/locator-is-visible.spec.ts › isVisible should be true for opacity:0 [fail] +page/locator-is-visible.spec.ts › isVisible with invalid selector should throw [pass] +page/locator-list.spec.ts › locator.all should work [fail] +page/locator-misc-1.spec.ts › focus should respect strictness [fail] +page/locator-misc-1.spec.ts › should check the box [fail] +page/locator-misc-1.spec.ts › should check the box using setChecked [fail] +page/locator-misc-1.spec.ts › should clear input [pass] +page/locator-misc-1.spec.ts › should dispatch click event via ElementHandles [fail] +page/locator-misc-1.spec.ts › should fill input [pass] +page/locator-misc-1.spec.ts › should fill input when Node is removed [pass] +page/locator-misc-1.spec.ts › should focus and blur a button [fail] +page/locator-misc-1.spec.ts › should hover @smoke [pass] +page/locator-misc-1.spec.ts › should hover when Node is removed [pass] +page/locator-misc-1.spec.ts › should select single option [fail] +page/locator-misc-1.spec.ts › should uncheck the box [fail] +page/locator-misc-1.spec.ts › should upload the file [timeout] +page/locator-misc-2.spec.ts › Locator.locator() and FrameLocator.locator() should accept locator [fail] +page/locator-misc-2.spec.ts › locator.count should work with deleted Map in main world [pass] +page/locator-misc-2.spec.ts › should combine visible with other selectors [fail] +page/locator-misc-2.spec.ts › should press @smoke [fail] +page/locator-misc-2.spec.ts › should pressSequentially [fail] +page/locator-misc-2.spec.ts › should return bounding box [fail] +page/locator-misc-2.spec.ts › should scroll into view [fail] +page/locator-misc-2.spec.ts › should scroll zero-sized element into view [fail] +page/locator-misc-2.spec.ts › should select textarea [fail] +page/locator-misc-2.spec.ts › should take screenshot [fail] +page/locator-misc-2.spec.ts › should type [fail] +page/locator-misc-2.spec.ts › should waitFor [fail] +page/locator-misc-2.spec.ts › should waitFor hidden [fail] +page/locator-query.spec.ts › alias methods coverage [fail] +page/locator-query.spec.ts › should allow some, but not all nested frameLocators [fail] +page/locator-query.spec.ts › should enforce same frame for has/leftOf/rightOf/above/below/near [pass] +page/locator-query.spec.ts › should filter by case-insensitive regex in a child [fail] +page/locator-query.spec.ts › should filter by case-insensitive regex in multiple children [fail] +page/locator-query.spec.ts › should filter by regex [fail] +page/locator-query.spec.ts › should filter by regex and regexp flags [fail] +page/locator-query.spec.ts › should filter by regex with a single quote [fail] +page/locator-query.spec.ts › should filter by regex with quotes [fail] +page/locator-query.spec.ts › should filter by regex with special symbols [fail] +page/locator-query.spec.ts › should filter by text [fail] +page/locator-query.spec.ts › should filter by text 2 [fail] +page/locator-query.spec.ts › should filter by text with quotes [fail] +page/locator-query.spec.ts › should respect first() and last() @smoke [fail] +page/locator-query.spec.ts › should respect nth() [fail] +page/locator-query.spec.ts › should support has:locator [fail] +page/locator-query.spec.ts › should support locator.and [fail] +page/locator-query.spec.ts › should support locator.filter [fail] +page/locator-query.spec.ts › should support locator.locator with and/or [fail] +page/locator-query.spec.ts › should support locator.or [fail] +page/locator-query.spec.ts › should throw on capture w/ nth() [fail] +page/locator-query.spec.ts › should throw on due to strictness [fail] +page/locator-query.spec.ts › should throw on due to strictness 2 [fail] +page/matchers.misc.spec.ts › should outlive frame navigation [pass] +page/matchers.misc.spec.ts › should print no-locator-resolved error when locator matcher did not resolve to any element [fail] +page/network-post-data.spec.ts › should get post data for file/blob [fail] +page/network-post-data.spec.ts › should get post data for navigator.sendBeacon api calls [fail] +page/network-post-data.spec.ts › should return correct postData buffer for utf-8 body [fail] +page/network-post-data.spec.ts › should return post data for PUT requests [fail] +page/network-post-data.spec.ts › should return post data w/o content-type @smoke [fail] +page/network-post-data.spec.ts › should throw on invalid JSON in post data [fail] +page/page-accessibility.spec.ts › autocomplete [fail] +page/page-accessibility.spec.ts › checkbox with and tabIndex and label should not have children [fail] +page/page-accessibility.spec.ts › checkbox without label should not have children [fail] +page/page-accessibility.spec.ts › keyshortcuts [fail] +page/page-accessibility.spec.ts › multiselectable [fail] +page/page-accessibility.spec.ts › non editable textbox with role and tabIndex and label should not have children [fail] +page/page-accessibility.spec.ts › orientation [fail] +page/page-accessibility.spec.ts › rich text editable fields should have children [fail] +page/page-accessibility.spec.ts › rich text editable fields with role should have children [fail] +page/page-accessibility.spec.ts › roledescription [fail] +page/page-accessibility.spec.ts › should not report text nodes inside controls [fail] +page/page-accessibility.spec.ts › should return null when the element is no longer in DOM [fail] +page/page-accessibility.spec.ts › should show uninteresting nodes [fail] +page/page-accessibility.spec.ts › should work @smoke [fail] +page/page-accessibility.spec.ts › should work a button [fail] +page/page-accessibility.spec.ts › should work an input [fail] +page/page-accessibility.spec.ts › should work on a menu [fail] +page/page-accessibility.spec.ts › should work when there is a title [fail] +page/page-accessibility.spec.ts › should work with aria-invalid accessibility tree [fail] +page/page-accessibility.spec.ts › should work with regular text [fail] +page/page-add-init-script.spec.ts › init script should run only once in iframe [pass] +page/page-add-init-script.spec.ts › init script should run only once in popup [fail] +page/page-add-init-script.spec.ts › should evaluate before anything else on the page [pass] +page/page-add-init-script.spec.ts › should support multiple scripts [pass] +page/page-add-init-script.spec.ts › should throw without path and content [pass] +page/page-add-init-script.spec.ts › should work after a cross origin navigation [pass] +page/page-add-init-script.spec.ts › should work with CSP [fail] +page/page-add-init-script.spec.ts › should work with a path [pass] +page/page-add-init-script.spec.ts › should work with content @smoke [pass] +page/page-add-init-script.spec.ts › should work with trailing comments [pass] +page/page-add-locator-handler.spec.ts › should not work with force:true [fail] +page/page-add-locator-handler.spec.ts › should removeLocatorHandler [pass] +page/page-add-locator-handler.spec.ts › should throw when handler times out [pass] +page/page-add-locator-handler.spec.ts › should throw when page closes [pass] +page/page-add-locator-handler.spec.ts › should wait for hidden by default [fail] +page/page-add-locator-handler.spec.ts › should wait for hidden by default 2 [pass] +page/page-add-locator-handler.spec.ts › should work [pass] +page/page-add-locator-handler.spec.ts › should work when owner frame detaches [pass] +page/page-add-locator-handler.spec.ts › should work with a custom check [pass] +page/page-add-locator-handler.spec.ts › should work with locator.hover() [pass] +page/page-add-locator-handler.spec.ts › should work with noWaitAfter [pass] +page/page-add-locator-handler.spec.ts › should work with times: option [fail] +page/page-add-locator-handler.spec.ts › should work with toBeVisible [pass] +page/page-add-locator-handler.spec.ts › should work with toHaveScreenshot [fail] +page/page-add-script-tag.spec.ts › should include sourceURL when path is provided [pass] +page/page-add-script-tag.spec.ts › should throw a nice error when the request fails [pass] +page/page-add-script-tag.spec.ts › should throw an error if loading from url fail [pass] +page/page-add-script-tag.spec.ts › should throw an error if no options are provided [pass] +page/page-add-script-tag.spec.ts › should throw when added with URL to the CSP page [pass] +page/page-add-script-tag.spec.ts › should throw when added with content to the CSP page [pass] +page/page-add-script-tag.spec.ts › should work with a content and type=module [pass] +page/page-add-script-tag.spec.ts › should work with a path [pass] +page/page-add-script-tag.spec.ts › should work with a path and type=module [pass] +page/page-add-script-tag.spec.ts › should work with a url [pass] +page/page-add-script-tag.spec.ts › should work with a url and type=module [fail] +page/page-add-script-tag.spec.ts › should work with content [pass] +page/page-add-style-tag.spec.ts › should include sourceURL when path is provided [pass] +page/page-add-style-tag.spec.ts › should throw an error if loading from url fail [pass] +page/page-add-style-tag.spec.ts › should throw an error if no options are provided [pass] +page/page-add-style-tag.spec.ts › should throw when added with URL to the CSP page [pass] +page/page-add-style-tag.spec.ts › should throw when added with content to the CSP page [pass] +page/page-add-style-tag.spec.ts › should work with a path [pass] +page/page-add-style-tag.spec.ts › should work with a url @smoke [pass] +page/page-add-style-tag.spec.ts › should work with content [pass] +page/page-autowaiting-basic.spec.ts › should await cross-process navigation when clicking anchor [fail] +page/page-autowaiting-basic.spec.ts › should await form-get on click [fail] +page/page-autowaiting-basic.spec.ts › should await form-post on click [fail] +page/page-autowaiting-basic.spec.ts › should await navigation when clicking anchor [fail] +page/page-autowaiting-basic.spec.ts › should not stall on JS navigation link [fail] +page/page-autowaiting-basic.spec.ts › should report navigation in the log when clicking anchor [fail] +page/page-autowaiting-basic.spec.ts › should work with dblclick without noWaitAfter when navigation is stalled [fail] +page/page-autowaiting-basic.spec.ts › should work with goto following click [fail] +page/page-autowaiting-basic.spec.ts › should work with noWaitAfter: true [fail] +page/page-autowaiting-basic.spec.ts › should work with waitForLoadState(load) [fail] +page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank [pass] +page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank after non-about:blank [pass] +page/page-autowaiting-no-hang.spec.ts › calling window.open and window.close [fail] +page/page-autowaiting-no-hang.spec.ts › calling window.stop async [pass] +page/page-autowaiting-no-hang.spec.ts › calling window.stop sync [pass] +page/page-autowaiting-no-hang.spec.ts › clicking on links which do not commit navigation [fail] +page/page-autowaiting-no-hang.spec.ts › opening a popup [pass] +page/page-basic.spec.ts › async stacks should work [pass] +page/page-basic.spec.ts › frame.press should work [fail] +page/page-basic.spec.ts › has navigator.webdriver set to true [pass] +page/page-basic.spec.ts › page.close should work with page.close [pass] +page/page-basic.spec.ts › page.close should work with window.close [pass] +page/page-basic.spec.ts › page.frame should respect name [fail] +page/page-basic.spec.ts › page.frame should respect url [fail] +page/page-basic.spec.ts › page.press should work [pass] +page/page-basic.spec.ts › page.press should work for Enter [fail] +page/page-basic.spec.ts › page.title should return the page title [pass] +page/page-basic.spec.ts › page.url should include hashes [pass] +page/page-basic.spec.ts › page.url should work [pass] +page/page-basic.spec.ts › should be callable twice [pass] +page/page-basic.spec.ts › should fail with error upon disconnect [pass] +page/page-basic.spec.ts › should fire domcontentloaded when expected [pass] +page/page-basic.spec.ts › should fire load when expected [pass] +page/page-basic.spec.ts › should have sane user agent [fail] +page/page-basic.spec.ts › should iterate over page properties [pass] +page/page-basic.spec.ts › should pass page to close event [pass] +page/page-basic.spec.ts › should pass self as argument to domcontentloaded event [pass] +page/page-basic.spec.ts › should pass self as argument to load event [pass] +page/page-basic.spec.ts › should provide access to the opener page [pass] +page/page-basic.spec.ts › should reject all promises when page is closed [fail] +page/page-basic.spec.ts › should return null if parent page has been closed [fail] +page/page-basic.spec.ts › should set the page close state [pass] +page/page-basic.spec.ts › should terminate network waiters [pass] +page/page-check.spec.ts › should check radio [fail] +page/page-check.spec.ts › should check radio by aria role [fail] +page/page-check.spec.ts › should check the box @smoke [fail] +page/page-check.spec.ts › should check the box by aria role [fail] +page/page-check.spec.ts › should check the box inside a button [fail] +page/page-check.spec.ts › should check the box using setChecked [fail] +page/page-check.spec.ts › should check the label with position [fail] +page/page-check.spec.ts › should not check the checked box [fail] +page/page-check.spec.ts › should not uncheck the unchecked box [fail] +page/page-check.spec.ts › should throw when not a checkbox [fail] +page/page-check.spec.ts › should throw when not a checkbox 2 [fail] +page/page-check.spec.ts › should uncheck radio by aria role [fail] +page/page-check.spec.ts › should uncheck the box [fail] +page/page-check.spec.ts › should uncheck the box by aria role [fail] +page/page-check.spec.ts › trial run should not check [fail] +page/page-check.spec.ts › trial run should not uncheck [fail] +page/page-click-during-navigation.spec.ts › should not fail with internal error upon navigation [pass] +page/page-click-react.spec.ts › should not retarget the handle when element is recycled [unknown] +page/page-click-react.spec.ts › should not retarget when element changes on hover [pass] +page/page-click-react.spec.ts › should not retarget when element is recycled on hover [pass] +page/page-click-react.spec.ts › should report that selector does not match anymore [unknown] +page/page-click-react.spec.ts › should retarget when element is recycled before enabled check [unknown] +page/page-click-react.spec.ts › should retarget when element is recycled during hit testing [unknown] +page/page-click-react.spec.ts › should timeout when click opens alert [fail] +page/page-click-scroll.spec.ts › should not crash when force-clicking hidden input [fail] +page/page-click-scroll.spec.ts › should not hit scroll bar [fail] +page/page-click-scroll.spec.ts › should scroll into view display:contents [fail] +page/page-click-scroll.spec.ts › should scroll into view display:contents with a child [fail] +page/page-click-scroll.spec.ts › should scroll into view display:contents with position [fail] +page/page-click-scroll.spec.ts › should scroll into view element in iframe [fail] +page/page-click-scroll.spec.ts › should scroll into view span element [fail] +page/page-click-timeout-1.spec.ts › should avoid side effects after timeout [pass] +page/page-click-timeout-1.spec.ts › should timeout waiting for button to be enabled [fail] +page/page-click-timeout-2.spec.ts › should timeout waiting for display:none to be gone [pass] +page/page-click-timeout-2.spec.ts › should timeout waiting for visibility:hidden to be gone [pass] +page/page-click-timeout-3.spec.ts › should fail when element jumps during hit testing [fail] +page/page-click-timeout-3.spec.ts › should report wrong hit target subtree [pass] +page/page-click-timeout-3.spec.ts › should still click when force but hit target is obscured [pass] +page/page-click-timeout-3.spec.ts › should timeout waiting for hit target [pass] +page/page-click-timeout-4.spec.ts › should click for the second time after first timeout [pass] +page/page-click-timeout-4.spec.ts › should timeout waiting for stable position [pass] +page/page-click.spec.ts › ensure events are dispatched in the individual tasks [fail] +page/page-click.spec.ts › should click a button in scrolling container with offset [pass] +page/page-click.spec.ts › should click a button that is overlaid by a permission popup [fail] +page/page-click.spec.ts › should click a partially obscured button [pass] +page/page-click.spec.ts › should click a rotated button [pass] +page/page-click.spec.ts › should click a very large button with offset [pass] +page/page-click.spec.ts › should click an offscreen element when scroll-behavior is smooth [fail] +page/page-click.spec.ts › should click button inside frameset [pass] +page/page-click.spec.ts › should click disabled div [fail] +page/page-click.spec.ts › should click if opened select covers the button [fail] +page/page-click.spec.ts › should click in a nested transformed iframe [fail] +page/page-click.spec.ts › should click in a transformed iframe [fail] +page/page-click.spec.ts › should click in a transformed iframe with force [fail] +page/page-click.spec.ts › should click in an iframe with border [fail] +page/page-click.spec.ts › should click in an iframe with border 2 [fail] +page/page-click.spec.ts › should click links which cause navigation [fail] +page/page-click.spec.ts › should click offscreen buttons [pass] +page/page-click.spec.ts › should click on a span with an inline element inside [fail] +page/page-click.spec.ts › should click on checkbox input and toggle [fail] +page/page-click.spec.ts › should click on checkbox label and toggle [pass] +page/page-click.spec.ts › should click svg [fail] +page/page-click.spec.ts › should click the 1x1 div [fail] +page/page-click.spec.ts › should click the button @smoke [pass] +page/page-click.spec.ts › should click the button after a cross origin navigation [pass] +page/page-click.spec.ts › should click the button after navigation [pass] +page/page-click.spec.ts › should click the button behind sticky header [fail] +page/page-click.spec.ts › should click the button if window.Node is removed [pass] +page/page-click.spec.ts › should click the button inside an iframe [fail] +page/page-click.spec.ts › should click the button when window.innerWidth is corrupted [pass] +page/page-click.spec.ts › should click the button with em border with offset [pass] +page/page-click.spec.ts › should click the button with fixed position inside an iframe [fail] +page/page-click.spec.ts › should click the button with px border with offset [pass] +page/page-click.spec.ts › should click when one of inline box children is outside of viewport [fail] +page/page-click.spec.ts › should click wrapped links [pass] +page/page-click.spec.ts › should click zero-sized input by label [fail] +page/page-click.spec.ts › should climb dom for inner label with pointer-events:none [fail] +page/page-click.spec.ts › should climb up to [role=button] [fail] +page/page-click.spec.ts › should climb up to a [role=link] [fail] +page/page-click.spec.ts › should climb up to a anchor [fail] +page/page-click.spec.ts › should dispatch microtasks in order [fail] +page/page-click.spec.ts › should double click the button [fail] +page/page-click.spec.ts › should fail when element detaches after animation [pass] +page/page-click.spec.ts › should fail when element is animating from outside the viewport with force [fail] +page/page-click.spec.ts › should fail when obscured and not waiting for hit target [fail] +page/page-click.spec.ts › should fire contextmenu event on right click [pass] +page/page-click.spec.ts › should fire contextmenu event on right click in correct order [fail] +page/page-click.spec.ts › should issue clicks in parallel in page and popup [pass] +page/page-click.spec.ts › should not hang when frame is detached [pass] +page/page-click.spec.ts › should not throw UnhandledPromiseRejection when page closes [pass] +page/page-click.spec.ts › should not throw protocol error when navigating during the click [pass] +page/page-click.spec.ts › should not wait with force [pass] +page/page-click.spec.ts › should report nice error when element is detached and force-clicked [pass] +page/page-click.spec.ts › should retry when element detaches after animation [pass] +page/page-click.spec.ts › should retry when element is animating from outside the viewport [fail] +page/page-click.spec.ts › should retry when navigating during the click [pass] +page/page-click.spec.ts › should scroll and click the button [pass] +page/page-click.spec.ts › should scroll and click the button with smooth scroll behavior [pass] +page/page-click.spec.ts › should select the text by triple clicking [fail] +page/page-click.spec.ts › should update modifiers correctly [pass] +page/page-click.spec.ts › should wait for BUTTON to be clickable when it has pointer-events:none [fail] +page/page-click.spec.ts › should wait for LABEL to be clickable when it has pointer-events:none [fail] +page/page-click.spec.ts › should wait for becoming hit target [pass] +page/page-click.spec.ts › should wait for becoming hit target with trial run [pass] +page/page-click.spec.ts › should wait for button to be enabled [fail] +page/page-click.spec.ts › should wait for input to be enabled [fail] +page/page-click.spec.ts › should wait for select to be enabled [fail] +page/page-click.spec.ts › should wait for stable position [pass] +page/page-click.spec.ts › should waitFor display:none to be gone [pass] +page/page-click.spec.ts › should waitFor visibility:hidden to be gone [pass] +page/page-click.spec.ts › should waitFor visible when already visible [pass] +page/page-click.spec.ts › should waitFor visible when parent is hidden [fail] +page/page-click.spec.ts › trial run should not click [pass] +page/page-click.spec.ts › trial run should not double click [pass] +page/page-click.spec.ts › trial run should work with short timeout [pass] +page/page-close.spec.ts › should close page with active dialog [fail] +page/page-close.spec.ts › should not accept dialog after close [fail] +page/page-dialog.spec.ts › should accept the confirm prompt [pass] +page/page-dialog.spec.ts › should allow accepting prompts @smoke [pass] +page/page-dialog.spec.ts › should auto-dismiss the alert without listeners [fail] +page/page-dialog.spec.ts › should auto-dismiss the prompt without listeners [pass] +page/page-dialog.spec.ts › should be able to close context with open alert [fail] +page/page-dialog.spec.ts › should dismiss the confirm prompt [pass] +page/page-dialog.spec.ts › should dismiss the prompt [pass] +page/page-dialog.spec.ts › should fire [pass] +page/page-dialog.spec.ts › should handle multiple alerts [fail] +page/page-dialog.spec.ts › should handle multiple confirms [fail] +page/page-dispatchevent.spec.ts › should be atomic [fail] +page/page-dispatchevent.spec.ts › should dispatch absolute device orientation event [pass] +page/page-dispatchevent.spec.ts › should dispatch click after a cross origin navigation [pass] +page/page-dispatchevent.spec.ts › should dispatch click after navigation [pass] +page/page-dispatchevent.spec.ts › should dispatch click event @smoke [pass] +page/page-dispatchevent.spec.ts › should dispatch click event properties [pass] +page/page-dispatchevent.spec.ts › should dispatch click event via ElementHandles [pass] +page/page-dispatchevent.spec.ts › should dispatch click on a span with an inline element inside [fail] +page/page-dispatchevent.spec.ts › should dispatch click svg [fail] +page/page-dispatchevent.spec.ts › should dispatch click when node is added in shadow dom [pass] +page/page-dispatchevent.spec.ts › should dispatch device motion event [pass] +page/page-dispatchevent.spec.ts › should dispatch device orientation event [pass] +page/page-dispatchevent.spec.ts › should dispatch drag drop events [pass] +page/page-dispatchevent.spec.ts › should dispatch drag drop events via ElementHandles [pass] +page/page-dispatchevent.spec.ts › should dispatch wheel event [pass] +page/page-dispatchevent.spec.ts › should not fail when element is blocked on hover [fail] +page/page-dispatchevent.spec.ts › should throw if argument is from different frame [pass] +page/page-drag.spec.ts › Drag and drop › iframe › should drag into an iframe [unknown] +page/page-drag.spec.ts › Drag and drop › iframe › should drag out of an iframe [unknown] +page/page-drag.spec.ts › Drag and drop › should allow specifying the position [fail] +page/page-drag.spec.ts › Drag and drop › should be able to drag the mouse in a frame [pass] +page/page-drag.spec.ts › Drag and drop › should cancel on escape [fail] +page/page-drag.spec.ts › Drag and drop › should not send dragover on the first mousemove [unknown] +page/page-drag.spec.ts › Drag and drop › should respect the drop effect [fail] +page/page-drag.spec.ts › Drag and drop › should send the right events [fail] +page/page-drag.spec.ts › Drag and drop › should work @smoke [fail] +page/page-drag.spec.ts › Drag and drop › should work if a frame is stalled [fail] +page/page-drag.spec.ts › Drag and drop › should work if the drag event is captured but not canceled [fail] +page/page-drag.spec.ts › Drag and drop › should work if the drag is canceled [pass] +page/page-drag.spec.ts › Drag and drop › should work inside iframe [fail] +page/page-drag.spec.ts › Drag and drop › should work with locators [fail] +page/page-drag.spec.ts › Drag and drop › should work with the helper method [fail] +page/page-drag.spec.ts › should handle custom dataTransfer [fail] +page/page-drag.spec.ts › should report event.buttons [pass] +page/page-drag.spec.ts › should work if not doing a drag [pass] +page/page-drag.spec.ts › what happens when dragging element is destroyed [fail] +page/page-emulate-media.spec.ts › should change the actual colors in css [fail] +page/page-emulate-media.spec.ts › should default to light [fail] +page/page-emulate-media.spec.ts › should emulate colorScheme should work @smoke [fail] +page/page-emulate-media.spec.ts › should emulate forcedColors [fail] +page/page-emulate-media.spec.ts › should emulate reduced motion [fail] +page/page-emulate-media.spec.ts › should emulate type @smoke [fail] +page/page-emulate-media.spec.ts › should keep reduced motion and color emulation after reload [fail] +page/page-emulate-media.spec.ts › should throw in case of bad colorScheme argument [pass] +page/page-emulate-media.spec.ts › should throw in case of bad media argument [pass] +page/page-emulate-media.spec.ts › should work during navigation [fail] +page/page-evaluate-handle.spec.ts › should accept multiple nested handles [pass] +page/page-evaluate-handle.spec.ts › should accept nested handle [pass] +page/page-evaluate-handle.spec.ts › should accept nested window handle [pass] +page/page-evaluate-handle.spec.ts › should accept object handle as an argument [pass] +page/page-evaluate-handle.spec.ts › should accept object handle to primitive types [pass] +page/page-evaluate-handle.spec.ts › should accept object handle to unserializable value [pass] +page/page-evaluate-handle.spec.ts › should accept same handle multiple times [pass] +page/page-evaluate-handle.spec.ts › should accept same nested object multiple times [pass] +page/page-evaluate-handle.spec.ts › should pass configurable args [pass] +page/page-evaluate-handle.spec.ts › should work [pass] +page/page-evaluate-handle.spec.ts › should work with primitives [pass] +page/page-evaluate-no-stall.spec.ts › should throw when no main execution context [fail] +page/page-evaluate-no-stall.spec.ts › should throw while pending navigation [pass] +page/page-evaluate-no-stall.spec.ts › should work [pass] +page/page-evaluate.spec.ts › should accept "undefined" as one of multiple parameters [pass] +page/page-evaluate.spec.ts › should accept a string [pass] +page/page-evaluate.spec.ts › should accept a string with comments [pass] +page/page-evaluate.spec.ts › should accept a string with semi colons [pass] +page/page-evaluate.spec.ts › should accept element handle as an argument [fail] +page/page-evaluate.spec.ts › should alias Window, Document and Node [pass] +page/page-evaluate.spec.ts › should await promise [pass] +page/page-evaluate.spec.ts › should await promise from popup [pass] +page/page-evaluate.spec.ts › should be able to throw a tricky error [pass] +page/page-evaluate.spec.ts › should evaluate date [pass] +page/page-evaluate.spec.ts › should evaluate exception [fail] +page/page-evaluate.spec.ts › should evaluate exception with a function on the stack [pass] +page/page-evaluate.spec.ts › should evaluate in the page context [pass] +page/page-evaluate.spec.ts › should evaluate url [pass] +page/page-evaluate.spec.ts › should ignore buggy toJSON [pass] +page/page-evaluate.spec.ts › should jsonValue() date [pass] +page/page-evaluate.spec.ts › should jsonValue() url [pass] +page/page-evaluate.spec.ts › should modify global environment [pass] +page/page-evaluate.spec.ts › should not add a toJSON property to newly created Arrays after evaluation [pass] +page/page-evaluate.spec.ts › should not expose the injected script export [pass] +page/page-evaluate.spec.ts › should not leak handles [fail] +page/page-evaluate.spec.ts › should not leak utility script [pass] +page/page-evaluate.spec.ts › should not throw an error when evaluation does a navigation [pass] +page/page-evaluate.spec.ts › should not throw an error when evaluation does a synchronous navigation and returns an object [pass] +page/page-evaluate.spec.ts › should not throw an error when evaluation does a synchronous navigation and returns undefined [pass] +page/page-evaluate.spec.ts › should not use Array.prototype.toJSON when evaluating [pass] +page/page-evaluate.spec.ts › should not use toJSON in jsonValue [pass] +page/page-evaluate.spec.ts › should not use toJSON when evaluating [pass] +page/page-evaluate.spec.ts › should pass exception argument [pass] +page/page-evaluate.spec.ts › should properly serialize PerformanceMeasure object [pass] +page/page-evaluate.spec.ts › should properly serialize null arguments [pass] +page/page-evaluate.spec.ts › should properly serialize null fields [pass] +page/page-evaluate.spec.ts › should properly serialize undefined arguments [pass] +page/page-evaluate.spec.ts › should properly serialize undefined fields [pass] +page/page-evaluate.spec.ts › should properly serialize window.performance object [pass] +page/page-evaluate.spec.ts › should reject promise with exception [pass] +page/page-evaluate.spec.ts › should respect use strict expression [pass] +page/page-evaluate.spec.ts › should return -0 [pass] +page/page-evaluate.spec.ts › should return -Infinity [pass] +page/page-evaluate.spec.ts › should return Infinity [pass] +page/page-evaluate.spec.ts › should return NaN [pass] +page/page-evaluate.spec.ts › should return complex objects [pass] +page/page-evaluate.spec.ts › should return undefined for non-serializable objects [pass] +page/page-evaluate.spec.ts › should return undefined for objects with symbols [pass] +page/page-evaluate.spec.ts › should return undefined properties [pass] +page/page-evaluate.spec.ts › should roundtrip date [pass] +page/page-evaluate.spec.ts › should roundtrip promise to unserializable values [pass] +page/page-evaluate.spec.ts › should roundtrip promise to value [pass] +page/page-evaluate.spec.ts › should roundtrip regex [pass] +page/page-evaluate.spec.ts › should roundtrip unserializable values [fail] +page/page-evaluate.spec.ts › should roundtrip url [pass] +page/page-evaluate.spec.ts › should simulate a user gesture [pass] +page/page-evaluate.spec.ts › should support thrown numbers as error messages [pass] +page/page-evaluate.spec.ts › should support thrown strings as error messages [pass] +page/page-evaluate.spec.ts › should throw a nice error after a navigation [pass] +page/page-evaluate.spec.ts › should throw error with detailed information on exception inside promise [pass] +page/page-evaluate.spec.ts › should throw if underlying element was disposed [fail] +page/page-evaluate.spec.ts › should throw when evaluation triggers reload [pass] +page/page-evaluate.spec.ts › should throw when frame is detached [pass] +page/page-evaluate.spec.ts › should throw when passed more than one parameter [pass] +page/page-evaluate.spec.ts › should transfer -0 [pass] +page/page-evaluate.spec.ts › should transfer -Infinity [pass] +page/page-evaluate.spec.ts › should transfer 100Mb of data from page to node.js [pass] +page/page-evaluate.spec.ts › should transfer Infinity [pass] +page/page-evaluate.spec.ts › should transfer NaN [pass] +page/page-evaluate.spec.ts › should transfer arrays [pass] +page/page-evaluate.spec.ts › should transfer arrays as arrays, not objects [pass] +page/page-evaluate.spec.ts › should transfer bigint [pass] +page/page-evaluate.spec.ts › should transfer maps as empty objects [pass] +page/page-evaluate.spec.ts › should work @smoke [pass] +page/page-evaluate.spec.ts › should work even when JSON is set to null [pass] +page/page-evaluate.spec.ts › should work for circular object [pass] +page/page-evaluate.spec.ts › should work from-inside an exposed function [fail] +page/page-evaluate.spec.ts › should work right after a cross-origin navigation [fail] +page/page-evaluate.spec.ts › should work right after framenavigated [fail] +page/page-evaluate.spec.ts › should work with Array.from/map [pass] +page/page-evaluate.spec.ts › should work with CSP [fail] +page/page-evaluate.spec.ts › should work with busted Array.prototype.map/push [pass] +page/page-evaluate.spec.ts › should work with function shorthands [pass] +page/page-evaluate.spec.ts › should work with large strings [pass] +page/page-evaluate.spec.ts › should work with large unicode strings [pass] +page/page-evaluate.spec.ts › should work with new Function() and CSP [fail] +page/page-evaluate.spec.ts › should work with non-strict expressions [pass] +page/page-evaluate.spec.ts › should work with overridden Object.defineProperty [pass] +page/page-evaluate.spec.ts › should work with overridden URL/Date/RegExp [pass] +page/page-evaluate.spec.ts › should work with overridden globalThis.Window/Document/Node [pass] +page/page-evaluate.spec.ts › should work with overwritten Promise [pass] +page/page-evaluate.spec.ts › should work with unicode chars [pass] +page/page-event-console.spec.ts › do not update console count on unhandled rejections [pass] +page/page-event-console.spec.ts › should emit same log twice [pass] +page/page-event-console.spec.ts › should format the message correctly with time/timeLog/timeEnd [fail] +page/page-event-console.spec.ts › should have location for console API calls [fail] +page/page-event-console.spec.ts › should not fail for window object [fail] +page/page-event-console.spec.ts › should not throw when there are console messages in detached iframes [pass] +page/page-event-console.spec.ts › should trigger correct Log [timeout] +page/page-event-console.spec.ts › should use object previews for arrays and objects [fail] +page/page-event-console.spec.ts › should use object previews for errors [pass] +page/page-event-console.spec.ts › should use text() for inspection [pass] +page/page-event-console.spec.ts › should work @smoke [fail] +page/page-event-console.spec.ts › should work for different console API calls [fail] +page/page-event-load.spec.ts › should fire once [pass] +page/page-event-load.spec.ts › should fire once with iframe navigation [pass] +page/page-event-network.spec.ts › Page.Events.Request @smoke [fail] +page/page-event-network.spec.ts › Page.Events.RequestFailed @smoke [fail] +page/page-event-network.spec.ts › Page.Events.RequestFinished @smoke [pass] +page/page-event-network.spec.ts › Page.Events.Response @smoke [pass] +page/page-event-network.spec.ts › interrupt request.response() and request.allHeaders() on page.close [fail] +page/page-event-network.spec.ts › should fire events in proper order [pass] +page/page-event-network.spec.ts › should resolve responses after a navigation [pass] +page/page-event-network.spec.ts › should support redirects [pass] +page/page-event-pageerror.spec.ts › should contain sourceURL [timeout] +page/page-event-pageerror.spec.ts › should contain the Error.name property [timeout] +page/page-event-pageerror.spec.ts › should emit error from unhandled rejects [fail] +page/page-event-pageerror.spec.ts › should fire [timeout] +page/page-event-pageerror.spec.ts › should handle object [timeout] +page/page-event-pageerror.spec.ts › should handle odd values [timeout] +page/page-event-pageerror.spec.ts › should handle window [timeout] +page/page-event-pageerror.spec.ts › should not receive console message for pageError [timeout] +page/page-event-pageerror.spec.ts › should remove a listener of a non-existing event handler [pass] +page/page-event-pageerror.spec.ts › should support an empty Error.name property [timeout] +page/page-event-popup.spec.ts › should be able to capture alert [pass] +page/page-event-popup.spec.ts › should emit for immediately closed popups [fail] +page/page-event-popup.spec.ts › should emit for immediately closed popups 2 [pass] +page/page-event-popup.spec.ts › should not treat navigations as new popups [fail] +page/page-event-popup.spec.ts › should report popup opened from iframes [fail] +page/page-event-popup.spec.ts › should work @smoke [pass] +page/page-event-popup.spec.ts › should work with clicking target=_blank [fail] +page/page-event-popup.spec.ts › should work with clicking target=_blank and rel=noopener [fail] +page/page-event-popup.spec.ts › should work with empty url [pass] +page/page-event-popup.spec.ts › should work with fake-clicking target=_blank and rel=noopener [fail] +page/page-event-popup.spec.ts › should work with noopener and about:blank [pass] +page/page-event-popup.spec.ts › should work with noopener and no url [fail] +page/page-event-popup.spec.ts › should work with noopener and url [pass] +page/page-event-popup.spec.ts › should work with window features [pass] +page/page-event-request.spec.ts › main resource xhr should have type xhr [fail] +page/page-event-request.spec.ts › should fire for fetches [pass] +page/page-event-request.spec.ts › should fire for iframes [pass] +page/page-event-request.spec.ts › should fire for navigation requests [pass] +page/page-event-request.spec.ts › should fire requestfailed when intercepting race [unknown] +page/page-event-request.spec.ts › should report navigation requests and responses handled by service worker [timeout] +page/page-event-request.spec.ts › should report navigation requests and responses handled by service worker with routing [timeout] +page/page-event-request.spec.ts › should report requests and responses handled by service worker [fail] +page/page-event-request.spec.ts › should report requests and responses handled by service worker with routing [fail] +page/page-event-request.spec.ts › should return response body when Cross-Origin-Opener-Policy is set [fail] +page/page-expose-function.spec.ts › exposeBinding should work @smoke [fail] +page/page-expose-function.spec.ts › exposeBinding(handle) should work with element handles [fail] +page/page-expose-function.spec.ts › exposeBindingHandle should not throw during navigation [fail] +page/page-expose-function.spec.ts › exposeBindingHandle should throw for multiple arguments [fail] +page/page-expose-function.spec.ts › exposeBindingHandle should work [fail] +page/page-expose-function.spec.ts › should alias Window, Document and Node [fail] +page/page-expose-function.spec.ts › should await returned promise [fail] +page/page-expose-function.spec.ts › should be callable from-inside addInitScript [fail] +page/page-expose-function.spec.ts › should fail with busted Array.prototype.toJSON [fail] +page/page-expose-function.spec.ts › should not result in unhandled rejection [timeout] +page/page-expose-function.spec.ts › should serialize cycles [fail] +page/page-expose-function.spec.ts › should support throwing "null" [fail] +page/page-expose-function.spec.ts › should survive navigation [fail] +page/page-expose-function.spec.ts › should throw exception in page context [fail] +page/page-expose-function.spec.ts › should throw for duplicate registrations [pass] +page/page-expose-function.spec.ts › should work [fail] +page/page-expose-function.spec.ts › should work after cross origin navigation [fail] +page/page-expose-function.spec.ts › should work on frames [fail] +page/page-expose-function.spec.ts › should work on frames before navigation [fail] +page/page-expose-function.spec.ts › should work with busted Array.prototype.map/push [fail] +page/page-expose-function.spec.ts › should work with complex objects [fail] +page/page-expose-function.spec.ts › should work with handles and complex objects [fail] +page/page-expose-function.spec.ts › should work with overridden console object [fail] +page/page-expose-function.spec.ts › should work with setContent [fail] +page/page-fill.spec.ts › fill back to back [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - color [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - date [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - datetime-local [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - month [unknown] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - range [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - time [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - week [unknown] +page/page-fill.spec.ts › should be able to clear using fill() [pass] +page/page-fill.spec.ts › should be able to fill exponent into the input[type=number] [fail] +page/page-fill.spec.ts › should be able to fill input[type=number] with empty string [fail] +page/page-fill.spec.ts › should be able to fill the body [fail] +page/page-fill.spec.ts › should be able to fill the input[type=number] [fail] +page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [fail] +page/page-fill.spec.ts › should fill color input [fail] +page/page-fill.spec.ts › should fill contenteditable [pass] +page/page-fill.spec.ts › should fill contenteditable with new lines [fail] +page/page-fill.spec.ts › should fill date input after clicking [fail] +page/page-fill.spec.ts › should fill datetime-local input [fail] +page/page-fill.spec.ts › should fill different input types [pass] +page/page-fill.spec.ts › should fill elements with existing value and selection [pass] +page/page-fill.spec.ts › should fill fixed position input [fail] +page/page-fill.spec.ts › should fill input [pass] +page/page-fill.spec.ts › should fill month input [fail] +page/page-fill.spec.ts › should fill range input [fail] +page/page-fill.spec.ts › should fill textarea @smoke [pass] +page/page-fill.spec.ts › should fill time input [fail] +page/page-fill.spec.ts › should fill week input [fail] +page/page-fill.spec.ts › should not be able to fill text into the input[type=number] [fail] +page/page-fill.spec.ts › should not throw when fill causes navigation [fail] +page/page-fill.spec.ts › should retry on disabled element [pass] +page/page-fill.spec.ts › should retry on invisible element [pass] +page/page-fill.spec.ts › should retry on readonly element [pass] +page/page-fill.spec.ts › should throw if passed a non-string value [pass] +page/page-fill.spec.ts › should throw nice error without injected script stack when element is not an [fail] +page/page-fill.spec.ts › should throw on incorrect color value [fail] +page/page-fill.spec.ts › should throw on incorrect date [fail] +page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] +page/page-fill.spec.ts › should throw on incorrect month [unknown] +page/page-fill.spec.ts › should throw on incorrect range value [fail] +page/page-fill.spec.ts › should throw on incorrect time [fail] +page/page-fill.spec.ts › should throw on incorrect week [unknown] +page/page-fill.spec.ts › should throw on unsupported inputs [pass] +page/page-focus.spec.ts › clicking checkbox should activate it [unknown] +page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [fail] +page/page-focus.spec.ts › should emit blur event [fail] +page/page-focus.spec.ts › should emit focus event [fail] +page/page-focus.spec.ts › should traverse focus [fail] +page/page-focus.spec.ts › should traverse focus in all directions [fail] +page/page-focus.spec.ts › should traverse only form elements [flaky] +page/page-focus.spec.ts › should work @smoke [fail] +page/page-goto.spec.ts › js redirect overrides url bar navigation [pass] +page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] +page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] +page/page-goto.spec.ts › should capture iframe navigation request [pass] +page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] +page/page-goto.spec.ts › should fail when canceled by another navigation [fail] +page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] +page/page-goto.spec.ts › should fail when exceeding browser context timeout [fail] +page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] +page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] +page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] +page/page-goto.spec.ts › should fail when main resources failed to load [pass] +page/page-goto.spec.ts › should fail when navigating and show the url at the error message [fail] +page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] +page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] +page/page-goto.spec.ts › should fail when navigating to bad url [fail] +page/page-goto.spec.ts › should fail when replaced by another navigation [fail] +page/page-goto.spec.ts › should fail when server returns 204 [timeout] +page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] +page/page-goto.spec.ts › should navigate to about:blank [pass] +page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] +page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] +page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] +page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] +page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] +page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] +page/page-goto.spec.ts › should not leak listeners during navigation [pass] +page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] +page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] +page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] +page/page-goto.spec.ts › should override referrer-policy [fail] +page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] +page/page-goto.spec.ts › should properly wait for load [pass] +page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] +page/page-goto.spec.ts › should report raw buffer for main resource [fail] +page/page-goto.spec.ts › should return from goto if new navigation is started [fail] +page/page-goto.spec.ts › should return last response in redirect chain [pass] +page/page-goto.spec.ts › should return response when page changes its URL after load [pass] +page/page-goto.spec.ts › should return url with basic auth info [pass] +page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] +page/page-goto.spec.ts › should send referer [fail] +page/page-goto.spec.ts › should send referer of cross-origin URL [fail] +page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [fail] +page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] +page/page-goto.spec.ts › should use http for no protocol [pass] +page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] +page/page-goto.spec.ts › should work @smoke [pass] +page/page-goto.spec.ts › should work cross-process [pass] +page/page-goto.spec.ts › should work when navigating to 404 [pass] +page/page-goto.spec.ts › should work when navigating to data url [pass] +page/page-goto.spec.ts › should work when navigating to valid url [pass] +page/page-goto.spec.ts › should work when page calls history API in beforeunload [fail] +page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] +page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] +page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [pass] +page/page-goto.spec.ts › should work with anchor navigation [timeout] +page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] +page/page-goto.spec.ts › should work with file URL [pass] +page/page-goto.spec.ts › should work with file URL with subframes [fail] +page/page-goto.spec.ts › should work with lazy loading iframes [fail] +page/page-goto.spec.ts › should work with redirects [fail] +page/page-goto.spec.ts › should work with self requesting page [pass] +page/page-goto.spec.ts › should work with subframes return 204 [pass] +page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] +page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] +page/page-history.spec.ts › page.goBack during renderer-initiated navigation [fail] +page/page-history.spec.ts › page.goBack should work @smoke [fail] +page/page-history.spec.ts › page.goBack should work for file urls [fail] +page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] +page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] +page/page-history.spec.ts › page.reload during renderer-initiated navigation [fail] +page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] +page/page-history.spec.ts › page.reload should work [pass] +page/page-history.spec.ts › page.reload should work on a page with a hash [pass] +page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] +page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] +page/page-history.spec.ts › page.reload should work with data url [pass] +page/page-history.spec.ts › page.reload should work with same origin redirect [pass] +page/page-history.spec.ts › regression test for issue 20791 [pass] +page/page-history.spec.ts › should reload proper page [pass] +page/page-keyboard.spec.ts › insertText should only emit input event [fail] +page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [fail] +page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] +page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [fail] +page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [fail] +page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] +page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] +page/page-keyboard.spec.ts › should handle selectAll [pass] +page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] +page/page-keyboard.spec.ts › should move around the selection in a contenteditable [fail] +page/page-keyboard.spec.ts › should move to the start of the document [unknown] +page/page-keyboard.spec.ts › should move with the arrow keys [pass] +page/page-keyboard.spec.ts › should not type canceled events [pass] +page/page-keyboard.spec.ts › should press Enter [fail] +page/page-keyboard.spec.ts › should press plus [fail] +page/page-keyboard.spec.ts › should press shift plus [fail] +page/page-keyboard.spec.ts › should press the meta key [pass] +page/page-keyboard.spec.ts › should report multiple modifiers [fail] +page/page-keyboard.spec.ts › should report shiftKey [pass] +page/page-keyboard.spec.ts › should scroll with PageDown [pass] +page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] +page/page-keyboard.spec.ts › should send a character with insertText [fail] +page/page-keyboard.spec.ts › should send proper codes while typing [pass] +page/page-keyboard.spec.ts › should send proper codes while typing with shift [pass] +page/page-keyboard.spec.ts › should shift raw codes [pass] +page/page-keyboard.spec.ts › should specify location [fail] +page/page-keyboard.spec.ts › should specify repeat property [pass] +page/page-keyboard.spec.ts › should support MacOS shortcuts [unknown] +page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] +page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] +page/page-keyboard.spec.ts › should support simple copy-pasting [fail] +page/page-keyboard.spec.ts › should support simple cut-pasting [fail] +page/page-keyboard.spec.ts › should support undo-redo [fail] +page/page-keyboard.spec.ts › should throw on unknown keys [pass] +page/page-keyboard.spec.ts › should type after context menu was opened [pass] +page/page-keyboard.spec.ts › should type all kinds of characters [pass] +page/page-keyboard.spec.ts › should type emoji [pass] +page/page-keyboard.spec.ts › should type emoji into an iframe [pass] +page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] +page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [fail] +page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [fail] +page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [fail] +page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] +page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] +page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [fail] +page/page-leaks.spec.ts › click should not leak [fail] +page/page-leaks.spec.ts › expect should not leak [fail] +page/page-leaks.spec.ts › fill should not leak [fail] +page/page-leaks.spec.ts › waitFor should not leak [fail] +page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] +page/page-listeners.spec.ts › should wait [pass] +page/page-listeners.spec.ts › wait should throw [pass] +page/page-mouse.spec.ts › down and up should generate click [pass] +page/page-mouse.spec.ts › should always round down [fail] +page/page-mouse.spec.ts › should click the document @smoke [pass] +page/page-mouse.spec.ts › should dblclick the div [fail] +page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] +page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] +page/page-mouse.spec.ts › should pointerdown the div with a custom button [fail] +page/page-mouse.spec.ts › should report correct buttons property [pass] +page/page-mouse.spec.ts › should select the text with mouse [pass] +page/page-mouse.spec.ts › should set modifier keys on click [pass] +page/page-mouse.spec.ts › should trigger hover state [pass] +page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] +page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] +page/page-mouse.spec.ts › should tween mouse movement [pass] +page/page-navigation.spec.ts › should work with _blank target [pass] +page/page-navigation.spec.ts › should work with _blank target in form [fail] +page/page-navigation.spec.ts › should work with cross-process _blank target [pass] +page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] +page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] +page/page-network-idle.spec.ts › should wait for networkidle from the popup [fail] +page/page-network-idle.spec.ts › should wait for networkidle in setContent [fail] +page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [fail] +page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [fail] +page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] +page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] +page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [fail] +page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [fail] +page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] +page/page-network-idle.spec.ts › should work after repeated navigations in the same page [pass] +page/page-network-request.spec.ts › page.reload return 304 status code [pass] +page/page-network-request.spec.ts › should get the same headers as the server [fail] +page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] +page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] +page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] +page/page-network-request.spec.ts › should handle mixed-content blocked requests [flaky] +page/page-network-request.spec.ts › should not allow to access frame on popup main request [fail] +page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] +page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] +page/page-network-request.spec.ts › should not work for a redirect and interception [pass] +page/page-network-request.spec.ts › should override post data content type [pass] +page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] +page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] +page/page-network-request.spec.ts › should parse the json post data [fail] +page/page-network-request.spec.ts › should report all cookies in one header [pass] +page/page-network-request.spec.ts › should report raw headers [fail] +page/page-network-request.spec.ts › should report raw response headers in redirects [pass] +page/page-network-request.spec.ts › should return event source [fail] +page/page-network-request.spec.ts › should return headers [pass] +page/page-network-request.spec.ts › should return multipart/form-data [fail] +page/page-network-request.spec.ts › should return navigation bit [pass] +page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] +page/page-network-request.spec.ts › should return postData [fail] +page/page-network-request.spec.ts › should work for a redirect [pass] +page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] +page/page-network-request.spec.ts › should work for main frame navigation request [pass] +page/page-network-request.spec.ts › should work for subframe navigation request [pass] +page/page-network-request.spec.ts › should work with binary post data [fail] +page/page-network-request.spec.ts › should work with binary post data and interception [fail] +page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [pass] +page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] +page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [pass] +page/page-network-response.spec.ts › should provide a Response with a file URL [fail] +page/page-network-response.spec.ts › should reject response.finished if context closes [timeout] +page/page-network-response.spec.ts › should reject response.finished if page closes [pass] +page/page-network-response.spec.ts › should report all headers [fail] +page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] +page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] +page/page-network-response.spec.ts › should return body [fail] +page/page-network-response.spec.ts › should return body for prefetch script [fail] +page/page-network-response.spec.ts › should return body with compression [fail] +page/page-network-response.spec.ts › should return headers after route.fulfill [pass] +page/page-network-response.spec.ts › should return json [fail] +page/page-network-response.spec.ts › should return multiple header value [pass] +page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [pass] +page/page-network-response.spec.ts › should return status text [pass] +page/page-network-response.spec.ts › should return text [fail] +page/page-network-response.spec.ts › should return uncompressed text [fail] +page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] +page/page-network-response.spec.ts › should wait until response completes [fail] +page/page-network-response.spec.ts › should work @smoke [pass] +page/page-network-sizes.spec.ts › should handle redirects [pass] +page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] +page/page-network-sizes.spec.ts › should have the correct responseBodySize [pass] +page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] +page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [pass] +page/page-network-sizes.spec.ts › should return sizes without hanging [pass] +page/page-network-sizes.spec.ts › should set bodySize and headersSize [fail] +page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] +page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] +page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [pass] +page/page-network-sizes.spec.ts › should throw for failed requests [pass] +page/page-network-sizes.spec.ts › should work with 200 status code [pass] +page/page-network-sizes.spec.ts › should work with 401 status code [pass] +page/page-network-sizes.spec.ts › should work with 404 status code [pass] +page/page-network-sizes.spec.ts › should work with 500 status code [fail] +page/page-object-count.spec.ts › should count objects [flaky] +page/page-request-continue.spec.ts › continue should delete headers on redirects [pass] +page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] +page/page-request-continue.spec.ts › continue should propagate headers to redirects [pass] +page/page-request-continue.spec.ts › post data › should amend binary post data [fail] +page/page-request-continue.spec.ts › post data › should amend longer post data [pass] +page/page-request-continue.spec.ts › post data › should amend method and post data [pass] +page/page-request-continue.spec.ts › post data › should amend post data [pass] +page/page-request-continue.spec.ts › post data › should amend utf8 post data [pass] +page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] +page/page-request-continue.spec.ts › post data › should use content-type from original request [pass] +page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] +page/page-request-continue.spec.ts › should amend HTTP headers [pass] +page/page-request-continue.spec.ts › should amend method [pass] +page/page-request-continue.spec.ts › should amend method on main request [pass] +page/page-request-continue.spec.ts › should continue preload link requests [pass] +page/page-request-continue.spec.ts › should delete header with undefined value [pass] +page/page-request-continue.spec.ts › should delete the origin header [pass] +page/page-request-continue.spec.ts › should intercept css variable with background url [fail] +page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [pass] +page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [timeout] +page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] +page/page-request-continue.spec.ts › should not throw when continuing while page is closing [pass] +page/page-request-continue.spec.ts › should override method along with url [fail] +page/page-request-continue.spec.ts › should override request url [timeout] +page/page-request-continue.spec.ts › should work [pass] +page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] +page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] +page/page-request-fallback.spec.ts › post data › should amend json post data [pass] +page/page-request-fallback.spec.ts › post data › should amend post data [pass] +page/page-request-fallback.spec.ts › should amend HTTP headers [pass] +page/page-request-fallback.spec.ts › should amend method [pass] +page/page-request-fallback.spec.ts › should chain once [fail] +page/page-request-fallback.spec.ts › should delete header with undefined value [pass] +page/page-request-fallback.spec.ts › should fall back [pass] +page/page-request-fallback.spec.ts › should fall back after exception [pass] +page/page-request-fallback.spec.ts › should fall back async [fail] +page/page-request-fallback.spec.ts › should not chain abort [fail] +page/page-request-fallback.spec.ts › should not chain fulfill [fail] +page/page-request-fallback.spec.ts › should override request url [fail] +page/page-request-fallback.spec.ts › should work [pass] +page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [pass] +page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] +page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] +page/page-request-fulfill.spec.ts › should fetch original request and fulfill [pass] +page/page-request-fulfill.spec.ts › should fulfill json [fail] +page/page-request-fulfill.spec.ts › should fulfill preload link requests [pass] +page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [timeout] +page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] +page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] +page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] +page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [timeout] +page/page-request-fulfill.spec.ts › should fulfill with har response [fail] +page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] +page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [pass] +page/page-request-fulfill.spec.ts › should include the origin header [pass] +page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] +page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [pass] +page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [timeout] +page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [pass] +page/page-request-fulfill.spec.ts › should work [pass] +page/page-request-fulfill.spec.ts › should work with buffer as body [fail] +page/page-request-fulfill.spec.ts › should work with file path [fail] +page/page-request-fulfill.spec.ts › should work with status code 422 [pass] +page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] +page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] +page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [pass] +page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] +page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] +page/page-request-intercept.spec.ts › should fulfill with any response [fail] +page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] +page/page-request-intercept.spec.ts › should give access to the intercepted response body [pass] +page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [fail] +page/page-request-intercept.spec.ts › should intercept with post data override [pass] +page/page-request-intercept.spec.ts › should intercept with url override [fail] +page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [pass] +page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] +page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] +page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] +page/page-route.spec.ts › route.abort should throw if called twice [pass] +page/page-route.spec.ts › route.continue should throw if called twice [pass] +page/page-route.spec.ts › route.fallback should throw if called twice [fail] +page/page-route.spec.ts › route.fulfill should throw if called twice [fail] +page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] +page/page-route.spec.ts › should allow null origin for about:blank [fail] +page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [pass] +page/page-route.spec.ts › should be able to remove headers [fail] +page/page-route.spec.ts › should be abortable [pass] +page/page-route.spec.ts › should be abortable with custom error codes [fail] +page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] +page/page-route.spec.ts › should contain raw request header [pass] +page/page-route.spec.ts › should contain raw response header [pass] +page/page-route.spec.ts › should contain raw response header after fulfill [pass] +page/page-route.spec.ts › should contain referer header [pass] +page/page-route.spec.ts › should fail navigation when aborting main resource [fail] +page/page-route.spec.ts › should fulfill with redirect status [pass] +page/page-route.spec.ts › should intercept @smoke [fail] +page/page-route.spec.ts › should intercept main resource during cross-process navigation [pass] +page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] +page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [pass] +page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] +page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] +page/page-route.spec.ts › should not fulfill with redirect status [fail] +page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] +page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] +page/page-route.spec.ts › should not work with redirects [fail] +page/page-route.spec.ts › should override cookie header [fail] +page/page-route.spec.ts › should pause intercepted XHR until continue [pass] +page/page-route.spec.ts › should pause intercepted fetch request until continue [pass] +page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] +page/page-route.spec.ts › should reject cors with disallowed credentials [fail] +page/page-route.spec.ts › should respect cors overrides [fail] +page/page-route.spec.ts › should send referer [fail] +page/page-route.spec.ts › should show custom HTTP headers [fail] +page/page-route.spec.ts › should support ? in glob pattern [pass] +page/page-route.spec.ts › should support async handler w/ times [pass] +page/page-route.spec.ts › should support cors for different methods [fail] +page/page-route.spec.ts › should support cors with GET [pass] +page/page-route.spec.ts › should support cors with POST [fail] +page/page-route.spec.ts › should support cors with credentials [fail] +page/page-route.spec.ts › should support the times parameter with route matching [pass] +page/page-route.spec.ts › should unroute [fail] +page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [pass] +page/page-route.spec.ts › should work when POST is redirected with 302 [fail] +page/page-route.spec.ts › should work when header manipulation headers with redirect [pass] +page/page-route.spec.ts › should work with badly encoded server [pass] +page/page-route.spec.ts › should work with custom referer headers [fail] +page/page-route.spec.ts › should work with encoded server [fail] +page/page-route.spec.ts › should work with encoded server - 2 [fail] +page/page-route.spec.ts › should work with equal requests [pass] +page/page-route.spec.ts › should work with redirect inside sync XHR [fail] +page/page-route.spec.ts › should work with redirects for subresources [fail] +page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] +page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] +page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] +page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] +page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] +page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] +page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] +page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] +page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] +page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] +page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [fail] +page/page-screenshot.spec.ts › page screenshot › path option should work [fail] +page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] +page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] +page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] +page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] +page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] +page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] +page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] +page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] +page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] +page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] +page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] +page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] +page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] +page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] +page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] +page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] +page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] +page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] +page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] +page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] +page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] +page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] +page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] +page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] +page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] +page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] +page/page-screenshot.spec.ts › should capture css box-shadow [fail] +page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] +page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [fail] +page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] +page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] +page/page-select-option.spec.ts › should fall back to selecting by label [pass] +page/page-select-option.spec.ts › should not allow null items [pass] +page/page-select-option.spec.ts › should not select single option when some attributes do not match [pass] +page/page-select-option.spec.ts › should not throw when select causes navigation [pass] +page/page-select-option.spec.ts › should respect event bubbling [pass] +page/page-select-option.spec.ts › should return [] on no matched values [pass] +page/page-select-option.spec.ts › should return [] on no values [pass] +page/page-select-option.spec.ts › should return an array of matched values [pass] +page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] +page/page-select-option.spec.ts › should select multiple options [pass] +page/page-select-option.spec.ts › should select multiple options with attributes [pass] +page/page-select-option.spec.ts › should select only first option [pass] +page/page-select-option.spec.ts › should select single option @smoke [pass] +page/page-select-option.spec.ts › should select single option by handle [pass] +page/page-select-option.spec.ts › should select single option by index [pass] +page/page-select-option.spec.ts › should select single option by label [pass] +page/page-select-option.spec.ts › should select single option by multiple attributes [pass] +page/page-select-option.spec.ts › should select single option by value [pass] +page/page-select-option.spec.ts › should throw if passed wrong types [fail] +page/page-select-option.spec.ts › should throw when element is not a `); const locator = await recorder.focusElement('input'); @@ -295,8 +295,8 @@ await page.Locator("#input").FillAsync(\"John\");`); expect(message.text()).toBe('John'); }); - test('should fill japanese text', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should fill japanese text', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); // In Japanese, "てすと" or "テスト" means "test". await recorder.setContentAndWait(``); @@ -329,8 +329,8 @@ await page.Locator("#input").FillAsync(\"てすと\");`); expect(message.text()).toBe('てすと'); }); - test('should fill textarea', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should fill textarea', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); const locator = await recorder.focusElement('textarea'); @@ -346,9 +346,9 @@ await page.Locator("#input").FillAsync(\"てすと\");`); expect(message.text()).toBe('John'); }); - test('should fill textarea with new lines at the end', async ({ page, openRecorder }) => { + test('should fill textarea with new lines at the end', async ({ openRecorder }) => { test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/23774' }); - const recorder = await openRecorder(); + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); const textarea = page.locator('textarea'); await textarea.evaluate(e => e.addEventListener('input', () => (window as any).lastInputValue = e.value)); @@ -361,8 +361,8 @@ await page.Locator("#input").FillAsync(\"てすと\");`); expect(sources.get('JavaScript')!.text).not.toContain(`Enter`); }); - test('should fill [contentEditable]', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should fill [contentEditable]', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(`
`); const locator = await recorder.focusElement('div'); @@ -378,8 +378,8 @@ await page.Locator("#input").FillAsync(\"てすと\");`); expect(message.text()).toBe('John Doe'); }); - test('should press', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should press', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -412,8 +412,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`); expect(messages[0].text()).toBe('press'); }); - test('should update selected element after pressing Tab', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should update selected element after pressing Tab', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(` @@ -441,8 +441,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`); await page.locator('input[name="two"]').fill('barfoo321');`); }); - test('should record ArrowDown', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should record ArrowDown', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -463,8 +463,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`); expect(messages[0].text()).toBe('press:ArrowDown'); }); - test('should emit single keyup on ArrowDown', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should emit single keyup on ArrowDown', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -488,8 +488,8 @@ await page.GetByRole(AriaRole.Textbox).PressAsync("Shift+Enter");`); expect(messages[1].text()).toBe('up:ArrowDown'); }); - test('should check', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should check', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -520,8 +520,8 @@ await page.Locator("#checkbox").CheckAsync();`); expect(message.text()).toBe('true'); }); - test('should check a radio button', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should check a radio button', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -539,8 +539,8 @@ await page.Locator("#checkbox").CheckAsync();`); expect(message.text()).toBe('true'); }); - test('should check with keyboard', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should check with keyboard', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -558,8 +558,8 @@ await page.Locator("#checkbox").CheckAsync();`); expect(message.text()).toBe('true'); }); - test('should uncheck', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should uncheck', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(``); @@ -590,8 +590,8 @@ await page.Locator("#checkbox").UncheckAsync();`); expect(message.text()).toBe('false'); }); - test('should select', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should select', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(''); @@ -623,8 +623,8 @@ await page.Locator("#age").SelectOptionAsync(new[] { "2" });`); expect(message.text()).toBe('2'); }); - test('should select with size attribute', async ({ page, openRecorder }) => { - const recorder = await openRecorder(); + test('should select with size attribute', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(` +
one
one
two
`; @@ -224,7 +225,7 @@ test('should reset mouse position', async ({ reusedContext, browserName, platfor await expect(page.locator('#one')).toHaveCSS('background-color', 'rgb(0, 0, 255)'); await expect(page.locator('#two')).toHaveCSS('background-color', 'rgb(0, 0, 255)'); - await page.mouse.move(10, 45); + await page.mouse.move(10, 75); await expect(page.locator('#one')).toHaveCSS('background-color', 'rgb(0, 0, 255)'); await expect(page.locator('#two')).toHaveCSS('background-color', 'rgb(255, 0, 0)'); From d7020cba6309092a70e76f5389c753d87887ebfb Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 3 Oct 2024 18:16:49 -0700 Subject: [PATCH 243/805] test: scroll mobile page with background-attachment: fixed (#31992) Reference: https://github.com/microsoft/playwright/issues/31551 Reference: https://github.com/microsoft/playwright/issues/23573 --- tests/assets/input/background-fixed.html | 16 ++++++++++++++++ .../browsercontext-viewport-mobile.spec.ts | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/assets/input/background-fixed.html diff --git a/tests/assets/input/background-fixed.html b/tests/assets/input/background-fixed.html new file mode 100644 index 0000000000000..5093939a5baaa --- /dev/null +++ b/tests/assets/input/background-fixed.html @@ -0,0 +1,16 @@ + + + + + +
tall
+ + diff --git a/tests/library/browsercontext-viewport-mobile.spec.ts b/tests/library/browsercontext-viewport-mobile.spec.ts index 2e0f90ceb09ca..ed774e383a568 100644 --- a/tests/library/browsercontext-viewport-mobile.spec.ts +++ b/tests/library/browsercontext-viewport-mobile.spec.ts @@ -188,6 +188,22 @@ it.describe('mobile viewport', () => { await context.close(); }); + it('should scroll mobile page with background-attachment: fixed', { + annotation: [ + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31551' }, + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/23573' }, + ] + }, async ({ playwright, browser, server, browserName, isLinux, headless }) => { + it.fixme(browserName === 'webkit' && isLinux && headless, 'Fails on WPE apparently due to accelerated compositing + fixed layout'); + const iPhone = playwright.devices['iPhone 12']; + const context = await browser.newContext({ ...iPhone }); + const page = await context.newPage(); + await page.goto(server.PREFIX + '/input/background-fixed.html'); + await page.getByRole('button').click(); + expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(1000); + await context.close(); + }); + it('view scale should reset after navigation', async ({ browser, browserName }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/26876' }); const context = await browser.newContext({ From dfa4ab8726c417a602d028e590b39d8e38a8b23c Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 4 Oct 2024 10:06:56 +0200 Subject: [PATCH 244/805] test: speed up only-changed CT test (#32947) --- tests/playwright-test/only-changed.spec.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/playwright-test/only-changed.spec.ts b/tests/playwright-test/only-changed.spec.ts index b632ba262ac54..5a9c6ee121a6d 100644 --- a/tests/playwright-test/only-changed.spec.ts +++ b/tests/playwright-test/only-changed.spec.ts @@ -21,7 +21,7 @@ const test = baseTest.extend<{ git(command: string): void }>({ git: async ({}, use, testInfo) => { const baseDir = testInfo.outputPath(); - const git = (command: string) => execSync(`git ${command}`, { cwd: baseDir }); + const git = (command: string) => execSync(`git ${command}`, { cwd: baseDir, stdio: process.env.PWTEST_DEBUG ? 'inherit' : 'ignore' }); git(`init --initial-branch=main`); git(`config --local user.name "Robert Botman"`); @@ -204,7 +204,7 @@ test('should suppport component tests', async ({ runInlineTest, git, writeFiles test('pass', async ({ mount }) => { const component = await mount(); - await expect(component).toHaveText('Button'); + await expect(component).toHaveText('Button', { timeout: 1000 }); }); `, 'src/button2.test.tsx': ` @@ -213,7 +213,7 @@ test('should suppport component tests', async ({ runInlineTest, git, writeFiles test('pass', async ({ mount }) => { const component = await mount(); - await expect(component).toHaveText('Button'); + await expect(component).toHaveText('Button', { timeout: 1000 }); }); `, 'src/button3.test.tsx': ` @@ -229,7 +229,7 @@ test('should suppport component tests', async ({ runInlineTest, git, writeFiles git(`add .`); git(`commit -m "init"`); - const result = await runInlineTest({}, { 'workers': 1, 'only-changed': true }); + const result = await runInlineTest({}, { 'only-changed': true }); expect(result.exitCode).toBe(0); expect(result.passed).toBe(0); @@ -242,10 +242,10 @@ test('should suppport component tests', async ({ runInlineTest, git, writeFiles test('pass', async ({ mount }) => { const component = await mount(); - await expect(component).toHaveText('Different Button'); + await expect(component).toHaveText('Different Button', { timeout: 1000 }); }); ` - }, { 'workers': 1, 'only-changed': true }); + }, { 'only-changed': true }); expect(result2.exitCode).toBe(1); expect(result2.failed).toBe(1); @@ -260,7 +260,7 @@ test('should suppport component tests', async ({ runInlineTest, git, writeFiles 'src/contents.ts': ` export const content = 'Changed Content'; ` - }, { 'workers': 1, 'only-changed': true }); + }, { 'only-changed': true }); expect(result3.exitCode).toBe(1); expect(result3.failed).toBe(2); From 0a45549533ba2b7fee031f5e682433c122398cf8 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Fri, 4 Oct 2024 02:14:08 -0700 Subject: [PATCH 245/805] feat(chromium): roll to r1140 (#32949) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 4 +- packages/playwright-core/browsers.json | 4 +- .../src/server/deviceDescriptorsSource.json | 96 +++++++++---------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 356f2b0151d2c..6df15c2024cdc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-130.0.6723.19-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-130.0.6723.31-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 130.0.6723.19 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 130.0.6723.31 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 131.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 3fc99636e3806..00c7a751f4566 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,9 +3,9 @@ "browsers": [ { "name": "chromium", - "revision": "1139", + "revision": "1140", "installByDefault": true, - "browserVersion": "130.0.6723.19" + "browserVersion": "130.0.6723.31" }, { "name": "chromium-tip-of-tree", diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index b411b0f0fd0a8..1b0a015346334 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -110,7 +110,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S5": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -121,7 +121,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -132,7 +132,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 360, "height": 740 @@ -143,7 +143,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 740, "height": 360 @@ -154,7 +154,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 320, "height": 658 @@ -165,7 +165,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+ landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 658, "height": 320 @@ -176,7 +176,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "viewport": { "width": 712, "height": 1138 @@ -187,7 +187,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -1098,7 +1098,7 @@ "defaultBrowserType": "webkit" }, "LG Optimus L70": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,7 @@ "defaultBrowserType": "chromium" }, "LG Optimus L70 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,7 @@ "defaultBrowserType": "webkit" }, "Pixel 2": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36 Edg/130.0.6723.19", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36 Edg/130.0.6723.31", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.19 Safari/537.36 Edg/130.0.6723.19", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36 Edg/130.0.6723.31", "screen": { "width": 1920, "height": 1080 From 895be9f8de4b1fe06d839370a95ed8464365ac7d Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 4 Oct 2024 11:34:04 +0200 Subject: [PATCH 246/805] chore: lint java docs snippets (#32945) --- .github/workflows/infra.yml | 8 +- docs/src/accessibility-testing-java.md | 96 +++++++-------- docs/src/api-testing-java.md | 54 +++++---- docs/src/api/class-apiresponseassertions.md | 8 +- docs/src/api/class-browser.md | 22 ++-- docs/src/api/class-browsercontext.md | 5 +- docs/src/api/class-consolemessage.md | 4 +- docs/src/api/class-formdata.md | 6 +- docs/src/api/class-keyboard.md | 2 +- docs/src/api/class-locator.md | 2 +- docs/src/api/class-locatorassertions.md | 8 +- docs/src/api/class-page.md | 41 +++---- docs/src/api/class-pageassertions.md | 6 +- docs/src/api/class-playwrightassertions.md | 5 +- docs/src/api/params.md | 10 +- docs/src/emulation.md | 4 +- docs/src/locators.md | 12 +- docs/src/mock.md | 13 ++- docs/src/network.md | 6 +- docs/src/pom.md | 2 +- docs/src/release-notes-java.md | 16 ++- docs/src/screenshots.md | 2 +- docs/src/test-runners-java.md | 4 +- utils/doclint/linting-code-snippets/cli.js | 11 ++ .../linting-code-snippets/java/.gitignore | 2 + .../linting-code-snippets/java/pom.xml | 53 +++++++++ .../java/src/main/java/JavaSyntaxChecker.java | 110 ++++++++++++++++++ 27 files changed, 352 insertions(+), 160 deletions(-) create mode 100644 utils/doclint/linting-code-snippets/java/.gitignore create mode 100644 utils/doclint/linting-code-snippets/java/pom.xml create mode 100644 utils/doclint/linting-code-snippets/java/src/main/java/JavaSyntaxChecker.java diff --git a/.github/workflows/infra.yml b/.github/workflows/infra.yml index f33c8535f07f1..905597c8bddd0 100644 --- a/.github/workflows/infra.yml +++ b/.github/workflows/infra.yml @@ -38,7 +38,7 @@ jobs: run: npm audit --omit dev lint-snippets: name: "Lint snippets" - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -50,6 +50,12 @@ jobs: - uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x + - uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '21' - run: npm ci - run: pip install -r utils/doclint/linting-code-snippets/python/requirements.txt + - run: mvn package + working-directory: utils/doclint/linting-code-snippets/java - run: node utils/doclint/linting-code-snippets/cli.js diff --git a/docs/src/accessibility-testing-java.md b/docs/src/accessibility-testing-java.md index d62bac64fad37..13f9c4e3e496c 100644 --- a/docs/src/accessibility-testing-java.md +++ b/docs/src/accessibility-testing-java.md @@ -70,22 +70,24 @@ For example, you can use [`AxeBuilder.include()`](https://github.com/dequelabs/a `AxeBuilder.analyze()` will scan the page *in its current state* when you call it. To scan parts of a page that are revealed based on UI interactions, use [Locators](./locators.md) to interact with the page before invoking `analyze()`: ```java -@Test -void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception { - page.navigate("https://your-site.com/"); +public class HomepageTests { + @Test + void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception { + page.navigate("https://your-site.com/"); - page.locator("button[aria-label=\"Navigation Menu\"]").click(); + page.locator("button[aria-label=\"Navigation Menu\"]").click(); - // It is important to waitFor() the page to be in the desired - // state *before* running analyze(). Otherwise, axe might not - // find all the elements your test expects it to scan. - page.locator("#navigation-menu-flyout").waitFor(); + // It is important to waitFor() the page to be in the desired + // state *before* running analyze(). Otherwise, axe might not + // find all the elements your test expects it to scan. + page.locator("#navigation-menu-flyout").waitFor(); - AxeResults accessibilityScanResults = new AxeBuilder(page) - .include(Arrays.asList("#navigation-menu-flyout")) - .analyze(); + AxeResults accessibilityScanResults = new AxeBuilder(page) + .include(Arrays.asList("#navigation-menu-flyout")) + .analyze(); - assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); + assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); + } } ``` @@ -158,38 +160,40 @@ This approach avoids the downsides of using `AxeBuilder.exclude()` at the cost o Here is an example of using fingerprints based on only rule IDs and "target" selectors pointing to each violation: ```java -@Test -shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception { - page.navigate("https://your-site.com/"); +public class HomepageTests { + @Test + shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception { + page.navigate("https://your-site.com/"); - AxeResults accessibilityScanResults = new AxeBuilder(page).analyze(); + AxeResults accessibilityScanResults = new AxeBuilder(page).analyze(); - List violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults); + List violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults); - assertEquals(Arrays.asList( - new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"), - new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"), - new ViolationFingerprint("label", "[input]") - ), violationFingerprints); -} + assertEquals(Arrays.asList( + new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"), + new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"), + new ViolationFingerprint("label", "[input]") + ), violationFingerprints); + } -// You can make your "fingerprint" as specific as you like. This one considers a violation to be -// "the same" if it corresponds the same Axe rule on the same element. -// -// Using a record type makes it easy to compare fingerprints with assertEquals -public record ViolationFingerprint(String ruleId, String target) { } - -public List fingerprintsFromScanResults(AxeResults results) { - return results.getViolations().stream() - // Each violation refers to one rule and multiple "nodes" which violate it - .flatMap(violation -> violation.getNodes().stream() - .map(node -> new ViolationFingerprint( - violation.getId(), - // Each node contains a "target", which is a CSS selector that uniquely identifies it - // If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors - node.getTarget().toString() - ))) - .collect(Collectors.toList()); + // You can make your "fingerprint" as specific as you like. This one considers a violation to be + // "the same" if it corresponds the same Axe rule on the same element. + // + // Using a record type makes it easy to compare fingerprints with assertEquals + public record ViolationFingerprint(String ruleId, String target) { } + + public List fingerprintsFromScanResults(AxeResults results) { + return results.getViolations().stream() + // Each violation refers to one rule and multiple "nodes" which violate it + .flatMap(violation -> violation.getNodes().stream() + .map(node -> new ViolationFingerprint( + violation.getId(), + // Each node contains a "target", which is a CSS selector that uniquely identifies it + // If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors + node.getTarget().toString() + ))) + .collect(Collectors.toList()); + } } ``` @@ -208,11 +212,11 @@ This example fixture creates an `AxeBuilder` object which is pre-configured with ```java class AxeTestFixtures extends TestFixtures { - AxeBuilder makeAxeBuilder() { - return new AxeBuilder(page) - .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa']) - .exclude('#commonly-reused-element-with-known-issue'); - } + AxeBuilder makeAxeBuilder() { + return new AxeBuilder(page) + .withTags(new String[]{"wcag2a", "wcag2aa", "wcag21a", "wcag21aa"}) + .exclude("#commonly-reused-element-with-known-issue"); + } } ``` @@ -229,7 +233,7 @@ public class HomepageTests extends AxeTestFixtures { AxeResults accessibilityScanResults = makeAxeBuilder() // Automatically uses the shared AxeBuilder configuration, // but supports additional test-specific configuration too - .include('#specific-element-under-test') + .include("#specific-element-under-test") .analyze(); assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations()); diff --git a/docs/src/api-testing-java.md b/docs/src/api-testing-java.md index 987aad5de87a0..e8020e12ce4f3 100644 --- a/docs/src/api-testing-java.md +++ b/docs/src/api-testing-java.md @@ -194,6 +194,7 @@ public class TestGitHubAPI { These tests assume that repository exists. You probably want to create a new one before running tests and delete it afterwards. Use `@BeforeAll` and `@AfterAll` hooks for that. ```java +public class TestGitHubAPI { // ... void createTestRepository() { @@ -223,6 +224,7 @@ These tests assume that repository exists. You probably want to create a new one disposeAPIRequestContext(); closePlaywright(); } +} ``` ### Complete test example @@ -381,18 +383,20 @@ The following test creates a new issue via API and then navigates to the list of project to check that it appears at the top of the list. The check is performed using [LocatorAssertions]. ```java -@Test -void lastCreatedIssueShouldBeFirstInTheList() { - Map data = new HashMap<>(); - data.put("title", "[Feature] request 1"); - data.put("body", "Feature description"); - APIResponse newIssue = request.post("/repos/" + USER + "/" + REPO + "/issues", - RequestOptions.create().setData(data)); - assertTrue(newIssue.ok()); - - page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); - Locator firstIssue = page.locator("a[data-hovercard-type='issue']").first(); - assertThat(firstIssue).hasText("[Feature] request 1"); +public class TestGitHubAPI { + @Test + void lastCreatedIssueShouldBeFirstInTheList() { + Map data = new HashMap<>(); + data.put("title", "[Feature] request 1"); + data.put("body", "Feature description"); + APIResponse newIssue = request.post("/repos/" + USER + "/" + REPO + "/issues", + RequestOptions.create().setData(data)); + assertTrue(newIssue.ok()); + + page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); + Locator firstIssue = page.locator("a[data-hovercard-type='issue']").first(); + assertThat(firstIssue).hasText("[Feature] request 1"); + } } ``` @@ -402,18 +406,20 @@ The following test creates a new issue via user interface in the browser and the it was created: ```java -@Test -void lastCreatedIssueShouldBeOnTheServer() { - page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); - page.locator("text=New Issue").click(); - page.locator("[aria-label='Title']").fill("Bug report 1"); - page.locator("[aria-label='Comment body']").fill("Bug description"); - page.locator("text=Submit new issue").click(); - String issueId = page.url().substring(page.url().lastIndexOf('/')); - - APIResponse newIssue = request.get("https://github.com/" + USER + "/" + REPO + "/issues/" + issueId); - assertThat(newIssue).isOK(); - assertTrue(newIssue.text().contains("Bug report 1")); +public class TestGitHubAPI { + @Test + void lastCreatedIssueShouldBeOnTheServer() { + page.navigate("https://github.com/" + USER + "/" + REPO + "/issues"); + page.locator("text=New Issue").click(); + page.locator("[aria-label='Title']").fill("Bug report 1"); + page.locator("[aria-label='Comment body']").fill("Bug description"); + page.locator("text=Submit new issue").click(); + String issueId = page.url().substring(page.url().lastIndexOf('/')); + + APIResponse newIssue = request.get("https://github.com/" + USER + "/" + REPO + "/issues/" + issueId); + assertThat(newIssue).isOK(); + assertTrue(newIssue.text().contains("Bug report 1")); + } } ``` diff --git a/docs/src/api/class-apiresponseassertions.md b/docs/src/api/class-apiresponseassertions.md index 6fce864d0323d..9584365d887dd 100644 --- a/docs/src/api/class-apiresponseassertions.md +++ b/docs/src/api/class-apiresponseassertions.md @@ -14,15 +14,15 @@ test('navigates to login', async ({ page }) => { ``` ```java -... +// ... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestPage { - ... + // ... @Test void navigatesToLoginPage() { - ... - APIResponse response = page.request().get('https://playwright.dev'); + // ... + APIResponse response = page.request().get("https://playwright.dev"); assertThat(response).isOK(); } } diff --git a/docs/src/api/class-browser.md b/docs/src/api/class-browser.md index 59cf4c99c0aac..4dabfc52e4246 100644 --- a/docs/src/api/class-browser.md +++ b/docs/src/api/class-browser.md @@ -18,15 +18,15 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'. import com.microsoft.playwright.*; public class Example { - public static void main(String[] args) { - try (Playwright playwright = Playwright.create()) { - BrowserType firefox = playwright.firefox() - Browser browser = firefox.launch(); - Page page = browser.newPage(); - page.navigate('https://example.com'); - browser.close(); - } - } + public static void main(String[] args) { + try (Playwright playwright = Playwright.create()) { + BrowserType firefox = playwright.firefox(); + Browser browser = firefox.launch(); + Page page = browser.newPage(); + page.navigate("https://example.com"); + browser.close(); + } + } } ``` @@ -202,7 +202,7 @@ Browser browser = playwright.firefox().launch(); // Or 'chromium' or 'webkit'. BrowserContext context = browser.newContext(); // Create a new page in a pristine context. Page page = context.newPage(); -page.navigate('https://example.com'); +page.navigate("https://example.com"); // Graceful close up everything context.close(); @@ -331,7 +331,7 @@ await browser.stopTracing(); ```java browser.startTracing(page, new Browser.StartTracingOptions() .setPath(Paths.get("trace.json"))); -page.goto('https://www.google.com'); +page.navigate("https://www.google.com"); browser.stopTracing(); ``` diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md index b504bf457b16a..8d6c57a3e3c8a 100644 --- a/docs/src/api/class-browsercontext.md +++ b/docs/src/api/class-browsercontext.md @@ -655,7 +655,7 @@ import com.microsoft.playwright.*; public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { - BrowserType webkit = playwright.webkit() + BrowserType webkit = playwright.webkit(); Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); BrowserContext context = browser.newContext(); context.exposeBinding("pageURL", (source, args) -> source.page().url()); @@ -813,8 +813,9 @@ import java.util.Base64; public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { - BrowserType webkit = playwright.webkit() + BrowserType webkit = playwright.webkit(); Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); + BrowserContext context = browser.newContext(); context.exposeFunction("sha256", args -> { String text = (String) args[0]; MessageDigest crypto; diff --git a/docs/src/api/class-consolemessage.md b/docs/src/api/class-consolemessage.md index 2268ee3ed10a8..347838ae42141 100644 --- a/docs/src/api/class-consolemessage.md +++ b/docs/src/api/class-consolemessage.md @@ -44,8 +44,8 @@ ConsoleMessage msg = page.waitForConsoleMessage(() -> { }); // Deconstruct console.log arguments -msg.args().get(0).jsonValue() // hello -msg.args().get(1).jsonValue() // 42 +msg.args().get(0).jsonValue(); // hello +msg.args().get(1).jsonValue(); // 42 ``` ```python async diff --git a/docs/src/api/class-formdata.md b/docs/src/api/class-formdata.md index 5ca85b361d00e..c5f4bcb51d14f 100644 --- a/docs/src/api/class-formdata.md +++ b/docs/src/api/class-formdata.md @@ -6,7 +6,7 @@ The [FormData] is used create form data that is sent via [APIRequestContext]. ```java import com.microsoft.playwright.options.FormData; -... +// ... FormData form = FormData.create() .set("firstName", "John") .set("lastName", "Doe") @@ -28,7 +28,7 @@ the new value onto the end of the existing set of values. ```java import com.microsoft.playwright.options.FormData; -... +// ... FormData form = FormData.create() // Only name and value are set. .append("firstName", "John") @@ -100,7 +100,7 @@ Sets a field on the form. File values can be passed either as `Path` or as `File ```java import com.microsoft.playwright.options.FormData; -... +// ... FormData form = FormData.create() // Only name and value are set. .set("firstName", "John") diff --git a/docs/src/api/class-keyboard.md b/docs/src/api/class-keyboard.md index 64a539cfbe9f9..f86c4ad11f4b6 100644 --- a/docs/src/api/class-keyboard.md +++ b/docs/src/api/class-keyboard.md @@ -257,7 +257,7 @@ await browser.close(); Page page = browser.newPage(); page.navigate("https://keycode.info"); page.keyboard().press("A"); -page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png")); +page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png"))); page.keyboard().press("ArrowLeft"); page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("ArrowLeft.png"))); page.keyboard().press("Shift+O"); diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md index 3a9504ad59a4a..8f0b53e16da7f 100644 --- a/docs/src/api/class-locator.md +++ b/docs/src/api/class-locator.md @@ -38,7 +38,7 @@ for li in page.get_by_role('listitem').all(): ``` ```java -for (Locator li : page.getByRole('listitem').all()) +for (Locator li : page.getByRole("listitem").all()) li.click(); ``` diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 1ff5e52119b37..bfff2b07adb03 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -14,14 +14,14 @@ test('status becomes submitted', async ({ page }) => { ``` ```java -... +// ... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestLocator { - ... + // ... @Test void statusBecomesSubmitted() { - ... + // ... page.getByRole(AriaRole.BUTTON).click(); assertThat(page.locator(".status")).hasText("Submitted"); } @@ -2048,7 +2048,7 @@ await expect(locator).toHaveValues([/R/, /G/]); ``` ```java -page.locator("id=favorite-colors").selectOption(["R", "G"]); +page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"}); assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") }); ``` diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 60512f51ca70d..7a3be809c6ba5 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -1041,9 +1041,9 @@ await page.dragAndDrop('#source', '#target', { ``` ```java -page.dragAndDrop("#source", '#target'); +page.dragAndDrop("#source", "#target"); // or specify exact positions relative to the top-left corners of the elements: -page.dragAndDrop("#source", '#target', new Page.DragAndDropOptions() +page.dragAndDrop("#source", "#target", new Page.DragAndDropOptions() .setSourcePosition(34, 7).setTargetPosition(10, 20)); ``` @@ -1716,7 +1716,7 @@ public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType webkit = playwright.webkit(); - Browser browser = webkit.launch({ headless: false }); + Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); BrowserContext context = browser.newContext(); Page page = context.newPage(); page.exposeBinding("pageURL", (source, args) -> source.page().url()); @@ -1886,26 +1886,27 @@ public class Example { public static void main(String[] args) { try (Playwright playwright = Playwright.create()) { BrowserType webkit = playwright.webkit(); - Browser browser = webkit.launch({ headless: false }); + Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false)); Page page = browser.newPage(); page.exposeFunction("sha256", args -> { - String text = (String) args[0]; - MessageDigest crypto; try { - crypto = MessageDigest.getInstance("SHA-256"); + String text = (String) args[0]; + MessageDigest crypto = MessageDigest.getInstance("SHA-256"); + byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(token); } catch (NoSuchAlgorithmException e) { return null; } - byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8)); - return Base64.getEncoder().encodeToString(token); }); - page.setContent("\n" + "\n" + - "
\n"); + "
" + ); page.click("button"); } } @@ -2106,7 +2107,7 @@ const frame = page.frame({ url: /.*domain.*/ }); ``` ```java -Frame frame = page.frameByUrl(Pattern.compile(".*domain.*"); +Frame frame = page.frameByUrl(Pattern.compile(".*domain.*")); ``` ```py @@ -3161,12 +3162,12 @@ await page.getByRole('button', { name: 'Start here' }).click(); ```java // Setup the handler. -page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () => { +page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () -> { page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("No thanks")).click(); }); // Write the test as usual. -page.goto("https://example.com"); +page.navigate("https://example.com"); page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click(); ``` @@ -3218,12 +3219,12 @@ await page.getByRole('button', { name: 'Start here' }).click(); ```java // Setup the handler. -page.addLocatorHandler(page.getByText("Confirm your security details")), () => { +page.addLocatorHandler(page.getByText("Confirm your security details"), () -> { page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Remind me later")).click(); }); // Write the test as usual. -page.goto("https://example.com"); +page.navigate("https://example.com"); page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click(); ``` @@ -3275,12 +3276,12 @@ await page.getByRole('button', { name: 'Start here' }).click(); ```java // Setup the handler. -page.addLocatorHandler(page.locator("body")), () => { +page.addLocatorHandler(page.locator("body"), () -> { page.evaluate("window.removeObstructionsForTestIfNeeded()"); -}, new Page.AddLocatorHandlerOptions.setNoWaitAfter(true)); +}, new Page.AddLocatorHandlerOptions().setNoWaitAfter(true)); // Write the test as usual. -page.goto("https://example.com"); +page.navigate("https://example.com"); page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click(); ``` @@ -3326,7 +3327,7 @@ await page.addLocatorHandler(page.getByLabel('Close'), async locator => { ``` ```java -page.addLocatorHandler(page.getByLabel("Close"), locator => { +page.addLocatorHandler(page.getByLabel("Close"), locator -> { locator.click(); }, new Page.AddLocatorHandlerOptions().setTimes(1)); ``` diff --git a/docs/src/api/class-pageassertions.md b/docs/src/api/class-pageassertions.md index 5e56907656d32..8eefd41f023aa 100644 --- a/docs/src/api/class-pageassertions.md +++ b/docs/src/api/class-pageassertions.md @@ -14,14 +14,14 @@ test('navigates to login', async ({ page }) => { ``` ```java -... +// ... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestPage { - ... + // ... @Test void navigatesToLoginPage() { - ... + // ... page.getByText("Sign in").click(); assertThat(page).hasURL(Pattern.compile(".*/login")); } diff --git a/docs/src/api/class-playwrightassertions.md b/docs/src/api/class-playwrightassertions.md index 7a960e34e1a56..aa4e0a42a4bf4 100644 --- a/docs/src/api/class-playwrightassertions.md +++ b/docs/src/api/class-playwrightassertions.md @@ -35,14 +35,13 @@ def test_status_becomes_submitted(page: Page) -> None: ``` ```java -... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestExample { - ... + // ... @Test void statusBecomesSubmitted() { - ... + // ... page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } diff --git a/docs/src/api/params.md b/docs/src/api/params.md index 1f9c03d77af35..462b225e6e758 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -1488,19 +1488,19 @@ page.get_by_text(re.compile("^hello$", re.IGNORECASE)) ```java // Matches -page.getByText("world") +page.getByText("world"); // Matches first
-page.getByText("Hello world") +page.getByText("Hello world"); // Matches second
-page.getByText("Hello", new Page.GetByTextOptions().setExact(true)) +page.getByText("Hello", new Page.GetByTextOptions().setExact(true)); // Matches both
s -page.getByText(Pattern.compile("Hello")) +page.getByText(Pattern.compile("Hello")); // Matches second
-page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)) +page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE)); ``` ```csharp diff --git a/docs/src/emulation.md b/docs/src/emulation.md index d1f7bc3400186..12b44a49c8e2e 100644 --- a/docs/src/emulation.md +++ b/docs/src/emulation.md @@ -188,7 +188,7 @@ page.setViewportSize(1600, 1200); // Emulate high-DPI BrowserContext context = browser.newContext(new Browser.NewContextOptions() .setViewportSize(2560, 1440) - .setDeviceScaleFactor(2); + .setDeviceScaleFactor(2)); ``` ```python async @@ -378,7 +378,7 @@ const context = await browser.newContext({ ```java BrowserContext context = browser.newContext(new Browser.NewContextOptions() - .setPermissions(Arrays.asList("notifications")); + .setPermissions(Arrays.asList("notifications"))); ``` ```python async diff --git a/docs/src/locators.md b/docs/src/locators.md index 8ade71efb7faf..0aa918e53c998 100644 --- a/docs/src/locators.md +++ b/docs/src/locators.md @@ -122,7 +122,7 @@ await locator.click(); ```java Locator locator = page.getByRole(AriaRole.BUTTON, - new Page.GetByRoleOptions().setName("Sign in")) + new Page.GetByRoleOptions().setName("Sign in")); locator.hover(); locator.click(); @@ -946,7 +946,7 @@ page.getByRole(AriaRole.LISTITEM) .setName("Product 2")))) .getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Add to cart")) - .click() + .click(); ``` ```python async @@ -987,7 +987,7 @@ assertThat(page .getByRole(AriaRole.LISTITEM) .filter(new Locator.FilterOptions() .setHas(page.GetByRole(AriaRole.HEADING, - new Page.GetByRoleOptions().setName("Product 2")))) + new Page.GetByRoleOptions().setName("Product 2"))))) .hasCount(1); ``` @@ -1033,7 +1033,7 @@ assertThat(page .filter(new Locator.FilterOptions() .setHas(page.GetByRole(AriaRole.LIST) .GetByRole(AriaRole.HEADING, - new Page.GetByRoleOptions().setName("Product 2")))) + new Page.GetByRoleOptions().setName("Product 2"))))) .hasCount(1); ``` @@ -1079,7 +1079,7 @@ await expect(page ```java assertThat(page .getByRole(AriaRole.LISTITEM) - .filter(new Locator.FilterOptions().setHasNot(page.getByText("Product 2"))) + .filter(new Locator.FilterOptions().setHasNot(page.getByText("Product 2")))) .hasCount(1); ``` @@ -1356,7 +1356,7 @@ expect(page.get_by_role("listitem")).to_have_count(3) ``` ```java -assertThat(page.getByRole(AriaRole.LISTITEM).hasCount(3); +assertThat(page.getByRole(AriaRole.LISTITEM)).hasCount(3); ``` ```csharp diff --git a/docs/src/mock.md b/docs/src/mock.md index 87ddf2ec96c3a..5c87e91d5b15e 100644 --- a/docs/src/mock.md +++ b/docs/src/mock.md @@ -195,15 +195,15 @@ await Expect(page.GetByTextAsync("Loquat", new () { Exact = true })).ToBeVisible page.route("*/**/api/v1/fruits", route -> { Response response = route.fetch(); byte[] json = response.body(); - parsed = new Gson().fromJson(json, JsonObject.class) + JsonObject parsed = new Gson().fromJson(new String(json), JsonObject.class); parsed.add(new JsonObject().add("name", "Loquat").add("id", 100)); // Fulfill using the original response, while patching the response body // with the given JSON object. - route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(json.toString())); + route.fulfill(new Route.FulfillOptions().setResponse(response).setBody(parsed.toString())); }); // Go to the page -page.goto("https://demo.playwright.dev/api-mocking"); +page.navigate("https://demo.playwright.dev/api-mocking"); // Assert that the Loquat fruit is visible assertThat(page.getByText("Loquat", new Page.GetByTextOptions().setExact(true))).isVisible(); @@ -294,7 +294,7 @@ page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions() ); // Go to the page -page.goto("https://demo.playwright.dev/api-mocking"); +page.navigate("https://demo.playwright.dev/api-mocking"); // Assert that the fruit is visible assertThat(page.getByText("Strawberry")).isVisible(); @@ -392,10 +392,11 @@ page.routeFromHAR(Path.of("./hars/fruit.har"), new RouteFromHAROptions() ); // Go to the page -page.goto("https://demo.playwright.dev/api-mocking"); +page.navigate("https://demo.playwright.dev/api-mocking"); // Assert that the Playwright fruit is visible -assertThat(page.getByText("Playwright", new Page.GetByTextOptions().setExact(true))).isVisible(); +assertThat(page.getByText("Playwright", new Page.GetByTextOptions() + .setExact(true))).isVisible(); ``` In the trace of our test we can see that the route was fulfilled from the HAR file and the API was not called. ![trace showing the HAR file being used](https://github.com/microsoft/playwright/assets/13063165/1bd7ab66-ea4f-43c2-a4e5-ca17d4837ff1) diff --git a/docs/src/network.md b/docs/src/network.md index 4d6f229678b84..33c012d9b5d11 100644 --- a/docs/src/network.md +++ b/docs/src/network.md @@ -146,8 +146,8 @@ const browser = await chromium.launch({ ```java Browser browser = chromium.launch(new BrowserType.LaunchOptions() .setProxy(new Proxy("http://myproxy.com:3128") - .setUsername('usr') - .setPassword('pwd'))); + .setUsername("usr") + .setPassword("pwd"))); ``` ```python async @@ -627,7 +627,7 @@ page.route("**/title.html", route -> { String body = response.text(); body = body.replace("", "<title>My prefix:"); Map<String, String> headers = response.headers(); - headers.put("content-type": "text/html"); + headers.put("content-type", "text/html"); route.fulfill(new Route.FulfillOptions() // Pass all fields from the response. .setResponse(response) diff --git a/docs/src/pom.md b/docs/src/pom.md index 983598a2c2825..5108d5718ba95 100644 --- a/docs/src/pom.md +++ b/docs/src/pom.md @@ -289,7 +289,7 @@ Page objects can then be used inside a test. ```java import models.SearchPage; import com.microsoft.playwright.*; -... +// ... // In the test Page page = browser.newPage(); diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index ae9735861129c..908a7683574c5 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -378,7 +378,7 @@ New method [`method: Page.addLocatorHandler`] registers a callback that will be // Setup the handler. page.addLocatorHandler( page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Hej! You are in control of your cookies.")), - () - > { + () -> { page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Accept all")).click(); }); // Write the test as usual. @@ -1187,14 +1187,12 @@ Playwright for Java 1.18 introduces [Web-First Assertions](./test-assertions). Consider the following example: ```java -... import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; public class TestExample { - ... @Test void statusBecomesSubmitted() { - ... + // ... page.locator("#submit-button").click(); assertThat(page.locator(".status")).hasText("Submitted"); } @@ -1471,19 +1469,19 @@ button.click("button >> visible=true"); Traces are recorded using the new [`property: BrowserContext.tracing`] API: ```java -Browser browser = chromium.launch(); +Browser browser = playwright.chromium().launch(); BrowserContext context = browser.newContext(); // Start tracing before creating / navigating a page. -context.tracing.start(new Tracing.StartOptions() +context.tracing().start(new Tracing.StartOptions() .setScreenshots(true) - .setSnapshots(true); + .setSnapshots(true)); Page page = context.newPage(); -page.goto("https://playwright.dev"); +page.navigate("https://playwright.dev"); // Stop tracing and export it into a zip archive. -context.tracing.stop(new Tracing.StopOptions() +context.tracing().stop(new Tracing.StopOptions() .setPath(Paths.get("trace.zip"))); ``` diff --git a/docs/src/screenshots.md b/docs/src/screenshots.md index d1c7e0e04f8e6..ba50a852a45a0 100644 --- a/docs/src/screenshots.md +++ b/docs/src/screenshots.md @@ -21,7 +21,7 @@ page.screenshot(path="screenshot.png") ```java page.screenshot(new Page.ScreenshotOptions() - .setPath(Paths.get("screenshot.png"))) + .setPath(Paths.get("screenshot.png"))); ``` ```csharp diff --git a/docs/src/test-runners-java.md b/docs/src/test-runners-java.md index 1aaa7135c4f44..ed1d3d81e5e18 100644 --- a/docs/src/test-runners-java.md +++ b/docs/src/test-runners-java.md @@ -202,7 +202,7 @@ You can use a Gradle build configuration script, written in Groovy or Kotlin. }> <TabItem value="gradle"> -```java +```groovy plugins { application id 'java' @@ -234,7 +234,7 @@ test { </TabItem> <TabItem value="gradle-kotlin"> -```java +```groovy plugins { application id("java") diff --git a/utils/doclint/linting-code-snippets/cli.js b/utils/doclint/linting-code-snippets/cli.js index da193e5876795..146646a1f0312 100644 --- a/utils/doclint/linting-code-snippets/cli.js +++ b/utils/doclint/linting-code-snippets/cli.js @@ -209,6 +209,16 @@ class CSharpLintingService extends LintingService { } } +class JavaLintingService extends LintingService { + supports(codeLang) { + return codeLang === 'java'; + } + + async lint(snippets) { + return await this.spawnAsync('java', ['-jar', path.join(__dirname, 'java', 'target', 'java-syntax-checker-1.0-SNAPSHOT.jar')], snippets, path.join(__dirname, 'java')) + } +} + class LintingServiceFactory { constructor() { /** @type {LintingService[]} */ @@ -219,6 +229,7 @@ class LintingServiceFactory { this.services.push( new PythonLintingService(), new CSharpLintingService(), + new JavaLintingService(), ); } this._metrics = {}; diff --git a/utils/doclint/linting-code-snippets/java/.gitignore b/utils/doclint/linting-code-snippets/java/.gitignore new file mode 100644 index 0000000000000..8b8c81d7318df --- /dev/null +++ b/utils/doclint/linting-code-snippets/java/.gitignore @@ -0,0 +1,2 @@ +target/ +dependency-reduced-pom.xml diff --git a/utils/doclint/linting-code-snippets/java/pom.xml b/utils/doclint/linting-code-snippets/java/pom.xml new file mode 100644 index 0000000000000..ec040ad677da8 --- /dev/null +++ b/utils/doclint/linting-code-snippets/java/pom.xml @@ -0,0 +1,53 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.example</groupId> + <artifactId>java-syntax-checker</artifactId> + <version>1.0-SNAPSHOT</version> + + <properties> + <maven.compiler.source>15</maven.compiler.source> + <maven.compiler.target>15</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>com.github.javaparser</groupId> + <artifactId>javaparser-core</artifactId> + <version>3.26.2</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.11.0</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.5.1</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>JavaSyntaxChecker</mainClass> + </transformer> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/utils/doclint/linting-code-snippets/java/src/main/java/JavaSyntaxChecker.java b/utils/doclint/linting-code-snippets/java/src/main/java/JavaSyntaxChecker.java new file mode 100644 index 0000000000000..be2a5bbe35765 --- /dev/null +++ b/utils/doclint/linting-code-snippets/java/src/main/java/JavaSyntaxChecker.java @@ -0,0 +1,110 @@ +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.github.javaparser.JavaParser; +import com.github.javaparser.Problem; +import com.github.javaparser.ParseResult; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ParserConfiguration; +import com.github.javaparser.StaticJavaParser; + +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class JavaSyntaxChecker { + public static void main(String[] args) { + if (args.length == 0) { + System.out.println("Error: Please provide the path to the JSON file"); + return; + } + + String codeSnippetsPath = args[args.length - 1]; + List<CodeSnippet> codeSnippets = readCodeSnippets(codeSnippetsPath); + if (codeSnippets == null) { + System.out.println("Error: codeSnippets is null"); + return; + } + + List<Map<String, Object>> output = new ArrayList<>(); + + ParserConfiguration config = new ParserConfiguration(); + config.setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_17); + + for (CodeSnippet codeSnippet : codeSnippets) { + String cleanedCode = cleanSnippet(codeSnippet.code); + ParseResult<CompilationUnit> parseResult = new JavaParser(config).parse(cleanedCode); + List<Problem> syntaxErrors = parseResult.getProblems(); + + if (!syntaxErrors.isEmpty()) { + output.add(Map.of( + "status", "error", + "error", String.join("\n", syntaxErrors.stream() + .map(Problem::getMessage) + .collect(Collectors.toList())) + )); + } else { + output.add(Map.of("status", "ok")); + } + } + + System.out.println(new Gson().toJson(output)); + } + + private static String removeImports(String code) { + // Remove import statements + return Pattern.compile("^import.*;$", Pattern.MULTILINE) + .matcher(code) + .replaceAll(""); + } + + private static String cleanSnippet(String code) { + // if it contains "public class" then it's a full class, return immediately + if (code.contains("public class")) { + return code; + } + code = removeImports(code); + String wrappedCode = """ + import com.microsoft.playwright.*; + import static com.microsoft.playwright.assertions.PlaywrightAssertions.*; + + public class Example { + public static void main(String[] args) { + try (Playwright playwright = Playwright.create()) { + Browser browser = playwright.chromium().launch(); + BrowserContext context = browser.newContext(); + Page page = context.newPage(); + %s + } + } + } + """.formatted(code); + return wrappedCode; + } + + private static List<CodeSnippet> readCodeSnippets(String filePath) { + try (FileReader reader = new FileReader(filePath)) { + Type listType = new TypeToken<ArrayList<CodeSnippet>>(){}.getType(); + return new Gson().fromJson(reader, listType); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} + +class CodeSnippet { + String filePath; + String codeLang; + String code; + + public CodeSnippet(String filePath, String codeLang, String code) { + this.filePath = filePath; + this.codeLang = codeLang; + this.code = code; + } +} \ No newline at end of file From 10d6812058988f78672bc94eb0ee0985784d37fa Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Fri, 4 Oct 2024 04:54:56 -0700 Subject: [PATCH 247/805] chore: clear `pendingDocument()` for the same-document navigation (#32954) WebKit notifies about a pending same-document navigation through `Page.frameScheduledNavigation`, and committing it should clear the `pendingDocument()`. Extracted from #32899. --- packages/playwright-core/src/server/frames.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 7dc992813b275..d107a7f981e36 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -248,6 +248,11 @@ export class FrameManager { const frame = this._frames.get(frameId); if (!frame) return; + const pending = frame.pendingDocument(); + if (pending && pending.documentId === undefined && pending.request === undefined) { + // WebKit has notified about the same-document navigation being requested, so clear it. + frame.setPendingDocument(undefined); + } frame._url = url; const navigationEvent: NavigationEvent = { url, name: frame._name, isPublic: true }; this._fireInternalFrameNavigation(frame, navigationEvent); From ff0c4989040c00e8f70f84831aed6549343dfac6 Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Fri, 4 Oct 2024 14:18:21 +0200 Subject: [PATCH 248/805] fix(ct-vue): update default slot should work (#32952) Closes https://github.com/microsoft/playwright/issues/32809 We were writing onto the wrong object. --- packages/playwright-ct-vue/registerSource.mjs | 2 +- .../ct-vue-vite/src/components/SlotDefaultValue.vue | 3 +++ .../components/ct-vue-vite/tests/slots/slots.spec.js | 11 +++++++++++ .../components/ct-vue-vite/tests/slots/slots.spec.ts | 11 +++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/components/ct-vue-vite/src/components/SlotDefaultValue.vue diff --git a/packages/playwright-ct-vue/registerSource.mjs b/packages/playwright-ct-vue/registerSource.mjs index 07ce5298f41ca..33bc74e731594 100644 --- a/packages/playwright-ct-vue/registerSource.mjs +++ b/packages/playwright-ct-vue/registerSource.mjs @@ -188,7 +188,7 @@ function __pwWrapFunctions(slots) { for (const [key, value] of Object.entries(slots || {})) slotsWithRenderFunctions[key] = () => [value]; } else if (slots?.length) { - slots['default'] = () => slots; + slotsWithRenderFunctions['default'] = () => slots; } return slotsWithRenderFunctions; } diff --git a/tests/components/ct-vue-vite/src/components/SlotDefaultValue.vue b/tests/components/ct-vue-vite/src/components/SlotDefaultValue.vue new file mode 100644 index 0000000000000..c5944a3f8a9b9 --- /dev/null +++ b/tests/components/ct-vue-vite/src/components/SlotDefaultValue.vue @@ -0,0 +1,3 @@ +<template> + <slot>default value</slot> +</template> diff --git a/tests/components/ct-vue-vite/tests/slots/slots.spec.js b/tests/components/ct-vue-vite/tests/slots/slots.spec.js index a33c9dac920fa..7d36d9733b375 100644 --- a/tests/components/ct-vue-vite/tests/slots/slots.spec.js +++ b/tests/components/ct-vue-vite/tests/slots/slots.spec.js @@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-vue'; import DefaultSlot from '@/components/DefaultSlot.vue'; import NamedSlots from '@/components/NamedSlots.vue'; import Button from '@/components/Button.vue'; +import SlotDefaultValue from "@/components/SlotDefaultValue.vue"; test('render a default slot', async ({ mount }) => { const component = await mount(DefaultSlot, { @@ -49,3 +50,13 @@ test('render a component with a named slot', async ({ mount }) => { await expect(component).toContainText('Main Content'); await expect(component).toContainText('Footer'); }); + +test('updating default slot should work', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32809' } }, async ({ mount }) => { + const slots = { default: 'foo' }; + + const component = await mount(SlotDefaultValue, { slots }); + await expect(component).toHaveText('foo'); + + await component.update({ slots }); + await expect(component).toHaveText('foo'); +}); diff --git a/tests/components/ct-vue-vite/tests/slots/slots.spec.ts b/tests/components/ct-vue-vite/tests/slots/slots.spec.ts index a33c9dac920fa..7d36d9733b375 100644 --- a/tests/components/ct-vue-vite/tests/slots/slots.spec.ts +++ b/tests/components/ct-vue-vite/tests/slots/slots.spec.ts @@ -2,6 +2,7 @@ import { test, expect } from '@playwright/experimental-ct-vue'; import DefaultSlot from '@/components/DefaultSlot.vue'; import NamedSlots from '@/components/NamedSlots.vue'; import Button from '@/components/Button.vue'; +import SlotDefaultValue from "@/components/SlotDefaultValue.vue"; test('render a default slot', async ({ mount }) => { const component = await mount(DefaultSlot, { @@ -49,3 +50,13 @@ test('render a component with a named slot', async ({ mount }) => { await expect(component).toContainText('Main Content'); await expect(component).toContainText('Footer'); }); + +test('updating default slot should work', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32809' } }, async ({ mount }) => { + const slots = { default: 'foo' }; + + const component = await mount(SlotDefaultValue, { slots }); + await expect(component).toHaveText('foo'); + + await component.update({ slots }); + await expect(component).toHaveText('foo'); +}); From 1b457b1ff87fa2d16fcc04e704408a2dc4a5593f Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Fri, 4 Oct 2024 14:18:38 +0200 Subject: [PATCH 249/805] fix(html reporter): render annotation newlines (#32948) Closes https://github.com/microsoft/playwright/issues/32925. Before this change, newlines in annotation descriptions weren't respected. This change makes them shown. Here's how it looks for this annotation: ```ts test.info().annotations.push({ type: 'user story', description: '\n- user goes to the page\n- user clicks the button\n- user sees the result', }); ``` Before: <img width="1071" alt="Screenshot 2024-10-04 at 09 55 15" src="https://github.com/user-attachments/assets/89e74ff5-ea83-48da-a33b-833423916d95"> After: <img width="1031" alt="Screenshot 2024-10-04 at 09 51 08" src="https://github.com/user-attachments/assets/0f2914e8-bd88-4970-aa68-6a5a9828295c"> --- packages/html-reporter/src/testCaseView.css | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/html-reporter/src/testCaseView.css b/packages/html-reporter/src/testCaseView.css index 90e2f4057bd80..56be1d9620619 100644 --- a/packages/html-reporter/src/testCaseView.css +++ b/packages/html-reporter/src/testCaseView.css @@ -61,6 +61,7 @@ align-items: center; padding: 0 8px; line-height: 24px; + white-space: pre-wrap; } @media only screen and (max-width: 600px) { From 84b4fd4e4064d2551976d8e3f5094be44509e0cd Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Fri, 4 Oct 2024 07:25:18 -0700 Subject: [PATCH 250/805] feat: wait for pending navigation to resolve before many actions (#32899) This includes all actions that perform locator handler check. Note this makes it impossible to interact with the page while a main frame navigation is ongoing. This was already the case for Chromium, but now WebKit and Firefox align with it. Setting `PLAYWRIGHT_SKIP_NAVIGATION_CHECK` environment variable disables this behavior. --- packages/playwright-core/src/server/dom.ts | 10 +-- packages/playwright-core/src/server/frames.ts | 48 ++++++------ packages/playwright-core/src/server/page.ts | 34 +++++++- .../library/browsercontext-page-event.spec.ts | 16 ---- tests/page/page-autowaiting-no-hang.spec.ts | 77 ++++++++++++++++++- 5 files changed, 136 insertions(+), 49 deletions(-) diff --git a/packages/playwright-core/src/server/dom.ts b/packages/playwright-core/src/server/dom.ts index c2ed979fbecaa..76708245d4ab3 100644 --- a/packages/playwright-core/src/server/dom.ts +++ b/packages/playwright-core/src/server/dom.ts @@ -292,7 +292,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> { }; } - async _retryAction(progress: Progress, actionName: string, action: (retry: number) => Promise<PerformActionResult>, options: { trial?: boolean, force?: boolean, skipLocatorHandlersCheckpoint?: boolean }): Promise<'error:notconnected' | 'done'> { + async _retryAction(progress: Progress, actionName: string, action: (retry: number) => Promise<PerformActionResult>, options: { trial?: boolean, force?: boolean, skipActionPreChecks?: boolean }): Promise<'error:notconnected' | 'done'> { let retry = 0; // We progressively wait longer between retries, up to 500ms. const waitTime = [0, 20, 100, 100, 500]; @@ -310,8 +310,8 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> { } else { progress.log(`attempting ${actionName} action${options.trial ? ' (trial run)' : ''}`); } - if (!options.skipLocatorHandlersCheckpoint && !options.force) - await this._frame._page.performLocatorHandlersCheckpoint(progress); + if (!options.skipActionPreChecks && !options.force) + await this._frame._page.performActionPreChecks(progress); const result = await action(retry); ++retry; if (result === 'error:notvisible') { @@ -346,7 +346,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> { async _retryPointerAction(progress: Progress, actionName: ActionName, waitForEnabled: boolean, action: (point: types.Point) => Promise<void>, options: { waitAfter: boolean | 'disabled' } & types.PointerActionOptions & types.PointerActionWaitOptions): Promise<'error:notconnected' | 'done'> { // Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation. - const skipLocatorHandlersCheckpoint = actionName === 'move and up'; + const skipActionPreChecks = actionName === 'move and up'; return await this._retryAction(progress, actionName, async retry => { // By default, we scroll with protocol method to reveal the action point. // However, that might not work to scroll from under position:sticky elements @@ -360,7 +360,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> { ]; const forceScrollOptions = scrollOptions[retry % scrollOptions.length]; return await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options); - }, { ...options, skipLocatorHandlersCheckpoint }); + }, { ...options, skipActionPreChecks }); } async _performPointerAction( diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index d107a7f981e36..dd24193f219ae 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -791,11 +791,11 @@ export class Frame extends SdkObject { }, this._page._timeoutSettings.timeout(options)); } - async waitForSelectorInternal(progress: Progress, selector: string, performLocatorHandlersCheckpoint: boolean, options: types.WaitForElementOptions, scope?: dom.ElementHandle): Promise<dom.ElementHandle<Element> | null> { + async waitForSelectorInternal(progress: Progress, selector: string, performActionPreChecks: boolean, options: types.WaitForElementOptions, scope?: dom.ElementHandle): Promise<dom.ElementHandle<Element> | null> { const { state = 'visible' } = options; const promise = this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async continuePolling => { - if (performLocatorHandlersCheckpoint) - await this._page.performLocatorHandlersCheckpoint(progress); + if (performActionPreChecks) + await this._page.performActionPreChecks(progress); const resolved = await this.selectors.resolveInjectedForSelector(selector, options, scope); progress.throwIfAborted(); @@ -1118,12 +1118,12 @@ export class Frame extends SdkObject { progress: Progress, selector: string, strict: boolean | undefined, - performLocatorHandlersCheckpoint: boolean, + performActionPreChecks: boolean, action: (handle: dom.ElementHandle<Element>) => Promise<R | 'error:notconnected'>): Promise<R> { progress.log(`waiting for ${this._asLocator(selector)}`); return this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async continuePolling => { - if (performLocatorHandlersCheckpoint) - await this._page.performLocatorHandlersCheckpoint(progress); + if (performActionPreChecks) + await this._page.performActionPreChecks(progress); const resolved = await this.selectors.resolveInjectedForSelector(selector, { strict }); progress.throwIfAborted(); @@ -1167,7 +1167,7 @@ export class Frame extends SdkObject { } async rafrafTimeoutScreenshotElementWithProgress(progress: Progress, selector: string, timeout: number, options: ScreenshotOptions): Promise<Buffer> { - return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performLocatorHandlersCheckpoint */, async handle => { + return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, async handle => { await handle._frame.rafrafTimeout(timeout); return await this._page._screenshotter.screenshotElement(progress, handle, options); }); @@ -1176,21 +1176,21 @@ export class Frame extends SdkObject { async click(metadata: CallMetadata, selector: string, options: { noWaitAfter?: boolean } & types.MouseClickOptions & types.PointerActionWaitOptions) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter }))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._click(progress, { ...options, waitAfter: !options.noWaitAfter }))); }, this._page._timeoutSettings.timeout(options)); } async dblclick(metadata: CallMetadata, selector: string, options: types.MouseMultiClickOptions & types.PointerActionWaitOptions = {}) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._dblclick(progress, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._dblclick(progress, options))); }, this._page._timeoutSettings.timeout(options)); } async dragAndDrop(metadata: CallMetadata, source: string, target: string, options: types.DragActionOptions & types.PointerActionWaitOptions = {}) { const controller = new ProgressController(metadata, this); await controller.run(async progress => { - dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, !options.force /* performLocatorHandlersCheckpoint */, async handle => { + dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, !options.force /* performActionPreChecks */, async handle => { return handle._retryPointerAction(progress, 'move and down', false, async point => { await this._page.mouse.move(point.x, point.y); await this._page.mouse.down(); @@ -1202,7 +1202,7 @@ export class Frame extends SdkObject { }); })); // Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation. - dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performLocatorHandlersCheckpoint */, async handle => { + dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performActionPreChecks */, async handle => { return handle._retryPointerAction(progress, 'move and up', false, async point => { await this._page.mouse.move(point.x, point.y); await this._page.mouse.up(); @@ -1221,28 +1221,28 @@ export class Frame extends SdkObject { throw new Error('The page does not support tap. Use hasTouch context option to enable touch support.'); const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._tap(progress, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._tap(progress, options))); }, this._page._timeoutSettings.timeout(options)); } async fill(metadata: CallMetadata, selector: string, value: string, options: types.TimeoutOptions & types.StrictOptions & { force?: boolean }) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._fill(progress, value, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._fill(progress, value, options))); }, this._page._timeoutSettings.timeout(options)); } async focus(metadata: CallMetadata, selector: string, options: types.TimeoutOptions & types.StrictOptions = {}) { const controller = new ProgressController(metadata, this); await controller.run(async progress => { - dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performLocatorHandlersCheckpoint */, handle => handle._focus(progress))); + dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._focus(progress))); }, this._page._timeoutSettings.timeout(options)); } async blur(metadata: CallMetadata, selector: string, options: types.TimeoutOptions & types.StrictOptions = {}) { const controller = new ProgressController(metadata, this); await controller.run(async progress => { - dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performLocatorHandlersCheckpoint */, handle => handle._blur(progress))); + dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._blur(progress))); }, this._page._timeoutSettings.timeout(options)); } @@ -1349,14 +1349,14 @@ export class Frame extends SdkObject { async hover(metadata: CallMetadata, selector: string, options: types.PointerActionOptions & types.PointerActionWaitOptions = {}) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._hover(progress, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._hover(progress, options))); }, this._page._timeoutSettings.timeout(options)); } async selectOption(metadata: CallMetadata, selector: string, elements: dom.ElementHandle[], values: types.SelectOption[], options: types.CommonActionOptions = {}): Promise<string[]> { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._selectOption(progress, elements, values, options)); + return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._selectOption(progress, elements, values, options)); }, this._page._timeoutSettings.timeout(options)); } @@ -1364,35 +1364,35 @@ export class Frame extends SdkObject { const inputFileItems = await prepareFilesForUpload(this, params); const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true /* performLocatorHandlersCheckpoint */, handle => handle._setInputFiles(progress, inputFileItems))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, params.strict, true /* performActionPreChecks */, handle => handle._setInputFiles(progress, inputFileItems))); }, this._page._timeoutSettings.timeout(params)); } async type(metadata: CallMetadata, selector: string, text: string, options: { delay?: number } & types.TimeoutOptions & types.StrictOptions = {}) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performLocatorHandlersCheckpoint */, handle => handle._type(progress, text, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._type(progress, text, options))); }, this._page._timeoutSettings.timeout(options)); } async press(metadata: CallMetadata, selector: string, key: string, options: { delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & types.StrictOptions = {}) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performLocatorHandlersCheckpoint */, handle => handle._press(progress, key, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, true /* performActionPreChecks */, handle => handle._press(progress, key, options))); }, this._page._timeoutSettings.timeout(options)); } async check(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions = {}) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._setChecked(progress, true, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._setChecked(progress, true, options))); }, this._page._timeoutSettings.timeout(options)); } async uncheck(metadata: CallMetadata, selector: string, options: types.PointerActionWaitOptions = {}) { const controller = new ProgressController(metadata, this); return controller.run(async progress => { - return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performLocatorHandlersCheckpoint */, handle => handle._setChecked(progress, false, options))); + return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, !options.force /* performActionPreChecks */, handle => handle._setChecked(progress, false, options))); }, this._page._timeoutSettings.timeout(options)); } @@ -1421,7 +1421,7 @@ export class Frame extends SdkObject { await (new ProgressController(metadata, this)).run(async progress => { progress.log(`${metadata.apiName}${timeout ? ` with timeout ${timeout}ms` : ''}`); progress.log(`waiting for ${this._asLocator(selector)}`); - await this._page.performLocatorHandlersCheckpoint(progress); + await this._page.performActionPreChecks(progress); }, timeout); // Step 2: perform one-shot expect check without a timeout. @@ -1448,7 +1448,7 @@ export class Frame extends SdkObject { // Step 3: auto-retry expect with increasing timeouts. Bounded by the total remaining time. return await (new ProgressController(metadata, this)).run(async progress => { return await this.retryWithProgressAndTimeouts(progress, [100, 250, 500, 1000], async continuePolling => { - await this._page.performLocatorHandlersCheckpoint(progress); + await this._page.performActionPreChecks(progress); const { matches, received } = await this._expectInternal(progress, selector, options, lastIntermediateResult); if (matches === options.isNot) { // Keep waiting in these cases: diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 3fb72bb0c3d5b..f7f1ef67e821d 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -31,7 +31,7 @@ import * as accessibility from './accessibility'; import { FileChooser } from './fileChooser'; import type { Progress } from './progress'; import { ProgressController } from './progress'; -import { LongStandingScope, assert, createGuid } from '../utils'; +import { LongStandingScope, assert, createGuid, trimStringWithEllipsis } from '../utils'; import { ManualPromise } from '../utils/manualPromise'; import { debugLogger } from '../utils/debugLogger'; import type { ImageComparatorOptions } from '../utils/comparators'; @@ -45,6 +45,7 @@ import { parseEvaluationResultValue, source } from './isomorphic/utilityScriptSe import type { SerializedValue } from './isomorphic/utilityScriptSerializers'; import { TargetClosedError } from './errors'; import { asLocator } from '../utils'; +import { helper } from './helper'; export interface PageDelegate { readonly rawMouse: input.RawMouse; @@ -455,7 +456,34 @@ export class Page extends SdkObject { this._locatorHandlers.delete(uid); } - async performLocatorHandlersCheckpoint(progress: Progress) { + async performActionPreChecks(progress: Progress) { + await this._performWaitForNavigationCheck(progress); + progress.throwIfAborted(); + await this._performLocatorHandlersCheckpoint(progress); + progress.throwIfAborted(); + // Wait once again, just in case a locator handler caused a navigation. + await this._performWaitForNavigationCheck(progress); + } + + private async _performWaitForNavigationCheck(progress: Progress) { + if (process.env.PLAYWRIGHT_SKIP_NAVIGATION_CHECK) + return; + const mainFrame = this._frameManager.mainFrame(); + if (!mainFrame || !mainFrame.pendingDocument()) + return; + const url = mainFrame.pendingDocument()?.request?.url(); + const toUrl = url ? `" ${trimStringWithEllipsis(url, 200)}"` : ''; + progress.log(` waiting for${toUrl} navigation to finish...`); + await helper.waitForEvent(progress, mainFrame, frames.Frame.Events.InternalNavigation, (e: frames.NavigationEvent) => { + if (!e.isPublic) + return false; + if (!e.error) + progress.log(` navigated to "${trimStringWithEllipsis(mainFrame.url(), 200)}"`); + return true; + }).promise; + } + + private async _performLocatorHandlersCheckpoint(progress: Progress) { // Do not run locator handlers from inside locator handler callbacks to avoid deadlocks. if (this._locatorHandlerRunningCounter) return; @@ -559,7 +587,7 @@ export class Page extends SdkObject { const rafrafScreenshot = locator ? async (progress: Progress, timeout: number) => { return await locator.frame.rafrafTimeoutScreenshotElementWithProgress(progress, locator.selector, timeout, options || {}); } : async (progress: Progress, timeout: number) => { - await this.performLocatorHandlersCheckpoint(progress); + await this.performActionPreChecks(progress); await this.mainFrame().rafrafTimeout(timeout); return await this._screenshotter.screenshotPage(progress, options || {}); }; diff --git a/tests/library/browsercontext-page-event.spec.ts b/tests/library/browsercontext-page-event.spec.ts index b851dd0ce9b1e..30efb63fcf5c4 100644 --- a/tests/library/browsercontext-page-event.spec.ts +++ b/tests/library/browsercontext-page-event.spec.ts @@ -184,19 +184,3 @@ it('should work with Ctrl-clicking', async ({ browser, server, browserName }) => expect(await popup.opener()).toBe(null); await context.close(); }); - -it('should not hang on ctrl-click during provisional load', async ({ context, page, server, isWindows, browserName, isLinux }) => { - it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11595' }); - it.skip(browserName === 'chromium', 'Chromium does not dispatch renderer messages while navigation is provisional.'); - it.fixme(browserName === 'webkit' && isWindows, 'Timesout while trying to click'); - it.fixme(browserName === 'webkit' && isLinux, 'Timesout while trying to click'); - await page.goto(server.EMPTY_PAGE); - await page.setContent('<a href="/one-style.html">yo</a>'); - server.setRoute('/slow.html', () => {}); - const [popup] = await Promise.all([ - context.waitForEvent('page'), - server.waitForRequest('/slow.html').then(() => page.click('a', { modifiers: ['ControlOrMeta'] })), - page.evaluate(url => setTimeout(() => location.href = url, 0), server.CROSS_PROCESS_PREFIX + '/slow.html'), - ]); - expect(popup).toBeTruthy(); -}); diff --git a/tests/page/page-autowaiting-no-hang.spec.ts b/tests/page/page-autowaiting-no-hang.spec.ts index f580b8629a142..6fc7a088af8ae 100644 --- a/tests/page/page-autowaiting-no-hang.spec.ts +++ b/tests/page/page-autowaiting-no-hang.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { test as it } from './pageTest'; +import { test as it, expect } from './pageTest'; it('clicking on links which do not commit navigation', async ({ page, server, httpsServer }) => { await page.goto(server.EMPTY_PAGE); @@ -65,3 +65,78 @@ it('opening a popup', async function({ page, server }) { page.evaluate(() => window.open(window.location.href) && 1), ]); }); + +it('clicking in the middle of navigation that aborts', async ({ page, server }) => { + let abortCallback; + const abortPromise = new Promise(f => abortCallback = f); + + let stallCallback; + const stallPromise = new Promise(f => stallCallback = f); + + server.setRoute('/stall.html', async (req, res) => { + stallCallback(); + await abortPromise; + req.socket.destroy(); + }); + + await page.goto(server.PREFIX + '/one-style.html'); + page.goto(server.PREFIX + '/stall.html').catch(() => {}); + await stallPromise; + + const clickPromise = page.click('body'); + await page.waitForTimeout(1000); + abortCallback(); + + await clickPromise; +}); + +it('clicking in the middle of navigation that commits', async ({ page, server }) => { + let commitCallback; + const abortPromise = new Promise(f => commitCallback = f); + + let stallCallback; + const stallPromise = new Promise(f => stallCallback = f); + + server.setRoute('/stall.html', async (req, res) => { + stallCallback(); + await abortPromise; + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end('hello world'); + }); + + await page.goto(server.PREFIX + '/one-style.html'); + page.goto(server.PREFIX + '/stall.html').catch(() => {}); + await stallPromise; + + const clickPromise = page.click('body'); + await page.waitForTimeout(1000); + commitCallback(); + + await clickPromise; + await expect(page.locator('body')).toContainText('hello world'); +}); + +it('goBack in the middle of navigation that commits', async ({ page, server }) => { + let commitCallback; + const abortPromise = new Promise(f => commitCallback = f); + + let stallCallback; + const stallPromise = new Promise(f => stallCallback = f); + + server.setRoute('/stall.html', async (req, res) => { + stallCallback(); + await abortPromise; + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end('hello world'); + }); + + await page.goto(server.PREFIX + '/one-style.html'); + page.goto(server.PREFIX + '/stall.html').catch(() => {}); + await stallPromise; + + const goBackPromise = page.goBack().catch(() => {}); + await page.waitForTimeout(1000); + commitCallback(); + + await goBackPromise; +}); From 6be97f34dd35631c9822c4ccf9be73dc37192c08 Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Fri, 4 Oct 2024 16:29:13 +0200 Subject: [PATCH 251/805] docs(test-reporters): replace reporter showcase with list of interesting OSS implementations (#32896) As discussed yesterday, this PR replaces the "reporter showcase" with a list of interesting implementations for folks who are writing their own custom reporters. --------- Signed-off-by: Simon Knott <info@simonknott.de> --- docs/src/test-reporters-js.md | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/docs/src/test-reporters-js.md b/docs/src/test-reporters-js.md index 952d74b923bd2..ce5698005cba5 100644 --- a/docs/src/test-reporters-js.md +++ b/docs/src/test-reporters-js.md @@ -422,18 +422,10 @@ Or just pass the reporter file path as `--reporter` command line option: npx playwright test --reporter="./myreporter/my-awesome-reporter.ts" ``` -## Third party reporter showcase - -* [Allure](https://www.npmjs.com/package/allure-playwright) -* [Argos Visual Testing](https://argos-ci.com/docs/playwright) -* [Currents](https://www.npmjs.com/package/@currents/playwright) -* [GitHub Actions Reporter](https://www.npmjs.com/package/@estruyf/github-actions-reporter) -* [GitHub Pull Request Comment](https://github.com/marketplace/actions/playwright-report-comment) -* [Mail Reporter](https://www.npmjs.com/package/playwright-mail-reporter) -* [Microsoft Teams Reporter](https://www.npmjs.com/package/playwright-msteams-reporter) -* [Monocart](https://github.com/cenfun/monocart-reporter) +Here's a short list of open source reporter implementations that you can take a look at when writing your own reporter: + +* [Allure Reporter](https://github.com/allure-framework/allure-js/tree/main/packages/allure-playwright) +* [Github Actions Reporter](https://github.com/estruyf/playwright-github-actions-reporter) +* [Mail Reporter](https://github.com/estruyf/playwright-mail-reporter) * [ReportPortal](https://github.com/reportportal/agent-js-playwright) -* [Serenity/JS](https://serenity-js.org/handbook/test-runners/playwright-test) -* [Testmo](https://github.com/jonasclaes/playwright-testmo-reporter) -* [Testomat.io](https://github.com/testomatio/reporter/blob/master/docs/frameworks.md#playwright) -* [Tesults](https://www.tesults.com/docs/playwright) +* [Monocart](https://github.com/cenfun/monocart-reporter) From 80ff7c396a596854e11d95e36fb2d66afae53c6c Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Fri, 4 Oct 2024 16:38:13 +0200 Subject: [PATCH 252/805] chore(docs): fix code highlighting (#32927) Closes https://github.com/microsoft/playwright/issues/32921 This is the diff when rolling to `playwright.dev` locally: <img width="1262" alt="Screenshot 2024-10-02 at 14 54 42" src="https://github.com/user-attachments/assets/aade7ad4-420c-48c4-a2c9-03fe815a3959"> --------- Signed-off-by: Simon Knott <info@simonknott.de> --- docs/src/ci.md | 2 +- utils/markdown.js | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/docs/src/ci.md b/docs/src/ci.md index 6f6fc9a80e7e2..99033a3e2ed78 100644 --- a/docs/src/ci.md +++ b/docs/src/ci.md @@ -415,7 +415,7 @@ Large test suites can take very long to execute. By executing a preliminary test This will give you a faster feedback loop and slightly lower CI consumption while working on Pull Requests. To detect test files affected by your changeset, `--only-changed` analyses your suites' dependency graph. This is a heuristic and might miss tests, so it's important that you always run the full test suite after the preliminary test run. -```yml js title=".github/workflows/playwright.yml" +```yml js title=".github/workflows/playwright.yml" {24-26} name: Playwright Tests on: push: diff --git a/utils/markdown.js b/utils/markdown.js index 3e206ade3b1af..faf62f195118e 100644 --- a/utils/markdown.js +++ b/utils/markdown.js @@ -46,6 +46,7 @@ * lines: string[], * codeLang: string, * title?: string, + * highlight?: string, * }} MarkdownCodeNode */ /** @typedef {MarkdownBaseNode & { @@ -165,13 +166,14 @@ function buildTree(lines) { // Remaining items respect indent-based nesting. const [, indent, content] = /** @type {string[]} */ (line.match('^([ ]*)(.*)')); if (content.startsWith('```')) { - const [codeLang, title] = parseCodeBlockMetadata(content); + const [codeLang, title, highlight] = parseCodeBlockMetadata(content); /** @type {MarkdownNode} */ const node = { type: 'code', lines: [], codeLang, title, + highlight, }; line = lines[++i]; while (!line.trim().startsWith('```')) { @@ -255,14 +257,18 @@ function buildTree(lines) { /** * @param {String} firstLine - * @returns {[string, string|undefined]} + * @returns {[string, string|undefined, string|undefined]} */ function parseCodeBlockMetadata(firstLine) { const withoutBackticks = firstLine.substring(3); - const match = withoutBackticks.match(/ title="(.+)"$/); - if (match) - return [withoutBackticks.substring(0, match.index), match[1]]; - return [withoutBackticks, undefined]; + const titleMatch = withoutBackticks.match(/ title="(.+)"/); + const highlightMatch = withoutBackticks.match(/\{.*\}/); + + let codeLang = withoutBackticks; + if (titleMatch || highlightMatch) + codeLang = withoutBackticks.substring(0, titleMatch?.index ?? highlightMatch?.index); + + return [codeLang, titleMatch?.[1], highlightMatch?.[0]]; } /** @@ -328,7 +334,7 @@ function innerRenderMdNode(indent, node, lastNode, result, options) { if (node.type === 'code') { newLine(); - result.push(`${indent}\`\`\`${node.codeLang}${(options?.renderCodeBlockTitlesInHeader && node.title) ? ' title="' + node.title + '"' : ''}`); + result.push(`${indent}\`\`\`${node.codeLang}${(options?.renderCodeBlockTitlesInHeader && node.title) ? ' title="' + node.title + '"' : ''}${node.highlight ? ' ' + node.highlight : ''}`); if (!options?.renderCodeBlockTitlesInHeader && node.title) result.push(`${indent}// ${node.title}`); for (const line of node.lines) From 40670e6ffd579de4c61b6760f606ea90c4cc07cd Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Fri, 4 Oct 2024 16:49:32 +0200 Subject: [PATCH 253/805] fix(emulate media): document "no-preference" as deprecated (#32881) Closes https://github.com/microsoft/playwright/issues/32862. `prefers-color-scheme: no-preference` was removed from browsers. This PR marks it as deprecated in our docs and removes all mentions. --------- Signed-off-by: Simon Knott <info@simonknott.de> Co-authored-by: Dmitry Gozman <dgozman@gmail.com> --- docs/src/api/class-page.md | 17 ++++------------- docs/src/api/params.md | 4 ++-- docs/src/emulation.md | 2 +- docs/src/test-use-options-js.md | 2 +- packages/playwright-core/types/types.d.ts | 22 +++++++++++++--------- packages/playwright/types/test.d.ts | 3 ++- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 7a3be809c6ba5..373649154d4bd 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -1217,8 +1217,6 @@ await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches); // → true await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches); // → false -await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches); -// → false ``` ```java @@ -1227,8 +1225,6 @@ page.evaluate("() => matchMedia('(prefers-color-scheme: dark)').matches"); // → true page.evaluate("() => matchMedia('(prefers-color-scheme: light)').matches"); // → false -page.evaluate("() => matchMedia('(prefers-color-scheme: no-preference)').matches"); -// → false ``` ```python async @@ -1237,8 +1233,6 @@ await page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches") # → True await page.evaluate("matchMedia('(prefers-color-scheme: light)').matches") # → False -await page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches") -# → False ``` ```python sync @@ -1247,7 +1241,6 @@ page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches") # → True page.evaluate("matchMedia('(prefers-color-scheme: light)').matches") # → False -page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches") ``` ```csharp @@ -1256,8 +1249,6 @@ await page.EvaluateAsync("matchMedia('(prefers-color-scheme: dark)').matches"); // → true await page.EvaluateAsync("matchMedia('(prefers-color-scheme: light)').matches"); // → false -await page.EvaluateAsync("matchMedia('(prefers-color-scheme: no-preference)').matches"); -// → false ``` ### option: Page.emulateMedia.media @@ -1281,16 +1272,16 @@ Passing `'Null'` disables CSS media emulation. * langs: js, java - `colorScheme` <null|[ColorScheme]<"light"|"dark"|"no-preference">> -Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. Passing -`null` disables color scheme emulation. +Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. Passing +`null` disables color scheme emulation. `'no-preference'` is deprecated. ### option: Page.emulateMedia.colorScheme * since: v1.9 * langs: csharp, python - `colorScheme` <[ColorScheme]<"light"|"dark"|"no-preference"|"null">> -Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. Passing -`'Null'` disables color scheme emulation. +Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. Passing +`'Null'` disables color scheme emulation. `'no-preference'` is deprecated. ### option: Page.emulateMedia.reducedMotion * since: v1.12 diff --git a/docs/src/api/params.md b/docs/src/api/params.md index 462b225e6e758..63693030bbe60 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -639,14 +639,14 @@ If no origin is specified, the username and password are sent to any servers upo * langs: js, java - `colorScheme` <null|[ColorScheme]<"light"|"dark"|"no-preference">> -Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See +Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. See [`method: Page.emulateMedia`] for more details. Passing `null` resets emulation to system defaults. Defaults to `'light'`. ## context-option-colorscheme-csharp-python * langs: csharp, python - `colorScheme` <[ColorScheme]<"light"|"dark"|"no-preference"|"null">> -Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See +Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. See [`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'light'`. ## context-option-reducedMotion diff --git a/docs/src/emulation.md b/docs/src/emulation.md index 12b44a49c8e2e..fd0009f71c77f 100644 --- a/docs/src/emulation.md +++ b/docs/src/emulation.md @@ -558,7 +558,7 @@ await context.SetGeolocationAsync(new Geolocation() { Longitude = 48.858455, Lat **Note** you can only change geolocation for all pages in the context. ## Color Scheme and Media -Emulate the users `"colorScheme"`. Supported values are 'light', 'dark', 'no-preference'. You can also emulate the media type with [`method: Page.emulateMedia`]. +Emulate the users `"colorScheme"`. Supported values are 'light' and 'dark'. You can also emulate the media type with [`method: Page.emulateMedia`]. ```js title="playwright.config.ts" import { defineConfig } from '@playwright/test'; diff --git a/docs/src/test-use-options-js.md b/docs/src/test-use-options-js.md index c8c93c7cee537..6e1da0a228ce1 100644 --- a/docs/src/test-use-options-js.md +++ b/docs/src/test-use-options-js.md @@ -64,7 +64,7 @@ export default defineConfig({ | Option | Description | | :- | :- | -| [`property: TestOptions.colorScheme`] | [Emulates](./emulation.md#color-scheme-and-media) `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'` | +| [`property: TestOptions.colorScheme`] | [Emulates](./emulation.md#color-scheme-and-media) `'prefers-colors-scheme'` media feature, supported values are `'light'` and `'dark'` | | [`property: TestOptions.geolocation`] | Context [geolocation](./emulation.md#geolocation). | | [`property: TestOptions.locale`] | [Emulates](./emulation.md#locale--timezone) the user locale, for example `en-GB`, `de-DE`, etc. | | [`property: TestOptions.permissions`] | A list of [permissions](./emulation.md#permissions) to grant to all pages in the context. | diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 1f165c3d93fdb..0ecdf93904050 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -2553,16 +2553,15 @@ export interface Page { * // → true * await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches); * // → false - * await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches); - * // → false * ``` * * @param options */ emulateMedia(options?: { /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. - * Passing `null` disables color scheme emulation. + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. Passing `null` disables color scheme emulation. + * `'no-preference'` is deprecated. */ colorScheme?: null|"light"|"dark"|"no-preference"; @@ -9761,7 +9760,8 @@ export interface Browser { }>; /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. See * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. * Passing `null` resets emulation to system defaults. Defaults to `'light'`. */ @@ -14726,7 +14726,8 @@ export interface BrowserType<Unused = {}> { }>; /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. See * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. * Passing `null` resets emulation to system defaults. Defaults to `'light'`. */ @@ -16522,7 +16523,8 @@ export interface AndroidDevice { bypassCSP?: boolean; /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. See * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. * Passing `null` resets emulation to system defaults. Defaults to `'light'`. */ @@ -18998,7 +19000,8 @@ export interface Electron { bypassCSP?: boolean; /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. See * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. * Passing `null` resets emulation to system defaults. Defaults to `'light'`. */ @@ -21820,7 +21823,8 @@ export interface BrowserContextOptions { }>; /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. See * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. * Passing `null` resets emulation to system defaults. Defaults to `'light'`. */ diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 400d7cbcf3eef..41c88940c9eac 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5225,7 +5225,8 @@ export interface PlaywrightTestOptions { */ bypassCSP: boolean; /** - * Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See + * Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) + * media feature, supported values are `'light'` and `'dark'`. See * [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details. * Passing `null` resets emulation to system defaults. Defaults to `'light'`. * From 34ad67659ff721e44b70f7f8bbb6183c8c5eeebf Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Fri, 4 Oct 2024 08:22:27 -0700 Subject: [PATCH 254/805] test: remove some fixmes (#32953) --- tests/library/browsercontext-basic.spec.ts | 2 +- tests/library/browsercontext-cookies.spec.ts | 1 - tests/library/browsercontext-page-event.spec.ts | 4 +--- tests/library/browsercontext-proxy.spec.ts | 4 +++- tests/library/browsertype-connect.spec.ts | 1 - tests/library/capabilities.spec.ts | 17 ++++------------- tests/library/client-certificates.spec.ts | 3 +-- tests/library/clock.spec.ts | 6 ++++-- tests/library/download.spec.ts | 4 +--- tests/library/headful.spec.ts | 8 +++----- tests/library/inspector/cli-codegen-2.spec.ts | 3 --- tests/library/permissions.spec.ts | 3 ++- tests/library/popup.spec.ts | 9 ++++++--- tests/library/trace-viewer.spec.ts | 8 ++++---- tests/page/elementhandle-bounding-box.spec.ts | 2 -- ...elementhandle-wait-for-element-state.spec.ts | 2 -- tests/page/expect-misc.spec.ts | 1 - tests/page/frame-evaluate.spec.ts | 3 +-- tests/page/locator-misc-2.spec.ts | 1 - tests/page/page-click.spec.ts | 2 +- tests/page/page-mouse.spec.ts | 3 +-- tests/page/selectors-css.spec.ts | 1 - 22 files changed, 33 insertions(+), 55 deletions(-) diff --git a/tests/library/browsercontext-basic.spec.ts b/tests/library/browsercontext-basic.spec.ts index f075184cf95ed..df9db587d6482 100644 --- a/tests/library/browsercontext-basic.spec.ts +++ b/tests/library/browsercontext-basic.spec.ts @@ -254,7 +254,7 @@ it('should be able to navigate after disabling javascript', async ({ browser, se }); it('should not hang on promises after disabling javascript', async ({ browserName, contextFactory }) => { - it.fixme(browserName === 'webkit' || browserName === 'firefox'); + it.fixme(browserName === 'firefox'); const context = await contextFactory({ javaScriptEnabled: false }); const page = await context.newPage(); expect(await page.evaluate(() => 1)).toBe(1); diff --git a/tests/library/browsercontext-cookies.spec.ts b/tests/library/browsercontext-cookies.spec.ts index 9bb600c786237..f4dbefad5834a 100644 --- a/tests/library/browsercontext-cookies.spec.ts +++ b/tests/library/browsercontext-cookies.spec.ts @@ -406,7 +406,6 @@ it('should support requestStorageAccess', async ({ page, server, channel, browse it('should parse cookie with large Max-Age correctly', async ({ server, page, defaultSameSiteCookieValue, browserName, platform }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/30305' }); - it.fixme(browserName === 'webkit' && platform === 'linux', 'https://github.com/microsoft/playwright/issues/30305'); server.setRoute('/foobar', (req, res) => { res.setHeader('set-cookie', [ diff --git a/tests/library/browsercontext-page-event.spec.ts b/tests/library/browsercontext-page-event.spec.ts index 30efb63fcf5c4..15e2b661638ca 100644 --- a/tests/library/browsercontext-page-event.spec.ts +++ b/tests/library/browsercontext-page-event.spec.ts @@ -171,8 +171,6 @@ it('should work with Shift-clicking', async ({ browser, server, browserName }) = }); it('should work with Ctrl-clicking', async ({ browser, server, browserName }) => { - it.fixme(browserName === 'firefox', 'Reports an opener in this case.'); - const context = await browser.newContext(); const page = await context.newPage(); await page.goto(server.EMPTY_PAGE); @@ -181,6 +179,6 @@ it('should work with Ctrl-clicking', async ({ browser, server, browserName }) => context.waitForEvent('page'), page.click('a', { modifiers: ['ControlOrMeta'] }), ]); - expect(await popup.opener()).toBe(null); + expect(await popup.opener()).toBe(browserName === 'firefox' ? page : null); await context.close(); }); diff --git a/tests/library/browsercontext-proxy.spec.ts b/tests/library/browsercontext-proxy.spec.ts index 460c242998900..58bda44632b19 100644 --- a/tests/library/browsercontext-proxy.spec.ts +++ b/tests/library/browsercontext-proxy.spec.ts @@ -65,7 +65,9 @@ it('should use proxy', async ({ contextFactory, server, proxyServer }) => { }); -it('should set cookie for top-level domain', async ({ contextFactory, server, proxyServer, browserName, isLinux }) => { +it('should set cookie for top-level domain', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/18362' } +}, async ({ contextFactory, server, proxyServer, browserName, isLinux }) => { it.fixme(browserName === 'webkit' && isLinux); proxyServer.forwardTo(server.PORT, { allowConnectRequests: true }); diff --git a/tests/library/browsertype-connect.spec.ts b/tests/library/browsertype-connect.spec.ts index d494f63b192fa..a732985b5b9f0 100644 --- a/tests/library/browsertype-connect.spec.ts +++ b/tests/library/browsertype-connect.spec.ts @@ -761,7 +761,6 @@ for (const kind of ['launchServer', 'run-server'] as const) { }); test.describe('socks proxy', () => { - test.fixme(({ platform, browserName }) => browserName === 'webkit' && platform === 'win32'); test.skip(({ mode }) => mode !== 'default'); test.skip(kind === 'launchServer', 'not supported yet'); diff --git a/tests/library/capabilities.spec.ts b/tests/library/capabilities.spec.ts index 3f71c7db9e653..864022a1f4900 100644 --- a/tests/library/capabilities.spec.ts +++ b/tests/library/capabilities.spec.ts @@ -65,13 +65,9 @@ it('should respect CSP @smoke', async ({ page, server }) => { expect(await page.evaluate(() => window['testStatus'])).toBe('SUCCESS'); }); -it('should play video @smoke', async ({ page, asset, browserName, platform, macVersion, mode }) => { - // TODO: the test passes on Windows locally but fails on GitHub Action bot, - // apparently due to a Media Pack issue in the Windows Server. - // Also the test is very flaky on Linux WebKit. - it.fixme(browserName === 'webkit' && platform !== 'darwin'); - it.fixme(browserName === 'firefox', 'https://github.com/microsoft/playwright/issues/5721'); - it.fixme(browserName === 'webkit' && platform === 'darwin' && macVersion === 11, 'Does not work on BigSur'); +it('should play video @smoke', async ({ page, asset, browserName, isWindows, isLinux, mode }) => { + it.skip(browserName === 'webkit' && isWindows, 'passes locally but fails on GitHub Action bot, apparently due to a Media Pack issue in the Windows Server'); + it.fixme(browserName === 'firefox' && isLinux, 'https://github.com/microsoft/playwright/issues/5721'); it.skip(mode.startsWith('service')); // Safari only plays mp4 so we test WebKit with an .mp4 clip. @@ -85,8 +81,7 @@ it('should play video @smoke', async ({ page, asset, browserName, platform, macV }); it('should play webm video @smoke', async ({ page, asset, browserName, platform, macVersion, mode }) => { - it.fixme(browserName === 'webkit' && platform === 'darwin' && macVersion === 11, 'Does not work on BigSur'); - it.fixme(browserName === 'webkit' && platform === 'win32'); + it.skip(browserName === 'webkit' && platform === 'win32', 'not supported'); it.skip(mode.startsWith('service')); const absolutePath = asset('video_webm.html'); @@ -98,8 +93,6 @@ it('should play webm video @smoke', async ({ page, asset, browserName, platform, }); it('should play audio @smoke', async ({ page, server, browserName, platform }) => { - it.fixme(browserName === 'firefox' && platform === 'win32', 'https://github.com/microsoft/playwright/issues/10887'); - it.fixme(browserName === 'firefox' && platform === 'linux', 'https://github.com/microsoft/playwright/issues/10887'); it.fixme(browserName === 'webkit' && platform === 'win32', 'https://github.com/microsoft/playwright/issues/10892'); await page.goto(server.EMPTY_PAGE); await page.setContent(`<audio src="${server.PREFIX}/example.mp3"></audio>`); @@ -133,7 +126,6 @@ it('should support webgl 2 @smoke', async ({ page, browserName, headless, isWind it('should not crash on page with mp4 @smoke', async ({ page, server, platform, browserName }) => { it.fixme(browserName === 'webkit' && platform === 'win32', 'https://github.com/microsoft/playwright/issues/11009, times out in setContent'); - it.fixme(browserName === 'firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1697004'); await page.setContent(`<video><source src="${server.PREFIX}/movie.mp4"/></video>`); await page.waitForTimeout(1000); }); @@ -261,7 +253,6 @@ it('window.GestureEvent in WebKit', async ({ page, server, browserName }) => { it('requestFullscreen', async ({ page, server, browserName, headless, isLinux }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/22832' }); - it.fixme(browserName === 'chromium' && headless, 'fullscreenchange is not fired in headless Chromium'); await page.goto(server.EMPTY_PAGE); await page.evaluate(() => { const result = new Promise(resolve => document.addEventListener('fullscreenchange', resolve)); diff --git a/tests/library/client-certificates.spec.ts b/tests/library/client-certificates.spec.ts index cadf49deb9144..10c8a5223543b 100644 --- a/tests/library/client-certificates.spec.ts +++ b/tests/library/client-certificates.spec.ts @@ -728,8 +728,7 @@ test.describe('browser', () => { }); test('should return target connection errors when using http2', async ({ browser, startCCServer, asset, browserName, isMac, isLinux }) => { - test.skip(browserName === 'webkit' && isMac, 'WebKit on macOS doesn\n proxy localhost'); - test.fixme(browserName === 'webkit' && isLinux, 'WebKit on Linux does not support http2 https://bugs.webkit.org/show_bug.cgi?id=276990'); + test.skip(browserName === 'webkit' && isMac, 'WebKit on macOS does not proxy localhost'); test.skip(+process.versions.node.split('.')[0] < 20, 'http2.performServerHandshake is not supported in older Node.js versions'); const serverURL = await startCCServer({ http2: true }); diff --git a/tests/library/clock.spec.ts b/tests/library/clock.spec.ts index daad405e70bf9..3db8e968a28b4 100644 --- a/tests/library/clock.spec.ts +++ b/tests/library/clock.spec.ts @@ -1155,7 +1155,7 @@ it.describe('stubTimers', () => { }); }); - it.fixme('deletes global property on uninstall if it was inherited onto the global object', ({}) => { + it('restores global property on uninstall if it was inherited onto the global object', ({}) => { // Give the global object an inherited 'setTimeout' method const proto = { Date, setTimeout: () => {}, @@ -1167,8 +1167,10 @@ it.describe('stubTimers', () => { const { clock } = rawInstall(myGlobal, { now: 0, toFake: ['setTimeout'] }); expect(myGlobal.hasOwnProperty('setTimeout')).toBeTruthy(); + expect(myGlobal.setTimeout).not.toBe(proto.setTimeout); clock.uninstall(); - expect(myGlobal.hasOwnProperty('setTimeout')).toBeFalsy(); + expect(myGlobal.hasOwnProperty('setTimeout')).toBeTruthy(); + expect(myGlobal.setTimeout).toBe(proto.setTimeout); }); it('fakes Date constructor', ({ installEx }) => { diff --git a/tests/library/download.spec.ts b/tests/library/download.spec.ts index 9e6fb2b8e5adc..33e33f21b4530 100644 --- a/tests/library/download.spec.ts +++ b/tests/library/download.spec.ts @@ -305,10 +305,8 @@ it.describe('download event', () => { }); it('should report alt-click downloads', async ({ browser, server, browserName }) => { - it.fixme(browserName === 'firefox'); + it.skip(browserName === 'firefox', 'Firefox does not download on alt-click.'); - // Firefox does not download on alt-click by default. - // Our WebKit embedder does not download on alt-click, although Safari does. server.setRoute('/download', (req, res) => { res.setHeader('Content-Type', 'application/octet-stream'); res.end(`Hello world`); diff --git a/tests/library/headful.spec.ts b/tests/library/headful.spec.ts index cfeb9711c9917..5832ef44da4e2 100644 --- a/tests/library/headful.spec.ts +++ b/tests/library/headful.spec.ts @@ -192,7 +192,7 @@ it('should not block third party SameSite=None cookies', async ({ httpsServer, b }); it('should not override viewport size when passed null', async function({ browserName, server, browser }) { - it.fixme(browserName === 'webkit', 'Our WebKit embedder does not respect window features'); + it.skip(browserName === 'webkit', 'Our WebKit embedder does not respect window features'); const context = await browser.newContext({ viewport: null }); const page = await context.newPage(); @@ -230,8 +230,6 @@ it('Page.bringToFront should work', async ({ browser }) => { }); it('should click in OOPIF', async ({ browserName, launchPersistent, server }) => { - it.fixme(browserName === 'chromium', 'Click is offset by the infobar height'); - server.setRoute('/empty.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(`<iframe src="${server.CROSS_PROCESS_PREFIX}/iframe.html"></iframe>`); @@ -250,8 +248,8 @@ it('should click in OOPIF', async ({ browserName, launchPersistent, server }) => expect(consoleLog).toContain('ok'); }); -it('should click bottom row w/ infobar in OOPIF', async ({ browserName, launchPersistent, server }) => { - it.fixme(browserName === 'chromium', 'Click is offset by the infobar height'); +it('should click bottom row w/ infobar in OOPIF', async ({ browserName, launchPersistent, server, isWindows }) => { + it.fixme(browserName === 'chromium' && isWindows, 'Click is offset by the infobar height'); server.setRoute('/empty.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); diff --git a/tests/library/inspector/cli-codegen-2.spec.ts b/tests/library/inspector/cli-codegen-2.spec.ts index efde7d52f50ca..e4aa0a07867da 100644 --- a/tests/library/inspector/cli-codegen-2.spec.ts +++ b/tests/library/inspector/cli-codegen-2.spec.ts @@ -106,7 +106,6 @@ await page.CloseAsync();`); }); test('should upload a single file', async ({ openRecorder, browserName, asset, isLinux }) => { - test.fixme(browserName === 'firefox' && isLinux, 'https://bugzilla.mozilla.org/show_bug.cgi?id=1827551'); const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(` <form> @@ -137,7 +136,6 @@ await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-uplo }); test('should upload multiple files', async ({ openRecorder, browserName, asset, isLinux }) => { - test.fixme(browserName === 'firefox' && isLinux, 'https://bugzilla.mozilla.org/show_bug.cgi?id=1827551'); const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(` <form> @@ -168,7 +166,6 @@ await page.GetByRole(AriaRole.Textbox).SetInputFilesAsync(new[] { \"file-to-uplo }); test('should clear files', async ({ openRecorder, browserName, asset, isLinux }) => { - test.fixme(browserName === 'firefox' && isLinux, 'https://bugzilla.mozilla.org/show_bug.cgi?id=1827551'); const { page, recorder } = await openRecorder(); await recorder.setContentAndWait(` <form> diff --git a/tests/library/permissions.spec.ts b/tests/library/permissions.spec.ts index 0797a7e18b8d9..f9f7fdd7ce714 100644 --- a/tests/library/permissions.spec.ts +++ b/tests/library/permissions.spec.ts @@ -176,7 +176,8 @@ it('should support clipboard read', async ({ page, context, server, browserName, it('storage access', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31227' } }, async ({ page, context, server, browserName }) => { - it.fixme(browserName !== 'chromium'); + it.skip(browserName !== 'chromium', 'chromium-only api'); + await context.grantPermissions(['storage-access']); expect(await getPermission(page, 'storage-access')).toBe('granted'); server.setRoute('/set-cookie.html', (req, res) => { diff --git a/tests/library/popup.spec.ts b/tests/library/popup.spec.ts index 56865bdb532b2..1dcede604be20 100644 --- a/tests/library/popup.spec.ts +++ b/tests/library/popup.spec.ts @@ -262,14 +262,17 @@ it('should not throttle rAF in the opener page', async ({ page, server }) => { }); it('should not throw when click closes popup', async ({ browserName, page, server }) => { - it.fixme(browserName === 'firefox'); + it.fixme(browserName === 'firefox', 'locator.click: Target page, context or browser has been closed'); + await page.goto(server.EMPTY_PAGE); const [popup] = await Promise.all([ page.waitForEvent('popup'), - page.evaluate(() => { + page.evaluate(async browserName => { const w = window.open('about:blank'); + if (browserName === 'firefox') + await new Promise(x => w.onload = x); w.document.body.innerHTML = `<button onclick="window.close()">close</button>`; - }), + }, browserName), ]); await popup.getByRole('button').click(); }); diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index f369051a697cf..0eda4b092a111 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1452,18 +1452,18 @@ test.skip('should handle case where neither snapshots nor screenshots exist', as }); test('should show only one pointer with multilevel iframes', async ({ page, runAndTrace, server, browserName }) => { - test.fixme(browserName !== 'chromium', 'Elements in iframe are not marked'); + test.fixme(browserName === 'firefox', 'Elements in iframe are not marked'); server.setRoute('/level-0.html', (req, res) => { - res.writeHead(200); + res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(`<iframe src="/level-1.html" style="position: absolute; left: 100px"></iframe>`); }); server.setRoute('/level-1.html', (req, res) => { - res.writeHead(200); + res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(`<iframe src="/level-2.html"></iframe>`); }); server.setRoute('/level-2.html', (req, res) => { - res.writeHead(200); + res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(`<button>Click me</button>`); }); diff --git a/tests/page/elementhandle-bounding-box.spec.ts b/tests/page/elementhandle-bounding-box.spec.ts index 215dce0222990..c86d516e19ece 100644 --- a/tests/page/elementhandle-bounding-box.spec.ts +++ b/tests/page/elementhandle-bounding-box.spec.ts @@ -20,8 +20,6 @@ import { test as it, expect } from './pageTest'; it.skip(({ isAndroid }) => isAndroid); it('should work', async ({ page, server, browserName, headless, isLinux }) => { - it.fixme(browserName === 'firefox' && !headless && !isLinux); - await page.setViewportSize({ width: 500, height: 500 }); await page.goto(server.PREFIX + '/grid.html'); const elementHandle = await page.$('.box:nth-of-type(13)'); diff --git a/tests/page/elementhandle-wait-for-element-state.spec.ts b/tests/page/elementhandle-wait-for-element-state.spec.ts index bbccf620c7bb4..ae818339e4784 100644 --- a/tests/page/elementhandle-wait-for-element-state.spec.ts +++ b/tests/page/elementhandle-wait-for-element-state.spec.ts @@ -113,8 +113,6 @@ it('should wait for button with an aria-disabled parent', async ({ page }) => { }); it('should wait for stable position', async ({ page, server, browserName, platform }) => { - it.fixme(browserName === 'firefox' && platform === 'linux'); - await page.goto(server.PREFIX + '/input/button.html'); const button = await page.$('button'); await page.$eval('button', button => { diff --git a/tests/page/expect-misc.spec.ts b/tests/page/expect-misc.spec.ts index 36aa64151028a..7bf038231c201 100644 --- a/tests/page/expect-misc.spec.ts +++ b/tests/page/expect-misc.spec.ts @@ -349,7 +349,6 @@ test.describe('toBeInViewport', () => { }); test('should respect ratio option', async ({ page, isAndroid }) => { - test.fixme(isAndroid, 'fails due an upstream bug in Chrome, updating Chrome will fix it.'); await page.setContent(` <style>body, div, html { padding: 0; margin: 0; }</style> <div id=big style="height: 400vh;"></div> diff --git a/tests/page/frame-evaluate.spec.ts b/tests/page/frame-evaluate.spec.ts index b7feb2c0d64a0..16bcf6eac7cc7 100644 --- a/tests/page/frame-evaluate.spec.ts +++ b/tests/page/frame-evaluate.spec.ts @@ -133,8 +133,7 @@ it('should be isolated between frames', async ({ page, server }) => { }); it('should work in iframes that failed initial navigation', async ({ page, browserName }) => { - it.fail(browserName === 'chromium'); - it.fixme(browserName === 'firefox'); + it.fixme(browserName !== 'webkit'); // - Firefox does not report domcontentloaded for the iframe. // - Chromium and Firefox report empty url. diff --git a/tests/page/locator-misc-2.spec.ts b/tests/page/locator-misc-2.spec.ts index eb5765dbf1e70..b474d4ff2e46c 100644 --- a/tests/page/locator-misc-2.spec.ts +++ b/tests/page/locator-misc-2.spec.ts @@ -111,7 +111,6 @@ it('should take screenshot', async ({ page, server, browserName, headless, isAnd }); it('should return bounding box', async ({ page, server, browserName, headless, isAndroid, isLinux }) => { - it.fixme(browserName === 'firefox' && !headless && !isLinux); it.skip(isAndroid); await page.setViewportSize({ width: 500, height: 500 }); diff --git a/tests/page/page-click.spec.ts b/tests/page/page-click.spec.ts index aa02d210ebfe0..c2b024fec11a0 100644 --- a/tests/page/page-click.spec.ts +++ b/tests/page/page-click.spec.ts @@ -336,7 +336,7 @@ it('should click the button inside an iframe', async ({ page, server }) => { }); it('should click the button with fixed position inside an iframe', async ({ page, server, browserName }) => { - it.fixme(browserName === 'chromium' || browserName === 'webkit'); + it.fixme(browserName === 'chromium'); // @see https://github.com/GoogleChrome/puppeteer/issues/4110 // @see https://bugs.chromium.org/p/chromium/issues/detail?id=986390 diff --git a/tests/page/page-mouse.spec.ts b/tests/page/page-mouse.spec.ts index ae8ce84c7b488..f93ca4e2e2863 100644 --- a/tests/page/page-mouse.spec.ts +++ b/tests/page/page-mouse.spec.ts @@ -289,8 +289,7 @@ it('should not crash on mouse drag with any button', async ({ page }) => { it('should dispatch mouse move after context menu was opened', async ({ page, browserName, isWindows }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/20823' }); - it.fixme(browserName === 'firefox'); - it.skip(browserName === 'chromium' && isWindows, 'context menu support is best-effort for Linux and MacOS'); + it.fixme(browserName === 'chromium' && isWindows, 'context menu support is best-effort for Linux and MacOS'); await page.evaluate(() => { window['contextMenuPromise'] = new Promise(x => { window.addEventListener('contextmenu', x, false); diff --git a/tests/page/selectors-css.spec.ts b/tests/page/selectors-css.spec.ts index 172493dbeac5c..3c34bd5c55f3f 100644 --- a/tests/page/selectors-css.spec.ts +++ b/tests/page/selectors-css.spec.ts @@ -275,7 +275,6 @@ it('should work with :nth-child', async ({ page, server }) => { }); it('should work with :nth-child(of) notation with nested functions', async ({ page, browserName, browserMajorVersion }) => { - it.fixme(browserName === 'firefox', 'Should enable once Firefox supports this syntax'); it.skip(browserName === 'chromium' && browserMajorVersion < 111, 'https://caniuse.com/css-nth-child-of'); await page.setContent(` From eaeaa0b1582978e518438c95f6b8b5a765afa117 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Fri, 4 Oct 2024 08:22:36 -0700 Subject: [PATCH 255/805] test: remove tests that we are not going to ever fix (#32962) --- tests/page/page-click-react.spec.ts | 75 ----------------------------- 1 file changed, 75 deletions(-) diff --git a/tests/page/page-click-react.spec.ts b/tests/page/page-click-react.spec.ts index 35626910c10e7..f1ee9af3da4bb 100644 --- a/tests/page/page-click-react.spec.ts +++ b/tests/page/page-click-react.spec.ts @@ -21,47 +21,6 @@ declare const renderComponent; declare const e; declare const MyButton; -it('should report that selector does not match anymore', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })])); - }); - const __testHookAfterStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })])); - else - renderComponent(e('div', {}, [])); - }); - const error = await page.dblclick('text=button1', { __testHookAfterStable, timeout: 3000 } as any).catch(e => e); - expect(await page.evaluate('window.button1')).toBe(undefined); - expect(await page.evaluate('window.button2')).toBe(undefined); - expect(error.message).toContain('page.dblclick: Timeout 3000ms exceeded.'); - expect(error.message).toContain('element does not match the selector anymore'); -}); - -it('should not retarget the handle when element is recycled', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })])); - }); - const __testHookBeforeStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2', disabled: true }), e(MyButton, { name: 'button1' })])); - }); - const handle = await page.$('text=button1'); - const error = await handle.click({ __testHookBeforeStable, timeout: 3000 } as any).catch(e => e); - expect(await page.evaluate('window.button1')).toBe(undefined); - expect(await page.evaluate('window.button2')).toBe(undefined); - expect(error.message).toContain('elementHandle.click: Timeout 3000ms exceeded.'); - expect(error.message).toContain('element is disabled - waiting'); -}); - it('should timeout when click opens alert', async ({ page, server }) => { const dialogPromise = page.waitForEvent('dialog'); await page.setContent(`<div onclick='window.alert(123)'>Click me</div>`); @@ -71,40 +30,6 @@ it('should timeout when click opens alert', async ({ page, server }) => { await dialog.dismiss(); }); -it('should retarget when element is recycled during hit testing', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2' })])); - }); - const __testHookAfterStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2' }), e(MyButton, { name: 'button1' })])); - }); - await page.click('text=button1', { __testHookAfterStable } as any); - expect(await page.evaluate('window.button1')).toBe(true); - expect(await page.evaluate('window.button2')).toBe(undefined); -}); - -it('should retarget when element is recycled before enabled check', async ({ page, server }) => { - it.fixme(); - - await page.goto(server.PREFIX + '/react.html'); - await page.evaluate(() => { - renderComponent(e('div', {}, [e(MyButton, { name: 'button1' }), e(MyButton, { name: 'button2', disabled: true })])); - }); - const __testHookBeforeStable = () => page.evaluate(() => { - window['counter'] = (window['counter'] || 0) + 1; - if (window['counter'] === 1) - renderComponent(e('div', {}, [e(MyButton, { name: 'button2', disabled: true }), e(MyButton, { name: 'button1' })])); - }); - await page.click('text=button1', { __testHookBeforeStable } as any); - expect(await page.evaluate('window.button1')).toBe(true); - expect(await page.evaluate('window.button2')).toBe(undefined); -}); - it('should not retarget when element changes on hover', async ({ page, server }) => { await page.goto(server.PREFIX + '/react.html'); await page.evaluate(() => { From 9f842da8b31bb94d10abf86c78296013e553a86a Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Fri, 4 Oct 2024 08:23:25 -0700 Subject: [PATCH 256/805] fix: throw when element handle is detached while waiting for selector (#32961) --- packages/playwright-core/src/server/frames.ts | 2 ++ tests/page/page-wait-for-selector-2.spec.ts | 28 +++++++++++++++++++ tests/page/selectors-frame.spec.ts | 11 -------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index dd24193f219ae..6dc412c235357 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -805,6 +805,8 @@ export class Frame extends SdkObject { return continuePolling; } const result = await resolved.injected.evaluateHandle((injected, { info, root }) => { + if (root && !root.isConnected) + throw injected.createStacklessError('Element is not attached to the DOM'); const elements = injected.querySelectorAll(info.parsed, root || document); const element: Element | undefined = elements[0]; const visible = element ? injected.utils.isElementVisible(element) : false; diff --git a/tests/page/page-wait-for-selector-2.spec.ts b/tests/page/page-wait-for-selector-2.spec.ts index 5a23e581c7421..4f473f86f25aa 100644 --- a/tests/page/page-wait-for-selector-2.spec.ts +++ b/tests/page/page-wait-for-selector-2.spec.ts @@ -328,3 +328,31 @@ it('should fail when navigating while on handle', async ({ page, mode, server }) const error = await body.waitForSelector('div', { __testHookBeforeAdoptNode } as any).catch(e => e); expect(error.message).toContain(`waiting for locator('div') to be visible`); }); + +it('should fail if element handle was detached while waiting', async ({ page, server }) => { + await page.setContent(`<button>hello</button>`); + const button = await page.$('button'); + const promise = button.waitForSelector('something').catch(e => e); + await page.waitForTimeout(100); + await page.evaluate(() => document.body.innerText = ''); + const error = await promise; + expect(error.message).toContain('Element is not attached to the DOM'); +}); + +it('should succeed if element handle was detached while waiting for hidden', async ({ page, server }) => { + await page.setContent(`<button>hello</button>`); + const button = await page.$('button'); + const promise = button.waitForSelector('something', { state: 'hidden' }); + await page.waitForTimeout(100); + await page.evaluate(() => document.body.innerText = ''); + await promise; +}); + +it('should succeed if element handle was detached while waiting for detached', async ({ page, server }) => { + await page.setContent(`<button>hello</button>`); + const button = await page.$('button'); + const promise = button.waitForSelector('something', { state: 'detached' }); + await page.waitForTimeout(100); + await page.evaluate(() => document.body.innerText = ''); + await promise; +}); diff --git a/tests/page/selectors-frame.spec.ts b/tests/page/selectors-frame.spec.ts index c32a00e8e987d..fda55e995880c 100644 --- a/tests/page/selectors-frame.spec.ts +++ b/tests/page/selectors-frame.spec.ts @@ -308,17 +308,6 @@ it('click should survive navigation', async ({ page, server }) => { await promise; }); -it('should fail if element removed while waiting on element handle', async ({ page, server }) => { - it.fixme(); - await routeIframe(page); - await page.goto(server.PREFIX + '/iframe.html'); - const button = await page.$('button'); - const promise = button.waitForSelector('something'); - await page.waitForTimeout(100); - await page.evaluate(() => document.body.innerText = ''); - await promise; -}); - it('should non work for non-frame', async ({ page, server }) => { await routeIframe(page); await page.setContent('<div></div>'); From b284df984bd2fe831174b7953842cd252dcbc100 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Fri, 4 Oct 2024 09:23:11 -0700 Subject: [PATCH 257/805] test: enable test after chromium roll to 1140 (#32965) Fixes #32355. Fixed after the last roll #32949. --- tests/page/interception.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/page/interception.spec.ts b/tests/page/interception.spec.ts index e50b5fdb086ca..f12d2d179bf28 100644 --- a/tests/page/interception.spec.ts +++ b/tests/page/interception.spec.ts @@ -125,7 +125,6 @@ it('should intercept worker requests when enabled after worker creation', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32355' } }, async ({ page, server, isAndroid, browserName }) => { it.skip(isAndroid); - it.fixme(browserName === 'chromium'); await page.goto(server.EMPTY_PAGE); server.setRoute('/data_for_worker', (req, res) => res.end('failed to intercept')); From ddeabdf770146d83bac72f15a4e956aa9aa24af3 Mon Sep 17 00:00:00 2001 From: Max Schmitt <max@schmitt.mx> Date: Fri, 4 Oct 2024 18:47:35 +0200 Subject: [PATCH 258/805] devops: speculative fix for flakiness dashboard data loss (#32963) --- utils/flakiness-dashboard/host.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/flakiness-dashboard/host.json b/utils/flakiness-dashboard/host.json index 6432c26df3bf2..851a54849c091 100644 --- a/utils/flakiness-dashboard/host.json +++ b/utils/flakiness-dashboard/host.json @@ -12,6 +12,9 @@ "queues": { "batchSize": 1, "newBatchThreshold": 0 + }, + "blobs": { + "maxDegreeOfParallelism": 1 } }, "extensionBundle": { From de4a4d1ce15dd4c4c0ab3a43cc8775e10e3f514b Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Mon, 7 Oct 2024 09:59:13 +0200 Subject: [PATCH 259/805] fix(har timing): record `connect` timing for proxied connections (#32855) Fixes a bug discovered in https://github.com/microsoft/playwright/pull/32647. When using http proxy, the `connect` event isn't emitted so we don't populate `tcpConnectionAt`. The updated version of `https-proxy-agent` emits a `proxyConnect` as a replacement, so this PR updates and listens to that event. For socks proxies, the `on("socket")` event is emitted once the SOCKS connection is established, which is the equivalent of having a TCP connection available. --------- Signed-off-by: Simon Knott <info@simonknott.de> Co-authored-by: Max Schmitt <max@schmitt.mx> --- .../playwright-core/ThirdPartyNotices.txt | 392 +----------------- .../bundles/utils/package-lock.json | 69 +-- .../bundles/utils/package.json | 4 +- packages/playwright-core/src/server/fetch.ts | 34 +- .../socksClientCertificatesInterceptor.ts | 2 +- packages/playwright-core/src/utils/network.ts | 2 +- tests/library/har.spec.ts | 23 +- 7 files changed, 94 insertions(+), 432 deletions(-) diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index 0a3ca6a5f4f79..a5d4ca7d0b7dc 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -6,7 +6,7 @@ This project incorporates components from the projects listed below. The origina - @types/node@17.0.24 (https://github.com/DefinitelyTyped/DefinitelyTyped) - @types/yauzl@2.10.0 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- agent-base@6.0.2 (https://github.com/TooTallNate/node-agent-base) +- agent-base@7.1.1 (https://github.com/TooTallNate/proxy-agents) - balanced-match@1.0.2 (https://github.com/juliangruber/balanced-match) - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) @@ -23,7 +23,7 @@ This project incorporates components from the projects listed below. The origina - fd-slicer@1.1.0 (https://github.com/andrewrk/node-fd-slicer) - get-stream@5.2.0 (https://github.com/sindresorhus/get-stream) - graceful-fs@4.2.10 (https://github.com/isaacs/node-graceful-fs) -- https-proxy-agent@5.0.0 (https://github.com/TooTallNate/node-https-proxy-agent) +- https-proxy-agent@7.0.5 (https://github.com/TooTallNate/proxy-agents) - ip-address@9.0.5 (https://github.com/beaugunderson/ip-address) - is-docker@2.2.1 (https://github.com/sindresorhus/is-docker) - is-wsl@2.2.0 (https://github.com/sindresorhus/is-wsl) @@ -42,7 +42,7 @@ This project incorporates components from the projects listed below. The origina - retry@0.12.0 (https://github.com/tim-kos/node-retry) - signal-exit@3.0.7 (https://github.com/tapjs/signal-exit) - smart-buffer@4.2.0 (https://github.com/JoshGlazebrook/smart-buffer) -- socks-proxy-agent@6.1.1 (https://github.com/TooTallNate/node-socks-proxy-agent) +- socks-proxy-agent@8.0.4 (https://github.com/TooTallNate/proxy-agents) - socks@2.8.3 (https://github.com/JoshGlazebrook/socks) - sprintf-js@1.1.3 (https://github.com/alexei/sprintf.js) - stack-utils@2.0.5 (https://github.com/tapjs/stack-utils) @@ -103,128 +103,11 @@ MIT License ========================================= END OF @types/yauzl@2.10.0 AND INFORMATION -%% agent-base@6.0.2 NOTICES AND INFORMATION BEGIN HERE +%% agent-base@7.1.1 NOTICES AND INFORMATION BEGIN HERE ========================================= -agent-base -========== -### Turn a function into an [`http.Agent`][http.Agent] instance -[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI) - -This module provides an `http.Agent` generator. That is, you pass it an async -callback function, and it returns a new `http.Agent` instance that will invoke the -given callback function when sending outbound HTTP requests. - -#### Some subclasses: - -Here's some more interesting uses of `agent-base`. -Send a pull request to list yours! - - * [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints - * [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints - * [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS - * [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS - - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install agent-base -``` - - -Example -------- - -Here's a minimal example that creates a new `net.Socket` connection to the server -for every HTTP request (i.e. the equivalent of `agent: false` option): - -```js -var net = require('net'); -var tls = require('tls'); -var url = require('url'); -var http = require('http'); -var agent = require('agent-base'); - -var endpoint = 'http://nodejs.org/api/'; -var parsed = url.parse(endpoint); - -// This is the important part! -parsed.agent = agent(function (req, opts) { - var socket; - // `secureEndpoint` is true when using the https module - if (opts.secureEndpoint) { - socket = tls.connect(opts); - } else { - socket = net.connect(opts); - } - return socket; -}); - -// Everything else works just like normal... -http.get(parsed, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -Returning a Promise or using an `async` function is also supported: - -```js -agent(async function (req, opts) { - await sleep(1000); - // etc… -}); -``` - -Return another `http.Agent` instance to "pass through" the responsibility -for that HTTP request to that agent: - -```js -agent(function (req, opts) { - return opts.secureEndpoint ? https.globalAgent : http.globalAgent; -}); -``` - - -API ---- - -## Agent(Function callback[, Object options]) → [http.Agent][] - -Creates a base `http.Agent` that will execute the callback function `callback` -for every HTTP request that it is used as the `agent` for. The callback function -is responsible for creating a `stream.Duplex` instance of some kind that will be -used as the underlying socket in the HTTP request. - -The `options` object accepts the following properties: - - * `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional). - -The callback function should have the following signature: - -### callback(http.ClientRequest req, Object options, Function cb) → undefined - -The ClientRequest `req` can be accessed to read request headers and -and the path, etc. The `options` object contains the options passed -to the `http.request()`/`https.request()` function call, and is formatted -to be directly passed to `net.connect()`/`tls.connect()`, or however -else you want a Socket to be created. Pass the created socket to -the callback function `cb` once created, and the HTTP request will -continue to proceed. - -If the `https` module is used to invoke the HTTP request, then the -`secureEndpoint` property on `options` _will be set to `true`_. - - -License -------- - (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -244,14 +127,8 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent -[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent -[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent -[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent -[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent ========================================= -END OF agent-base@6.0.2 AND INFORMATION +END OF agent-base@7.1.1 AND INFORMATION %% balanced-match@1.0.2 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -629,124 +506,11 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ========================================= END OF graceful-fs@4.2.10 AND INFORMATION -%% https-proxy-agent@5.0.0 NOTICES AND INFORMATION BEGIN HERE +%% https-proxy-agent@7.0.5 NOTICES AND INFORMATION BEGIN HERE ========================================= -https-proxy-agent -================ -### An HTTP(s) proxy `http.Agent` implementation for HTTPS -[![Build Status](https://github.com/TooTallNate/node-https-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-https-proxy-agent/actions?workflow=Node+CI) - -This module provides an `http.Agent` implementation that connects to a specified -HTTP or HTTPS proxy server, and can be used with the built-in `https` module. - -Specifically, this `Agent` implementation connects to an intermediary "proxy" -server and issues the [CONNECT HTTP method][CONNECT], which tells the proxy to -open a direct TCP connection to the destination server. - -Since this agent implements the CONNECT HTTP method, it also works with other -protocols that use this method when connecting over proxies (i.e. WebSockets). -See the "Examples" section below for more. - - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install https-proxy-agent -``` - - -Examples --------- - -#### `https` module example - -``` js -var url = require('url'); -var https = require('https'); -var HttpsProxyAgent = require('https-proxy-agent'); - -// HTTP/HTTPS proxy to connect to -var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; -console.log('using proxy server %j', proxy); - -// HTTPS endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'https://graph.facebook.com/tootallnate'; -console.log('attempting to GET %j', endpoint); -var options = url.parse(endpoint); - -// create an instance of the `HttpsProxyAgent` class with the proxy server information -var agent = new HttpsProxyAgent(proxy); -options.agent = agent; - -https.get(options, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -#### `ws` WebSocket connection example - -``` js -var url = require('url'); -var WebSocket = require('ws'); -var HttpsProxyAgent = require('https-proxy-agent'); - -// HTTP/HTTPS proxy to connect to -var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; -console.log('using proxy server %j', proxy); - -// WebSocket endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'ws://echo.websocket.org'; -var parsed = url.parse(endpoint); -console.log('attempting to connect to WebSocket %j', endpoint); - -// create an instance of the `HttpsProxyAgent` class with the proxy server information -var options = url.parse(proxy); - -var agent = new HttpsProxyAgent(options); - -// finally, initiate the WebSocket connection -var socket = new WebSocket(endpoint, { agent: agent }); - -socket.on('open', function () { - console.log('"open" event!'); - socket.send('hello world'); -}); - -socket.on('message', function (data, flags) { - console.log('"message" event! %j %j', data, flags); - socket.close(); -}); -``` - -API ---- - -### new HttpsProxyAgent(Object options) - -The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects -to the specified "HTTP(s) proxy server" in order to proxy HTTPS and/or WebSocket -requests. This is achieved by using the [HTTP `CONNECT` method][CONNECT]. - -The `options` argument may either be a string URI of the proxy server to use, or an -"options" object with more specific properties: - - * `host` - String - Proxy host to connect to (may use `hostname` as well). Required. - * `port` - Number - Proxy port to connect to. Required. - * `protocol` - String - If `https:`, then use TLS to connect to the proxy. - * `headers` - Object - Additional HTTP headers to be sent on the HTTP CONNECT method. - * Any other options given are passed to the `net.connect()`/`tls.connect()` functions. - - -License -------- - (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -766,10 +530,8 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[CONNECT]: http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling ========================================= -END OF https-proxy-agent@5.0.0 AND INFORMATION +END OF https-proxy-agent@7.0.5 AND INFORMATION %% ip-address@9.0.5 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -1207,141 +969,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF smart-buffer@4.2.0 AND INFORMATION -%% socks-proxy-agent@6.1.1 NOTICES AND INFORMATION BEGIN HERE +%% socks-proxy-agent@8.0.4 NOTICES AND INFORMATION BEGIN HERE ========================================= -socks-proxy-agent -================ -### A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS -[![Build Status](https://github.com/TooTallNate/node-socks-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-socks-proxy-agent/actions?workflow=Node+CI) - -This module provides an `http.Agent` implementation that connects to a -specified SOCKS proxy server, and can be used with the built-in `http` -and `https` modules. - -It can also be used in conjunction with the `ws` module to establish a WebSocket -connection over a SOCKS proxy. See the "Examples" section below. - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install socks-proxy-agent -``` - - -Examples --------- - -#### TypeScript example - -```ts -import https from 'https'; -import { SocksProxyAgent } from 'socks-proxy-agent'; - -const info = { - host: 'br41.nordvpn.com', - userId: 'your-name@gmail.com', - password: 'abcdef12345124' -}; -const agent = new SocksProxyAgent(info); - -https.get('https://jsonip.org', { agent }, (res) => { - console.log(res.headers); - res.pipe(process.stdout); -}); -``` - -#### `http` module example - -```js -var url = require('url'); -var http = require('http'); -var SocksProxyAgent = require('socks-proxy-agent'); - -// SOCKS proxy to connect to -var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; -console.log('using proxy server %j', proxy); - -// HTTP endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'http://nodejs.org/api/'; -console.log('attempting to GET %j', endpoint); -var opts = url.parse(endpoint); - -// create an instance of the `SocksProxyAgent` class with the proxy server information -var agent = new SocksProxyAgent(proxy); -opts.agent = agent; - -http.get(opts, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -#### `https` module example - -```js -var url = require('url'); -var https = require('https'); -var SocksProxyAgent = require('socks-proxy-agent'); - -// SOCKS proxy to connect to -var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; -console.log('using proxy server %j', proxy); - -// HTTP endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'https://encrypted.google.com/'; -console.log('attempting to GET %j', endpoint); -var opts = url.parse(endpoint); - -// create an instance of the `SocksProxyAgent` class with the proxy server information -var agent = new SocksProxyAgent(proxy); -opts.agent = agent; - -https.get(opts, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -#### `ws` WebSocket connection example - -``` js -var WebSocket = require('ws'); -var SocksProxyAgent = require('socks-proxy-agent'); - -// SOCKS proxy to connect to -var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; -console.log('using proxy server %j', proxy); - -// WebSocket endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'ws://echo.websocket.org'; -console.log('attempting to connect to WebSocket %j', endpoint); - -// create an instance of the `SocksProxyAgent` class with the proxy server information -var agent = new SocksProxyAgent(proxy); - -// initiate the WebSocket connection -var socket = new WebSocket(endpoint, { agent: agent }); - -socket.on('open', function () { - console.log('"open" event!'); - socket.send('hello world'); -}); - -socket.on('message', function (data, flags) { - console.log('"message" event! %j %j', data, flags); - socket.close(); -}); -``` - -License -------- - (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -1362,7 +994,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF socks-proxy-agent@6.1.1 AND INFORMATION +END OF socks-proxy-agent@8.0.4 AND INFORMATION %% socks@2.8.3 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index eef68ef8ee768..0e5e761433bf0 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -13,7 +13,7 @@ "debug": "^4.3.4", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", - "https-proxy-agent": "5.0.0", + "https-proxy-agent": "7.0.5", "jpeg-js": "0.4.4", "mime": "^3.0.0", "minimatch": "^3.1.2", @@ -23,7 +23,7 @@ "proxy-from-env": "1.1.0", "retry": "0.12.0", "signal-exit": "3.0.7", - "socks-proxy-agent": "6.1.1", + "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", "ws": "8.17.1" }, @@ -130,14 +130,15 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/balanced-match": { @@ -224,15 +225,16 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/ip-address": { @@ -382,16 +384,17 @@ } }, "node_modules/socks-proxy-agent": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", - "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, "node_modules/sprintf-js": { @@ -523,11 +526,11 @@ } }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "requires": { - "debug": "4" + "debug": "^4.3.4" } }, "balanced-match": { @@ -588,11 +591,11 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "requires": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" } }, @@ -696,13 +699,13 @@ } }, "socks-proxy-agent": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", - "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" } }, "sprintf-js": { diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index a7c66192e08fd..06637adabee9a 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -14,7 +14,7 @@ "debug": "^4.3.4", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", - "https-proxy-agent": "5.0.0", + "https-proxy-agent": "7.0.5", "jpeg-js": "0.4.4", "mime": "^3.0.0", "minimatch": "^3.1.2", @@ -24,7 +24,7 @@ "proxy-from-env": "1.1.0", "retry": "0.12.0", "signal-exit": "3.0.7", - "socks-proxy-agent": "6.1.1", + "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", "ws": "8.17.1" }, diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 4bf05e22af715..4408d91133280 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -20,7 +20,6 @@ import http from 'http'; import https from 'https'; import type { Readable, TransformCallback } from 'stream'; import { pipeline, Transform } from 'stream'; -import url from 'url'; import zlib from 'zlib'; import type { HTTPCredentials } from '../../types/types'; import { TimeoutSettings } from '../common/timeoutSettings'; @@ -489,11 +488,11 @@ export abstract class APIRequestContext extends SdkObject { // happy eyeballs don't emit lookup and connect events, so we use our custom ones const happyEyeBallsTimings = timingForSocket(socket); dnsLookupAt = happyEyeBallsTimings.dnsLookupAt; - tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt; + tcpConnectionAt ??= happyEyeBallsTimings.tcpConnectionAt; // non-happy-eyeballs sockets socket.on('lookup', () => { dnsLookupAt = monotonicTime(); }); - socket.on('connect', () => { tcpConnectionAt = monotonicTime(); }); + socket.on('connect', () => { tcpConnectionAt ??= monotonicTime(); }); socket.on('secureConnect', () => { tlsHandshakeAt = monotonicTime(); @@ -509,11 +508,21 @@ export abstract class APIRequestContext extends SdkObject { } }); + // when using socks proxy, having the socket means the connection got established + if (agent instanceof SocksProxyAgent) + tcpConnectionAt ??= monotonicTime(); + serverIPAddress = socket.remoteAddress; serverPort = socket.remotePort; }); request.on('finish', () => { requestFinishAt = monotonicTime(); }); + // http proxy + request.on('proxyConnect', () => { + tcpConnectionAt ??= monotonicTime(); + }); + + progress.log(`→ ${options.method} ${url.toString()}`); if (options.headers) { for (const [name, value] of Object.entries(options.headers)) @@ -680,17 +689,16 @@ export class GlobalAPIRequestContext extends APIRequestContext { } export function createProxyAgent(proxy: types.ProxySettings) { - const proxyOpts = url.parse(proxy.server); - if (proxyOpts.protocol?.startsWith('socks')) { - return new SocksProxyAgent({ - host: proxyOpts.hostname, - port: proxyOpts.port || undefined, - }); - } + const proxyURL = new URL(proxy.server); + if (proxyURL.protocol?.startsWith('socks')) + return new SocksProxyAgent(proxyURL); + if (proxy.username) - proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`; - // TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method. - return new HttpsProxyAgent(proxyOpts); + proxyURL.username = proxy.username; + if (proxy.password) + proxyURL.password = proxy.password; + // TODO: We should use HttpProxyAgent conditional on proxyURL.protocol instead of always using CONNECT method. + return new HttpsProxyAgent(proxyURL); } function toHeadersArray(rawHeaders: string[]): types.HeadersArray { diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index b041ffb8290e2..4e850f4a8415b 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -98,7 +98,7 @@ class SocksProxyConnection { async connect() { if (this.socksProxy.proxyAgentFromOptions) - this.target = await this.socksProxy.proxyAgentFromOptions.callback(new EventEmitter() as any, { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); + this.target = await this.socksProxy.proxyAgentFromOptions.connect(new EventEmitter() as any, { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); else this.target = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port); diff --git a/packages/playwright-core/src/utils/network.ts b/packages/playwright-core/src/utils/network.ts index f04b828d6749a..632c74fe3a19d 100644 --- a/packages/playwright-core/src/utils/network.ts +++ b/packages/playwright-core/src/utils/network.ts @@ -50,7 +50,7 @@ export function httpRequest(params: HTTPRequestParams, onResponse: (r: http.Inco const proxyURL = getProxyForUrl(params.url); if (proxyURL) { - const parsedProxyURL = url.parse(proxyURL); + const parsedProxyURL = new URL(proxyURL); if (params.url.startsWith('http:')) { options = { path: parsedUrl.href, diff --git a/tests/library/har.spec.ts b/tests/library/har.spec.ts index bbd4dcc49b4ad..3a103478259c1 100644 --- a/tests/library/har.spec.ts +++ b/tests/library/har.spec.ts @@ -24,9 +24,9 @@ import type { Log } from '../../packages/trace/src/har'; import { parseHar } from '../config/utils'; const { createHttp2Server } = require('../../packages/playwright-core/lib/utils'); -async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>, testInfo: any, options: { outputPath?: string } & Partial<Pick<BrowserContextOptions['recordHar'], 'content' | 'omitContent' | 'mode'>> = {}) { +async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>, testInfo: any, options: { outputPath?: string, proxy?: BrowserContextOptions['proxy'] } & Partial<Pick<BrowserContextOptions['recordHar'], 'content' | 'omitContent' | 'mode'>> = {}) { const harPath = testInfo.outputPath(options.outputPath || 'test.har'); - const context = await contextFactory({ recordHar: { path: harPath, ...options }, ignoreHTTPSErrors: true }); + const context = await contextFactory({ recordHar: { path: harPath, ...options }, ignoreHTTPSErrors: true, proxy: options.proxy }); const page = await context.newPage(); return { page, @@ -858,6 +858,25 @@ it('should respect minimal mode for API Requests', async ({ contextFactory, serv expect(entry.response.bodySize).toBe(-1); }); +it('should include timings when using http proxy', async ({ contextFactory, server, proxyServer }, testInfo) => { + proxyServer.forwardTo(server.PORT, { allowConnectRequests: true }); + const { page, getLog } = await pageWithHar(contextFactory, testInfo, { proxy: { server: `localhost:${proxyServer.PORT}` } }); + const response = await page.request.get(server.EMPTY_PAGE); + await response.body(); + await expect(response).toBeOK(); + const log = await getLog(); + expect(log.entries[0].timings.connect).toBeGreaterThan(0); +}); + +it('should include timings when using socks proxy', async ({ contextFactory, server, socksPort }, testInfo) => { + const { page, getLog } = await pageWithHar(contextFactory, testInfo, { proxy: { server: `socks5://localhost:${socksPort}` } }); + const response = await page.request.get(server.EMPTY_PAGE); + await response.body(); + await expect(response).toBeOK(); + const log = await getLog(); + expect(log.entries[0].timings.connect).toBeGreaterThan(0); +}); + it('should include redirects from API request', async ({ contextFactory, server }, testInfo) => { server.setRedirect('/redirect-me', '/simple.json'); const { page, getLog } = await pageWithHar(contextFactory, testInfo); From 317ddd4117e5ff30db938e6cdecf26300c6bf38c Mon Sep 17 00:00:00 2001 From: Bruno <brunojairbarros@hotmail.com> Date: Mon, 7 Oct 2024 05:48:30 -0300 Subject: [PATCH 260/805] docs(best practices): tabs with yarn and pnpm commands added (#32980) --- docs/src/best-practices-js.md | 244 +++++++++++++++++++++++++++++++++- 1 file changed, 243 insertions(+), 1 deletion(-) diff --git a/docs/src/best-practices-js.md b/docs/src/best-practices-js.md index 3b70817923ad5..0c4e71d3a5e85 100644 --- a/docs/src/best-practices-js.md +++ b/docs/src/best-practices-js.md @@ -112,10 +112,40 @@ Playwright has a [test generator](./codegen.md) that can generate tests and pick To pick a locator run the `codegen` command followed by the URL that you would like to pick a locator from. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright codegen playwright.dev ``` +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright codegen playwright.dev +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright codegen playwright.dev +``` + +</TabItem> + +</Tabs> + This will open a new browser window as well as the Playwright inspector. To pick a locator first click on the 'Record' button to stop the recording. By default when you run the `codegen` command it will start a new recording. Once you stop the recording the 'Pick Locator' button will be available to click. You can then hover over any element on your page in the browser window and see the locator highlighted below your cursor. Clicking on an element will add the locator into the Playwright inspector. You can either copy the locator and paste into your test file or continue to explore the locator by editing it in the Playwright Inspector, for example by modifying the text, and seeing the results in the browser window. @@ -170,10 +200,40 @@ You can live debug your test by clicking or editing the locators in your test in You can also debug your tests with the Playwright inspector by running your tests with the `--debug` flag. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright test --debug ``` +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright test --debug +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright test --debug +``` + +</TabItem> + +</Tabs> + You can then step through your test, view actionability logs and edit the locator live and see it highlighted in the browser window. This will show you which locators match, how many of them there are. <img width="1350" alt="debugging with the playwright inspector" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212276296-4f5b18e7-2bd7-4766-9aa5-783517bd4aa2.png" /> @@ -182,9 +242,39 @@ You can then step through your test, view actionability logs and edit the locato To debug a specific test add the name of the test file and the line number of the test followed by the `--debug` flag. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright test example.spec.ts:9 --debug ``` + +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright test example.spec.ts:9 --debug +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright test example.spec.ts:9 --debug +``` + +</TabItem> + +</Tabs> #### Debugging on CI For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of videos and screenshots. The trace viewer gives you a full trace of your tests as a local Progressive Web App (PWA) that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action using dev tools, view network requests and more. @@ -193,14 +283,75 @@ For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of Traces are configured in the Playwright config file and are set to run on CI on the first retry of a failed test. We don't recommend setting this to `on` so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the `--trace` flag. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright test --trace on ``` + +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright test --trace on +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright test --trace on +``` + +</TabItem> + +</Tabs> + Once you run this command your traces will be recorded for each test and can be viewed directly from the HTML report. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright show-report -```` +``` + +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright show-report +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright show-report +``` + +</TabItem> + +</Tabs> <img width="1516" alt="Playwrights HTML report" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212279022-d929d4c0-2271-486a-a75f-166ac231d25f.png" /> @@ -246,17 +397,78 @@ export default defineConfig({ By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npm install -D @playwright/test@latest ``` + +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn add --dev @playwright/test@latest +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm install --save-dev @playwright/test@latest +``` + +</TabItem> + +</Tabs> + Check the [release notes](./release-notes.md) to see what the latest version is and what changes have been released. You can see what version of Playwright you have by running the following command. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright --version ``` +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright --version +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright --version +``` + +</TabItem> + +</Tabs> + ### Run tests on CI Setup CI/CD and run your tests frequently. The more often you run your tests the better. Ideally you should run your tests on each commit and pull request. Playwright comes with a [GitHub actions workflow](/ci-intro.md) so that tests will run on CI for you with no setup required. Playwright can also be setup on the [CI environment](/ci.md) of your choice. @@ -282,10 +494,40 @@ test('runs in parallel 2', async ({ page }) => { /* ... */ }); Playwright can [shard](./test-parallel.md#shard-tests-between-multiple-machines) a test suite, so that it can be executed on multiple machines. +<Tabs + defaultValue="npm" + values={[ + {label: 'npm', value: 'npm'}, + {label: 'yarn', value: 'yarn'}, + {label: 'pnpm', value: 'pnpm'} + ] +}> +<TabItem value="npm"> + ```bash npx playwright test --shard=1/3 ``` +</TabItem> + +<TabItem value="yarn"> + +```bash +yarn playwright test --shard=1/3 +``` + +</TabItem> + +<TabItem value="pnpm"> + +```bash +pnpm exec playwright test --shard=1/3 +``` + +</TabItem> + +</Tabs> + ## Productivity tips ### Use Soft assertions From 001ba3770641d460691801ac2460e62f80518aad Mon Sep 17 00:00:00 2001 From: Max Schmitt <max@schmitt.mx> Date: Mon, 7 Oct 2024 11:08:07 +0200 Subject: [PATCH 261/805] test: update webview2 skipme's (#32984) This leaves only reasonable skipmes for WebView2 in the code base. --- tests/page/locator-misc-2.spec.ts | 4 ++-- tests/page/page-accessibility.spec.ts | 6 ++---- tests/page/page-click-scroll.spec.ts | 3 +-- tests/page/page-screenshot.spec.ts | 3 +-- tests/webview2/webview2-app/webview2.csproj | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/tests/page/locator-misc-2.spec.ts b/tests/page/locator-misc-2.spec.ts index b474d4ff2e46c..4eaf5972a074b 100644 --- a/tests/page/locator-misc-2.spec.ts +++ b/tests/page/locator-misc-2.spec.ts @@ -42,8 +42,8 @@ it('should scroll into view', async ({ page, server, isAndroid }) => { } }); -it('should scroll zero-sized element into view', async ({ page, isAndroid, isElectron, isWebView2, browserName, isMac, macVersion }) => { - it.fixme(isAndroid || isElectron || isWebView2); +it('should scroll zero-sized element into view', async ({ page, isAndroid, isElectron, browserName, isMac, macVersion }) => { + it.fixme(isAndroid || isElectron); it.skip(browserName === 'webkit' && isMac && macVersion < 11, 'WebKit for macOS 10.15 is frozen.'); await page.setContent(` diff --git a/tests/page/page-accessibility.spec.ts b/tests/page/page-accessibility.spec.ts index 63a267ec94593..c6619b7f9cbb0 100644 --- a/tests/page/page-accessibility.spec.ts +++ b/tests/page/page-accessibility.spec.ts @@ -143,9 +143,8 @@ it('should not report text nodes inside controls', async function({ page, browse expect(await page.accessibility.snapshot()).toEqual(golden); }); -it('rich text editable fields should have children', async function({ page, browserName, browserVersion, isWebView2 }) { +it('rich text editable fields should have children', async function({ page, browserName, browserVersion }) { it.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); - it.skip(isWebView2, 'WebView2 is missing a Chromium fix'); await page.setContent(` <div contenteditable="true"> @@ -177,9 +176,8 @@ it('rich text editable fields should have children', async function({ page, brow expect(snapshot.children[0]).toEqual(golden); }); -it('rich text editable fields with role should have children', async function({ page, browserName, browserVersion, isWebView2 }) { +it('rich text editable fields with role should have children', async function({ page, browserName, browserVersion }) { it.skip(browserName === 'webkit', 'WebKit rich text accessibility is iffy'); - it.skip(isWebView2, 'WebView2 is missing a Chromium fix'); await page.setContent(` <div contenteditable="true" role='textbox'> diff --git a/tests/page/page-click-scroll.spec.ts b/tests/page/page-click-scroll.spec.ts index 758a8d0eb95e3..d3e55cdffbc42 100644 --- a/tests/page/page-click-scroll.spec.ts +++ b/tests/page/page-click-scroll.spec.ts @@ -78,9 +78,8 @@ it('should scroll into view display:contents with position', async ({ page, brow expect(await page.evaluate('window._clicked')).toBe(true); }); -it('should not crash when force-clicking hidden input', async ({ page, isWebView2 }) => { +it('should not crash when force-clicking hidden input', async ({ page }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/18183' }); - it.fixme(isWebView2); await page.setContent(`<input type=hidden>`); const error = await page.locator('input').click({ force: true, timeout: 2000 }).catch(e => e); diff --git a/tests/page/page-screenshot.spec.ts b/tests/page/page-screenshot.spec.ts index c441641b4db18..07e53e4a711f6 100644 --- a/tests/page/page-screenshot.spec.ts +++ b/tests/page/page-screenshot.spec.ts @@ -291,10 +291,9 @@ it.describe('page screenshot', () => { expect(screenshot).toMatchSnapshot('screenshot-canvas.png'); }); - it('should capture canvas changes', async ({ page, isElectron, browserName, isMac, isWebView2 }) => { + it('should capture canvas changes', async ({ page, isElectron, browserName, isMac }) => { it.fixme(browserName === 'webkit' && isMac, 'https://github.com/microsoft/playwright/issues/8796,https://github.com/microsoft/playwright/issues/16180'); it.skip(isElectron); - it.skip(isWebView2); await page.goto('data:text/html,<canvas></canvas>'); await page.evaluate(() => { const canvas = document.querySelector('canvas'); diff --git a/tests/webview2/webview2-app/webview2.csproj b/tests/webview2/webview2-app/webview2.csproj index 84849567c4c66..4636d47030164 100644 --- a/tests/webview2/webview2-app/webview2.csproj +++ b/tests/webview2/webview2-app/webview2.csproj @@ -9,7 +9,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2210.55" /> + <PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2792.45" /> </ItemGroup> </Project> \ No newline at end of file From e6afb650befcbe19ac051e1f151ea9deb4e943f2 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Mon, 7 Oct 2024 02:58:03 -0700 Subject: [PATCH 262/805] test: mark a few tests as fixme (#32985) --- tests/config/utils.ts | 2 +- tests/library/browsercontext-viewport.spec.ts | 4 +++- tests/library/page-clock.spec.ts | 1 + tests/page/expect-misc.spec.ts | 2 ++ tests/page/frame-goto.spec.ts | 3 ++- tests/page/interception.spec.ts | 3 ++- tests/page/locator-misc-1.spec.ts | 4 +++- tests/page/page-click.spec.ts | 4 +++- tests/page/page-request-fulfill.spec.ts | 4 +++- 9 files changed, 20 insertions(+), 7 deletions(-) diff --git a/tests/config/utils.ts b/tests/config/utils.ts index 74158aeeae6ae..3743e97d80797 100644 --- a/tests/config/utils.ts +++ b/tests/config/utils.ts @@ -61,7 +61,7 @@ export function expectedSSLError(browserName: string, platform: string): RegExp else if (platform === 'win32') return /SSL peer certificate or SSH remote key was not OK/; else - return /Unacceptable TLS certificate/; + return /Unacceptable TLS certificate|Operation was cancelled/; } return /SSL_ERROR_UNKNOWN/; } diff --git a/tests/library/browsercontext-viewport.spec.ts b/tests/library/browsercontext-viewport.spec.ts index 4fdd181f8fb26..356e3300798e9 100644 --- a/tests/library/browsercontext-viewport.spec.ts +++ b/tests/library/browsercontext-viewport.spec.ts @@ -139,7 +139,9 @@ browserTest('should report null viewportSize when given null viewport', async ({ await context.close(); }); -browserTest('should drag with high dpi', async ({ browser, server }) => { +browserTest('should drag with high dpi', async ({ browser, server, headless }) => { + browserTest.fixme(!headless, 'Flaky on all browser in headed'); + const page = await browser.newPage({ deviceScaleFactor: 2 }); await page.goto(server.PREFIX + '/drag-n-drop.html'); await page.hover('#source'); diff --git a/tests/library/page-clock.spec.ts b/tests/library/page-clock.spec.ts index d541d5d135631..a660e5e8a4de4 100644 --- a/tests/library/page-clock.spec.ts +++ b/tests/library/page-clock.spec.ts @@ -354,6 +354,7 @@ it.describe('popup', () => { page.waitForEvent('popup'), page.evaluate(url => window.open(url), server.PREFIX + '/popup.html'), ]); + await popup.waitForLoadState(); const popupTime = await popup.evaluate('time'); expect(popupTime).toBe(1000); }); diff --git a/tests/page/expect-misc.spec.ts b/tests/page/expect-misc.spec.ts index 7bf038231c201..2242a5537822c 100644 --- a/tests/page/expect-misc.spec.ts +++ b/tests/page/expect-misc.spec.ts @@ -349,6 +349,8 @@ test.describe('toBeInViewport', () => { }); test('should respect ratio option', async ({ page, isAndroid }) => { + test.fixme(isAndroid, 'ratio 0.24 is not in viewport for unknown reason'); + await page.setContent(` <style>body, div, html { padding: 0; margin: 0; }</style> <div id=big style="height: 400vh;"></div> diff --git a/tests/page/frame-goto.spec.ts b/tests/page/frame-goto.spec.ts index 56146572f2c1f..6603282bb323f 100644 --- a/tests/page/frame-goto.spec.ts +++ b/tests/page/frame-goto.spec.ts @@ -43,8 +43,9 @@ it('should reject when frame detaches', async ({ page, server, browserName }) => expect(error.message.toLowerCase()).toContain('frame was detached'); }); -it('should continue after client redirect', async ({ page, server, isAndroid, mode }) => { +it('should continue after client redirect', async ({ page, server, isAndroid, browserName }) => { it.fixme(isAndroid); + it.fixme(browserName === 'firefox', 'script.js is requested before navigationCommitted arrives'); server.setRoute('/frames/script.js', () => {}); const url = server.PREFIX + '/frames/child-redirect.html'; diff --git a/tests/page/interception.spec.ts b/tests/page/interception.spec.ts index f12d2d179bf28..9447a80fcd1ef 100644 --- a/tests/page/interception.spec.ts +++ b/tests/page/interception.spec.ts @@ -123,8 +123,9 @@ it('should intercept network activity from worker', async function({ page, serve it('should intercept worker requests when enabled after worker creation', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32355' } -}, async ({ page, server, isAndroid, browserName }) => { +}, async ({ page, server, isAndroid, browserName, browserMajorVersion }) => { it.skip(isAndroid); + it.skip(browserName === 'chromium' && browserMajorVersion < 130, 'fixed in Chromium 130'); await page.goto(server.EMPTY_PAGE); server.setRoute('/data_for_worker', (req, res) => res.end('failed to intercept')); diff --git a/tests/page/locator-misc-1.spec.ts b/tests/page/locator-misc-1.spec.ts index 01745368981a6..616beb3e7fd89 100644 --- a/tests/page/locator-misc-1.spec.ts +++ b/tests/page/locator-misc-1.spec.ts @@ -25,7 +25,9 @@ it('should hover @smoke', async ({ page, server }) => { expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); }); -it('should hover when Node is removed', async ({ page, server }) => { +it('should hover when Node is removed', async ({ page, server, headless }) => { + it.skip(!headless, 'headed messes up with hover'); + await page.goto(server.PREFIX + '/input/scrollable.html'); await page.evaluate(() => delete window['Node']); const button = page.locator('#button-6'); diff --git a/tests/page/page-click.spec.ts b/tests/page/page-click.spec.ts index c2b024fec11a0..fccef2ed0e7d4 100644 --- a/tests/page/page-click.spec.ts +++ b/tests/page/page-click.spec.ts @@ -94,7 +94,9 @@ it('should not throw UnhandledPromiseRejection when page closes', async ({ page, ]).catch(e => {}); }); -it('should click the 1x1 div', async ({ page }) => { +it('should click the 1x1 div', async ({ page, browserName, isWindows }) => { + it.fixme(browserName === 'firefox' && isWindows, 'always times out'); + await page.setContent(`<div style="width: 1px; height: 1px;" onclick="window.__clicked = true"></div>`); await page.click('div'); expect(await page.evaluate('window.__clicked')).toBe(true); diff --git a/tests/page/page-request-fulfill.spec.ts b/tests/page/page-request-fulfill.spec.ts index 8170cb73d596a..3edcd0ba0a97e 100644 --- a/tests/page/page-request-fulfill.spec.ts +++ b/tests/page/page-request-fulfill.spec.ts @@ -309,8 +309,10 @@ it('should fetch original request and fulfill', async ({ page, server, isElectro expect(await page.title()).toEqual('Woof-Woof'); }); -it('should fulfill with multiple set-cookie', async ({ page, server, isElectron, electronMajorVersion }) => { +it('should fulfill with multiple set-cookie', async ({ page, server, isElectron, electronMajorVersion, isAndroid }) => { it.skip(isElectron && electronMajorVersion < 14, 'Electron 14+ is required'); + it.skip(isAndroid, 'Android does not have an isolated context per test, so we get cookies from other tests'); + const cookies = ['a=b', 'c=d']; await page.route('**/multiple-set-cookie.html', async route => { void route.fulfill({ From d3fbf1aaeb73ea1c8da448d6f7cb3d318f99c2ed Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Mon, 7 Oct 2024 12:12:12 +0200 Subject: [PATCH 263/805] fix(clock): amend setSystemTime docs (#32901) As discussed yesterday over https://github.com/microsoft/playwright/issues/32807. Adds some words to differentiate `setSystemTime` from `setFixedTime`. --------- Signed-off-by: Simon Knott <info@simonknott.de> Co-authored-by: Dmitry Gozman <dgozman@gmail.com> --- docs/src/api/class-clock.md | 4 +++- packages/playwright-core/types/types.d.ts | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/src/api/class-clock.md b/docs/src/api/class-clock.md index f2ee2433b4b34..38ca329769257 100644 --- a/docs/src/api/class-clock.md +++ b/docs/src/api/class-clock.md @@ -193,6 +193,8 @@ Resumes timers. Once this method is called, time resumes flowing, timers are fir Makes `Date.now` and `new Date()` return fixed fake time at all times, keeps all the timers running. +Use this method for simple scenarios where you only need to test with a predefined time. For more advanced scenarios, use [`method: Clock.install`] instead. Read docs on [clock emulation](../clock.md) to learn more. + **Usage** ```js @@ -249,7 +251,7 @@ Time to be set. ## async method: Clock.setSystemTime * since: v1.45 -Sets current system time but does not trigger any timers. +Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for example switching from summer to winter time, or changing time zones. **Usage** diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 0ecdf93904050..fe182dac4e839 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -18544,6 +18544,10 @@ export interface Clock { /** * Makes `Date.now` and `new Date()` return fixed fake time at all times, keeps all the timers running. * + * Use this method for simple scenarios where you only need to test with a predefined time. For more advanced + * scenarios, use [clock.install([options])](https://playwright.dev/docs/api/class-clock#clock-install) instead. Read + * docs on [clock emulation](https://playwright.dev/docs/clock) to learn more. + * * **Usage** * * ```js @@ -18557,7 +18561,8 @@ export interface Clock { setFixedTime(time: number|string|Date): Promise<void>; /** - * Sets current system time but does not trigger any timers. + * Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for + * example switching from summer to winter time, or changing time zones. * * **Usage** * From 9a6f03eb87f985735c766bcefa6f8927bdd85f8c Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Mon, 7 Oct 2024 18:43:25 +0200 Subject: [PATCH 264/805] fix(fetch): listener leaks on Socket (#32956) Closes https://github.com/microsoft/playwright/issues/32951 `node:http` reuses TCP Sockets under the hood. We weren't cleaning up our listeners, leading to the `MaxListenersExceededWarning`. This PR adds cleanup logic. It also raises the warning threshhold, so that it doesn't trigger until there's 100 concurrent requests over the same socket. --- packages/playwright-core/src/server/fetch.ts | 52 +++++++++++--------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 4408d91133280..243e89cf1c9f4 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -24,7 +24,7 @@ import zlib from 'zlib'; import type { HTTPCredentials } from '../../types/types'; import { TimeoutSettings } from '../common/timeoutSettings'; import { getUserAgent } from '../utils/userAgent'; -import { assert, constructURLBasedOnBaseURL, createGuid, monotonicTime } from '../utils'; +import { assert, constructURLBasedOnBaseURL, createGuid, eventsHelper, monotonicTime, type RegisteredListener } from '../utils'; import { HttpsProxyAgent, SocksProxyAgent } from '../utilsBundle'; import { BrowserContext, verifyClientCertificates } from './browserContext'; import { CookieStore, domainMatches, parseRawCookie } from './cookieStore'; @@ -311,8 +311,11 @@ export abstract class APIRequestContext extends SdkObject { let securityDetails: har.SecurityDetails | undefined; + const listeners: RegisteredListener[] = []; + const request = requestConstructor(url, requestOptions as any, async response => { const responseAt = monotonicTime(); + const notifyRequestFinished = (body?: Buffer) => { const endAt = monotonicTime(); // spec: http://www.softwareishard.com/blog/har-12-spec/#timings @@ -477,12 +480,13 @@ export abstract class APIRequestContext extends SdkObject { }); request.on('error', reject); - const disposeListener = () => { - reject(new Error('Request context disposed.')); - request.destroy(); - }; - this.on(APIRequestContext.Events.Dispose, disposeListener); - request.on('close', () => this.off(APIRequestContext.Events.Dispose, disposeListener)); + listeners.push( + eventsHelper.addEventListener(this, APIRequestContext.Events.Dispose, () => { + reject(new Error('Request context disposed.')); + request.destroy(); + }) + ); + request.on('close', () => eventsHelper.removeEventListeners(listeners)); request.on('socket', socket => { // happy eyeballs don't emit lookup and connect events, so we use our custom ones @@ -491,22 +495,24 @@ export abstract class APIRequestContext extends SdkObject { tcpConnectionAt ??= happyEyeBallsTimings.tcpConnectionAt; // non-happy-eyeballs sockets - socket.on('lookup', () => { dnsLookupAt = monotonicTime(); }); - socket.on('connect', () => { tcpConnectionAt ??= monotonicTime(); }); - socket.on('secureConnect', () => { - tlsHandshakeAt = monotonicTime(); - - if (socket instanceof TLSSocket) { - const peerCertificate = socket.getPeerCertificate(); - securityDetails = { - protocol: socket.getProtocol() ?? undefined, - subjectName: peerCertificate.subject.CN, - validFrom: new Date(peerCertificate.valid_from).getTime() / 1000, - validTo: new Date(peerCertificate.valid_to).getTime() / 1000, - issuer: peerCertificate.issuer.CN - }; - } - }); + listeners.push( + eventsHelper.addEventListener(socket, 'lookup', () => { dnsLookupAt = monotonicTime(); }), + eventsHelper.addEventListener(socket, 'connect', () => { tcpConnectionAt ??= monotonicTime(); }), + eventsHelper.addEventListener(socket, 'secureConnect', () => { + tlsHandshakeAt = monotonicTime(); + + if (socket instanceof TLSSocket) { + const peerCertificate = socket.getPeerCertificate(); + securityDetails = { + protocol: socket.getProtocol() ?? undefined, + subjectName: peerCertificate.subject.CN, + validFrom: new Date(peerCertificate.valid_from).getTime() / 1000, + validTo: new Date(peerCertificate.valid_to).getTime() / 1000, + issuer: peerCertificate.issuer.CN + }; + } + }), + ); // when using socks proxy, having the socket means the connection got established if (agent instanceof SocksProxyAgent) From 4fe33db392b075ee302ddb6309b8fd3be5aad2e7 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky <yurys@chromium.org> Date: Mon, 7 Oct 2024 13:52:55 -0700 Subject: [PATCH 265/805] docs(route): header override propagation (#32971) Fix https://github.com/microsoft/playwright/issues/32939 --- docs/src/api/class-route.md | 2 +- packages/playwright-core/types/types.d.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/src/api/class-route.md b/docs/src/api/class-route.md index 106fbf55e0c5c..c4e5fcb2e4c46 100644 --- a/docs/src/api/class-route.md +++ b/docs/src/api/class-route.md @@ -102,7 +102,7 @@ await page.RouteAsync("**/*", async route => **Details** -Note that any overrides such as [`option: url`] or [`option: headers`] only apply to the request being routed. If this request results in a redirect, overrides will not be applied to the new redirected request. If you want to propagate a header through redirects, use the combination of [`method: Route.fetch`] and [`method: Route.fulfill`] instead. +The [`option: headers`] option applies to both the routed request and any redirects it initiates. However, [`option: url`], [`option: method`], and [`option: postData`] only apply to the original request and are not carried over to redirected requests. [`method: Route.continue`] will immediately send the request to the network, other matching handlers won't be invoked. Use [`method: Route.fallback`] If you want next matching handler in the chain to be invoked. diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index fe182dac4e839..abf92c0141aa6 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -20614,12 +20614,12 @@ export interface Route { * * **Details** * - * Note that any overrides such as [`url`](https://playwright.dev/docs/api/class-route#route-continue-option-url) or - * [`headers`](https://playwright.dev/docs/api/class-route#route-continue-option-headers) only apply to the request - * being routed. If this request results in a redirect, overrides will not be applied to the new redirected request. - * If you want to propagate a header through redirects, use the combination of - * [route.fetch([options])](https://playwright.dev/docs/api/class-route#route-fetch) and - * [route.fulfill([options])](https://playwright.dev/docs/api/class-route#route-fulfill) instead. + * The [`headers`](https://playwright.dev/docs/api/class-route#route-continue-option-headers) option applies to both + * the routed request and any redirects it initiates. However, + * [`url`](https://playwright.dev/docs/api/class-route#route-continue-option-url), + * [`method`](https://playwright.dev/docs/api/class-route#route-continue-option-method), and + * [`postData`](https://playwright.dev/docs/api/class-route#route-continue-option-post-data) only apply to the + * original request and are not carried over to redirected requests. * * [route.continue([options])](https://playwright.dev/docs/api/class-route#route-continue) will immediately send the * request to the network, other matching handlers won't be invoked. Use From 4ab857ce8e055c2adcc07f62c453816853f71451 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky <yurys@chromium.org> Date: Mon, 7 Oct 2024 14:06:28 -0700 Subject: [PATCH 266/805] test: fetch header propagation on redirect (#32970) Documenting current behavior with and without interception. Reference https://github.com/microsoft/playwright/issues/32939 --- tests/page/page-request-continue.spec.ts | 191 +++++++++++++++++++++++ 1 file changed, 191 insertions(+) diff --git a/tests/page/page-request-continue.spec.ts b/tests/page/page-request-continue.spec.ts index 7487b3e35b16e..2df84e133aa05 100644 --- a/tests/page/page-request-continue.spec.ts +++ b/tests/page/page-request-continue.spec.ts @@ -17,6 +17,7 @@ import { test as it, expect } from './pageTest'; import type { Route } from 'playwright-core'; +import type * as http from 'http'; it('should work', async ({ page, server }) => { await page.route('**/*', route => route.continue()); @@ -473,6 +474,196 @@ it('continue should delete headers on redirects', { expect(serverRequest.headers.foo).toBeFalsy(); }); +it('propagate headers same origin redirect', { + annotation: [ + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' }, + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' }, + ] +}, async ({ page, server }) => { + await page.goto(server.PREFIX + '/empty.html'); + let resolve; + const serverRequestPromise = new Promise<http.IncomingMessage>(f => resolve = f); + server.setRoute('/something', (request, response) => { + if (request.method === 'OPTIONS') { + response.writeHead(204, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE', + 'Access-Control-Allow-Headers': 'authorization,custom', + }); + response.end(); + return; + } + resolve(request); + response.writeHead(200, { }); + response.end('done'); + }); + await server.setRedirect('/redirect', '/something'); + const text = await page.evaluate(async url => { + const data = await fetch(url, { + headers: { + authorization: 'credentials', + custom: 'foo' + }, + credentials: 'include', + }); + return data.text(); + }, server.PREFIX + '/redirect'); + expect(text).toBe('done'); + const serverRequest = await serverRequestPromise; + expect.soft(serverRequest.headers['authorization']).toBe('credentials'); + expect.soft(serverRequest.headers['custom']).toBe('foo'); +}); + +it('propagate headers cross origin', { + annotation: [ + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' }, + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' }, + ] +}, async ({ page, server }) => { + await page.goto(server.PREFIX + '/empty.html'); + let resolve; + const serverRequestPromise = new Promise<http.IncomingMessage>(f => resolve = f); + server.setRoute('/something', (request, response) => { + if (request.method === 'OPTIONS') { + response.writeHead(204, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE', + 'Access-Control-Allow-Headers': 'authorization,custom', + }); + response.end(); + return; + } + resolve(request); + response.writeHead(200, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + }); + response.end('done'); + }); + const text = await page.evaluate(async url => { + const data = await fetch(url, { + headers: { + authorization: 'credentials', + custom: 'foo' + }, + credentials: 'include', + }); + return data.text(); + }, server.CROSS_PROCESS_PREFIX + '/something'); + expect(text).toBe('done'); + const serverRequest = await serverRequestPromise; + expect.soft(serverRequest.headers['authorization']).toBe('credentials'); + expect.soft(serverRequest.headers['custom']).toBe('foo'); +}); + +it('propagate headers cross origin redirect', { + annotation: [ + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' }, + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' }, + ] +}, async ({ page, server }) => { + await page.goto(server.PREFIX + '/empty.html'); + let resolve; + const serverRequestPromise = new Promise<http.IncomingMessage>(f => resolve = f); + server.setRoute('/something', (request, response) => { + if (request.method === 'OPTIONS') { + response.writeHead(204, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE', + 'Access-Control-Allow-Headers': 'authorization,custom', + }); + response.end(); + return; + } + resolve(request); + response.writeHead(200, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + }); + response.end('done'); + }); + server.setRoute('/redirect', (request, response) => { + response.writeHead(301, { location: `${server.CROSS_PROCESS_PREFIX}/something` }); + response.end(); + }); + const text = await page.evaluate(async url => { + const data = await fetch(url, { + headers: { + authorization: 'credentials', + custom: 'foo' + }, + credentials: 'include', + }); + return data.text(); + }, server.PREFIX + '/redirect'); + expect(text).toBe('done'); + const serverRequest = await serverRequestPromise; + // Authorization header not propagated to cross-origin redirect. + expect.soft(serverRequest.headers['authorization']).toBeFalsy(); + expect.soft(serverRequest.headers['custom']).toBe('foo'); +}); + +it('propagate headers cross origin redirect after interception', { + annotation: [ + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' }, + { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' }, + ] +}, async ({ page, server, browserName }) => { + await page.goto(server.PREFIX + '/empty.html'); + let resolve; + const serverRequestPromise = new Promise<http.IncomingMessage>(f => resolve = f); + server.setRoute('/something', (request, response) => { + if (request.method === 'OPTIONS') { + response.writeHead(204, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, DELETE', + 'Access-Control-Allow-Headers': 'authorization,custom', + }); + response.end(); + return; + } + resolve(request); + response.writeHead(200, { + 'Access-Control-Allow-Origin': server.PREFIX, + 'Access-Control-Allow-Credentials': 'true', + }); + response.end('done'); + }); + server.setRoute('/redirect', (request, response) => { + response.writeHead(301, { location: `${server.CROSS_PROCESS_PREFIX}/something` }); + response.end(); + }); + await page.route('**/redirect', async route => { + await route.continue({ + headers: { + ...route.request().headers(), + authorization: 'credentials', + custom: 'foo' + } + }); + }); + const text = await page.evaluate(async url => { + const data = await fetch(url, { + headers: { + authorization: 'none', + }, + credentials: 'include', + }); + return data.text(); + }, server.PREFIX + '/redirect'); + expect(text).toBe('done'); + const serverRequest = await serverRequestPromise; + if (browserName === 'webkit') + expect.soft(serverRequest.headers['authorization']).toBeFalsy(); + else + expect.soft(serverRequest.headers['authorization']).toBe('credentials'); + expect.soft(serverRequest.headers['custom']).toBe('foo'); +}); + it('should intercept css variable with background url', async ({ page, server }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/19158' }); From 4d13677ebd92d9358f691fe149595e6d86803cb1 Mon Sep 17 00:00:00 2001 From: Aaron Sherwood <69980784+asherwoodcnet@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:24:18 -0700 Subject: [PATCH 267/805] chore: add Devuan OS fallback to Debian (#32990) --- packages/playwright-core/src/utils/hostPlatform.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/playwright-core/src/utils/hostPlatform.ts b/packages/playwright-core/src/utils/hostPlatform.ts index 9664418e3d885..8c20d65cce3f6 100644 --- a/packages/playwright-core/src/utils/hostPlatform.ts +++ b/packages/playwright-core/src/utils/hostPlatform.ts @@ -86,15 +86,20 @@ function calculatePlatform(): { hostPlatform: HostPlatform, isOfficiallySupporte return { hostPlatform: ('ubuntu22.04' + archSuffix) as HostPlatform, isOfficiallySupportedPlatform: false }; return { hostPlatform: ('ubuntu24.04' + archSuffix) as HostPlatform, isOfficiallySupportedPlatform: false }; } - if (distroInfo?.id === 'debian' || distroInfo?.id === 'raspbian') { + if (distroInfo?.id === 'debian' || distroInfo?.id === 'raspbian' || distroInfo?.id === 'devuan') { const isOfficiallySupportedPlatform = distroInfo?.id === 'debian'; - if (distroInfo?.version === '11') + let debianVersion = distroInfo?.version; + if (distroInfo.id === 'devuan') { + // Devuan is debian-based but it's always 7 versions behind + debianVersion = String(parseInt(distroInfo.version, 10) + 7); + } + if (debianVersion === '11') return { hostPlatform: ('debian11' + archSuffix) as HostPlatform, isOfficiallySupportedPlatform }; - if (distroInfo?.version === '12') + if (debianVersion === '12') return { hostPlatform: ('debian12' + archSuffix) as HostPlatform, isOfficiallySupportedPlatform }; // use most recent supported release for 'debian testing' and 'unstable'. // they never include a numeric version entry in /etc/os-release. - if (distroInfo?.version === '') + if (debianVersion === '') return { hostPlatform: ('debian12' + archSuffix) as HostPlatform, isOfficiallySupportedPlatform }; } return { hostPlatform: ('ubuntu20.04' + archSuffix) as HostPlatform, isOfficiallySupportedPlatform: false }; From 6ba5ee3a834a0ba18f5596650bc03d30d94dc468 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky <yurys@chromium.org> Date: Mon, 7 Oct 2024 15:42:12 -0700 Subject: [PATCH 268/805] chore(ui-mode): expand all button (#32994) <img width="230" alt="image" src="https://github.com/user-attachments/assets/dd7fa3a1-39ec-4b88-9279-d664c9c4e5cd"> Reference https://github.com/microsoft/playwright/issues/32825 --- .../src/ui/uiModeTestListView.tsx | 16 ++++++++++-- packages/trace-viewer/src/ui/uiModeView.tsx | 5 ++++ .../playwright-test/ui-mode-test-tree.spec.ts | 26 +++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/packages/trace-viewer/src/ui/uiModeTestListView.tsx b/packages/trace-viewer/src/ui/uiModeTestListView.tsx index 99a5f22dfa8b4..ce1c0fef373d9 100644 --- a/packages/trace-viewer/src/ui/uiModeTestListView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTestListView.tsx @@ -47,12 +47,14 @@ export const TestListView: React.FC<{ isLoading?: boolean, onItemSelected: (item: { treeItem?: TreeItem, testCase?: reporterTypes.TestCase, testFile?: SourceLocation }) => void, requestedCollapseAllCount: number, + requestedExpandAllCount: number, setFilterText: (text: string) => void, onRevealSource: () => void, -}> = ({ filterText, testModel, testServerConnection, testTree, runTests, runningState, watchAll, watchedTreeIds, setWatchedTreeIds, isLoading, onItemSelected, requestedCollapseAllCount, setFilterText, onRevealSource }) => { +}> = ({ filterText, testModel, testServerConnection, testTree, runTests, runningState, watchAll, watchedTreeIds, setWatchedTreeIds, isLoading, onItemSelected, requestedCollapseAllCount, requestedExpandAllCount, setFilterText, onRevealSource }) => { const [treeState, setTreeState] = React.useState<TreeState>({ expandedItems: new Map() }); const [selectedTreeItemId, setSelectedTreeItemId] = React.useState<string | undefined>(); const [collapseAllCount, setCollapseAllCount] = React.useState(requestedCollapseAllCount); + const [expandAllCount, setExpandAllCount] = React.useState(requestedExpandAllCount); // Look for a first failure within the run batch to select it. React.useEffect(() => { @@ -67,6 +69,16 @@ export const TestListView: React.FC<{ return; } + if (expandAllCount !== requestedExpandAllCount) { + treeState.expandedItems.clear(); + for (const item of testTree.flatTreeItems()) + treeState.expandedItems.set(item.id, true); + setExpandAllCount(requestedExpandAllCount); + setSelectedTreeItemId(undefined); + setTreeState({ ...treeState }); + return; + } + if (!runningState || runningState.itemSelectedByUser) return; let selectedTreeItem: TreeItem | undefined; @@ -85,7 +97,7 @@ export const TestListView: React.FC<{ if (selectedTreeItem) setSelectedTreeItemId(selectedTreeItem.id); - }, [runningState, setSelectedTreeItemId, testTree, collapseAllCount, setCollapseAllCount, requestedCollapseAllCount, treeState, setTreeState]); + }, [runningState, setSelectedTreeItemId, testTree, collapseAllCount, setCollapseAllCount, requestedCollapseAllCount, expandAllCount, setExpandAllCount, requestedExpandAllCount, treeState, setTreeState]); // Compute selected item. const { selectedTreeItem } = React.useMemo(() => { diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index a5f1af7d993ad..69a598864145f 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -90,6 +90,7 @@ export const UIModeView: React.FC<{}> = ({ const commandQueue = React.useRef(Promise.resolve()); const runTestBacklog = React.useRef<Set<string>>(new Set()); const [collapseAllCount, setCollapseAllCount] = React.useState(0); + const [expandAllCount, setExpandAllCount] = React.useState(0); const [isDisconnected, setIsDisconnected] = React.useState(false); const [hasBrowsers, setHasBrowsers] = React.useState(true); const [testServerConnection, setTestServerConnection] = React.useState<TestServerConnection>(); @@ -473,6 +474,9 @@ export const UIModeView: React.FC<{}> = ({ <ToolbarButton icon='collapse-all' title='Collapse all' onClick={() => { setCollapseAllCount(collapseAllCount + 1); }} /> + <ToolbarButton icon='expand-all' title='Expand all' onClick={() => { + setExpandAllCount(expandAllCount + 1); + }} /> </Toolbar> <TestListView filterText={filterText} @@ -487,6 +491,7 @@ export const UIModeView: React.FC<{}> = ({ setWatchedTreeIds={setWatchedTreeIds} isLoading={isLoading} requestedCollapseAllCount={collapseAllCount} + requestedExpandAllCount={expandAllCount} setFilterText={setFilterText} onRevealSource={onRevealSource} /> diff --git a/tests/playwright-test/ui-mode-test-tree.spec.ts b/tests/playwright-test/ui-mode-test-tree.spec.ts index 7346c204e4ce2..2c19ea0a873c7 100644 --- a/tests/playwright-test/ui-mode-test-tree.spec.ts +++ b/tests/playwright-test/ui-mode-test-tree.spec.ts @@ -297,6 +297,32 @@ test('should collapse all', async ({ runUITest }) => { `); }); +test('should expand all', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32825' } +}, async ({ runUITest }) => { + const { page } = await runUITest(basicTestTree); + + await page.getByTestId('test-tree').getByText('suite').click(); + await page.getByTitle('Collapse all').click(); + await expect.poll(dumpTestTree(page)).toContain(` + ► ◯ a.test.ts + ► ◯ b.test.ts + `); + + await page.getByTitle('Expand all').click(); + await expect.poll(dumpTestTree(page)).toContain(` + ▼ ◯ a.test.ts + ◯ passes + ◯ fails + ▼ ◯ suite + ◯ inner passes + ◯ inner fails + ▼ ◯ b.test.ts + ◯ passes + ◯ fails + `); +}); + test('should resolve title conflicts', async ({ runUITest }) => { const { page } = await runUITest({ 'a.test.ts': ` From 7047c3a6c6fdd5738a979ad32f0995ff70196b15 Mon Sep 17 00:00:00 2001 From: Pavel Feldman <pavel.feldman@gmail.com> Date: Mon, 7 Oct 2024 17:12:36 -0700 Subject: [PATCH 269/805] fix(codegen): do not codegen non-existing fixtures (#32993) Closes https://github.com/microsoft/playwright/issues/32981 --- .../playwright-core/src/server/codegen/javascript.ts | 10 +++++++--- tests/library/inspector/cli-codegen-test.spec.ts | 10 ++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/playwright-core/src/server/codegen/javascript.ts b/packages/playwright-core/src/server/codegen/javascript.ts index 17f627b601e22..558670cd47842 100644 --- a/packages/playwright-core/src/server/codegen/javascript.ts +++ b/packages/playwright-core/src/server/codegen/javascript.ts @@ -138,7 +138,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { generateTestHeader(options: LanguageGeneratorOptions): string { const formatter = new JavaScriptFormatter(); - const useText = formatContextOptions(options.contextOptions, options.deviceName); + const useText = formatContextOptions(options.contextOptions, options.deviceName, this._isTest); formatter.add(` import { test, expect${options.deviceName ? ', devices' : ''} } from '@playwright/test'; ${useText ? '\ntest.use(' + useText + ');\n' : ''} @@ -157,7 +157,7 @@ ${useText ? '\ntest.use(' + useText + ');\n' : ''} (async () => { const browser = await ${options.browserName}.launch(${formatObjectOrVoid(options.launchOptions)}); - const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName)});`); + const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName, false)});`); return formatter.format(); } @@ -199,8 +199,12 @@ function formatObjectOrVoid(value: any, indent = ' '): string { return result === '{}' ? '' : result; } -function formatContextOptions(options: BrowserContextOptions, deviceName: string | undefined): string { +function formatContextOptions(options: BrowserContextOptions, deviceName: string | undefined, isTest: boolean): string { const device = deviceName && deviceDescriptors[deviceName]; + if (isTest) { + // No recordHAR fixture in test. + options = { ...options, recordHar: undefined }; + } if (!device) return formatObjectOrVoid(options); // Filter out all the properties from the device descriptor. diff --git a/tests/library/inspector/cli-codegen-test.spec.ts b/tests/library/inspector/cli-codegen-test.spec.ts index a5d5cb6fcec9f..18eba826349f5 100644 --- a/tests/library/inspector/cli-codegen-test.spec.ts +++ b/tests/library/inspector/cli-codegen-test.spec.ts @@ -85,13 +85,11 @@ test('test', async ({ page }) => {`; await cli.waitFor(expectedResult); }); -test('should work with --save-har', async ({ runCLI }, testInfo) => { +test('should not generate recordHAR with --save-har', async ({ runCLI }, testInfo) => { const harFileName = testInfo.outputPath('har.har'); - const expectedResult = ` - recordHar: { - mode: 'minimal', - path: '${harFileName.replace(/\\/g, '\\\\')}' - }`; + const expectedResult = `test.use({ + serviceWorkers: 'block' +});`; const cli = runCLI(['--target=playwright-test', `--save-har=${harFileName}`], { autoExitWhen: expectedResult, }); From 04bf425268fb442f8861c4b897bdeb1f8f62c9fc Mon Sep 17 00:00:00 2001 From: Mark <1031496+mrkstwrt@users.noreply.github.com> Date: Tue, 8 Oct 2024 01:14:46 +0100 Subject: [PATCH 270/805] feat(base-reporter): Add tags to test output (#32930) --- packages/playwright/src/reporters/base.ts | 3 ++- tests/playwright-test/reporter-base.spec.ts | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 6776ce606f358..4249429a364c8 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -410,7 +410,8 @@ export function formatTestTitle(config: FullConfig, test: TestCase, step?: TestS else location = `${relativeTestPath(config, test)}:${step?.location?.line ?? test.location.line}:${step?.location?.column ?? test.location.column}`; const projectTitle = projectName ? `[${projectName}] › ` : ''; - return `${projectTitle}${location} › ${titles.join(' › ')}${stepSuffix(step)}`; + const tags = test.tags.length > 0 ? ` ${test.tags.join(' ')}` : ''; + return `${projectTitle}${location} › ${titles.join(' › ')}${stepSuffix(step)}${tags}`; } function formatTestHeader(config: FullConfig, test: TestCase, options: { indent?: string, index?: number, mode?: 'default' | 'error' } = {}): string { diff --git a/tests/playwright-test/reporter-base.spec.ts b/tests/playwright-test/reporter-base.spec.ts index 6d6e499605399..85ba731bf56b2 100644 --- a/tests/playwright-test/reporter-base.spec.ts +++ b/tests/playwright-test/reporter-base.spec.ts @@ -418,5 +418,19 @@ for (const useIntermediateMergeReport of [false, true] as const) { expect(result.passed).toBe(1); expect(result.output).toMatch(/\d+ passed \(\d+(\.\d)?(ms|s)\)/); }); + + test('should output tags', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.ts': ` + const { test, expect } = require('@playwright/test'); + test('passes', { tag: ['@foo', '@bar'] }, async ({}) => { + expect(0).toBe(0); + }); + `, + }); + const text = result.output; + + expect(text).toContain('passes @foo @bar'); + }); }); -} \ No newline at end of file +} From 1b589c4bd323e1392221ff5ebbc206a7ea10834b Mon Sep 17 00:00:00 2001 From: Simon Knott <info@simonknott.de> Date: Tue, 8 Oct 2024 10:13:21 +0200 Subject: [PATCH 271/805] Revert "fix(har timing): record `connect` timing for proxied connections" (#32989) Reverts microsoft/playwright#32855. This broke two tests on main, and we don't yet know how to fix it other than downgrading. --- .../playwright-core/ThirdPartyNotices.txt | 392 +++++++++++++++++- .../bundles/utils/package-lock.json | 69 ++- .../bundles/utils/package.json | 4 +- packages/playwright-core/src/server/fetch.ts | 34 +- .../socksClientCertificatesInterceptor.ts | 2 +- packages/playwright-core/src/utils/network.ts | 2 +- tests/library/har.spec.ts | 23 +- 7 files changed, 432 insertions(+), 94 deletions(-) diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index a5d4ca7d0b7dc..0a3ca6a5f4f79 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -6,7 +6,7 @@ This project incorporates components from the projects listed below. The origina - @types/node@17.0.24 (https://github.com/DefinitelyTyped/DefinitelyTyped) - @types/yauzl@2.10.0 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- agent-base@7.1.1 (https://github.com/TooTallNate/proxy-agents) +- agent-base@6.0.2 (https://github.com/TooTallNate/node-agent-base) - balanced-match@1.0.2 (https://github.com/juliangruber/balanced-match) - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) @@ -23,7 +23,7 @@ This project incorporates components from the projects listed below. The origina - fd-slicer@1.1.0 (https://github.com/andrewrk/node-fd-slicer) - get-stream@5.2.0 (https://github.com/sindresorhus/get-stream) - graceful-fs@4.2.10 (https://github.com/isaacs/node-graceful-fs) -- https-proxy-agent@7.0.5 (https://github.com/TooTallNate/proxy-agents) +- https-proxy-agent@5.0.0 (https://github.com/TooTallNate/node-https-proxy-agent) - ip-address@9.0.5 (https://github.com/beaugunderson/ip-address) - is-docker@2.2.1 (https://github.com/sindresorhus/is-docker) - is-wsl@2.2.0 (https://github.com/sindresorhus/is-wsl) @@ -42,7 +42,7 @@ This project incorporates components from the projects listed below. The origina - retry@0.12.0 (https://github.com/tim-kos/node-retry) - signal-exit@3.0.7 (https://github.com/tapjs/signal-exit) - smart-buffer@4.2.0 (https://github.com/JoshGlazebrook/smart-buffer) -- socks-proxy-agent@8.0.4 (https://github.com/TooTallNate/proxy-agents) +- socks-proxy-agent@6.1.1 (https://github.com/TooTallNate/node-socks-proxy-agent) - socks@2.8.3 (https://github.com/JoshGlazebrook/socks) - sprintf-js@1.1.3 (https://github.com/alexei/sprintf.js) - stack-utils@2.0.5 (https://github.com/tapjs/stack-utils) @@ -103,11 +103,128 @@ MIT License ========================================= END OF @types/yauzl@2.10.0 AND INFORMATION -%% agent-base@7.1.1 NOTICES AND INFORMATION BEGIN HERE +%% agent-base@6.0.2 NOTICES AND INFORMATION BEGIN HERE ========================================= +agent-base +========== +### Turn a function into an [`http.Agent`][http.Agent] instance +[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI) + +This module provides an `http.Agent` generator. That is, you pass it an async +callback function, and it returns a new `http.Agent` instance that will invoke the +given callback function when sending outbound HTTP requests. + +#### Some subclasses: + +Here's some more interesting uses of `agent-base`. +Send a pull request to list yours! + + * [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints + * [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints + * [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS + * [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install agent-base +``` + + +Example +------- + +Here's a minimal example that creates a new `net.Socket` connection to the server +for every HTTP request (i.e. the equivalent of `agent: false` option): + +```js +var net = require('net'); +var tls = require('tls'); +var url = require('url'); +var http = require('http'); +var agent = require('agent-base'); + +var endpoint = 'http://nodejs.org/api/'; +var parsed = url.parse(endpoint); + +// This is the important part! +parsed.agent = agent(function (req, opts) { + var socket; + // `secureEndpoint` is true when using the https module + if (opts.secureEndpoint) { + socket = tls.connect(opts); + } else { + socket = net.connect(opts); + } + return socket; +}); + +// Everything else works just like normal... +http.get(parsed, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +Returning a Promise or using an `async` function is also supported: + +```js +agent(async function (req, opts) { + await sleep(1000); + // etc… +}); +``` + +Return another `http.Agent` instance to "pass through" the responsibility +for that HTTP request to that agent: + +```js +agent(function (req, opts) { + return opts.secureEndpoint ? https.globalAgent : http.globalAgent; +}); +``` + + +API +--- + +## Agent(Function callback[, Object options]) → [http.Agent][] + +Creates a base `http.Agent` that will execute the callback function `callback` +for every HTTP request that it is used as the `agent` for. The callback function +is responsible for creating a `stream.Duplex` instance of some kind that will be +used as the underlying socket in the HTTP request. + +The `options` object accepts the following properties: + + * `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional). + +The callback function should have the following signature: + +### callback(http.ClientRequest req, Object options, Function cb) → undefined + +The ClientRequest `req` can be accessed to read request headers and +and the path, etc. The `options` object contains the options passed +to the `http.request()`/`https.request()` function call, and is formatted +to be directly passed to `net.connect()`/`tls.connect()`, or however +else you want a Socket to be created. Pass the created socket to +the callback function `cb` once created, and the HTTP request will +continue to proceed. + +If the `https` module is used to invoke the HTTP request, then the +`secureEndpoint` property on `options` _will be set to `true`_. + + +License +------- + (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -127,8 +244,14 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent +[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent +[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent +[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent +[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent ========================================= -END OF agent-base@7.1.1 AND INFORMATION +END OF agent-base@6.0.2 AND INFORMATION %% balanced-match@1.0.2 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -506,11 +629,124 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ========================================= END OF graceful-fs@4.2.10 AND INFORMATION -%% https-proxy-agent@7.0.5 NOTICES AND INFORMATION BEGIN HERE +%% https-proxy-agent@5.0.0 NOTICES AND INFORMATION BEGIN HERE ========================================= +https-proxy-agent +================ +### An HTTP(s) proxy `http.Agent` implementation for HTTPS +[![Build Status](https://github.com/TooTallNate/node-https-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-https-proxy-agent/actions?workflow=Node+CI) + +This module provides an `http.Agent` implementation that connects to a specified +HTTP or HTTPS proxy server, and can be used with the built-in `https` module. + +Specifically, this `Agent` implementation connects to an intermediary "proxy" +server and issues the [CONNECT HTTP method][CONNECT], which tells the proxy to +open a direct TCP connection to the destination server. + +Since this agent implements the CONNECT HTTP method, it also works with other +protocols that use this method when connecting over proxies (i.e. WebSockets). +See the "Examples" section below for more. + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install https-proxy-agent +``` + + +Examples +-------- + +#### `https` module example + +``` js +var url = require('url'); +var https = require('https'); +var HttpsProxyAgent = require('https-proxy-agent'); + +// HTTP/HTTPS proxy to connect to +var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; +console.log('using proxy server %j', proxy); + +// HTTPS endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'https://graph.facebook.com/tootallnate'; +console.log('attempting to GET %j', endpoint); +var options = url.parse(endpoint); + +// create an instance of the `HttpsProxyAgent` class with the proxy server information +var agent = new HttpsProxyAgent(proxy); +options.agent = agent; + +https.get(options, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +#### `ws` WebSocket connection example + +``` js +var url = require('url'); +var WebSocket = require('ws'); +var HttpsProxyAgent = require('https-proxy-agent'); + +// HTTP/HTTPS proxy to connect to +var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; +console.log('using proxy server %j', proxy); + +// WebSocket endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'ws://echo.websocket.org'; +var parsed = url.parse(endpoint); +console.log('attempting to connect to WebSocket %j', endpoint); + +// create an instance of the `HttpsProxyAgent` class with the proxy server information +var options = url.parse(proxy); + +var agent = new HttpsProxyAgent(options); + +// finally, initiate the WebSocket connection +var socket = new WebSocket(endpoint, { agent: agent }); + +socket.on('open', function () { + console.log('"open" event!'); + socket.send('hello world'); +}); + +socket.on('message', function (data, flags) { + console.log('"message" event! %j %j', data, flags); + socket.close(); +}); +``` + +API +--- + +### new HttpsProxyAgent(Object options) + +The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects +to the specified "HTTP(s) proxy server" in order to proxy HTTPS and/or WebSocket +requests. This is achieved by using the [HTTP `CONNECT` method][CONNECT]. + +The `options` argument may either be a string URI of the proxy server to use, or an +"options" object with more specific properties: + + * `host` - String - Proxy host to connect to (may use `hostname` as well). Required. + * `port` - Number - Proxy port to connect to. Required. + * `protocol` - String - If `https:`, then use TLS to connect to the proxy. + * `headers` - Object - Additional HTTP headers to be sent on the HTTP CONNECT method. + * Any other options given are passed to the `net.connect()`/`tls.connect()` functions. + + +License +------- + (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -530,8 +766,10 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +[CONNECT]: http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling ========================================= -END OF https-proxy-agent@7.0.5 AND INFORMATION +END OF https-proxy-agent@5.0.0 AND INFORMATION %% ip-address@9.0.5 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -969,11 +1207,141 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF smart-buffer@4.2.0 AND INFORMATION -%% socks-proxy-agent@8.0.4 NOTICES AND INFORMATION BEGIN HERE +%% socks-proxy-agent@6.1.1 NOTICES AND INFORMATION BEGIN HERE ========================================= +socks-proxy-agent +================ +### A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS +[![Build Status](https://github.com/TooTallNate/node-socks-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-socks-proxy-agent/actions?workflow=Node+CI) + +This module provides an `http.Agent` implementation that connects to a +specified SOCKS proxy server, and can be used with the built-in `http` +and `https` modules. + +It can also be used in conjunction with the `ws` module to establish a WebSocket +connection over a SOCKS proxy. See the "Examples" section below. + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install socks-proxy-agent +``` + + +Examples +-------- + +#### TypeScript example + +```ts +import https from 'https'; +import { SocksProxyAgent } from 'socks-proxy-agent'; + +const info = { + host: 'br41.nordvpn.com', + userId: 'your-name@gmail.com', + password: 'abcdef12345124' +}; +const agent = new SocksProxyAgent(info); + +https.get('https://jsonip.org', { agent }, (res) => { + console.log(res.headers); + res.pipe(process.stdout); +}); +``` + +#### `http` module example + +```js +var url = require('url'); +var http = require('http'); +var SocksProxyAgent = require('socks-proxy-agent'); + +// SOCKS proxy to connect to +var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; +console.log('using proxy server %j', proxy); + +// HTTP endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'http://nodejs.org/api/'; +console.log('attempting to GET %j', endpoint); +var opts = url.parse(endpoint); + +// create an instance of the `SocksProxyAgent` class with the proxy server information +var agent = new SocksProxyAgent(proxy); +opts.agent = agent; + +http.get(opts, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +#### `https` module example + +```js +var url = require('url'); +var https = require('https'); +var SocksProxyAgent = require('socks-proxy-agent'); + +// SOCKS proxy to connect to +var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; +console.log('using proxy server %j', proxy); + +// HTTP endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'https://encrypted.google.com/'; +console.log('attempting to GET %j', endpoint); +var opts = url.parse(endpoint); + +// create an instance of the `SocksProxyAgent` class with the proxy server information +var agent = new SocksProxyAgent(proxy); +opts.agent = agent; + +https.get(opts, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +#### `ws` WebSocket connection example + +``` js +var WebSocket = require('ws'); +var SocksProxyAgent = require('socks-proxy-agent'); + +// SOCKS proxy to connect to +var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; +console.log('using proxy server %j', proxy); + +// WebSocket endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'ws://echo.websocket.org'; +console.log('attempting to connect to WebSocket %j', endpoint); + +// create an instance of the `SocksProxyAgent` class with the proxy server information +var agent = new SocksProxyAgent(proxy); + +// initiate the WebSocket connection +var socket = new WebSocket(endpoint, { agent: agent }); + +socket.on('open', function () { + console.log('"open" event!'); + socket.send('hello world'); +}); + +socket.on('message', function (data, flags) { + console.log('"message" event! %j %j', data, flags); + socket.close(); +}); +``` + +License +------- + (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -994,7 +1362,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF socks-proxy-agent@8.0.4 AND INFORMATION +END OF socks-proxy-agent@6.1.1 AND INFORMATION %% socks@2.8.3 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index 0e5e761433bf0..eef68ef8ee768 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -13,7 +13,7 @@ "debug": "^4.3.4", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", - "https-proxy-agent": "7.0.5", + "https-proxy-agent": "5.0.0", "jpeg-js": "0.4.4", "mime": "^3.0.0", "minimatch": "^3.1.2", @@ -23,7 +23,7 @@ "proxy-from-env": "1.1.0", "retry": "0.12.0", "signal-exit": "3.0.7", - "socks-proxy-agent": "8.0.4", + "socks-proxy-agent": "6.1.1", "stack-utils": "2.0.5", "ws": "8.17.1" }, @@ -130,15 +130,14 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "license": "MIT", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dependencies": { - "debug": "^4.3.4" + "debug": "4" }, "engines": { - "node": ">= 14" + "node": ">= 6.0.0" } }, "node_modules/balanced-match": { @@ -225,16 +224,15 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "license": "MIT", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "6", "debug": "4" }, "engines": { - "node": ">= 14" + "node": ">= 6" } }, "node_modules/ip-address": { @@ -384,17 +382,16 @@ } }, "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "license": "MIT", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" }, "engines": { - "node": ">= 14" + "node": ">= 10" } }, "node_modules/sprintf-js": { @@ -526,11 +523,11 @@ } }, "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "requires": { - "debug": "^4.3.4" + "debug": "4" } }, "balanced-match": { @@ -591,11 +588,11 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "requires": { - "agent-base": "^7.0.2", + "agent-base": "6", "debug": "4" } }, @@ -699,13 +696,13 @@ } }, "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" } }, "sprintf-js": { diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index 06637adabee9a..a7c66192e08fd 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -14,7 +14,7 @@ "debug": "^4.3.4", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", - "https-proxy-agent": "7.0.5", + "https-proxy-agent": "5.0.0", "jpeg-js": "0.4.4", "mime": "^3.0.0", "minimatch": "^3.1.2", @@ -24,7 +24,7 @@ "proxy-from-env": "1.1.0", "retry": "0.12.0", "signal-exit": "3.0.7", - "socks-proxy-agent": "8.0.4", + "socks-proxy-agent": "6.1.1", "stack-utils": "2.0.5", "ws": "8.17.1" }, diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 243e89cf1c9f4..12f1d21d93988 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -20,6 +20,7 @@ import http from 'http'; import https from 'https'; import type { Readable, TransformCallback } from 'stream'; import { pipeline, Transform } from 'stream'; +import url from 'url'; import zlib from 'zlib'; import type { HTTPCredentials } from '../../types/types'; import { TimeoutSettings } from '../common/timeoutSettings'; @@ -492,12 +493,12 @@ export abstract class APIRequestContext extends SdkObject { // happy eyeballs don't emit lookup and connect events, so we use our custom ones const happyEyeBallsTimings = timingForSocket(socket); dnsLookupAt = happyEyeBallsTimings.dnsLookupAt; - tcpConnectionAt ??= happyEyeBallsTimings.tcpConnectionAt; + tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt; // non-happy-eyeballs sockets listeners.push( eventsHelper.addEventListener(socket, 'lookup', () => { dnsLookupAt = monotonicTime(); }), - eventsHelper.addEventListener(socket, 'connect', () => { tcpConnectionAt ??= monotonicTime(); }), + eventsHelper.addEventListener(socket, 'connect', () => { tcpConnectionAt = monotonicTime(); }), eventsHelper.addEventListener(socket, 'secureConnect', () => { tlsHandshakeAt = monotonicTime(); @@ -514,21 +515,11 @@ export abstract class APIRequestContext extends SdkObject { }), ); - // when using socks proxy, having the socket means the connection got established - if (agent instanceof SocksProxyAgent) - tcpConnectionAt ??= monotonicTime(); - serverIPAddress = socket.remoteAddress; serverPort = socket.remotePort; }); request.on('finish', () => { requestFinishAt = monotonicTime(); }); - // http proxy - request.on('proxyConnect', () => { - tcpConnectionAt ??= monotonicTime(); - }); - - progress.log(`→ ${options.method} ${url.toString()}`); if (options.headers) { for (const [name, value] of Object.entries(options.headers)) @@ -695,16 +686,17 @@ export class GlobalAPIRequestContext extends APIRequestContext { } export function createProxyAgent(proxy: types.ProxySettings) { - const proxyURL = new URL(proxy.server); - if (proxyURL.protocol?.startsWith('socks')) - return new SocksProxyAgent(proxyURL); - + const proxyOpts = url.parse(proxy.server); + if (proxyOpts.protocol?.startsWith('socks')) { + return new SocksProxyAgent({ + host: proxyOpts.hostname, + port: proxyOpts.port || undefined, + }); + } if (proxy.username) - proxyURL.username = proxy.username; - if (proxy.password) - proxyURL.password = proxy.password; - // TODO: We should use HttpProxyAgent conditional on proxyURL.protocol instead of always using CONNECT method. - return new HttpsProxyAgent(proxyURL); + proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`; + // TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method. + return new HttpsProxyAgent(proxyOpts); } function toHeadersArray(rawHeaders: string[]): types.HeadersArray { diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index 4e850f4a8415b..b041ffb8290e2 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -98,7 +98,7 @@ class SocksProxyConnection { async connect() { if (this.socksProxy.proxyAgentFromOptions) - this.target = await this.socksProxy.proxyAgentFromOptions.connect(new EventEmitter() as any, { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); + this.target = await this.socksProxy.proxyAgentFromOptions.callback(new EventEmitter() as any, { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); else this.target = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port); diff --git a/packages/playwright-core/src/utils/network.ts b/packages/playwright-core/src/utils/network.ts index 632c74fe3a19d..f04b828d6749a 100644 --- a/packages/playwright-core/src/utils/network.ts +++ b/packages/playwright-core/src/utils/network.ts @@ -50,7 +50,7 @@ export function httpRequest(params: HTTPRequestParams, onResponse: (r: http.Inco const proxyURL = getProxyForUrl(params.url); if (proxyURL) { - const parsedProxyURL = new URL(proxyURL); + const parsedProxyURL = url.parse(proxyURL); if (params.url.startsWith('http:')) { options = { path: parsedUrl.href, diff --git a/tests/library/har.spec.ts b/tests/library/har.spec.ts index 3a103478259c1..bbd4dcc49b4ad 100644 --- a/tests/library/har.spec.ts +++ b/tests/library/har.spec.ts @@ -24,9 +24,9 @@ import type { Log } from '../../packages/trace/src/har'; import { parseHar } from '../config/utils'; const { createHttp2Server } = require('../../packages/playwright-core/lib/utils'); -async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>, testInfo: any, options: { outputPath?: string, proxy?: BrowserContextOptions['proxy'] } & Partial<Pick<BrowserContextOptions['recordHar'], 'content' | 'omitContent' | 'mode'>> = {}) { +async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise<BrowserContext>, testInfo: any, options: { outputPath?: string } & Partial<Pick<BrowserContextOptions['recordHar'], 'content' | 'omitContent' | 'mode'>> = {}) { const harPath = testInfo.outputPath(options.outputPath || 'test.har'); - const context = await contextFactory({ recordHar: { path: harPath, ...options }, ignoreHTTPSErrors: true, proxy: options.proxy }); + const context = await contextFactory({ recordHar: { path: harPath, ...options }, ignoreHTTPSErrors: true }); const page = await context.newPage(); return { page, @@ -858,25 +858,6 @@ it('should respect minimal mode for API Requests', async ({ contextFactory, serv expect(entry.response.bodySize).toBe(-1); }); -it('should include timings when using http proxy', async ({ contextFactory, server, proxyServer }, testInfo) => { - proxyServer.forwardTo(server.PORT, { allowConnectRequests: true }); - const { page, getLog } = await pageWithHar(contextFactory, testInfo, { proxy: { server: `localhost:${proxyServer.PORT}` } }); - const response = await page.request.get(server.EMPTY_PAGE); - await response.body(); - await expect(response).toBeOK(); - const log = await getLog(); - expect(log.entries[0].timings.connect).toBeGreaterThan(0); -}); - -it('should include timings when using socks proxy', async ({ contextFactory, server, socksPort }, testInfo) => { - const { page, getLog } = await pageWithHar(contextFactory, testInfo, { proxy: { server: `socks5://localhost:${socksPort}` } }); - const response = await page.request.get(server.EMPTY_PAGE); - await response.body(); - await expect(response).toBeOK(); - const log = await getLog(); - expect(log.entries[0].timings.connect).toBeGreaterThan(0); -}); - it('should include redirects from API request', async ({ contextFactory, server }, testInfo) => { server.setRedirect('/redirect-me', '/simple.json'); const { page, getLog } = await pageWithHar(contextFactory, testInfo); From 0f2cbdedacec25bd6894e22055f63c49c43ea208 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Tue, 8 Oct 2024 02:47:24 -0700 Subject: [PATCH 272/805] fix(routeWebSocket): do not show in the trace (#32991) --- packages/playwright-core/src/client/network.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index c24f0de431de1..f3b066c171735 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -462,6 +462,7 @@ export class WebSocketRoute extends ChannelOwner<channels.WebSocketRouteChannel> constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.WebSocketRouteInitializer) { super(parent, type, guid, initializer); + this.markAsInternalType(); this._server = { onMessage: (handler: (message: string | Buffer) => any) => { From 5b29ead6f07b6a2a7d967513e2bb97d2de23bf26 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Tue, 8 Oct 2024 03:53:38 -0700 Subject: [PATCH 273/805] chore(driver): roll driver to recent Node.js LTS version (#33005) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- utils/build/build-playwright-driver.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/build/build-playwright-driver.sh b/utils/build/build-playwright-driver.sh index 09c3fc75aee21..d587cdc94dc49 100755 --- a/utils/build/build-playwright-driver.sh +++ b/utils/build/build-playwright-driver.sh @@ -4,7 +4,7 @@ set -x trap "cd $(pwd -P)" EXIT SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)" -NODE_VERSION="20.17.0" # autogenerated via ./update-playwright-driver-version.mjs +NODE_VERSION="20.18.0" # autogenerated via ./update-playwright-driver-version.mjs cd "$(dirname "$0")" PACKAGE_VERSION=$(node -p "require('../../package.json').version") From 814f7eb5563f32c3dde029bd07c87f99803bfdcb Mon Sep 17 00:00:00 2001 From: Dmitry Gozman <dgozman@gmail.com> Date: Tue, 8 Oct 2024 03:59:35 -0700 Subject: [PATCH 274/805] test: fix/fixme/update a few tests (#33006) --- tests/android/device.spec.ts | 2 +- tests/android/webview.spec.ts | 2 +- tests/page/locator-misc-1.spec.ts | 4 +++- tests/page/page-click.spec.ts | 7 +++---- tests/page/page-request-continue.spec.ts | 4 +++- tests/page/workers.spec.ts | 1 + tests/playwright-test/runner.spec.ts | 10 +++++----- 7 files changed, 17 insertions(+), 13 deletions(-) diff --git a/tests/android/device.spec.ts b/tests/android/device.spec.ts index 8fed6564501e0..8b750ca1153e1 100644 --- a/tests/android/device.spec.ts +++ b/tests/android/device.spec.ts @@ -55,6 +55,6 @@ test('androidDevice.push', async function({ androidDevice }) { test('androidDevice.fill', async function({ androidDevice }) { await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity'); - await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'Hello'); + await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'Hello', { timeout: test.info().timeout }); expect((await androidDevice.info({ res: 'org.chromium.webview_shell:id/url_field' })).text).toBe('Hello'); }); diff --git a/tests/android/webview.spec.ts b/tests/android/webview.spec.ts index 650f8f299ceee..a0d03b69b65e0 100644 --- a/tests/android/webview.spec.ts +++ b/tests/android/webview.spec.ts @@ -47,7 +47,7 @@ test('should navigate page externally', async function({ androidDevice }) { const webview = await androidDevice.webView({ pkg: 'org.chromium.webview_shell' }); const page = await webview.page(); - await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'data:text/html,<title>Hello world!'); + await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'data:text/html,Hello world!', { timeout: test.info().timeout }); await Promise.all([ page.waitForNavigation(), androidDevice.press({ res: 'org.chromium.webview_shell:id/url_field' }, 'Enter') diff --git a/tests/page/locator-misc-1.spec.ts b/tests/page/locator-misc-1.spec.ts index 616beb3e7fd89..eaa0375c32e9e 100644 --- a/tests/page/locator-misc-1.spec.ts +++ b/tests/page/locator-misc-1.spec.ts @@ -18,7 +18,9 @@ import { test as it, expect } from './pageTest'; import path from 'path'; -it('should hover @smoke', async ({ page, server }) => { +it('should hover @smoke', async ({ page, server, headless }) => { + it.skip(!headless, 'headed messes up with hover'); + await page.goto(server.PREFIX + '/input/scrollable.html'); const button = page.locator('#button-6'); await button.hover(); diff --git a/tests/page/page-click.spec.ts b/tests/page/page-click.spec.ts index fccef2ed0e7d4..4a09c0d488546 100644 --- a/tests/page/page-click.spec.ts +++ b/tests/page/page-click.spec.ts @@ -85,8 +85,9 @@ it('should click on a span with an inline element inside', async ({ page }) => { expect(await page.evaluate('CLICKED')).toBe(42); }); -it('should not throw UnhandledPromiseRejection when page closes', async ({ page, isWebView2 }) => { +it('should not throw UnhandledPromiseRejection when page closes', async ({ page, isWebView2, browserName, isWindows }) => { it.skip(isWebView2, 'Page.close() is not supported in WebView2'); + it.fixme(browserName === 'firefox' && isWindows, 'makes the next test to always timeout'); await Promise.all([ page.close(), @@ -94,9 +95,7 @@ it('should not throw UnhandledPromiseRejection when page closes', async ({ page, ]).catch(e => {}); }); -it('should click the 1x1 div', async ({ page, browserName, isWindows }) => { - it.fixme(browserName === 'firefox' && isWindows, 'always times out'); - +it('should click the 1x1 div', async ({ page }) => { await page.setContent(`
`); await page.click('div'); expect(await page.evaluate('window.__clicked')).toBe(true); diff --git a/tests/page/page-request-continue.spec.ts b/tests/page/page-request-continue.spec.ts index 2df84e133aa05..a0e0e15f5579f 100644 --- a/tests/page/page-request-continue.spec.ts +++ b/tests/page/page-request-continue.spec.ts @@ -563,7 +563,9 @@ it('propagate headers cross origin redirect', { { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/13106' }, { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32045' }, ] -}, async ({ page, server }) => { +}, async ({ page, server, isAndroid }) => { + it.fixme(isAndroid, 'receives authorization:credentials header'); + await page.goto(server.PREFIX + '/empty.html'); let resolve; const serverRequestPromise = new Promise(f => resolve = f); diff --git a/tests/page/workers.spec.ts b/tests/page/workers.spec.ts index 1d53a73923601..327a2ed45daba 100644 --- a/tests/page/workers.spec.ts +++ b/tests/page/workers.spec.ts @@ -244,6 +244,7 @@ it('should support extra http headers', { it('should support offline', async ({ page, server, browserName }) => { it.fixme(browserName === 'firefox'); + it.fixme(browserName === 'webkit', 'flaky on all platforms'); const [worker] = await Promise.all([ page.waitForEvent('worker'), diff --git a/tests/playwright-test/runner.spec.ts b/tests/playwright-test/runner.spec.ts index 701b1e825d1f5..c197879bd5947 100644 --- a/tests/playwright-test/runner.spec.ts +++ b/tests/playwright-test/runner.spec.ts @@ -145,13 +145,13 @@ test('should ignore subprocess creation error because of SIGINT', async ({ inter process.kill(-testProcess.process.pid!, 'SIGINT'); const { exitCode } = await testProcess.exited; - expect(exitCode).toBe(130); + expect.soft(exitCode).toBe(130); const result = parseTestRunnerOutput(testProcess.output); - expect(result.passed).toBe(0); - expect(result.failed).toBe(0); - expect(result.didNotRun).toBe(2); - expect(result.output).not.toContain('worker process exited unexpectedly'); + expect.soft(result.passed).toBe(0); + expect.soft(result.failed).toBe(0); + expect.soft(result.didNotRun).toBe(2); + expect.soft(result.output).not.toContain('worker process exited unexpectedly'); }); test('sigint should stop workers', async ({ interactWithTestRunner }) => { From 47a889ac486ace02e92268d865797f51787cc18f Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 8 Oct 2024 14:01:45 +0200 Subject: [PATCH 275/805] chore: roll stable-test-runner to 1.48.0-beta-1728384960000 (#33008) --- .../stable-test-runner/package-lock.json | 46 +++++++++---------- .../stable-test-runner/package.json | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/playwright-test/stable-test-runner/package-lock.json b/tests/playwright-test/stable-test-runner/package-lock.json index ffa522a45588f..180f4d9b33395 100644 --- a/tests/playwright-test/stable-test-runner/package-lock.json +++ b/tests/playwright-test/stable-test-runner/package-lock.json @@ -5,16 +5,16 @@ "packages": { "": { "dependencies": { - "@playwright/test": "1.47.0-beta-1725531189000" + "@playwright/test": "1.48.0-beta-1728384960000" } }, "node_modules/@playwright/test": { - "version": "1.47.0-beta-1725531189000", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0-beta-1725531189000.tgz", - "integrity": "sha512-vIXLYI725qen6gbrkiD+KphLnjHEHumK7lv6BYP4ZTzbI48Cc7eKkysrLIP1EajghejmPa0DCwsrQmMEElM1mQ==", + "version": "1.48.0-beta-1728384960000", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.0-beta-1728384960000.tgz", + "integrity": "sha512-bqQorY7LKVldgwAsUbjULdwKEoUlZ8OOHRZmM/1XyGiGqJwzTGdr0x8Ss312BvKddAh+5pz8cbaPopw10Rp3Ng==", "license": "Apache-2.0", "dependencies": { - "playwright": "1.47.0-beta-1725531189000" + "playwright": "1.48.0-beta-1728384960000" }, "bin": { "playwright": "cli.js" @@ -38,12 +38,12 @@ } }, "node_modules/playwright": { - "version": "1.47.0-beta-1725531189000", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0-beta-1725531189000.tgz", - "integrity": "sha512-OkqvMHZOGrXL0xR8qUb0sY4/VK0CElbgJjC2pMVo77zxfOaBjzWVT3Zq5+zeoAOc+LUTWrG8YJNpRIlLoiDZlg==", + "version": "1.48.0-beta-1728384960000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0-beta-1728384960000.tgz", + "integrity": "sha512-5pIZTwoktOGYJL+YpF2RNhGzVUY6rA/ceQAT0lEQSZaL55MKUzraD2FAoZoBnz84cIIks2ZSlXt8j5mJ5xXt8g==", "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.0-beta-1725531189000" + "playwright-core": "1.48.0-beta-1728384960000" }, "bin": { "playwright": "cli.js" @@ -56,9 +56,9 @@ } }, "node_modules/playwright-core": { - "version": "1.47.0-beta-1725531189000", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0-beta-1725531189000.tgz", - "integrity": "sha512-a3jiPt5nHo14i/4is7diMKiq+e0Tc/UNjiVy7fHH1gfPw9kHQMAgWuoOYwMAawFNFOyYuZSk4KNBTRfVgtMkVw==", + "version": "1.48.0-beta-1728384960000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0-beta-1728384960000.tgz", + "integrity": "sha512-atIhpuvqvVEW5luPhwzhdcXsGdPvzOBLXAg3+MvOLY+6Q4JcTfXMTtTmltP+llUV+LAgj38foQz+6tKTzNMlWg==", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -70,11 +70,11 @@ }, "dependencies": { "@playwright/test": { - "version": "1.47.0-beta-1725531189000", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.0-beta-1725531189000.tgz", - "integrity": "sha512-vIXLYI725qen6gbrkiD+KphLnjHEHumK7lv6BYP4ZTzbI48Cc7eKkysrLIP1EajghejmPa0DCwsrQmMEElM1mQ==", + "version": "1.48.0-beta-1728384960000", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.0-beta-1728384960000.tgz", + "integrity": "sha512-bqQorY7LKVldgwAsUbjULdwKEoUlZ8OOHRZmM/1XyGiGqJwzTGdr0x8Ss312BvKddAh+5pz8cbaPopw10Rp3Ng==", "requires": { - "playwright": "1.47.0-beta-1725531189000" + "playwright": "1.48.0-beta-1728384960000" } }, "fsevents": { @@ -84,18 +84,18 @@ "optional": true }, "playwright": { - "version": "1.47.0-beta-1725531189000", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0-beta-1725531189000.tgz", - "integrity": "sha512-OkqvMHZOGrXL0xR8qUb0sY4/VK0CElbgJjC2pMVo77zxfOaBjzWVT3Zq5+zeoAOc+LUTWrG8YJNpRIlLoiDZlg==", + "version": "1.48.0-beta-1728384960000", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0-beta-1728384960000.tgz", + "integrity": "sha512-5pIZTwoktOGYJL+YpF2RNhGzVUY6rA/ceQAT0lEQSZaL55MKUzraD2FAoZoBnz84cIIks2ZSlXt8j5mJ5xXt8g==", "requires": { "fsevents": "2.3.2", - "playwright-core": "1.47.0-beta-1725531189000" + "playwright-core": "1.48.0-beta-1728384960000" } }, "playwright-core": { - "version": "1.47.0-beta-1725531189000", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0-beta-1725531189000.tgz", - "integrity": "sha512-a3jiPt5nHo14i/4is7diMKiq+e0Tc/UNjiVy7fHH1gfPw9kHQMAgWuoOYwMAawFNFOyYuZSk4KNBTRfVgtMkVw==" + "version": "1.48.0-beta-1728384960000", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0-beta-1728384960000.tgz", + "integrity": "sha512-atIhpuvqvVEW5luPhwzhdcXsGdPvzOBLXAg3+MvOLY+6Q4JcTfXMTtTmltP+llUV+LAgj38foQz+6tKTzNMlWg==" } } } diff --git a/tests/playwright-test/stable-test-runner/package.json b/tests/playwright-test/stable-test-runner/package.json index c30cd47132047..3e32d0bbb7c07 100644 --- a/tests/playwright-test/stable-test-runner/package.json +++ b/tests/playwright-test/stable-test-runner/package.json @@ -1,6 +1,6 @@ { "private": true, "dependencies": { - "@playwright/test": "1.47.0-beta-1725531189000" + "@playwright/test": "1.48.0-beta-1728384960000" } } From 992994f036fee8e2a784d65850f0c40bc48149f0 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Tue, 8 Oct 2024 05:13:45 -0700 Subject: [PATCH 276/805] feat(chromium-tip-of-tree): roll to r1267 (#33007) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 00c7a751f4566..f5b25f36cde82 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -9,9 +9,9 @@ }, { "name": "chromium-tip-of-tree", - "revision": "1266", + "revision": "1267", "installByDefault": false, - "browserVersion": "131.0.6754.0" + "browserVersion": "131.0.6764.0" }, { "name": "firefox", From 042161e1ce4040a3a03b00a214a7f010c41da995 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Oct 2024 14:17:50 +0200 Subject: [PATCH 277/805] Reapply "fix(har timing): record connect timing for proxied connections" (#32855) (#33003) This reapplies what we reverted in https://github.com/microsoft/playwright/pull/32989. Max and me debugged this, and found that the test failures come from SOCKS proxy now preferring IPv6 over IPv4. We've updated the tests and made sure that this doesn't mask any breaking change. I'm enabling CQ1 to make sure we don't oversee any other CI failures. --- .../playwright-core/ThirdPartyNotices.txt | 392 +----------------- .../bundles/utils/package-lock.json | 69 +-- .../bundles/utils/package.json | 4 +- packages/playwright-core/src/server/fetch.ts | 34 +- .../socksClientCertificatesInterceptor.ts | 2 +- packages/playwright-core/src/utils/network.ts | 2 +- tests/config/proxy.ts | 2 +- tests/config/serverFixtures.ts | 2 +- tests/library/client-certificates.spec.ts | 2 +- tests/library/har.spec.ts | 23 +- 10 files changed, 97 insertions(+), 435 deletions(-) diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index 0a3ca6a5f4f79..a5d4ca7d0b7dc 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -6,7 +6,7 @@ This project incorporates components from the projects listed below. The origina - @types/node@17.0.24 (https://github.com/DefinitelyTyped/DefinitelyTyped) - @types/yauzl@2.10.0 (https://github.com/DefinitelyTyped/DefinitelyTyped) -- agent-base@6.0.2 (https://github.com/TooTallNate/node-agent-base) +- agent-base@7.1.1 (https://github.com/TooTallNate/proxy-agents) - balanced-match@1.0.2 (https://github.com/juliangruber/balanced-match) - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) @@ -23,7 +23,7 @@ This project incorporates components from the projects listed below. The origina - fd-slicer@1.1.0 (https://github.com/andrewrk/node-fd-slicer) - get-stream@5.2.0 (https://github.com/sindresorhus/get-stream) - graceful-fs@4.2.10 (https://github.com/isaacs/node-graceful-fs) -- https-proxy-agent@5.0.0 (https://github.com/TooTallNate/node-https-proxy-agent) +- https-proxy-agent@7.0.5 (https://github.com/TooTallNate/proxy-agents) - ip-address@9.0.5 (https://github.com/beaugunderson/ip-address) - is-docker@2.2.1 (https://github.com/sindresorhus/is-docker) - is-wsl@2.2.0 (https://github.com/sindresorhus/is-wsl) @@ -42,7 +42,7 @@ This project incorporates components from the projects listed below. The origina - retry@0.12.0 (https://github.com/tim-kos/node-retry) - signal-exit@3.0.7 (https://github.com/tapjs/signal-exit) - smart-buffer@4.2.0 (https://github.com/JoshGlazebrook/smart-buffer) -- socks-proxy-agent@6.1.1 (https://github.com/TooTallNate/node-socks-proxy-agent) +- socks-proxy-agent@8.0.4 (https://github.com/TooTallNate/proxy-agents) - socks@2.8.3 (https://github.com/JoshGlazebrook/socks) - sprintf-js@1.1.3 (https://github.com/alexei/sprintf.js) - stack-utils@2.0.5 (https://github.com/tapjs/stack-utils) @@ -103,128 +103,11 @@ MIT License ========================================= END OF @types/yauzl@2.10.0 AND INFORMATION -%% agent-base@6.0.2 NOTICES AND INFORMATION BEGIN HERE +%% agent-base@7.1.1 NOTICES AND INFORMATION BEGIN HERE ========================================= -agent-base -========== -### Turn a function into an [`http.Agent`][http.Agent] instance -[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI) - -This module provides an `http.Agent` generator. That is, you pass it an async -callback function, and it returns a new `http.Agent` instance that will invoke the -given callback function when sending outbound HTTP requests. - -#### Some subclasses: - -Here's some more interesting uses of `agent-base`. -Send a pull request to list yours! - - * [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints - * [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints - * [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS - * [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS - - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install agent-base -``` - - -Example -------- - -Here's a minimal example that creates a new `net.Socket` connection to the server -for every HTTP request (i.e. the equivalent of `agent: false` option): - -```js -var net = require('net'); -var tls = require('tls'); -var url = require('url'); -var http = require('http'); -var agent = require('agent-base'); - -var endpoint = 'http://nodejs.org/api/'; -var parsed = url.parse(endpoint); - -// This is the important part! -parsed.agent = agent(function (req, opts) { - var socket; - // `secureEndpoint` is true when using the https module - if (opts.secureEndpoint) { - socket = tls.connect(opts); - } else { - socket = net.connect(opts); - } - return socket; -}); - -// Everything else works just like normal... -http.get(parsed, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -Returning a Promise or using an `async` function is also supported: - -```js -agent(async function (req, opts) { - await sleep(1000); - // etc… -}); -``` - -Return another `http.Agent` instance to "pass through" the responsibility -for that HTTP request to that agent: - -```js -agent(function (req, opts) { - return opts.secureEndpoint ? https.globalAgent : http.globalAgent; -}); -``` - - -API ---- - -## Agent(Function callback[, Object options]) → [http.Agent][] - -Creates a base `http.Agent` that will execute the callback function `callback` -for every HTTP request that it is used as the `agent` for. The callback function -is responsible for creating a `stream.Duplex` instance of some kind that will be -used as the underlying socket in the HTTP request. - -The `options` object accepts the following properties: - - * `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional). - -The callback function should have the following signature: - -### callback(http.ClientRequest req, Object options, Function cb) → undefined - -The ClientRequest `req` can be accessed to read request headers and -and the path, etc. The `options` object contains the options passed -to the `http.request()`/`https.request()` function call, and is formatted -to be directly passed to `net.connect()`/`tls.connect()`, or however -else you want a Socket to be created. Pass the created socket to -the callback function `cb` once created, and the HTTP request will -continue to proceed. - -If the `https` module is used to invoke the HTTP request, then the -`secureEndpoint` property on `options` _will be set to `true`_. - - -License -------- - (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -244,14 +127,8 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent -[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent -[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent -[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent -[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent ========================================= -END OF agent-base@6.0.2 AND INFORMATION +END OF agent-base@7.1.1 AND INFORMATION %% balanced-match@1.0.2 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -629,124 +506,11 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ========================================= END OF graceful-fs@4.2.10 AND INFORMATION -%% https-proxy-agent@5.0.0 NOTICES AND INFORMATION BEGIN HERE +%% https-proxy-agent@7.0.5 NOTICES AND INFORMATION BEGIN HERE ========================================= -https-proxy-agent -================ -### An HTTP(s) proxy `http.Agent` implementation for HTTPS -[![Build Status](https://github.com/TooTallNate/node-https-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-https-proxy-agent/actions?workflow=Node+CI) - -This module provides an `http.Agent` implementation that connects to a specified -HTTP or HTTPS proxy server, and can be used with the built-in `https` module. - -Specifically, this `Agent` implementation connects to an intermediary "proxy" -server and issues the [CONNECT HTTP method][CONNECT], which tells the proxy to -open a direct TCP connection to the destination server. - -Since this agent implements the CONNECT HTTP method, it also works with other -protocols that use this method when connecting over proxies (i.e. WebSockets). -See the "Examples" section below for more. - - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install https-proxy-agent -``` - - -Examples --------- - -#### `https` module example - -``` js -var url = require('url'); -var https = require('https'); -var HttpsProxyAgent = require('https-proxy-agent'); - -// HTTP/HTTPS proxy to connect to -var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; -console.log('using proxy server %j', proxy); - -// HTTPS endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'https://graph.facebook.com/tootallnate'; -console.log('attempting to GET %j', endpoint); -var options = url.parse(endpoint); - -// create an instance of the `HttpsProxyAgent` class with the proxy server information -var agent = new HttpsProxyAgent(proxy); -options.agent = agent; - -https.get(options, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -#### `ws` WebSocket connection example - -``` js -var url = require('url'); -var WebSocket = require('ws'); -var HttpsProxyAgent = require('https-proxy-agent'); - -// HTTP/HTTPS proxy to connect to -var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; -console.log('using proxy server %j', proxy); - -// WebSocket endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'ws://echo.websocket.org'; -var parsed = url.parse(endpoint); -console.log('attempting to connect to WebSocket %j', endpoint); - -// create an instance of the `HttpsProxyAgent` class with the proxy server information -var options = url.parse(proxy); - -var agent = new HttpsProxyAgent(options); - -// finally, initiate the WebSocket connection -var socket = new WebSocket(endpoint, { agent: agent }); - -socket.on('open', function () { - console.log('"open" event!'); - socket.send('hello world'); -}); - -socket.on('message', function (data, flags) { - console.log('"message" event! %j %j', data, flags); - socket.close(); -}); -``` - -API ---- - -### new HttpsProxyAgent(Object options) - -The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects -to the specified "HTTP(s) proxy server" in order to proxy HTTPS and/or WebSocket -requests. This is achieved by using the [HTTP `CONNECT` method][CONNECT]. - -The `options` argument may either be a string URI of the proxy server to use, or an -"options" object with more specific properties: - - * `host` - String - Proxy host to connect to (may use `hostname` as well). Required. - * `port` - Number - Proxy port to connect to. Required. - * `protocol` - String - If `https:`, then use TLS to connect to the proxy. - * `headers` - Object - Additional HTTP headers to be sent on the HTTP CONNECT method. - * Any other options given are passed to the `net.connect()`/`tls.connect()` functions. - - -License -------- - (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -766,10 +530,8 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[CONNECT]: http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling ========================================= -END OF https-proxy-agent@5.0.0 AND INFORMATION +END OF https-proxy-agent@7.0.5 AND INFORMATION %% ip-address@9.0.5 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -1207,141 +969,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF smart-buffer@4.2.0 AND INFORMATION -%% socks-proxy-agent@6.1.1 NOTICES AND INFORMATION BEGIN HERE +%% socks-proxy-agent@8.0.4 NOTICES AND INFORMATION BEGIN HERE ========================================= -socks-proxy-agent -================ -### A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS -[![Build Status](https://github.com/TooTallNate/node-socks-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-socks-proxy-agent/actions?workflow=Node+CI) - -This module provides an `http.Agent` implementation that connects to a -specified SOCKS proxy server, and can be used with the built-in `http` -and `https` modules. - -It can also be used in conjunction with the `ws` module to establish a WebSocket -connection over a SOCKS proxy. See the "Examples" section below. - -Installation ------------- - -Install with `npm`: - -``` bash -$ npm install socks-proxy-agent -``` - - -Examples --------- - -#### TypeScript example - -```ts -import https from 'https'; -import { SocksProxyAgent } from 'socks-proxy-agent'; - -const info = { - host: 'br41.nordvpn.com', - userId: 'your-name@gmail.com', - password: 'abcdef12345124' -}; -const agent = new SocksProxyAgent(info); - -https.get('https://jsonip.org', { agent }, (res) => { - console.log(res.headers); - res.pipe(process.stdout); -}); -``` - -#### `http` module example - -```js -var url = require('url'); -var http = require('http'); -var SocksProxyAgent = require('socks-proxy-agent'); - -// SOCKS proxy to connect to -var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; -console.log('using proxy server %j', proxy); - -// HTTP endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'http://nodejs.org/api/'; -console.log('attempting to GET %j', endpoint); -var opts = url.parse(endpoint); - -// create an instance of the `SocksProxyAgent` class with the proxy server information -var agent = new SocksProxyAgent(proxy); -opts.agent = agent; - -http.get(opts, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -#### `https` module example - -```js -var url = require('url'); -var https = require('https'); -var SocksProxyAgent = require('socks-proxy-agent'); - -// SOCKS proxy to connect to -var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; -console.log('using proxy server %j', proxy); - -// HTTP endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'https://encrypted.google.com/'; -console.log('attempting to GET %j', endpoint); -var opts = url.parse(endpoint); - -// create an instance of the `SocksProxyAgent` class with the proxy server information -var agent = new SocksProxyAgent(proxy); -opts.agent = agent; - -https.get(opts, function (res) { - console.log('"response" event!', res.headers); - res.pipe(process.stdout); -}); -``` - -#### `ws` WebSocket connection example - -``` js -var WebSocket = require('ws'); -var SocksProxyAgent = require('socks-proxy-agent'); - -// SOCKS proxy to connect to -var proxy = process.env.socks_proxy || 'socks://127.0.0.1:1080'; -console.log('using proxy server %j', proxy); - -// WebSocket endpoint for the proxy to connect to -var endpoint = process.argv[2] || 'ws://echo.websocket.org'; -console.log('attempting to connect to WebSocket %j', endpoint); - -// create an instance of the `SocksProxyAgent` class with the proxy server information -var agent = new SocksProxyAgent(proxy); - -// initiate the WebSocket connection -var socket = new WebSocket(endpoint, { agent: agent }); - -socket.on('open', function () { - console.log('"open" event!'); - socket.send('hello world'); -}); - -socket.on('message', function (data, flags) { - console.log('"message" event! %j %j', data, flags); - socket.close(); -}); -``` - -License -------- - (The MIT License) -Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net> +Copyright (c) 2013 Nathan Rajlich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -1362,7 +994,7 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF socks-proxy-agent@6.1.1 AND INFORMATION +END OF socks-proxy-agent@8.0.4 AND INFORMATION %% socks@2.8.3 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index eef68ef8ee768..0e5e761433bf0 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -13,7 +13,7 @@ "debug": "^4.3.4", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", - "https-proxy-agent": "5.0.0", + "https-proxy-agent": "7.0.5", "jpeg-js": "0.4.4", "mime": "^3.0.0", "minimatch": "^3.1.2", @@ -23,7 +23,7 @@ "proxy-from-env": "1.1.0", "retry": "0.12.0", "signal-exit": "3.0.7", - "socks-proxy-agent": "6.1.1", + "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", "ws": "8.17.1" }, @@ -130,14 +130,15 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/balanced-match": { @@ -224,15 +225,16 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/ip-address": { @@ -382,16 +384,17 @@ } }, "node_modules/socks-proxy-agent": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", - "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, "node_modules/sprintf-js": { @@ -523,11 +526,11 @@ } }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "requires": { - "debug": "4" + "debug": "^4.3.4" } }, "balanced-match": { @@ -588,11 +591,11 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "requires": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" } }, @@ -696,13 +699,13 @@ } }, "socks-proxy-agent": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", - "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.1", - "socks": "^2.6.1" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" } }, "sprintf-js": { diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index a7c66192e08fd..06637adabee9a 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -14,7 +14,7 @@ "debug": "^4.3.4", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", - "https-proxy-agent": "5.0.0", + "https-proxy-agent": "7.0.5", "jpeg-js": "0.4.4", "mime": "^3.0.0", "minimatch": "^3.1.2", @@ -24,7 +24,7 @@ "proxy-from-env": "1.1.0", "retry": "0.12.0", "signal-exit": "3.0.7", - "socks-proxy-agent": "6.1.1", + "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", "ws": "8.17.1" }, diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 12f1d21d93988..243e89cf1c9f4 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -20,7 +20,6 @@ import http from 'http'; import https from 'https'; import type { Readable, TransformCallback } from 'stream'; import { pipeline, Transform } from 'stream'; -import url from 'url'; import zlib from 'zlib'; import type { HTTPCredentials } from '../../types/types'; import { TimeoutSettings } from '../common/timeoutSettings'; @@ -493,12 +492,12 @@ export abstract class APIRequestContext extends SdkObject { // happy eyeballs don't emit lookup and connect events, so we use our custom ones const happyEyeBallsTimings = timingForSocket(socket); dnsLookupAt = happyEyeBallsTimings.dnsLookupAt; - tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt; + tcpConnectionAt ??= happyEyeBallsTimings.tcpConnectionAt; // non-happy-eyeballs sockets listeners.push( eventsHelper.addEventListener(socket, 'lookup', () => { dnsLookupAt = monotonicTime(); }), - eventsHelper.addEventListener(socket, 'connect', () => { tcpConnectionAt = monotonicTime(); }), + eventsHelper.addEventListener(socket, 'connect', () => { tcpConnectionAt ??= monotonicTime(); }), eventsHelper.addEventListener(socket, 'secureConnect', () => { tlsHandshakeAt = monotonicTime(); @@ -515,11 +514,21 @@ export abstract class APIRequestContext extends SdkObject { }), ); + // when using socks proxy, having the socket means the connection got established + if (agent instanceof SocksProxyAgent) + tcpConnectionAt ??= monotonicTime(); + serverIPAddress = socket.remoteAddress; serverPort = socket.remotePort; }); request.on('finish', () => { requestFinishAt = monotonicTime(); }); + // http proxy + request.on('proxyConnect', () => { + tcpConnectionAt ??= monotonicTime(); + }); + + progress.log(`→ ${options.method} ${url.toString()}`); if (options.headers) { for (const [name, value] of Object.entries(options.headers)) @@ -686,17 +695,16 @@ export class GlobalAPIRequestContext extends APIRequestContext { } export function createProxyAgent(proxy: types.ProxySettings) { - const proxyOpts = url.parse(proxy.server); - if (proxyOpts.protocol?.startsWith('socks')) { - return new SocksProxyAgent({ - host: proxyOpts.hostname, - port: proxyOpts.port || undefined, - }); - } + const proxyURL = new URL(proxy.server); + if (proxyURL.protocol?.startsWith('socks')) + return new SocksProxyAgent(proxyURL); + if (proxy.username) - proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`; - // TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method. - return new HttpsProxyAgent(proxyOpts); + proxyURL.username = proxy.username; + if (proxy.password) + proxyURL.password = proxy.password; + // TODO: We should use HttpProxyAgent conditional on proxyURL.protocol instead of always using CONNECT method. + return new HttpsProxyAgent(proxyURL); } function toHeadersArray(rawHeaders: string[]): types.HeadersArray { diff --git a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts index b041ffb8290e2..4e850f4a8415b 100644 --- a/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts +++ b/packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts @@ -98,7 +98,7 @@ class SocksProxyConnection { async connect() { if (this.socksProxy.proxyAgentFromOptions) - this.target = await this.socksProxy.proxyAgentFromOptions.callback(new EventEmitter() as any, { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); + this.target = await this.socksProxy.proxyAgentFromOptions.connect(new EventEmitter() as any, { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); else this.target = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port); diff --git a/packages/playwright-core/src/utils/network.ts b/packages/playwright-core/src/utils/network.ts index f04b828d6749a..632c74fe3a19d 100644 --- a/packages/playwright-core/src/utils/network.ts +++ b/packages/playwright-core/src/utils/network.ts @@ -50,7 +50,7 @@ export function httpRequest(params: HTTPRequestParams, onResponse: (r: http.Inco const proxyURL = getProxyForUrl(params.url); if (proxyURL) { - const parsedProxyURL = url.parse(proxyURL); + const parsedProxyURL = new URL(proxyURL); if (params.url.startsWith('http:')) { options = { path: parsedUrl.href, diff --git a/tests/config/proxy.ts b/tests/config/proxy.ts index f9672cfb1b97e..782dfc781449b 100644 --- a/tests/config/proxy.ts +++ b/tests/config/proxy.ts @@ -114,7 +114,7 @@ export async function setupSocksForwardingServer({ const socksProxy = new SocksProxy(); socksProxy.setPattern('*'); socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload: SocksSocketRequestedPayload) => { - if (!['127.0.0.1', 'fake-localhost-127-0-0-1.nip.io', 'localhost'].includes(payload.host) || payload.port !== allowedTargetPort) { + if (!['127.0.0.1', '0:0:0:0:0:0:0:1', 'fake-localhost-127-0-0-1.nip.io', 'localhost'].includes(payload.host) || payload.port !== allowedTargetPort) { socksProxy.sendSocketError({ uid: payload.uid, error: 'ECONNREFUSED' }); return; } diff --git a/tests/config/serverFixtures.ts b/tests/config/serverFixtures.ts index a156f2ac5fec8..2bff8e6369035 100644 --- a/tests/config/serverFixtures.ts +++ b/tests/config/serverFixtures.ts @@ -51,7 +51,7 @@ export const serverFixtures: Fixtures = { const socksServer = new MockSocksServer(); const socksPort = port + 2; - await socksServer.listen(socksPort, 'localhost'); + await socksServer.listen(socksPort, loopback); const proxyPort = port + 3; const proxyServer = await TestProxy.create(proxyPort); diff --git a/tests/library/client-certificates.spec.ts b/tests/library/client-certificates.spec.ts index 10c8a5223543b..8e0a4cdf47c31 100644 --- a/tests/library/client-certificates.spec.ts +++ b/tests/library/client-certificates.spec.ts @@ -390,7 +390,7 @@ test.describe('browser', () => { }); expect(connectHosts).toEqual([]); await page.goto(serverURL); - const host = browserName === 'webkit' && isMac ? 'localhost' : '127.0.0.1'; + const host = browserName === 'webkit' && isMac ? '0:0:0:0:0:0:0:1' : '127.0.0.1'; expect(connectHosts).toEqual([`${host}:${serverPort}`]); await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); await page.close(); diff --git a/tests/library/har.spec.ts b/tests/library/har.spec.ts index bbd4dcc49b4ad..a5d4a6fa0ea2f 100644 --- a/tests/library/har.spec.ts +++ b/tests/library/har.spec.ts @@ -24,9 +24,9 @@ import type { Log } from '../../packages/trace/src/har'; import { parseHar } from '../config/utils'; const { createHttp2Server } = require('../../packages/playwright-core/lib/utils'); -async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise, testInfo: any, options: { outputPath?: string } & Partial> = {}) { +async function pageWithHar(contextFactory: (options?: BrowserContextOptions) => Promise, testInfo: any, options: { outputPath?: string, proxy?: BrowserContextOptions['proxy'] } & Partial> = {}) { const harPath = testInfo.outputPath(options.outputPath || 'test.har'); - const context = await contextFactory({ recordHar: { path: harPath, ...options }, ignoreHTTPSErrors: true }); + const context = await contextFactory({ recordHar: { path: harPath, ...options }, ignoreHTTPSErrors: true, proxy: options.proxy }); const page = await context.newPage(); return { page, @@ -858,6 +858,25 @@ it('should respect minimal mode for API Requests', async ({ contextFactory, serv expect(entry.response.bodySize).toBe(-1); }); +it('should include timings when using http proxy', async ({ contextFactory, server, proxyServer }, testInfo) => { + proxyServer.forwardTo(server.PORT, { allowConnectRequests: true }); + const { page, getLog } = await pageWithHar(contextFactory, testInfo, { proxy: { server: `localhost:${proxyServer.PORT}` } }); + const response = await page.request.get(server.EMPTY_PAGE); + expect(proxyServer.connectHosts).toEqual([`localhost:${server.PORT}`]); + await expect(response).toBeOK(); + const log = await getLog(); + expect(log.entries[0].timings.connect).toBeGreaterThan(0); +}); + +it('should include timings when using socks proxy', async ({ contextFactory, server, socksPort }, testInfo) => { + const { page, getLog } = await pageWithHar(contextFactory, testInfo, { proxy: { server: `socks5://localhost:${socksPort}` } }); + const response = await page.request.get(server.EMPTY_PAGE); + expect(await response.text()).toContain('Served by the SOCKS proxy'); + await expect(response).toBeOK(); + const log = await getLog(); + expect(log.entries[0].timings.connect).toBeGreaterThan(0); +}); + it('should include redirects from API request', async ({ contextFactory, server }, testInfo) => { server.setRedirect('/redirect-me', '/simple.json'); const { page, getLog } = await pageWithHar(contextFactory, testInfo); From d0f2170e215176e38a99a251be655e6852889448 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 8 Oct 2024 16:00:40 +0200 Subject: [PATCH 278/805] Revert "fix(test): do not allow mixing tests from different types (#29284)" (#33002) This reverts commit 4784139bb0bce071c0745c6c07f623c37d3c70ce. Closes https://github.com/microsoft/playwright/issues/29734 --- packages/playwright/src/common/test.ts | 4 +--- packages/playwright/src/common/testType.ts | 28 +++++++++------------- tests/playwright-test/basic.spec.ts | 19 --------------- 3 files changed, 12 insertions(+), 39 deletions(-) diff --git a/packages/playwright/src/common/test.ts b/packages/playwright/src/common/test.ts index 9cf88dc634f5d..3e7fb30a1ae81 100644 --- a/packages/playwright/src/common/test.ts +++ b/packages/playwright/src/common/test.ts @@ -56,12 +56,10 @@ export class Suite extends Base { _fullProject: FullProjectInternal | undefined; _fileId: string | undefined; readonly _type: 'root' | 'project' | 'file' | 'describe'; - readonly _testTypeImpl: TestTypeImpl | undefined; - constructor(title: string, type: 'root' | 'project' | 'file' | 'describe', testTypeImpl?: TestTypeImpl) { + constructor(title: string, type: 'root' | 'project' | 'file' | 'describe') { super(title); this._type = type; - this._testTypeImpl = testTypeImpl; } get type(): 'root' | 'project' | 'file' | 'describe' { diff --git a/packages/playwright/src/common/testType.ts b/packages/playwright/src/common/testType.ts index f0882735dc7e2..adf6bc3734ed1 100644 --- a/packages/playwright/src/common/testType.ts +++ b/packages/playwright/src/common/testType.ts @@ -38,7 +38,7 @@ export class TestTypeImpl { test.only = wrapFunctionWithLocation(this._createTest.bind(this, 'only')); test.describe = wrapFunctionWithLocation(this._describe.bind(this, 'default')); test.describe.only = wrapFunctionWithLocation(this._describe.bind(this, 'only')); - test.describe.configure = this._configure.bind(this); + test.describe.configure = wrapFunctionWithLocation(this._configure.bind(this)); test.describe.fixme = wrapFunctionWithLocation(this._describe.bind(this, 'fixme')); test.describe.parallel = wrapFunctionWithLocation(this._describe.bind(this, 'parallel')); test.describe.parallel.only = wrapFunctionWithLocation(this._describe.bind(this, 'parallel.only')); @@ -53,7 +53,7 @@ export class TestTypeImpl { test.fixme = wrapFunctionWithLocation(this._modifier.bind(this, 'fixme')); test.fail = wrapFunctionWithLocation(this._modifier.bind(this, 'fail')); test.slow = wrapFunctionWithLocation(this._modifier.bind(this, 'slow')); - test.setTimeout = this._setTimeout.bind(this); + test.setTimeout = wrapFunctionWithLocation(this._setTimeout.bind(this)); test.step = this._step.bind(this); test.use = wrapFunctionWithLocation(this._use.bind(this)); test.extend = wrapFunctionWithLocation(this._extend.bind(this)); @@ -66,7 +66,7 @@ export class TestTypeImpl { this.test = test; } - private _currentSuite(title: string): Suite | undefined { + private _currentSuite(location: Location, title: string): Suite | undefined { const suite = currentlyLoadingFileSuite(); if (!suite) { throw new Error([ @@ -78,18 +78,12 @@ export class TestTypeImpl { ` when one of the dependencies in your package.json depends on @playwright/test.`, ].join('\n')); } - if (suite._testTypeImpl && suite._testTypeImpl !== this) { - throw new Error([ - `Can't call ${title} inside a describe() suite of a different test type.`, - `Make sure to use the same "test" function (created by the test.extend() call) for all declarations inside a suite.`, - ].join('\n')); - } return suite; } private _createTest(type: 'default' | 'only' | 'skip' | 'fixme' | 'fail', location: Location, title: string, fnOrDetails: Function | TestDetails, fn?: Function) { throwIfRunningInsideJest(); - const suite = this._currentSuite('test()'); + const suite = this._currentSuite(location, 'test()'); if (!suite) return; @@ -118,7 +112,7 @@ export class TestTypeImpl { private _describe(type: 'default' | 'only' | 'serial' | 'serial.only' | 'parallel' | 'parallel.only' | 'skip' | 'fixme', location: Location, titleOrFn: string | Function, fnOrDetails?: TestDetails | Function, fn?: Function) { throwIfRunningInsideJest(); - const suite = this._currentSuite('test.describe()'); + const suite = this._currentSuite(location, 'test.describe()'); if (!suite) return; @@ -141,7 +135,7 @@ export class TestTypeImpl { } const validatedDetails = validateTestDetails(details); - const child = new Suite(title, 'describe', this); + const child = new Suite(title, 'describe'); child._requireFile = suite._requireFile; child.location = location; child._staticAnnotations.push(...validatedDetails.annotations); @@ -170,7 +164,7 @@ export class TestTypeImpl { } private _hook(name: 'beforeEach' | 'afterEach' | 'beforeAll' | 'afterAll', location: Location, title: string | Function, fn?: Function) { - const suite = this._currentSuite(`test.${name}()`); + const suite = this._currentSuite(location, `test.${name}()`); if (!suite) return; if (typeof title === 'function') { @@ -181,9 +175,9 @@ export class TestTypeImpl { suite._hooks.push({ type: name, fn: fn!, title, location }); } - private _configure(options: { mode?: 'default' | 'parallel' | 'serial', retries?: number, timeout?: number }) { + private _configure(location: Location, options: { mode?: 'default' | 'parallel' | 'serial', retries?: number, timeout?: number }) { throwIfRunningInsideJest(); - const suite = this._currentSuite(`test.describe.configure()`); + const suite = this._currentSuite(location, `test.describe.configure()`); if (!suite) return; @@ -239,7 +233,7 @@ export class TestTypeImpl { testInfo[type](...modifierArgs as [any, any]); } - private _setTimeout(timeout: number) { + private _setTimeout(location: Location, timeout: number) { const suite = currentlyLoadingFileSuite(); if (suite) { suite._timeout = timeout; @@ -253,7 +247,7 @@ export class TestTypeImpl { } private _use(location: Location, fixtures: Fixtures) { - const suite = this._currentSuite(`test.use()`); + const suite = this._currentSuite(location, `test.use()`); if (!suite) return; suite._use.push({ fixtures, location }); diff --git a/tests/playwright-test/basic.spec.ts b/tests/playwright-test/basic.spec.ts index 6476255936e38..3b47603c2554a 100644 --- a/tests/playwright-test/basic.spec.ts +++ b/tests/playwright-test/basic.spec.ts @@ -550,22 +550,3 @@ test('should support describe.fixme', async ({ runInlineTest }) => { expect(result.skipped).toBe(3); expect(result.output).toContain('heytest4'); }); - -test('should not allow mixing test types', async ({ runInlineTest }) => { - const result = await runInlineTest({ - 'mixed.spec.ts': ` - import { test } from '@playwright/test'; - - export const test2 = test.extend({ - value: 42, - }); - - test.describe("test1 suite", () => { - test2("test 2", async () => {}); - }); - ` - }); - expect(result.exitCode).toBe(1); - expect(result.output).toContain(`Can't call test() inside a describe() suite of a different test type.`); - expect(result.output).toContain('> 9 | test2('); -}); From 6c9823eeafec15654958b55885b64d0383348d2a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 8 Oct 2024 08:33:45 -0700 Subject: [PATCH 279/805] chore: allow minimal height for trace attachments (#32996) --- .../trace-viewer/src/ui/attachmentsTab.tsx | 25 ++++++++++++------- .../web/src/components/codeMirrorWrapper.tsx | 2 ++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/trace-viewer/src/ui/attachmentsTab.tsx b/packages/trace-viewer/src/ui/attachmentsTab.tsx index 8b6cefe14df70..69bfcd68cce2f 100644 --- a/packages/trace-viewer/src/ui/attachmentsTab.tsx +++ b/packages/trace-viewer/src/ui/attachmentsTab.tsx @@ -20,7 +20,7 @@ import { ImageDiffView } from '@web/shared/imageDiffView'; import type { MultiTraceModel } from './modelUtil'; import { PlaceholderPanel } from './placeholderPanel'; import type { AfterActionTraceEventAttachment } from '@trace/trace'; -import { CodeMirrorWrapper } from '@web/components/codeMirrorWrapper'; +import { CodeMirrorWrapper, lineHeight } from '@web/components/codeMirrorWrapper'; import { isTextualMimeType } from '@isomorphic/mimeType'; import { Expandable } from '@web/components/expandable'; import { linkifyText } from '@web/renderUtils'; @@ -51,6 +51,11 @@ const ExpandableAttachment: React.FunctionComponent = } }, [expanded, attachmentText, placeholder, attachment]); + const snippetHeight = React.useMemo(() => { + const lineCount = attachmentText ? attachmentText.split('\n').length : 0; + return Math.min(Math.max(5, lineCount), 20) * lineHeight; + }, [attachmentText]); + const title = {linkifyText(attachment.name)} {hasContent && download} ; @@ -62,14 +67,16 @@ const ExpandableAttachment: React.FunctionComponent = {placeholder && {placeholder}} - {expanded && attachmentText !== null && - } + {expanded && attachmentText !== null &&
+ + +
} ; }; diff --git a/packages/web/src/components/codeMirrorWrapper.tsx b/packages/web/src/components/codeMirrorWrapper.tsx index f8180f2e25bec..5549f5737e1f8 100644 --- a/packages/web/src/components/codeMirrorWrapper.tsx +++ b/packages/web/src/components/codeMirrorWrapper.tsx @@ -28,6 +28,8 @@ export type SourceHighlight = { export type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl' | 'html' | 'css' | 'markdown'; +export const lineHeight = 20; + export interface SourceProps { text: string; language?: Language; From dbe881cfdc0e4a7f42442b8244c6d5ee2d607e82 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 8 Oct 2024 08:35:02 -0700 Subject: [PATCH 280/805] docs: add a section on balancing shards (#33011) Closes https://github.com/microsoft/playwright/issues/32922 --- docs/src/test-sharding-js.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/src/test-sharding-js.md b/docs/src/test-sharding-js.md index 263733e78db78..d4b474ca9b682 100644 --- a/docs/src/test-sharding-js.md +++ b/docs/src/test-sharding-js.md @@ -26,6 +26,25 @@ Now, if you run these shards in parallel on different jobs, your test suite comp Note that Playwright can only shard tests that can be run in parallel. By default, this means Playwright will shard test files. Learn about other options in the [parallelism guide](./test-parallel.md). + +## Balancing Shards + +Sharding can be done at two levels of granularity depending on whether you use the [`property: TestProject.fullyParallel`] option or not. This affects how the tests are balanced across the shards. + +**Sharding with fullyParallel** + +When `fullyParallel: true` is enabled, Playwright Test runs individual tests in parallel across multiple shards, ensuring each shard receives an even distribution of tests. This allows for test-level granularity, meaning each shard will attempt to balance the number of individual tests it runs. This is the preferred mode for ensuring even load distribution when sharding, as Playwright can optimize shard execution based on the total number of tests. + +**Sharding without fullyParallel** + +Without the fullyParallel setting, Playwright Test defaults to file-level granularity, meaning entire test files are assigned to shards. In this case, the number of tests per file can greatly influence shard distribution. If your test files are not evenly sized (i.e., some files contain many more tests than others), certain shards may end up running significantly more tests, while others may run fewer or even none. + +**Key Takeaways:** + +- **With** `fullyParallel: true`: Tests are split at the individual test level, leading to more balanced shard execution. +- **Without** `fullyParallel`: Tests are split at the file level, so to balance the shards, it's important to keep your test files small and evenly sized. +- To ensure the most effective use of sharding, especially in CI environments, it is recommended to use `fullyParallel: true` when aiming for balanced distribution across shards. Otherwise, you may need to manually organize your test files to avoid imbalances. + ## Merging reports from multiple shards In the previous example, each test shard has its own test report. If you want to have a combined report showing all the test results from all the shards, you can merge them. From 5121b19ac618432c9203282c07d8448b4889869d Mon Sep 17 00:00:00 2001 From: Fumiaki MATSUSHIMA Date: Wed, 9 Oct 2024 03:38:52 +0900 Subject: [PATCH 281/805] fix(codegen): fix unselect issue (#32127) Fixes https://github.com/microsoft/playwright/issues/31290 --- .../src/server/codegen/java.ts | 2 +- .../src/server/codegen/javascript.ts | 2 +- tests/library/inspector/cli-codegen-1.spec.ts | 89 ++++++++++++++++++- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/src/server/codegen/java.ts b/packages/playwright-core/src/server/codegen/java.ts index 507a040bcec66..5b417c6c3a82d 100644 --- a/packages/playwright-core/src/server/codegen/java.ts +++ b/packages/playwright-core/src/server/codegen/java.ts @@ -122,7 +122,7 @@ export class JavaLanguageGenerator implements LanguageGenerator { case 'navigate': return `${subject}.navigate(${quote(action.url)});`; case 'select': - return `${subject}.${this._asLocator(action.selector, inFrameLocator)}.selectOption(${formatSelectOption(action.options.length > 1 ? action.options : action.options[0])});`; + return `${subject}.${this._asLocator(action.selector, inFrameLocator)}.selectOption(${formatSelectOption(action.options.length === 1 ? action.options[0] : action.options)});`; case 'assertText': return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).${action.substring ? 'containsText' : 'hasText'}(${quote(action.text)});`; case 'assertChecked': diff --git a/packages/playwright-core/src/server/codegen/javascript.ts b/packages/playwright-core/src/server/codegen/javascript.ts index 558670cd47842..b68a8104a86e2 100644 --- a/packages/playwright-core/src/server/codegen/javascript.ts +++ b/packages/playwright-core/src/server/codegen/javascript.ts @@ -106,7 +106,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { case 'navigate': return `await ${subject}.goto(${quote(action.url)});`; case 'select': - return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length > 1 ? action.options : action.options[0])});`; + return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length === 1 ? action.options[0] : action.options)});`; case 'assertText': return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? 'toContainText' : 'toHaveText'}(${quote(action.text)});`; case 'assertChecked': diff --git a/tests/library/inspector/cli-codegen-1.spec.ts b/tests/library/inspector/cli-codegen-1.spec.ts index a876a25e47c2a..765ad241b676b 100644 --- a/tests/library/inspector/cli-codegen-1.spec.ts +++ b/tests/library/inspector/cli-codegen-1.spec.ts @@ -15,7 +15,7 @@ */ import { test, expect } from './inspectorTest'; -import type { ConsoleMessage } from 'playwright'; +import type { ConsoleMessage, Locator } from 'playwright'; test.describe('cli codegen', () => { test.skip(({ mode }) => mode !== 'default'); @@ -682,6 +682,93 @@ await page.Locator(\"#age\").SelectOptionAsync(new[] { \"2\" });`); expect(message.text()).toBe('2'); }); + const clickMultipleSelectOption = async (locator: Locator, withCtrlOrMeta = false) => { + const page = locator.page(); + + // Webkit can't click multiple select options + // https://github.com/microsoft/playwright/issues/32126 + if (page.context().browser().browserType().name() === 'webkit') { + const elem = await locator.elementHandle(); + const rect = await elem!.evaluate(e => { + return e.getBoundingClientRect()!; + }); + if (withCtrlOrMeta) + await page.keyboard.down('ControlOrMeta'); + + await page.mouse.click(rect.x + rect.width / 2, rect.y + rect.height / 2); + if (withCtrlOrMeta) + await page.keyboard.up('ControlOrMeta'); + + } else { + await locator.click({ modifiers: withCtrlOrMeta ? ['ControlOrMeta'] : [] }); + } + }; + + test('should select with multiple attribute', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); + + await recorder.setContentAndWait(``); + + const locator = await recorder.hoverOverElement('select'); + expect(locator).toBe(`locator('#age')`); + await clickMultipleSelectOption(page.getByRole('option', { name: '1' })); + + const [message, sources] = await Promise.all([ + page.waitForEvent('console', msg => msg.type() !== 'error' && msg.text().includes('2')), + recorder.waitForOutput('JavaScript', 'selectOption(['), + clickMultipleSelectOption(page.getByRole('option', { name: '2' }), true) + ]); + + expect(sources.get('JavaScript')!.text).toContain(` + await page.locator('#age').selectOption(['1', '2']);`); + + expect(sources.get('Java')!.text).toContain(` + page.locator("#age").selectOption(new String[] {"1", "2"});`); + + expect(sources.get('Python')!.text).toContain(` + page.locator("#age").select_option(["1", "2"])`); + + expect(sources.get('Python Async')!.text).toContain(` + await page.locator("#age").select_option(["1", "2"])`); + + expect(sources.get('C#')!.text).toContain(` +await page.Locator("#age").SelectOptionAsync(new[] { "1", "2" });`); + + expect(message.text()).toBe('[1,2]'); + }); + + test('should unselect with multiple attribute', async ({ openRecorder }) => { + const { page, recorder } = await openRecorder(); + + await recorder.setContentAndWait(``); + const locator = await recorder.hoverOverElement('select'); + expect(locator).toBe(`locator('#age')`); + await clickMultipleSelectOption(page.getByRole('option', { name: '1' })); + + const [message, sources] = await Promise.all([ + page.waitForEvent('console', msg => msg.type() !== 'error' && msg.text() === '[]'), + recorder.waitForOutput('JavaScript', 'selectOption(['), + clickMultipleSelectOption(page.getByRole('option', { name: '1' }), true) + ]); + + expect(sources.get('JavaScript')!.text).toContain(` + await page.locator('#age').selectOption([]);`); + + expect(sources.get('Java')!.text).toContain(` + page.locator("#age").selectOption(new String[0]);`); + + expect(sources.get('Python')!.text).toContain(` + page.locator("#age").select_option([])`); + + expect(sources.get('Python Async')!.text).toContain(` + await page.locator("#age").select_option([])`); + + expect(sources.get('C#')!.text).toContain(` +await page.Locator("#age").SelectOptionAsync(new[] { });`); + + expect(message.text()).toBe('[]'); + }); + test('should await popup', async ({ openRecorder }) => { const { page, recorder } = await openRecorder(); await recorder.setContentAndWait('link'); From 892d67ffef4a24d0c0aa0e2e17031283b5b497ee Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 8 Oct 2024 20:39:54 +0200 Subject: [PATCH 282/805] feat(test runner): allow stopping testrun with escape (#32584) Closes https://github.com/microsoft/playwright/issues/32579 --- packages/playwright/src/runner/watchMode.ts | 90 ++++++++++++--------- tests/playwright-test/watch.spec.ts | 22 ++++- 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/packages/playwright/src/runner/watchMode.ts b/packages/playwright/src/runner/watchMode.ts index bdbe2d5c2d279..310cdeb546443 100644 --- a/packages/playwright/src/runner/watchMode.ts +++ b/packages/playwright/src/runner/watchMode.ts @@ -16,7 +16,7 @@ import readline from 'readline'; import path from 'path'; -import { createGuid, getPackageManagerExecCommand, ManualPromise } from 'playwright-core/lib/utils'; +import { createGuid, eventsHelper, getPackageManagerExecCommand, ManualPromise } from 'playwright-core/lib/utils'; import type { ConfigLocation } from '../common/config'; import type { FullResult } from '../../types/testReporter'; import { colors } from 'playwright-core/lib/utilsBundle'; @@ -266,12 +266,47 @@ export async function runWatchModeLoop(configLocation: ConfigLocation, initialOp return result === 'passed' ? teardown.status : result; } +function readKeyPress(handler: (text: string, key: any) => T | undefined): { cancel(): void; result: Promise } { + const promise = new ManualPromise(); + + const rl = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 }); + readline.emitKeypressEvents(process.stdin, rl); + if (process.stdin.isTTY) + process.stdin.setRawMode(true); + + const listener = eventsHelper.addEventListener(process.stdin, 'keypress', (text: string, key: any) => { + const result = handler(text, key); + if (result) + promise.resolve(result); + }); + + const cancel = () => { + eventsHelper.removeEventListeners([listener]); + rl.close(); + if (process.stdin.isTTY) + process.stdin.setRawMode(false); + }; + + void promise.finally(cancel); + + return { result: promise, cancel }; +} + +const isInterrupt = (text: string, key: any) => text === '\x03' || text === '\x1B' || (key && key.name === 'escape') || (key && key.ctrl && key.name === 'c'); + async function runTests(watchOptions: WatchModeOptions, testServerConnection: TestServerConnection, options?: { title?: string, testIds?: string[], }) { printConfiguration(watchOptions, options?.title); + const waitForDone = readKeyPress((text: string, key: any) => { + if (isInterrupt(text, key)) { + testServerConnection.stopTestsNoReply({}); + return 'done'; + } + }); + await testServerConnection.runTests({ grep: watchOptions.grep, testIds: options?.testIds, @@ -281,30 +316,21 @@ async function runTests(watchOptions: WatchModeOptions, testServerConnection: Te reuseContext: connectWsEndpoint ? true : undefined, workers: connectWsEndpoint ? 1 : undefined, headed: connectWsEndpoint ? true : undefined, - }); + }).finally(() => waitForDone.cancel()); } -function readCommand(): { result: Promise, cancel: () => void } { - const result = new ManualPromise(); - const rl = readline.createInterface({ input: process.stdin, escapeCodeTimeout: 50 }); - readline.emitKeypressEvents(process.stdin, rl); - if (process.stdin.isTTY) - process.stdin.setRawMode(true); - - const handler = (text: string, key: any) => { - if (text === '\x03' || text === '\x1B' || (key && key.name === 'escape') || (key && key.ctrl && key.name === 'c')) { - result.resolve('interrupted'); - return; - } +function readCommand() { + return readKeyPress((text: string, key: any) => { + if (isInterrupt(text, key)) + return 'interrupted'; if (process.platform !== 'win32' && key && key.ctrl && key.name === 'z') { process.kill(process.ppid, 'SIGTSTP'); process.kill(process.pid, 'SIGTSTP'); } const name = key?.name; - if (name === 'q') { - result.resolve('exit'); - return; - } + if (name === 'q') + return 'exit'; + if (name === 'h') { process.stdout.write(`${separator()} Run tests @@ -324,26 +350,16 @@ Change settings } switch (name) { - case 'return': result.resolve('run'); break; - case 'r': result.resolve('repeat'); break; - case 'c': result.resolve('project'); break; - case 'p': result.resolve('file'); break; - case 't': result.resolve('grep'); break; - case 'f': result.resolve('failed'); break; - case 's': result.resolve('toggle-show-browser'); break; - case 'b': result.resolve('toggle-buffer-mode'); break; + case 'return': return 'run'; + case 'r': return 'repeat'; + case 'c': return 'project'; + case 'p': return 'file'; + case 't': return 'grep'; + case 'f': return 'failed'; + case 's': return 'toggle-show-browser'; + case 'b': return 'toggle-buffer-mode'; } - }; - - process.stdin.on('keypress', handler); - const cancel = () => { - process.stdin.off('keypress', handler); - rl.close(); - if (process.stdin.isTTY) - process.stdin.setRawMode(false); - }; - void result.finally(cancel); - return { result, cancel }; + }); } let showBrowserServer: PlaywrightServer | undefined; diff --git a/tests/playwright-test/watch.spec.ts b/tests/playwright-test/watch.spec.ts index 4f687f72fc539..2e5159b16b31e 100644 --- a/tests/playwright-test/watch.spec.ts +++ b/tests/playwright-test/watch.spec.ts @@ -421,6 +421,7 @@ test('should re-run failed tests on F > R', async ({ runWatchTest }) => { await testProcess.waitForOutput('npx playwright test (running failed tests) #2'); await testProcess.waitForOutput('c.test.ts:3:11 › fails'); expect(testProcess.output).not.toContain('a.test.ts:3:11'); + await testProcess.waitForOutput('Waiting for file changes.'); testProcess.clearOutput(); testProcess.write('r'); await testProcess.waitForOutput('npx playwright test (re-running tests) #3'); @@ -836,6 +837,25 @@ test('should run global teardown before exiting', async ({ runWatchTest }) => { await testProcess.waitForOutput('running teardown'); }); +test('should stop testrun on pressing escape', async ({ runWatchTest }) => { + const testProcess = await runWatchTest({ + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + test('stalls', async () => { + console.log('test started') + await new Promise(() => {}); + }); + `, + }); + await testProcess.waitForOutput('Waiting for file changes.'); + testProcess.clearOutput(); + testProcess.write('\r\n'); + + await testProcess.waitForOutput('test started'); + testProcess.write('\x1B'); + await testProcess.waitForOutput('1 interrupted'); +}); + test('buffer mode', async ({ runWatchTest, writeFiles }) => { const testProcess = await runWatchTest({ 'a.test.ts': ` @@ -880,4 +900,4 @@ test('buffer mode', async ({ runWatchTest, writeFiles }) => { await testProcess.waitForOutput('a.test.ts:3:11 › passes'); await testProcess.waitForOutput('b.test.ts:3:11 › passes'); -}); \ No newline at end of file +}); From bcf4ff1e47a5d911578b8b7e993e9f9f68d24a05 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 8 Oct 2024 11:58:01 -0700 Subject: [PATCH 283/805] chore(bidi): update setContent expectations for ff (#32992) --- tests/bidi/expectationReporter.ts | 3 +- .../bidi-firefox-beta-library.txt | 1911 ---------------- .../expectations/bidi-firefox-beta-page.txt | 1971 ----------------- .../bidi-firefox-nightly-library.txt | 398 ++-- .../bidi-firefox-nightly-page.txt | 1296 +++++------ 5 files changed, 862 insertions(+), 4717 deletions(-) delete mode 100644 tests/bidi/expectations/bidi-firefox-beta-library.txt delete mode 100644 tests/bidi/expectations/bidi-firefox-beta-page.txt diff --git a/tests/bidi/expectationReporter.ts b/tests/bidi/expectationReporter.ts index a6d31ac1f5405..e136149cc4339 100644 --- a/tests/bidi/expectationReporter.ts +++ b/tests/bidi/expectationReporter.ts @@ -56,7 +56,8 @@ class ExpectationReporter implements Reporter { const outcome = getOutcome(test); // Strip root and project names. const key = test.titlePath().slice(2).join(' › '); - if (!expectations.has(key) || expectations.get(key) === 'unknown') + if (!expectations.has(key) || expectations.get(key) === 'unknown' || + (expectations.get(key) === 'fail' && outcome === 'pass')) expectations.set(key, outcome); } const keys = Array.from(expectations.keys()); diff --git a/tests/bidi/expectations/bidi-firefox-beta-library.txt b/tests/bidi/expectations/bidi-firefox-beta-library.txt deleted file mode 100644 index f7ac5ee9167b3..0000000000000 --- a/tests/bidi/expectations/bidi-firefox-beta-library.txt +++ /dev/null @@ -1,1911 +0,0 @@ -library/beforeunload.spec.ts › should access page after beforeunload [fail] -library/beforeunload.spec.ts › should be able to navigate away from page with beforeunload [fail] -library/beforeunload.spec.ts › should close browser with beforeunload page [fail] -library/beforeunload.spec.ts › should close browsercontext with beforeunload page [pass] -library/beforeunload.spec.ts › should close page with beforeunload listener [pass] -library/beforeunload.spec.ts › should not stall on evaluate when dismissing beforeunload [fail] -library/beforeunload.spec.ts › should run beforeunload if asked for @smoke [fail] -library/browser.spec.ts › should create new page @smoke [pass] -library/browser.spec.ts › should dispatch page.on(close) upon browser.close and reject evaluate [pass] -library/browser.spec.ts › should return browserType [pass] -library/browser.spec.ts › should throw upon second create new page [pass] -library/browser.spec.ts › version should work [pass] -library/browsercontext-add-cookies.spec.ts › should add cookies with empty value [pass] -library/browsercontext-add-cookies.spec.ts › should allow unnamed cookies [fail] -library/browsercontext-add-cookies.spec.ts › should be able to set unsecure cookie for HTTP website [pass] -library/browsercontext-add-cookies.spec.ts › should default to setting secure cookie for HTTPS websites [pass] -library/browsercontext-add-cookies.spec.ts › should have |expires| set to |-1| for session cookies [pass] -library/browsercontext-add-cookies.spec.ts › should isolate cookies between launches [pass] -library/browsercontext-add-cookies.spec.ts › should isolate cookies in browser contexts [pass] -library/browsercontext-add-cookies.spec.ts › should isolate persistent cookies [pass] -library/browsercontext-add-cookies.spec.ts › should isolate send cookie header [fail] -library/browsercontext-add-cookies.spec.ts › should isolate session cookies [pass] -library/browsercontext-add-cookies.spec.ts › should not block third party SameSite=None cookies [fail] -library/browsercontext-add-cookies.spec.ts › should not set a cookie on a data URL page [pass] -library/browsercontext-add-cookies.spec.ts › should not set a cookie with blank page URL [pass] -library/browsercontext-add-cookies.spec.ts › should roundtrip cookie [pass] -library/browsercontext-add-cookies.spec.ts › should send cookie header [pass] -library/browsercontext-add-cookies.spec.ts › should set a cookie on a different domain [pass] -library/browsercontext-add-cookies.spec.ts › should set a cookie with a path [pass] -library/browsercontext-add-cookies.spec.ts › should set cookie with reasonable defaults [fail] -library/browsercontext-add-cookies.spec.ts › should set cookies for a frame [pass] -library/browsercontext-add-cookies.spec.ts › should set multiple cookies [pass] -library/browsercontext-add-cookies.spec.ts › should set secure cookies on secure WebSocket [fail] -library/browsercontext-add-cookies.spec.ts › should work @smoke [pass] -library/browsercontext-add-cookies.spec.ts › should work with expires=-1 [fail] -library/browsercontext-add-cookies.spec.ts › should(not) block third party cookies [fail] -library/browsercontext-add-init-script.spec.ts › should work with browser context scripts @smoke [pass] -library/browsercontext-add-init-script.spec.ts › should work with browser context scripts for already created pages [pass] -library/browsercontext-add-init-script.spec.ts › should work with browser context scripts with a path [pass] -library/browsercontext-add-init-script.spec.ts › should work without navigation in popup [fail] -library/browsercontext-add-init-script.spec.ts › should work without navigation, after all bindings [fail] -library/browsercontext-base-url.spec.ts › should be able to match a URL relative to its given URL with urlMatcher [fail] -library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newContext is passed to page.goto @smoke [pass] -library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browser.newPage is passed to page.goto [pass] -library/browsercontext-base-url.spec.ts › should construct a new URL when a baseURL in browserType.launchPersistentContext is passed to page.goto [fail] -library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL with a trailing slash in browser.newPage is passed to page.goto [pass] -library/browsercontext-base-url.spec.ts › should construct the URLs correctly when a baseURL without a trailing slash in browser.newPage is passed to page.goto [pass] -library/browsercontext-base-url.spec.ts › should not construct a new URL when valid URLs are passed [pass] -library/browsercontext-base-url.spec.ts › should not construct a new URL with baseURL when a glob was used [pass] -library/browsercontext-basic.spec.ts › close() should abort waitForEvent [fail] -library/browsercontext-basic.spec.ts › close() should be callable twice [pass] -library/browsercontext-basic.spec.ts › close() should work for empty context [pass] -library/browsercontext-basic.spec.ts › default user agent [pass] -library/browsercontext-basic.spec.ts › setContent should work after disabling javascript [fail] -library/browsercontext-basic.spec.ts › should be able to click across browser contexts [fail] -library/browsercontext-basic.spec.ts › should be able to navigate after disabling javascript [pass] -library/browsercontext-basic.spec.ts › should close all belonging pages once closing context [fail] -library/browsercontext-basic.spec.ts › should create new context @smoke [pass] -library/browsercontext-basic.spec.ts › should disable javascript [fail] -library/browsercontext-basic.spec.ts › should emulate media in cross-process iframe [fail] -library/browsercontext-basic.spec.ts › should emulate media in popup [fail] -library/browsercontext-basic.spec.ts › should emulate navigator.onLine [fail] -library/browsercontext-basic.spec.ts › should isolate localStorage and cookies @smoke [pass] -library/browsercontext-basic.spec.ts › should make a copy of default viewport [pass] -library/browsercontext-basic.spec.ts › should not allow deviceScaleFactor with null viewport [pass] -library/browsercontext-basic.spec.ts › should not allow isMobile with null viewport [pass] -library/browsercontext-basic.spec.ts › should not hang on promises after disabling javascript [pass] -library/browsercontext-basic.spec.ts › should not report frameless pages on error [pass] -library/browsercontext-basic.spec.ts › should pass self to close event [pass] -library/browsercontext-basic.spec.ts › should propagate default viewport to the page [pass] -library/browsercontext-basic.spec.ts › should respect deviceScaleFactor [pass] -library/browsercontext-basic.spec.ts › should return all of the pages [pass] -library/browsercontext-basic.spec.ts › should work with offline option [fail] -library/browsercontext-basic.spec.ts › window.open should use parent tab context [pass] -library/browsercontext-clearcookies.spec.ts › should clear cookies [pass] -library/browsercontext-clearcookies.spec.ts › should isolate cookies when clearing [pass] -library/browsercontext-clearcookies.spec.ts › should remove cookies by domain [pass] -library/browsercontext-clearcookies.spec.ts › should remove cookies by name [pass] -library/browsercontext-clearcookies.spec.ts › should remove cookies by name and domain [pass] -library/browsercontext-clearcookies.spec.ts › should remove cookies by name regex [pass] -library/browsercontext-clearcookies.spec.ts › should remove cookies by path [pass] -library/browsercontext-cookies.spec.ts › should add cookies with an expiration [pass] -library/browsercontext-cookies.spec.ts › should be able to send third party cookies via an iframe [fail] -library/browsercontext-cookies.spec.ts › should get a cookie @smoke [fail] -library/browsercontext-cookies.spec.ts › should get a non-session cookie [fail] -library/browsercontext-cookies.spec.ts › should get cookies from multiple urls [pass] -library/browsercontext-cookies.spec.ts › should get multiple cookies [fail] -library/browsercontext-cookies.spec.ts › should parse cookie with large Max-Age correctly [fail] -library/browsercontext-cookies.spec.ts › should properly report "Lax" sameSite cookie [pass] -library/browsercontext-cookies.spec.ts › should properly report "Strict" sameSite cookie [pass] -library/browsercontext-cookies.spec.ts › should properly report httpOnly cookie [pass] -library/browsercontext-cookies.spec.ts › should return cookies with empty value [pass] -library/browsercontext-cookies.spec.ts › should return no cookies in pristine browser context [pass] -library/browsercontext-cookies.spec.ts › should return secure cookies based on HTTP(S) protocol [pass] -library/browsercontext-cookies.spec.ts › should support requestStorageAccess [fail] -library/browsercontext-cookies.spec.ts › should work with subdomain cookie [pass] -library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching hostname [pass] -library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching port [pass] -library/browsercontext-credentials.spec.ts › should fail with correct credentials and mismatching scheme [pass] -library/browsercontext-credentials.spec.ts › should fail with wrong credentials [timeout] -library/browsercontext-credentials.spec.ts › should fail without credentials [timeout] -library/browsercontext-credentials.spec.ts › should return resource body [fail] -library/browsercontext-credentials.spec.ts › should work with correct credentials @smoke [fail] -library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin [fail] -library/browsercontext-credentials.spec.ts › should work with correct credentials and matching origin case insensitive [fail] -library/browsercontext-credentials.spec.ts › should work with setHTTPCredentials [timeout] -library/browsercontext-csp.spec.ts › should bypass CSP header [fail] -library/browsercontext-csp.spec.ts › should bypass CSP in iframes as well [fail] -library/browsercontext-csp.spec.ts › should bypass CSP meta tag @smoke [fail] -library/browsercontext-csp.spec.ts › should bypass after cross-process navigation [fail] -library/browsercontext-device.spec.ts › device › should emulate viewport and screen size [fail] -library/browsercontext-device.spec.ts › device › should emulate viewport without screen size [fail] -library/browsercontext-device.spec.ts › device › should reset scroll top after a navigation [pass] -library/browsercontext-device.spec.ts › device › should scroll to a precise position with mobile scale [pass] -library/browsercontext-device.spec.ts › device › should scroll to click [pass] -library/browsercontext-device.spec.ts › device › should scroll twice when emulated [fail] -library/browsercontext-device.spec.ts › device › should support clicking [pass] -library/browsercontext-device.spec.ts › device › should work @smoke [fail] -library/browsercontext-dsf.spec.ts › should fetch hidpi assets [fail] -library/browsercontext-dsf.spec.ts › should fetch lodpi assets @smoke [pass] -library/browsercontext-events.spec.ts › console event should work @smoke [pass] -library/browsercontext-events.spec.ts › console event should work in immediately closed popup [fail] -library/browsercontext-events.spec.ts › console event should work in popup [pass] -library/browsercontext-events.spec.ts › console event should work in popup 2 [fail] -library/browsercontext-events.spec.ts › dialog event should work @smoke [pass] -library/browsercontext-events.spec.ts › dialog event should work in immediately closed popup [pass] -library/browsercontext-events.spec.ts › dialog event should work in popup [pass] -library/browsercontext-events.spec.ts › dialog event should work in popup 2 [fail] -library/browsercontext-events.spec.ts › dialog event should work with inline script tag [fail] -library/browsercontext-events.spec.ts › weberror event should work [fail] -library/browsercontext-expose-function.spec.ts › expose binding should work [fail] -library/browsercontext-expose-function.spec.ts › exposeBindingHandle should work [fail] -library/browsercontext-expose-function.spec.ts › should be callable from-inside addInitScript [fail] -library/browsercontext-expose-function.spec.ts › should throw for duplicate registrations [pass] -library/browsercontext-expose-function.spec.ts › should work [fail] -library/browsercontext-expose-function.spec.ts › should work with CSP [fail] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail if response content-length header is missing (br) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should not fail with chunked responses (without Content-Length header) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › br decompression › should support decompression [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail if response content-length header is missing (deflate) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should not fail with chunked responses (without Content-Length header) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › deflate decompression › should support decompression [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail if response content-length header is missing (gzip) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response with content-length header (Z_BUF_ERROR) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with an empty response without content-length header (Z_BUF_ERROR) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should not fail with chunked responses (without Content-Length header) [pass] -library/browsercontext-fetch-algorithms.spec.ts › algorithms › gzip decompression › should support decompression [pass] -library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work [pass] -library/browsercontext-fetch-happy-eyeballs.spec.ts › get should work on request fixture [pass] -library/browsercontext-fetch-happy-eyeballs.spec.ts › https post should work with ignoreHTTPSErrors option [pass] -library/browsercontext-fetch-happy-eyeballs.spec.ts › should work with ip6 and port as the host [pass] -library/browsercontext-fetch.spec.ts › context request should export same storage state as context [pass] -library/browsercontext-fetch.spec.ts › delete should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › delete should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › delete should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › delete should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › delete should support post data [pass] -library/browsercontext-fetch.spec.ts › deleteshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › fetch should not throw on long set-cookie value [pass] -library/browsercontext-fetch.spec.ts › fetch should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › fetch should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › fetch should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › fetch should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › fetch should work [pass] -library/browsercontext-fetch.spec.ts › fetchshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › get should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › get should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › get should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › get should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › get should support post data [pass] -library/browsercontext-fetch.spec.ts › get should work @smoke [pass] -library/browsercontext-fetch.spec.ts › getshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › head should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › head should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › head should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › head should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › head should support post data [pass] -library/browsercontext-fetch.spec.ts › headshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › patch should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › patch should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › patch should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › patch should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › patch should support post data [pass] -library/browsercontext-fetch.spec.ts › patchshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › post should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › post should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › post should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › post should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › post should support post data [pass] -library/browsercontext-fetch.spec.ts › postshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › put should support failOnStatusCode [pass] -library/browsercontext-fetch.spec.ts › put should support params passed as URLSearchParams [pass] -library/browsercontext-fetch.spec.ts › put should support params passed as object [pass] -library/browsercontext-fetch.spec.ts › put should support params passed as string [pass] -library/browsercontext-fetch.spec.ts › put should support post data [pass] -library/browsercontext-fetch.spec.ts › putshould support ignoreHTTPSErrors option [pass] -library/browsercontext-fetch.spec.ts › should abort requests when browser context closes [pass] -library/browsercontext-fetch.spec.ts › should accept bool and numeric params [pass] -library/browsercontext-fetch.spec.ts › should add cookies from Set-Cookie header [pass] -library/browsercontext-fetch.spec.ts › should add default headers [fail] -library/browsercontext-fetch.spec.ts › should add default headers to redirects [pass] -library/browsercontext-fetch.spec.ts › should add session cookies to request [pass] -library/browsercontext-fetch.spec.ts › should allow to override default headers [pass] -library/browsercontext-fetch.spec.ts › should dispose [pass] -library/browsercontext-fetch.spec.ts › should dispose when context closes [pass] -library/browsercontext-fetch.spec.ts › should encode to application/json by default [pass] -library/browsercontext-fetch.spec.ts › should follow redirects [pass] -library/browsercontext-fetch.spec.ts › should follow redirects correctly when Location header contains UTF-8 characters [pass] -library/browsercontext-fetch.spec.ts › should handle cookies on redirects [pass] -library/browsercontext-fetch.spec.ts › should inherit ignoreHTTPSErrors from context [pass] -library/browsercontext-fetch.spec.ts › should not add context cookie if cookie header passed as a parameter [pass] -library/browsercontext-fetch.spec.ts › should not hang on a brotli encoded Range request [pass] -library/browsercontext-fetch.spec.ts › should not lose body while handling Set-Cookie header [pass] -library/browsercontext-fetch.spec.ts › should not work after context dispose [pass] -library/browsercontext-fetch.spec.ts › should not work after dispose [pass] -library/browsercontext-fetch.spec.ts › should override request parameters [pass] -library/browsercontext-fetch.spec.ts › should preserve cookie order from Set-Cookie header [pass] -library/browsercontext-fetch.spec.ts › should propagate custom headers with redirects [pass] -library/browsercontext-fetch.spec.ts › should propagate extra http headers with redirects [fail] -library/browsercontext-fetch.spec.ts › should remove cookie with expires far in the past [pass] -library/browsercontext-fetch.spec.ts › should remove cookie with negative max-age [pass] -library/browsercontext-fetch.spec.ts › should resolve url relative to baseURL [pass] -library/browsercontext-fetch.spec.ts › should respect timeout after redirects [pass] -library/browsercontext-fetch.spec.ts › should retry on ECONNRESET [pass] -library/browsercontext-fetch.spec.ts › should return error with wrong credentials [pass] -library/browsercontext-fetch.spec.ts › should return raw headers [pass] -library/browsercontext-fetch.spec.ts › should send content-length [pass] -library/browsercontext-fetch.spec.ts › should send secure cookie over http for localhost [pass] -library/browsercontext-fetch.spec.ts › should serialize data to json regardless of content-type [pass] -library/browsercontext-fetch.spec.ts › should set domain=localhost cookie [pass] -library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for browser.newPage [pass] -library/browsercontext-fetch.spec.ts › should support HTTPCredentials.send for newContext [pass] -library/browsercontext-fetch.spec.ts › should support SameSite cookie attribute over https [pass] -library/browsercontext-fetch.spec.ts › should support a timeout of 0 [pass] -library/browsercontext-fetch.spec.ts › should support application/x-www-form-urlencoded [pass] -library/browsercontext-fetch.spec.ts › should support brotli compression [pass] -library/browsercontext-fetch.spec.ts › should support cookie with empty value [pass] -library/browsercontext-fetch.spec.ts › should support deflate compression [pass] -library/browsercontext-fetch.spec.ts › should support gzip compression [pass] -library/browsercontext-fetch.spec.ts › should support https [pass] -library/browsercontext-fetch.spec.ts › should support multipart/form-data [pass] -library/browsercontext-fetch.spec.ts › should support multipart/form-data and keep the order [pass] -library/browsercontext-fetch.spec.ts › should support multipart/form-data with ReadStream values [pass] -library/browsercontext-fetch.spec.ts › should support repeating names in multipart/form-data [unknown] -library/browsercontext-fetch.spec.ts › should support set-cookie with SameSite and without Secure attribute over HTTP [pass] -library/browsercontext-fetch.spec.ts › should support timeout option [pass] -library/browsercontext-fetch.spec.ts › should throw informative error on corrupted brotli body [pass] -library/browsercontext-fetch.spec.ts › should throw informative error on corrupted deflate body [pass] -library/browsercontext-fetch.spec.ts › should throw informative error on corrupted gzip body [pass] -library/browsercontext-fetch.spec.ts › should throw nice error on unsupported data type [pass] -library/browsercontext-fetch.spec.ts › should throw on invalid header value [pass] -library/browsercontext-fetch.spec.ts › should throw on network error [pass] -library/browsercontext-fetch.spec.ts › should throw on network error after redirect [pass] -library/browsercontext-fetch.spec.ts › should throw on network error when sending body [pass] -library/browsercontext-fetch.spec.ts › should throw on network error when sending body after redirect [pass] -library/browsercontext-fetch.spec.ts › should throw on non-http(s) protocol [pass] -library/browsercontext-fetch.spec.ts › should update host header on redirect [pass] -library/browsercontext-fetch.spec.ts › should work with connectOverCDP [unknown] -library/browsercontext-fetch.spec.ts › should work with http credentials [pass] -library/browsercontext-fetch.spec.ts › should work with setHTTPCredentials [pass] -library/browsercontext-har.spec.ts › by default should abort requests not found in har [pass] -library/browsercontext-har.spec.ts › context.unrouteAll should stop context.routeFromHAR [fail] -library/browsercontext-har.spec.ts › fallback:continue should continue requests on bad har [pass] -library/browsercontext-har.spec.ts › fallback:continue should continue when not found in har [pass] -library/browsercontext-har.spec.ts › newPage should fulfill from har, matching the method and following redirects [pass] -library/browsercontext-har.spec.ts › page.unrouteAll should stop page.routeFromHAR [pass] -library/browsercontext-har.spec.ts › should apply overrides before routing from har [pass] -library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] -library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [fail] -library/browsercontext-har.spec.ts › should context.routeFromHAR, matching the method and following redirects [pass] -library/browsercontext-har.spec.ts › should disambiguate by header [fail] -library/browsercontext-har.spec.ts › should fulfill from har with content in a file [pass] -library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] -library/browsercontext-har.spec.ts › should goForward to redirected navigation [timeout] -library/browsercontext-har.spec.ts › should ignore aborted requests [pass] -library/browsercontext-har.spec.ts › should ignore boundary when matching multipart/form-data body [timeout] -library/browsercontext-har.spec.ts › should only context.routeFromHAR requests matching url filter [pass] -library/browsercontext-har.spec.ts › should only handle requests matching url filter [pass] -library/browsercontext-har.spec.ts › should only page.routeFromHAR requests matching url filter [fail] -library/browsercontext-har.spec.ts › should page.routeFromHAR, matching the method and following redirects [pass] -library/browsercontext-har.spec.ts › should produce extracted zip [fail] -library/browsercontext-har.spec.ts › should record overridden requests to har [timeout] -library/browsercontext-har.spec.ts › should reload redirected navigation [fail] -library/browsercontext-har.spec.ts › should round-trip extracted har.zip [fail] -library/browsercontext-har.spec.ts › should round-trip har with postData [fail] -library/browsercontext-har.spec.ts › should round-trip har.zip [fail] -library/browsercontext-har.spec.ts › should support regex filter [pass] -library/browsercontext-har.spec.ts › should update extracted har.zip for page [fail] -library/browsercontext-har.spec.ts › should update har.zip for context [fail] -library/browsercontext-har.spec.ts › should update har.zip for page [fail] -library/browsercontext-har.spec.ts › should update har.zip for page with different options [fail] -library/browsercontext-locale.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().locale [fail] -library/browsercontext-locale.spec.ts › should affect accept-language header @smoke [fail] -library/browsercontext-locale.spec.ts › should affect navigator.language [fail] -library/browsercontext-locale.spec.ts › should affect navigator.language in popups [fail] -library/browsercontext-locale.spec.ts › should be isolated between contexts [fail] -library/browsercontext-locale.spec.ts › should format date [fail] -library/browsercontext-locale.spec.ts › should format number [fail] -library/browsercontext-locale.spec.ts › should format number in popups [fail] -library/browsercontext-locale.spec.ts › should format number in workers [fail] -library/browsercontext-locale.spec.ts › should not change default locale in another context [fail] -library/browsercontext-locale.spec.ts › should work for multiple pages sharing same process [timeout] -library/browsercontext-network-event.spec.ts › BrowserContext.Events.Request [fail] -library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFailed [fail] -library/browsercontext-network-event.spec.ts › BrowserContext.Events.RequestFinished [pass] -library/browsercontext-network-event.spec.ts › BrowserContext.Events.Response [fail] -library/browsercontext-network-event.spec.ts › should fire events in proper order [pass] -library/browsercontext-network-event.spec.ts › should not fire events for favicon or favicon redirects [unknown] -library/browsercontext-page-event.spec.ts › should fire page lifecycle events [fail] -library/browsercontext-page-event.spec.ts › should have about:blank for empty url with domcontentloaded [timeout] -library/browsercontext-page-event.spec.ts › should have about:blank url with domcontentloaded [pass] -library/browsercontext-page-event.spec.ts › should have an opener [fail] -library/browsercontext-page-event.spec.ts › should have url [fail] -library/browsercontext-page-event.spec.ts › should have url after domcontentloaded [pass] -library/browsercontext-page-event.spec.ts › should not crash while redirecting of original request was missed [pass] -library/browsercontext-page-event.spec.ts › should not hang on ctrl-click during provisional load [fail] -library/browsercontext-page-event.spec.ts › should report initialized pages [fail] -library/browsercontext-page-event.spec.ts › should report when a new page is created and closed [fail] -library/browsercontext-page-event.spec.ts › should work with Ctrl-clicking [fail] -library/browsercontext-page-event.spec.ts › should work with Shift-clicking [fail] -library/browsercontext-pages.spec.ts › frame.focus should work multiple times [fail] -library/browsercontext-pages.spec.ts › page.context should return the correct instance [pass] -library/browsercontext-pages.spec.ts › should click the button with deviceScaleFactor set [fail] -library/browsercontext-pages.spec.ts › should click the button with offset with page scale [pass] -library/browsercontext-pages.spec.ts › should click with disabled javascript [pass] -library/browsercontext-pages.spec.ts › should keep selection in multiple pages [fail] -library/browsercontext-pages.spec.ts › should not be visible in context.pages [fail] -library/browsercontext-pages.spec.ts › should not hang with touch-enabled viewports [pass] -library/browsercontext-pages.spec.ts › should not leak listeners during navigation of 20 pages [pass] -library/browsercontext-pages.spec.ts › should return bounding box with page scale [pass] -library/browsercontext-proxy.spec.ts › does launch without a port [pass] -library/browsercontext-proxy.spec.ts › should authenticate [fail] -library/browsercontext-proxy.spec.ts › should authenticate with empty password [fail] -library/browsercontext-proxy.spec.ts › should exclude patterns [fail] -library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts [fail] -library/browsercontext-proxy.spec.ts › should isolate proxy credentials between contexts on navigation [fail] -library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › link-local [fail] -library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › localhost [fail] -library/browsercontext-proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] -library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [fail] -library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] -library/browsercontext-proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] -library/browsercontext-proxy.spec.ts › should set cookie for top-level domain [pass] -library/browsercontext-proxy.spec.ts › should throw for bad server value [pass] -library/browsercontext-proxy.spec.ts › should throw for socks4 authentication [pass] -library/browsercontext-proxy.spec.ts › should throw for socks5 authentication [pass] -library/browsercontext-proxy.spec.ts › should use ipv6 proxy [fail] -library/browsercontext-proxy.spec.ts › should use proxy [fail] -library/browsercontext-proxy.spec.ts › should use proxy for https urls [timeout] -library/browsercontext-proxy.spec.ts › should use proxy for second page [fail] -library/browsercontext-proxy.spec.ts › should use proxy twice [fail] -library/browsercontext-proxy.spec.ts › should use socks proxy [fail] -library/browsercontext-proxy.spec.ts › should use socks proxy in second page [fail] -library/browsercontext-proxy.spec.ts › should work when passing the proxy only on the context level [fail] -library/browsercontext-proxy.spec.ts › should work with IP:PORT notion [fail] -library/browsercontext-reuse.spec.ts › should continue issuing events after closing the reused page [pass] -library/browsercontext-reuse.spec.ts › should ignore binding from beforeunload [fail] -library/browsercontext-reuse.spec.ts › should not cache resources [timeout] -library/browsercontext-reuse.spec.ts › should re-add binding after reset [fail] -library/browsercontext-reuse.spec.ts › should reset mouse position [fail] -library/browsercontext-reuse.spec.ts › should reset serviceworker [pass] -library/browsercontext-reuse.spec.ts › should reset serviceworker that hangs in importScripts [pass] -library/browsercontext-reuse.spec.ts › should reset tracing [pass] -library/browsercontext-reuse.spec.ts › should work with clock emulation [pass] -library/browsercontext-route.spec.ts › should chain fallback [fail] -library/browsercontext-route.spec.ts › should chain fallback into page [pass] -library/browsercontext-route.spec.ts › should chain fallback w/ dynamic URL [fail] -library/browsercontext-route.spec.ts › should fall back async [fail] -library/browsercontext-route.spec.ts › should fall back to context.route [fail] -library/browsercontext-route.spec.ts › should ignore secure Set-Cookie header for insecure requests [pass] -library/browsercontext-route.spec.ts › should intercept [fail] -library/browsercontext-route.spec.ts › should not chain abort [pass] -library/browsercontext-route.spec.ts › should not chain fulfill [fail] -library/browsercontext-route.spec.ts › should overwrite post body with empty string [fail] -library/browsercontext-route.spec.ts › should support Set-Cookie header [fail] -library/browsercontext-route.spec.ts › should support async handler w/ times [fail] -library/browsercontext-route.spec.ts › should support the times parameter with route matching [fail] -library/browsercontext-route.spec.ts › should unroute [fail] -library/browsercontext-route.spec.ts › should use Set-Cookie header in future requests [fail] -library/browsercontext-route.spec.ts › should work if handler with times parameter was removed from another handler [fail] -library/browsercontext-route.spec.ts › should work with ignoreHTTPSErrors [fail] -library/browsercontext-route.spec.ts › should yield to page.route [fail] -library/browsercontext-service-worker-policy.spec.ts › block › blocks service worker registration [timeout] -library/browsercontext-service-worker-policy.spec.ts › block › should not throw error on about:blank [pass] -library/browsercontext-service-worker-policy.spec.ts › should allow service workers by default [pass] -library/browsercontext-set-extra-http-headers.spec.ts › should override extra headers from browser context [fail] -library/browsercontext-set-extra-http-headers.spec.ts › should throw for non-string header values [pass] -library/browsercontext-storage-state.spec.ts › should capture cookies [pass] -library/browsercontext-storage-state.spec.ts › should capture local storage [fail] -library/browsercontext-storage-state.spec.ts › should handle malformed file [pass] -library/browsercontext-storage-state.spec.ts › should handle missing file [pass] -library/browsercontext-storage-state.spec.ts › should not emit events about internal page [fail] -library/browsercontext-storage-state.spec.ts › should not restore localStorage twice [pass] -library/browsercontext-storage-state.spec.ts › should round-trip through the file [pass] -library/browsercontext-storage-state.spec.ts › should serialize storageState with lone surrogates [pass] -library/browsercontext-storage-state.spec.ts › should set local storage [fail] -library/browsercontext-storage-state.spec.ts › should work when service worker is intefering [pass] -library/browsercontext-strict.spec.ts › should not fail page.textContent in non-strict mode [fail] -library/browsercontext-strict.spec.ts › strict context mode › should fail page.click in strict mode [fail] -library/browsercontext-strict.spec.ts › strict context mode › should fail page.textContent in strict mode [fail] -library/browsercontext-strict.spec.ts › strict context mode › should opt out of strict mode [fail] -library/browsercontext-timezone-id.spec.ts › should affect Intl.DateTimeFormat().resolvedOptions().timeZone [fail] -library/browsercontext-timezone-id.spec.ts › should not change default timezone in another context [fail] -library/browsercontext-timezone-id.spec.ts › should throw for invalid timezone IDs when creating pages [fail] -library/browsercontext-timezone-id.spec.ts › should work @smoke [fail] -library/browsercontext-timezone-id.spec.ts › should work for multiple pages sharing same process [timeout] -library/browsercontext-user-agent.spec.ts › custom user agent for download [fail] -library/browsercontext-user-agent.spec.ts › should emulate device user-agent [fail] -library/browsercontext-user-agent.spec.ts › should make a copy of default options [fail] -library/browsercontext-user-agent.spec.ts › should work [fail] -library/browsercontext-user-agent.spec.ts › should work for navigator.userAgentData and sec-ch-ua headers [unknown] -library/browsercontext-user-agent.spec.ts › should work for subframes [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › default mobile viewports to 980 width [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › mouse should work with mobile viewports and cross process navigations [pass] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › respect meta viewport tag [pass] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should be detectable [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should detect touch when applying viewport with touches [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should emulate the hover media feature [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should fire orientationchange event [timeout] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should scroll when emulating a mobile viewport [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support landscape emulation [pass] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support mobile emulation [pass] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support touch emulation [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › should support window.orientation emulation [fail] -library/browsercontext-viewport-mobile.spec.ts › mobile viewport › view scale should reset after navigation [pass] -library/browsercontext-viewport.spec.ts › WebKit Windows headed should have a minimal viewport [unknown] -library/browsercontext-viewport.spec.ts › should be able to get correct orientation angle on non-mobile devices [fail] -library/browsercontext-viewport.spec.ts › should drag with high dpi [fail] -library/browsercontext-viewport.spec.ts › should emulate availWidth and availHeight [fail] -library/browsercontext-viewport.spec.ts › should emulate device height [fail] -library/browsercontext-viewport.spec.ts › should emulate device width [fail] -library/browsercontext-viewport.spec.ts › should get the proper default viewport size [pass] -library/browsercontext-viewport.spec.ts › should not have touch by default [pass] -library/browsercontext-viewport.spec.ts › should report null viewportSize when given null viewport [pass] -library/browsercontext-viewport.spec.ts › should return correct outerWidth and outerHeight [pass] -library/browsercontext-viewport.spec.ts › should set both screen and viewport options [fail] -library/browsercontext-viewport.spec.ts › should set the proper viewport size [pass] -library/browsercontext-viewport.spec.ts › should set window.screen.orientation.type for mobile devices [fail] -library/browsercontext-viewport.spec.ts › should support touch with null viewport [fail] -library/browsercontext-viewport.spec.ts › should throw on tap if hasTouch is not enabled [fail] -library/browsertype-basic.spec.ts › browserType.executablePath should work [unknown] -library/browsertype-basic.spec.ts › browserType.name should work [fail] -library/browsertype-basic.spec.ts › should throw when trying to connect with not-chromium [pass] -library/browsertype-connect.spec.ts › launchServer only › should be able to reconnect to a browser 12 times without warnings [timeout] -library/browsertype-connect.spec.ts › launchServer only › should properly disconnect when connection closes from the server side [timeout] -library/browsertype-connect.spec.ts › launchServer only › should work with cluster [timeout] -library/browsertype-connect.spec.ts › launchServer › disconnected event should be emitted when browser is closed or server is closed [timeout] -library/browsertype-connect.spec.ts › launchServer › disconnected event should have browser as argument [timeout] -library/browsertype-connect.spec.ts › launchServer › setInputFiles should preserve lastModified timestamp [timeout] -library/browsertype-connect.spec.ts › launchServer › should be able to connect 20 times to a single server without warnings [timeout] -library/browsertype-connect.spec.ts › launchServer › should be able to connect two browsers at the same time [timeout] -library/browsertype-connect.spec.ts › launchServer › should be able to connect when the wsEndpoint is passed as an option [timeout] -library/browsertype-connect.spec.ts › launchServer › should be able to reconnect to a browser [timeout] -library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 [timeout] -library/browsertype-connect.spec.ts › launchServer › should be able to visit ipv6 through localhost [timeout] -library/browsertype-connect.spec.ts › launchServer › should connect over http [timeout] -library/browsertype-connect.spec.ts › launchServer › should connect over wss [timeout] -library/browsertype-connect.spec.ts › launchServer › should emit close events on pages and contexts [timeout] -library/browsertype-connect.spec.ts › launchServer › should error when saving download after deletion [timeout] -library/browsertype-connect.spec.ts › launchServer › should filter launch options [timeout] -library/browsertype-connect.spec.ts › launchServer › should fulfill with global fetch result [timeout] -library/browsertype-connect.spec.ts › launchServer › should handle exceptions during connect [timeout] -library/browsertype-connect.spec.ts › launchServer › should ignore page.pause when headed [timeout] -library/browsertype-connect.spec.ts › launchServer › should not throw on close after disconnect [timeout] -library/browsertype-connect.spec.ts › launchServer › should print HTTP error [pass] -library/browsertype-connect.spec.ts › launchServer › should print custom ws close error [pass] -library/browsertype-connect.spec.ts › launchServer › should print ws error [pass] -library/browsertype-connect.spec.ts › launchServer › should properly disconnect when connection closes from the client side [timeout] -library/browsertype-connect.spec.ts › launchServer › should record trace with sources [timeout] -library/browsertype-connect.spec.ts › launchServer › should reject navigation when browser closes [timeout] -library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.close finishes [timeout] -library/browsertype-connect.spec.ts › launchServer › should reject waitForEvent before browser.onDisconnect fires [timeout] -library/browsertype-connect.spec.ts › launchServer › should reject waitForSelector when browser closes [timeout] -library/browsertype-connect.spec.ts › launchServer › should respect selectors [timeout] -library/browsertype-connect.spec.ts › launchServer › should save download [timeout] -library/browsertype-connect.spec.ts › launchServer › should save har [timeout] -library/browsertype-connect.spec.ts › launchServer › should saveAs videos from remote browser [timeout] -library/browsertype-connect.spec.ts › launchServer › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] -library/browsertype-connect.spec.ts › launchServer › should send extra headers with connect request [pass] -library/browsertype-connect.spec.ts › launchServer › should set the browser connected state [timeout] -library/browsertype-connect.spec.ts › launchServer › should support slowmo option [timeout] -library/browsertype-connect.spec.ts › launchServer › should terminate network waiters [timeout] -library/browsertype-connect.spec.ts › launchServer › should throw when calling waitForNavigation after disconnect [timeout] -library/browsertype-connect.spec.ts › launchServer › should throw when used after isConnected returns false [timeout] -library/browsertype-connect.spec.ts › launchServer › should timeout in connect while connecting [pass] -library/browsertype-connect.spec.ts › launchServer › should timeout in socket while connecting [pass] -library/browsertype-connect.spec.ts › launchServer › should upload large file [timeout] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should check proxy pattern on the client [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should forward non-forwarded requests [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should lead to the error page for forwarded requests when the connection is refused [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy based on the pattern [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy ipv6 localhost requests @smoke [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy local.playwright requests [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests @smoke [unknown] -library/browsertype-connect.spec.ts › launchServer › socks proxy › should proxy localhost requests from fetch api [unknown] -library/browsertype-connect.spec.ts › run-server › disconnected event should be emitted when browser is closed or server is closed [fail] -library/browsertype-connect.spec.ts › run-server › disconnected event should have browser as argument [fail] -library/browsertype-connect.spec.ts › run-server › setInputFiles should preserve lastModified timestamp [fail] -library/browsertype-connect.spec.ts › run-server › should be able to connect 20 times to a single server without warnings [fail] -library/browsertype-connect.spec.ts › run-server › should be able to connect two browsers at the same time [fail] -library/browsertype-connect.spec.ts › run-server › should be able to connect when the wsEndpoint is passed as an option [fail] -library/browsertype-connect.spec.ts › run-server › should be able to reconnect to a browser [fail] -library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 [fail] -library/browsertype-connect.spec.ts › run-server › should be able to visit ipv6 through localhost [fail] -library/browsertype-connect.spec.ts › run-server › should connect over http [fail] -library/browsertype-connect.spec.ts › run-server › should connect over wss [fail] -library/browsertype-connect.spec.ts › run-server › should emit close events on pages and contexts [fail] -library/browsertype-connect.spec.ts › run-server › should error when saving download after deletion [fail] -library/browsertype-connect.spec.ts › run-server › should filter launch options [fail] -library/browsertype-connect.spec.ts › run-server › should fulfill with global fetch result [fail] -library/browsertype-connect.spec.ts › run-server › should handle exceptions during connect [pass] -library/browsertype-connect.spec.ts › run-server › should ignore page.pause when headed [fail] -library/browsertype-connect.spec.ts › run-server › should not throw on close after disconnect [fail] -library/browsertype-connect.spec.ts › run-server › should print HTTP error [pass] -library/browsertype-connect.spec.ts › run-server › should print custom ws close error [pass] -library/browsertype-connect.spec.ts › run-server › should print ws error [pass] -library/browsertype-connect.spec.ts › run-server › should properly disconnect when connection closes from the client side [fail] -library/browsertype-connect.spec.ts › run-server › should record trace with sources [fail] -library/browsertype-connect.spec.ts › run-server › should reject navigation when browser closes [fail] -library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.close finishes [fail] -library/browsertype-connect.spec.ts › run-server › should reject waitForEvent before browser.onDisconnect fires [fail] -library/browsertype-connect.spec.ts › run-server › should reject waitForSelector when browser closes [fail] -library/browsertype-connect.spec.ts › run-server › should respect selectors [fail] -library/browsertype-connect.spec.ts › run-server › should save download [fail] -library/browsertype-connect.spec.ts › run-server › should save har [fail] -library/browsertype-connect.spec.ts › run-server › should saveAs videos from remote browser [fail] -library/browsertype-connect.spec.ts › run-server › should send default User-Agent and X-Playwright-Browser headers with connect request [fail] -library/browsertype-connect.spec.ts › run-server › should send extra headers with connect request [pass] -library/browsertype-connect.spec.ts › run-server › should set the browser connected state [fail] -library/browsertype-connect.spec.ts › run-server › should support slowmo option [fail] -library/browsertype-connect.spec.ts › run-server › should terminate network waiters [fail] -library/browsertype-connect.spec.ts › run-server › should throw when calling waitForNavigation after disconnect [fail] -library/browsertype-connect.spec.ts › run-server › should throw when used after isConnected returns false [fail] -library/browsertype-connect.spec.ts › run-server › should timeout in connect while connecting [pass] -library/browsertype-connect.spec.ts › run-server › should timeout in socket while connecting [pass] -library/browsertype-connect.spec.ts › run-server › should upload large file [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should check proxy pattern on the client [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should forward non-forwarded requests [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should lead to the error page for forwarded requests when the connection is refused [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy based on the pattern [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy ipv6 localhost requests @smoke [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy local.playwright requests [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests @smoke [fail] -library/browsertype-connect.spec.ts › run-server › socks proxy › should proxy localhost requests from fetch api [fail] -library/browsertype-connect.spec.ts › should refuse connecting when versions do not match [pass] -library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 hub + node chromium [unknown] -library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium [unknown] -library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone chromium through run-driver [unknown] -library/browsertype-launch-selenium.spec.ts › selenium grid 3.141.59 standalone non-chromium [unknown] -library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 hub + node chromium [unknown] -library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium [unknown] -library/browsertype-launch-selenium.spec.ts › selenium grid 4.8.3 standalone chromium broken driver [unknown] -library/browsertype-launch-server.spec.ts › launch server › should default to random wsPath [fail] -library/browsertype-launch-server.spec.ts › launch server › should fire "close" event during kill [fail] -library/browsertype-launch-server.spec.ts › launch server › should fire close event [fail] -library/browsertype-launch-server.spec.ts › launch server › should log protocol [fail] -library/browsertype-launch-server.spec.ts › launch server › should provide an error when ws endpoint is incorrect [fail] -library/browsertype-launch-server.spec.ts › launch server › should return child_process instance [fail] -library/browsertype-launch-server.spec.ts › launch server › should work [fail] -library/browsertype-launch-server.spec.ts › launch server › should work when wsPath is missing leading slash [fail] -library/browsertype-launch-server.spec.ts › launch server › should work with host [fail] -library/browsertype-launch-server.spec.ts › launch server › should work with port [fail] -library/browsertype-launch-server.spec.ts › launch server › should work with wsPath [fail] -library/browsertype-launch.spec.ts › should accept objects as options [pass] -library/browsertype-launch.spec.ts › should allow await using [pass] -library/browsertype-launch.spec.ts › should be callable twice [pass] -library/browsertype-launch.spec.ts › should fire close event for all contexts [pass] -library/browsertype-launch.spec.ts › should handle exception [pass] -library/browsertype-launch.spec.ts › should handle timeout [pass] -library/browsertype-launch.spec.ts › should reject all promises when browser is closed [pass] -library/browsertype-launch.spec.ts › should reject if executable path is invalid [pass] -library/browsertype-launch.spec.ts › should reject if launched browser fails immediately [fail] -library/browsertype-launch.spec.ts › should report launch log [pass] -library/browsertype-launch.spec.ts › should throw if page argument is passed [fail] -library/browsertype-launch.spec.ts › should throw if port option is passed [pass] -library/browsertype-launch.spec.ts › should throw if port option is passed for persistent context [pass] -library/browsertype-launch.spec.ts › should throw if userDataDir is passed as an argument [pass] -library/browsertype-launch.spec.ts › should throw if userDataDir option is passed [pass] -library/capabilities.spec.ts › Intl.ListFormat should work [pass] -library/capabilities.spec.ts › SharedArrayBuffer should work @smoke [fail] -library/capabilities.spec.ts › Web Assembly should work @smoke [pass] -library/capabilities.spec.ts › WebSocket should work @smoke [pass] -library/capabilities.spec.ts › loading in HTMLImageElement.prototype [pass] -library/capabilities.spec.ts › make sure that XMLHttpRequest upload events are emitted correctly [pass] -library/capabilities.spec.ts › navigator.clipboard should be present [pass] -library/capabilities.spec.ts › requestFullscreen [fail] -library/capabilities.spec.ts › service worker should cover the iframe [pass] -library/capabilities.spec.ts › service worker should register in an iframe [pass] -library/capabilities.spec.ts › serviceWorker should intercept document request [pass] -library/capabilities.spec.ts › should not crash on page with mp4 @smoke [fail] -library/capabilities.spec.ts › should not crash on showDirectoryPicker [flaky] -library/capabilities.spec.ts › should not crash on storage.getDirectory() [pass] -library/capabilities.spec.ts › should play audio @smoke [fail] -library/capabilities.spec.ts › should play video @smoke [pass] -library/capabilities.spec.ts › should play webm video @smoke [pass] -library/capabilities.spec.ts › should respect CSP @smoke [fail] -library/capabilities.spec.ts › should send no Content-Length header for GET requests with a Content-Type [pass] -library/capabilities.spec.ts › should set CloseEvent.wasClean to false when the server terminates a WebSocket connection [fail] -library/capabilities.spec.ts › should support webgl 2 @smoke [pass] -library/capabilities.spec.ts › should support webgl @smoke [fail] -library/capabilities.spec.ts › webkit should define window.safari [unknown] -library/capabilities.spec.ts › window.GestureEvent in WebKit [pass] -library/channels.spec.ts › exposeFunction should not leak [fail] -library/channels.spec.ts › should not generate dispatchers for subresources w/o listeners [pass] -library/channels.spec.ts › should scope CDPSession handles [unknown] -library/channels.spec.ts › should scope browser handles [pass] -library/channels.spec.ts › should scope context handles [pass] -library/channels.spec.ts › should work with the domain module [timeout] -library/chromium/bfcache.spec.ts › bindings should work after restoring from bfcache [fail] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › serviceWorker(), and fromServiceWorker() work [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setExtraHTTPHeaders [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › setOffline [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept only serviceworker request, not page [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker importScripts [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker requests (main and within) [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should intercept service worker update requests [unknown] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should produce network events, routing, and annotations for Service Worker (advanced) [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to content-type) of main service worker request [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report failure (due to redirect) of main service worker request [timeout] -library/chromium/chromium.spec.ts › PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS=1 › should report intercepted service worker requests in HAR [timeout] -library/chromium/chromium.spec.ts › Page.route should work with intervention headers [fail] -library/chromium/chromium.spec.ts › http credentials › httpCredentials [timeout] -library/chromium/chromium.spec.ts › serviceWorkers() should return current workers [timeout] -library/chromium/chromium.spec.ts › should close service worker together with the context [timeout] -library/chromium/chromium.spec.ts › should create a worker from a service worker [timeout] -library/chromium/chromium.spec.ts › should create a worker from service worker with noop routing [timeout] -library/chromium/chromium.spec.ts › should emit new service worker on update [timeout] -library/chromium/chromium.spec.ts › should not create a worker from a shared worker [pass] -library/chromium/chromium.spec.ts › should pass args with spaces [fail] -library/chromium/connect-over-cdp.spec.ts › emulate media should not be affected by second connectOverCDP [unknown] -library/chromium/connect-over-cdp.spec.ts › setInputFiles should preserve lastModified timestamp [fail] -library/chromium/connect-over-cdp.spec.ts › should allow tracing over cdp session [fail] -library/chromium/connect-over-cdp.spec.ts › should be able to connect via localhost [fail] -library/chromium/connect-over-cdp.spec.ts › should cleanup artifacts dir after connectOverCDP disconnects due to ws close [fail] -library/chromium/connect-over-cdp.spec.ts › should connect over a ws endpoint [fail] -library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session [fail] -library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session twice [fail] -library/chromium/connect-over-cdp.spec.ts › should connect to an existing cdp session when passed as a first argument [fail] -library/chromium/connect-over-cdp.spec.ts › should connect to existing page with iframe and navigate [fail] -library/chromium/connect-over-cdp.spec.ts › should connect to existing service workers [fail] -library/chromium/connect-over-cdp.spec.ts › should connect via https [fail] -library/chromium/connect-over-cdp.spec.ts › should connectOverCDP and manage downloads in default context [fail] -library/chromium/connect-over-cdp.spec.ts › should print custom ws close error [fail] -library/chromium/connect-over-cdp.spec.ts › should report all pages in an existing browser [fail] -library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpoint URL JSON webSocketDebuggerUrl is undefined [fail] -library/chromium/connect-over-cdp.spec.ts › should report an expected error when the endpointURL returns a non-expected status code [fail] -library/chromium/connect-over-cdp.spec.ts › should return valid browser from context.browser() [fail] -library/chromium/connect-over-cdp.spec.ts › should send default User-Agent header with connect request [timeout] -library/chromium/connect-over-cdp.spec.ts › should send extra headers with connect request [timeout] -library/chromium/connect-over-cdp.spec.ts › should use logger in default context [fail] -library/chromium/connect-over-cdp.spec.ts › should use proxy with connectOverCDP [fail] -library/chromium/css-coverage.spec.ts › should NOT report scripts across navigations [fail] -library/chromium/css-coverage.spec.ts › should ignore injected stylesheets [fail] -library/chromium/css-coverage.spec.ts › should report multiple stylesheets [fail] -library/chromium/css-coverage.spec.ts › should report sourceURLs [fail] -library/chromium/css-coverage.spec.ts › should report stylesheets across navigations [fail] -library/chromium/css-coverage.spec.ts › should report stylesheets that have no coverage [fail] -library/chromium/css-coverage.spec.ts › should work [fail] -library/chromium/css-coverage.spec.ts › should work with a recently loaded stylesheet [fail] -library/chromium/css-coverage.spec.ts › should work with complicated usecases [fail] -library/chromium/css-coverage.spec.ts › should work with media queries [fail] -library/chromium/disable-web-security.spec.ts › test init script w/ --disable-web-security [pass] -library/chromium/disable-web-security.spec.ts › test utility world in popup w/ --disable-web-security [pass] -library/chromium/js-coverage.spec.ts › should NOT report scripts across navigations when enabled [fail] -library/chromium/js-coverage.spec.ts › should ignore eval() scripts by default [fail] -library/chromium/js-coverage.spec.ts › should not hang when there is a debugger statement [fail] -library/chromium/js-coverage.spec.ts › should report multiple scripts [fail] -library/chromium/js-coverage.spec.ts › should report scripts across navigations when disabled [fail] -library/chromium/js-coverage.spec.ts › should report sourceURLs [fail] -library/chromium/js-coverage.spec.ts › should work [fail] -library/chromium/js-coverage.spec.ts › shouldn't ignore eval() scripts if reportAnonymousScripts is true [fail] -library/chromium/launcher.spec.ts › should not create pages automatically [fail] -library/chromium/launcher.spec.ts › should not throw with remote-debugging-port argument [fail] -library/chromium/launcher.spec.ts › should open devtools when "devtools: true" option is given [unknown] -library/chromium/launcher.spec.ts › should return background pages [fail] -library/chromium/launcher.spec.ts › should return background pages when recording video [fail] -library/chromium/launcher.spec.ts › should support request/response events when using backgroundPage() [fail] -library/chromium/launcher.spec.ts › should throw with remote-debugging-pipe argument [fail] -library/chromium/oopif.spec.ts › ElementHandle.boundingBox() should work [pass] -library/chromium/oopif.spec.ts › contentFrame should work [pass] -library/chromium/oopif.spec.ts › should allow cdp sessions on oopifs [fail] -library/chromium/oopif.spec.ts › should be able to click in iframe [fail] -library/chromium/oopif.spec.ts › should click [fail] -library/chromium/oopif.spec.ts › should click a button when it overlays oopif [fail] -library/chromium/oopif.spec.ts › should emit filechooser event for iframe [fail] -library/chromium/oopif.spec.ts › should emulate media [fail] -library/chromium/oopif.spec.ts › should emulate offline [fail] -library/chromium/oopif.spec.ts › should expose function [fail] -library/chromium/oopif.spec.ts › should get the proper viewport [unknown] -library/chromium/oopif.spec.ts › should handle oopif detach [pass] -library/chromium/oopif.spec.ts › should handle remote -> local -> remote transitions [pass] -library/chromium/oopif.spec.ts › should intercept response body from oopif [fail] -library/chromium/oopif.spec.ts › should load oopif iframes with subresources and route [pass] -library/chromium/oopif.spec.ts › should not throw on exposeFunction when oopif detaches [fail] -library/chromium/oopif.spec.ts › should report google.com frame with headed [pass] -library/chromium/oopif.spec.ts › should report main requests [pass] -library/chromium/oopif.spec.ts › should report oopif frames [pass] -library/chromium/oopif.spec.ts › should respect route [pass] -library/chromium/oopif.spec.ts › should support addInitScript [pass] -library/chromium/oopif.spec.ts › should support context options [fail] -library/chromium/oopif.spec.ts › should support exposeFunction [fail] -library/chromium/oopif.spec.ts › should take screenshot [fail] -library/chromium/session.spec.ts › should be able to detach session [fail] -library/chromium/session.spec.ts › should detach when page closes [fail] -library/chromium/session.spec.ts › should enable and disable domains independently [fail] -library/chromium/session.spec.ts › should not break page.close() [fail] -library/chromium/session.spec.ts › should only accept a page or frame [pass] -library/chromium/session.spec.ts › should reject protocol calls when page closes [fail] -library/chromium/session.spec.ts › should send events [fail] -library/chromium/session.spec.ts › should throw if target is part of main [fail] -library/chromium/session.spec.ts › should throw nice errors [fail] -library/chromium/session.spec.ts › should work [fail] -library/chromium/session.spec.ts › should work with main frame [fail] -library/chromium/session.spec.ts › should work with newBrowserCDPSession [fail] -library/chromium/tracing.spec.ts › should create directories as needed [fail] -library/chromium/tracing.spec.ts › should output a trace [fail] -library/chromium/tracing.spec.ts › should return a buffer [fail] -library/chromium/tracing.spec.ts › should run with custom categories if provided [fail] -library/chromium/tracing.spec.ts › should support a buffer without a path [fail] -library/chromium/tracing.spec.ts › should throw if tracing on two pages [fail] -library/chromium/tracing.spec.ts › should work without options [fail] -library/client-certificates.spec.ts › browser › persistentContext › should pass with matching certificates [fail] -library/client-certificates.spec.ts › browser › persistentContext › validate input [pass] -library/client-certificates.spec.ts › browser › should fail with matching certificates in legacy pfx format [pass] -library/client-certificates.spec.ts › browser › should fail with no client certificates [fail] -library/client-certificates.spec.ts › browser › should fail with self-signed client certificates [fail] -library/client-certificates.spec.ts › browser › should handle TLS renegotiation with client certificates [fail] -library/client-certificates.spec.ts › browser › should handle rejected certificate in handshake with HTTP/2 [pass] -library/client-certificates.spec.ts › browser › should have ignoreHTTPSErrors=false by default [fail] -library/client-certificates.spec.ts › browser › should keep supporting http [pass] -library/client-certificates.spec.ts › browser › should not hang on tls errors during TLS 1.2 handshake [fail] -library/client-certificates.spec.ts › browser › should pass with matching certificates [fail] -library/client-certificates.spec.ts › browser › should pass with matching certificates and trailing slash [fail] -library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format [fail] -library/client-certificates.spec.ts › browser › should pass with matching certificates in pfx format when passing as content [fail] -library/client-certificates.spec.ts › browser › should pass with matching certificates on context APIRequestContext instance [fail] -library/client-certificates.spec.ts › browser › should pass with matching certificates when passing as content [fail] -library/client-certificates.spec.ts › browser › should return target connection errors when using http2 [unknown] -library/client-certificates.spec.ts › browser › should throw a http error if the pfx passphrase is incorect [pass] -library/client-certificates.spec.ts › browser › support http2 [fail] -library/client-certificates.spec.ts › browser › support http2 if the browser only supports http1.1 [unknown] -library/client-certificates.spec.ts › browser › validate input [pass] -library/client-certificates.spec.ts › fetch › pass with trusted client certificates [pass] -library/client-certificates.spec.ts › fetch › pass with trusted client certificates in pfx format [pass] -library/client-certificates.spec.ts › fetch › should fail with matching certificates in legacy pfx format [pass] -library/client-certificates.spec.ts › fetch › should fail with no client certificates provided [pass] -library/client-certificates.spec.ts › fetch › should keep supporting http [pass] -library/client-certificates.spec.ts › fetch › should throw a http error if the pfx passphrase is incorect [pass] -library/client-certificates.spec.ts › fetch › should throw with untrusted client certs [pass] -library/client-certificates.spec.ts › fetch › should work in the browser with request interception [pass] -library/client-certificates.spec.ts › fetch › validate input [pass] -library/clock.spec.ts › Intl API › Creates a RelativeTimeFormat like normal [pass] -library/clock.spec.ts › Intl API › Executes formatRange like normal [pass] -library/clock.spec.ts › Intl API › Executes formatRangeToParts like normal [pass] -library/clock.spec.ts › Intl API › Executes resolvedOptions like normal [pass] -library/clock.spec.ts › Intl API › Executes supportedLocalesOf like normal [pass] -library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed a timestamp argument that is not first of the month [pass] -library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns false when passed no timestamp and system time is not first of the month [pass] -library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed a timestamp argument that is first of the month [pass] -library/clock.spec.ts › Intl API › formatToParts via isFirstOfMonth -> Returns true when passed no timestamp and system time is first of the month [pass] -library/clock.spec.ts › cancelAnimationFrame › does not remove interval [pass] -library/clock.spec.ts › cancelAnimationFrame › does not remove timeout [pass] -library/clock.spec.ts › cancelAnimationFrame › ignores null argument [pass] -library/clock.spec.ts › cancelAnimationFrame › removes animation frame [pass] -library/clock.spec.ts › cancelIdleCallback › removes idle callback [pass] -library/clock.spec.ts › clearInterval › ignores null argument [pass] -library/clock.spec.ts › clearInterval › removes interval [pass] -library/clock.spec.ts › clearInterval › removes interval with undefined interval [pass] -library/clock.spec.ts › clearInterval › removes timeout [pass] -library/clock.spec.ts › clearTimeout › ignores null argument [pass] -library/clock.spec.ts › clearTimeout › removes interval [pass] -library/clock.spec.ts › clearTimeout › removes interval with undefined interval [pass] -library/clock.spec.ts › clearTimeout › removes timeout [pass] -library/clock.spec.ts › date › creates Date objects representing clock time [pass] -library/clock.spec.ts › date › creates real Date objects [pass] -library/clock.spec.ts › date › creates regular date when passing a date as RFC 2822 string [pass] -library/clock.spec.ts › date › creates regular date when passing a date as string [pass] -library/clock.spec.ts › date › creates regular date when passing timestamp [pass] -library/clock.spec.ts › date › creates regular date when passing y, m, d [pass] -library/clock.spec.ts › date › creates regular date when passing y, m, d, h [pass] -library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m [pass] -library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s [pass] -library/clock.spec.ts › date › creates regular date when passing y, m, d, h, m, s, ms [pass] -library/clock.spec.ts › date › creates regular date when passing year, month [pass] -library/clock.spec.ts › date › listens to system clock changes [pass] -library/clock.spec.ts › date › listens to ticking clock [pass] -library/clock.spec.ts › date › mirrors UTC method [pass] -library/clock.spec.ts › date › mirrors native Date.prototype [pass] -library/clock.spec.ts › date › mirrors parse method [pass] -library/clock.spec.ts › date › mirrors toUTCString method [pass] -library/clock.spec.ts › date › provides date constructor [pass] -library/clock.spec.ts › date › returns clock.now() [pass] -library/clock.spec.ts › date › returns date as string representing clock time [pass] -library/clock.spec.ts › date › returns date as string when called as function [pass] -library/clock.spec.ts › date › returns date as string when calling with arguments [pass] -library/clock.spec.ts › date › returns date as string when calling with timestamp [pass] -library/clock.spec.ts › date › supports now method if present [pass] -library/clock.spec.ts › fastForward › handles multiple pending timers and types [pass] -library/clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] -library/clock.spec.ts › fastForward › pushes back execution time for skipped timers [pass] -library/clock.spec.ts › pauseAt › fire target timers [pass] -library/clock.spec.ts › pauseAt › pause at target time [pass] -library/clock.spec.ts › pauseAt › returns consumed clicks [pass] -library/clock.spec.ts › performance.now() › should listen to multiple ticks in performance.now [pass] -library/clock.spec.ts › performance.now() › should run along with clock.tick [pass] -library/clock.spec.ts › performance.now() › should run with ticks with timers set [pass] -library/clock.spec.ts › performance.now() › should start at 0 [pass] -library/clock.spec.ts › requestAnimationFrame › returns numeric id or object with numeric id [pass] -library/clock.spec.ts › requestAnimationFrame › returns unique id [pass] -library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() even when performance unavailable [pass] -library/clock.spec.ts › requestAnimationFrame › should be called with performance.now() when available [pass] -library/clock.spec.ts › requestAnimationFrame › should call callback once [pass] -library/clock.spec.ts › requestAnimationFrame › should properly schedule callback for 3rd frame [pass] -library/clock.spec.ts › requestAnimationFrame › should run every 16ms [pass] -library/clock.spec.ts › requestAnimationFrame › should schedule for next frame if on current frame [pass] -library/clock.spec.ts › requestAnimationFrame › should schedule two callbacks before the next frame at the same time [pass] -library/clock.spec.ts › requestAnimationFrame › throws if no arguments [pass] -library/clock.spec.ts › requestIdleCallback › doesn't runs if there are any timers and no timeout option [pass] -library/clock.spec.ts › requestIdleCallback › returns numeric id [pass] -library/clock.spec.ts › requestIdleCallback › returns unique id [pass] -library/clock.spec.ts › requestIdleCallback › runs after all timers [pass] -library/clock.spec.ts › requestIdleCallback › runs no later than timeout option even if there are any timers [pass] -library/clock.spec.ts › requestIdleCallback › throws if no arguments [pass] -library/clock.spec.ts › runFor › calls function with global object or null (strict mode) as this [pass] -library/clock.spec.ts › runFor › creates updated Date while ticking [pass] -library/clock.spec.ts › runFor › creates updated Date while ticking promises [pass] -library/clock.spec.ts › runFor › does not fire canceled intervals [pass] -library/clock.spec.ts › runFor › does not fire intervals canceled in a promise [pass] -library/clock.spec.ts › runFor › does not silently catch errors [pass] -library/clock.spec.ts › runFor › does not trigger without sufficient delay [pass] -library/clock.spec.ts › runFor › fires nested setTimeout calls in user-created promises properly [pass] -library/clock.spec.ts › runFor › fires nested setTimeout calls properly [pass] -library/clock.spec.ts › runFor › fires promise timers in correct order [pass] -library/clock.spec.ts › runFor › fires timer in intervals of "13" [pass] -library/clock.spec.ts › runFor › fires timer in intervals of 13 [pass] -library/clock.spec.ts › runFor › fires timers in correct order [pass] -library/clock.spec.ts › runFor › is not influenced by forward system clock changes [pass] -library/clock.spec.ts › runFor › is not influenced by forward system clock changes 2 [pass] -library/clock.spec.ts › runFor › is not influenced by forward system clock changes in promises [pass] -library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown [pass] -library/clock.spec.ts › runFor › is not influenced by forward system clock changes when an error is thrown 2 [pass] -library/clock.spec.ts › runFor › mini integration test [pass] -library/clock.spec.ts › runFor › should settle chained user-created promises [pass] -library/clock.spec.ts › runFor › should settle local nested promises before calling timeouts [pass] -library/clock.spec.ts › runFor › should settle local promises before calling timeouts [pass] -library/clock.spec.ts › runFor › should settle multiple user-created promises [pass] -library/clock.spec.ts › runFor › should settle nested user-created promises [pass] -library/clock.spec.ts › runFor › should settle user-created promises [pass] -library/clock.spec.ts › runFor › should settle user-created promises before calling more timeouts [pass] -library/clock.spec.ts › runFor › should settle user-created promises even if some throw [pass] -library/clock.spec.ts › runFor › throws for negative minutes [pass] -library/clock.spec.ts › runFor › throws on negative ticks [pass] -library/clock.spec.ts › runFor › triggers after sufficient delay [pass] -library/clock.spec.ts › runFor › triggers even when some throw [pass] -library/clock.spec.ts › runFor › triggers immediately without specified delay [pass] -library/clock.spec.ts › runFor › triggers in the order scheduled [pass] -library/clock.spec.ts › runFor › triggers multiple simultaneous timers [pass] -library/clock.spec.ts › runFor › triggers multiple simultaneous timers with zero callAt [pass] -library/clock.spec.ts › runFor › triggers simultaneous timers [pass] -library/clock.spec.ts › runFor › triggers timeouts and intervals in the order scheduled [pass] -library/clock.spec.ts › runFor › waits after setTimeout was called [pass] -library/clock.spec.ts › setInterval › does not schedule recurring timeout when cleared [pass] -library/clock.spec.ts › setInterval › does not throw if |undefined| or |null| is passed as a callback [pass] -library/clock.spec.ts › setInterval › is not influenced by backward system clock changes [pass] -library/clock.spec.ts › setInterval › is not influenced by forward system clock changes [pass] -library/clock.spec.ts › setInterval › passes setTimeout parameters [pass] -library/clock.spec.ts › setInterval › returns numeric id or object with numeric id [pass] -library/clock.spec.ts › setInterval › returns unique id [pass] -library/clock.spec.ts › setInterval › schedules recurring timeout [pass] -library/clock.spec.ts › setInterval › throws if no arguments [pass] -library/clock.spec.ts › setTimeout › calls correct timeout on recursive tick [pass] -library/clock.spec.ts › setTimeout › does not depend on this [pass] -library/clock.spec.ts › setTimeout › does not throw if |undefined| or |null| is passed as a callback [pass] -library/clock.spec.ts › setTimeout › is not influenced by backward system clock changes [pass] -library/clock.spec.ts › setTimeout › is not influenced by forward system clock changes [pass] -library/clock.spec.ts › setTimeout › parses no-numeric string times [pass] -library/clock.spec.ts › setTimeout › parses numeric string times [pass] -library/clock.spec.ts › setTimeout › passes setTimeout parameters [pass] -library/clock.spec.ts › setTimeout › returns numeric id or object with numeric id [pass] -library/clock.spec.ts › setTimeout › returns unique id [pass] -library/clock.spec.ts › setTimeout › sets timers on instance [pass] -library/clock.spec.ts › setTimeout › starts id from a large number [pass] -library/clock.spec.ts › setTimeout › throws if no arguments [pass] -library/clock.spec.ts › setTimeout › use of eval when not in node › evals non-function callbacks [pass] -library/clock.spec.ts › setTimeout › use of eval when not in node › only evals on global scope [pass] -library/clock.spec.ts › stubTimers › deletes global property on uninstall if it was inherited onto the global object [unknown] -library/clock.spec.ts › stubTimers › does not fake methods not provided [pass] -library/clock.spec.ts › stubTimers › fake Date constructor should mirror Date's properties [pass] -library/clock.spec.ts › stubTimers › fakes Date constructor [pass] -library/clock.spec.ts › stubTimers › fakes provided methods [pass] -library/clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] -library/clock.spec.ts › stubTimers › mirrors custom Date properties [pass] -library/clock.spec.ts › stubTimers › replace Event.prototype.timeStamp [pass] -library/clock.spec.ts › stubTimers › replaces global clearInterval [pass] -library/clock.spec.ts › stubTimers › replaces global clearTimeout [pass] -library/clock.spec.ts › stubTimers › replaces global performance.now [pass] -library/clock.spec.ts › stubTimers › replaces global setInterval [pass] -library/clock.spec.ts › stubTimers › replaces global setTimeout [pass] -library/clock.spec.ts › stubTimers › resets faked methods [pass] -library/clock.spec.ts › stubTimers › returns clock object [pass] -library/clock.spec.ts › stubTimers › sets initial timestamp [pass] -library/clock.spec.ts › stubTimers › should let performance.mark still be callable after install() (#136) [unknown] -library/clock.spec.ts › stubTimers › should not alter the global performance properties and methods [unknown] -library/clock.spec.ts › stubTimers › should replace the getEntries, getEntriesByX methods with noops that return [] [unknown] -library/clock.spec.ts › stubTimers › takes an object parameter [pass] -library/clock.spec.ts › stubTimers › uninstalls Date constructor [pass] -library/clock.spec.ts › stubTimers › uninstalls global performance.now [pass] -library/clock.spec.ts › works with concurrent runFor calls [pass] -library/clock.spec.ts › works with slow setTimeout in busy embedder [pass] -library/clock.spec.ts › works with slow setTimeout in busy embedder when not paused [pass] -library/component-parser.spec.ts › should escape [pass] -library/component-parser.spec.ts › should parse [pass] -library/component-parser.spec.ts › should parse all operators [pass] -library/component-parser.spec.ts › should parse bool [pass] -library/component-parser.spec.ts › should parse float values [pass] -library/component-parser.spec.ts › should parse identifiers [pass] -library/component-parser.spec.ts › should parse int values [pass] -library/component-parser.spec.ts › should parse regex [pass] -library/component-parser.spec.ts › should parse short attributes [pass] -library/component-parser.spec.ts › should parse unquoted string [pass] -library/component-parser.spec.ts › should throw on malformed selector [pass] -library/component-parser.spec.ts › should tolerate spacing [pass] -library/css-parser.spec.ts › should parse css [pass] -library/css-parser.spec.ts › should throw on malformed css [pass] -library/debug-controller.spec.ts › should highlight all [fail] -library/debug-controller.spec.ts › should navigate all [fail] -library/debug-controller.spec.ts › should pick element [fail] -library/debug-controller.spec.ts › should record [fail] -library/debug-controller.spec.ts › should record custom data-testid [fail] -library/debug-controller.spec.ts › should report pages [fail] -library/debug-controller.spec.ts › should reset for reuse [fail] -library/debug-controller.spec.ts › should reset routes before reuse [fail] -library/defaultbrowsercontext-1.spec.ts › context.addCookies() should work [fail] -library/defaultbrowsercontext-1.spec.ts › context.clearCookies() should work [fail] -library/defaultbrowsercontext-1.spec.ts › context.cookies() should work @smoke [fail] -library/defaultbrowsercontext-1.spec.ts › should support acceptDownloads option [fail] -library/defaultbrowsercontext-1.spec.ts › should support bypassCSP option [fail] -library/defaultbrowsercontext-1.spec.ts › should support deviceScaleFactor option [fail] -library/defaultbrowsercontext-1.spec.ts › should support httpCredentials option [fail] -library/defaultbrowsercontext-1.spec.ts › should support javascriptEnabled option [fail] -library/defaultbrowsercontext-1.spec.ts › should support offline option [fail] -library/defaultbrowsercontext-1.spec.ts › should support userAgent option [fail] -library/defaultbrowsercontext-1.spec.ts › should support viewport option [fail] -library/defaultbrowsercontext-1.spec.ts › should(not) block third party cookies [fail] -library/defaultbrowsercontext-2.spec.ts › coverage should work [unknown] -library/defaultbrowsercontext-2.spec.ts › should accept userDataDir [fail] -library/defaultbrowsercontext-2.spec.ts › should connect to a browser with the default page [fail] -library/defaultbrowsercontext-2.spec.ts › should create userDataDir if it does not exist [fail] -library/defaultbrowsercontext-2.spec.ts › should fire close event for a persistent context [fail] -library/defaultbrowsercontext-2.spec.ts › should handle exception [timeout] -library/defaultbrowsercontext-2.spec.ts › should handle timeout [pass] -library/defaultbrowsercontext-2.spec.ts › should have default URL when launching browser [fail] -library/defaultbrowsercontext-2.spec.ts › should have passed URL when launching with ignoreDefaultArgs: true [fail] -library/defaultbrowsercontext-2.spec.ts › should respect selectors [fail] -library/defaultbrowsercontext-2.spec.ts › should restore state from userDataDir [fail] -library/defaultbrowsercontext-2.spec.ts › should support colorScheme option [fail] -library/defaultbrowsercontext-2.spec.ts › should support extraHTTPHeaders option [fail] -library/defaultbrowsercontext-2.spec.ts › should support forcedColors option [fail] -library/defaultbrowsercontext-2.spec.ts › should support geolocation and permissions options [fail] -library/defaultbrowsercontext-2.spec.ts › should support har option [fail] -library/defaultbrowsercontext-2.spec.ts › should support hasTouch option [fail] -library/defaultbrowsercontext-2.spec.ts › should support ignoreHTTPSErrors option [fail] -library/defaultbrowsercontext-2.spec.ts › should support locale option [fail] -library/defaultbrowsercontext-2.spec.ts › should support reducedMotion option [fail] -library/defaultbrowsercontext-2.spec.ts › should support timezoneId option [fail] -library/defaultbrowsercontext-2.spec.ts › should throw if page argument is passed [fail] -library/defaultbrowsercontext-2.spec.ts › should work in persistent context [fail] -library/defaultbrowsercontext-2.spec.ts › user agent is up to date [fail] -library/download.spec.ts › download event › should be able to cancel pending downloads [fail] -library/download.spec.ts › download event › should close the context without awaiting the download [fail] -library/download.spec.ts › download event › should close the context without awaiting the failed download [unknown] -library/download.spec.ts › download event › should create subdirectories when saving to non-existent user-specified path [fail] -library/download.spec.ts › download event › should delete downloads on browser gone [fail] -library/download.spec.ts › download event › should delete downloads on context destruction [fail] -library/download.spec.ts › download event › should delete file [fail] -library/download.spec.ts › download event › should download large binary.zip [fail] -library/download.spec.ts › download event › should emit download event from nested iframes [timeout] -library/download.spec.ts › download event › should error when saving after deletion [fail] -library/download.spec.ts › download event › should error when saving with downloads disabled [fail] -library/download.spec.ts › download event › should expose stream [fail] -library/download.spec.ts › download event › should not fail explicitly to cancel a download even if that is already finished [fail] -library/download.spec.ts › download event › should report alt-click downloads [fail] -library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Blobs [timeout] -library/download.spec.ts › download event › should report download path within page.on('download', …) handler for Files [fail] -library/download.spec.ts › download event › should report download when navigation turns into download @smoke [timeout] -library/download.spec.ts › download event › should report downloads for download attribute [fail] -library/download.spec.ts › download event › should report downloads with acceptDownloads: false [fail] -library/download.spec.ts › download event › should report downloads with acceptDownloads: true [fail] -library/download.spec.ts › download event › should report downloads with interception [fail] -library/download.spec.ts › download event › should report new window downloads [fail] -library/download.spec.ts › download event › should report non-navigation downloads [fail] -library/download.spec.ts › download event › should report proper download url when download is from download attribute [fail] -library/download.spec.ts › download event › should save to overwritten filepath [fail] -library/download.spec.ts › download event › should save to two different paths with multiple saveAs calls [fail] -library/download.spec.ts › download event › should save to user-specified path without updating original path [fail] -library/download.spec.ts › download event › should throw if browser dies [fail] -library/download.spec.ts › download event › should work with Cross-Origin-Opener-Policy [timeout] -library/download.spec.ts › should be able to download a PDF file [fail] -library/download.spec.ts › should be able to download a inline PDF file via navigation [fail] -library/download.spec.ts › should be able to download a inline PDF file via response interception [fail] -library/download.spec.ts › should convert navigation to a resource with unsupported mime type into download [timeout] -library/download.spec.ts › should download even if there is no "attachment" value [fail] -library/download.spec.ts › should download links with data url [fail] -library/download.spec.ts › should download successfully when routing [fail] -library/download.spec.ts › should save to user-specified path [fail] -library/downloads-path.spec.ts › downloads path › should accept downloads in persistent context [fail] -library/downloads-path.spec.ts › downloads path › should delete downloads when context closes [fail] -library/downloads-path.spec.ts › downloads path › should delete downloads when persistent context closes [fail] -library/downloads-path.spec.ts › downloads path › should keep downloadsPath folder [fail] -library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder [fail] -library/downloads-path.spec.ts › downloads path › should report downloads in downloadsPath folder with a relative path [fail] -library/emulation-focus.spec.ts › should change document.activeElement [pass] -library/emulation-focus.spec.ts › should change focused iframe [pass] -library/emulation-focus.spec.ts › should focus popups by default [fail] -library/emulation-focus.spec.ts › should focus with more than one page/context [fail] -library/emulation-focus.spec.ts › should not affect mouse event target page [pass] -library/emulation-focus.spec.ts › should not affect screenshots [fail] -library/emulation-focus.spec.ts › should not fire blur events when interacting with more than one page/context [fail] -library/emulation-focus.spec.ts › should provide target for keyboard events [pass] -library/emulation-focus.spec.ts › should think that all pages are focused @smoke [fail] -library/emulation-focus.spec.ts › should think that it is focused by default [pass] -library/emulation-focus.spec.ts › should trigger hover state concurrently [fail] -library/events/add-listeners.spec.ts › EventEmitter tests › Listener order [pass] -library/events/add-listeners.spec.ts › EventEmitter tests › listener type check [pass] -library/events/add-listeners.spec.ts › EventEmitter tests › set max listeners test [pass] -library/events/add-listeners.spec.ts › EventEmitter tests › should work [pass] -library/events/check-listener-leaks.spec.ts › _maxListeners still has precedence over defaultMaxListeners [pass] -library/events/check-listener-leaks.spec.ts › defaultMaxListeners [pass] -library/events/check-listener-leaks.spec.ts › process-wide [pass] -library/events/events-list.spec.ts › EventEmitter › should maintain event names correctly [pass] -library/events/listener-count.spec.ts › Listener count test [pass] -library/events/listeners-side-effects.spec.ts › listeners empty check [pass] -library/events/listeners.spec.ts › Array copy modification does not modify orig [pass] -library/events/listeners.spec.ts › EventEmitter listeners with one listener [pass] -library/events/listeners.spec.ts › EventEmitter with no members [pass] -library/events/listeners.spec.ts › Modify array copy after multiple adds [pass] -library/events/listeners.spec.ts › listeners and once [pass] -library/events/listeners.spec.ts › listeners on prototype [pass] -library/events/listeners.spec.ts › listeners with conflicting types [pass] -library/events/listeners.spec.ts › raw listeners [pass] -library/events/listeners.spec.ts › raw listeners order [pass] -library/events/max-listeners.spec.ts › emit maxListeners on e [pass] -library/events/method-names.spec.ts › EventEmitter prototype test [pass] -library/events/modify-in-emit.spec.ts › add and remove listeners [pass] -library/events/modify-in-emit.spec.ts › removing callbacks in emit [pass] -library/events/num-args.spec.ts › should work [pass] -library/events/once.spec.ts › once() has different code paths based on the number of arguments being emitted [pass] -library/events/once.spec.ts › should work [pass] -library/events/prepend.spec.ts › EventEmitter functionality [pass] -library/events/prepend.spec.ts › Verify that the listener must be a function [pass] -library/events/remove-all-listeners-wait.spec.ts › should not throw with ignoreErrors [pass] -library/events/remove-all-listeners-wait.spec.ts › should wait [pass] -library/events/remove-all-listeners-wait.spec.ts › should wait all [pass] -library/events/remove-all-listeners-wait.spec.ts › wait should throw [pass] -library/events/remove-all-listeners.spec.ts › listener count after removeAllListeners [pass] -library/events/remove-all-listeners.spec.ts › listeners [pass] -library/events/remove-all-listeners.spec.ts › removeAllListeners on undefined _events [pass] -library/events/remove-all-listeners.spec.ts › removeAllListeners removes all listeners [pass] -library/events/remove-all-listeners.spec.ts › removeAllListeners returns EventEmitter [pass] -library/events/remove-all-listeners.spec.ts › removeAllListeners with no event type [pass] -library/events/remove-listeners.spec.ts › Eighth test [pass] -library/events/remove-listeners.spec.ts › Fifth test [pass] -library/events/remove-listeners.spec.ts › First test [pass] -library/events/remove-listeners.spec.ts › Fourth test [pass] -library/events/remove-listeners.spec.ts › Ninth test [pass] -library/events/remove-listeners.spec.ts › Second test [pass] -library/events/remove-listeners.spec.ts › Seventh test [pass] -library/events/remove-listeners.spec.ts › Sixth test [pass] -library/events/remove-listeners.spec.ts › Tenth test [pass] -library/events/remove-listeners.spec.ts › Third test [pass] -library/events/set-max-listeners-side-effects.spec.ts › set max listeners test [pass] -library/events/special-event-names.spec.ts › should support special event names [pass] -library/events/subclass.spec.ts › MyEE2 instance [pass] -library/events/subclass.spec.ts › myee instance [pass] -library/events/symbols.spec.ts › should support symbols [pass] -library/favicon.spec.ts › should load svg favicon with prefer-color-scheme [unknown] -library/fetch-proxy.spec.ts › context request should pick up proxy credentials [timeout] -library/fetch-proxy.spec.ts › global request should pick up proxy credentials [pass] -library/fetch-proxy.spec.ts › should support proxy.bypass [pass] -library/fetch-proxy.spec.ts › should use socks proxy [pass] -library/fetch-proxy.spec.ts › should work with context level proxy [pass] -library/firefox/launcher.spec.ts › should pass firefox user preferences [fail] -library/firefox/launcher.spec.ts › should pass firefox user preferences in persistent [fail] -library/geolocation.spec.ts › should isolate contexts [fail] -library/geolocation.spec.ts › should not modify passed default options object [pass] -library/geolocation.spec.ts › should throw when invalid longitude [fail] -library/geolocation.spec.ts › should throw with missing latitude [pass] -library/geolocation.spec.ts › should throw with missing longitude in default options [pass] -library/geolocation.spec.ts › should use context options [timeout] -library/geolocation.spec.ts › should use context options for popup [timeout] -library/geolocation.spec.ts › should work @smoke [timeout] -library/geolocation.spec.ts › watchPosition should be notified [timeout] -library/global-fetch-cookie.spec.ts › should do case-insensitive match of cookie domain [pass] -library/global-fetch-cookie.spec.ts › should do case-insensitive match of request domain [pass] -library/global-fetch-cookie.spec.ts › should export cookies to storage state [pass] -library/global-fetch-cookie.spec.ts › should filter outgoing cookies by domain [pass] -library/global-fetch-cookie.spec.ts › should filter outgoing cookies by path [pass] -library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header [pass] -library/global-fetch-cookie.spec.ts › should override cookie from Set-Cookie header even if it expired [pass] -library/global-fetch-cookie.spec.ts › should preserve local storage on import/export of storage state [pass] -library/global-fetch-cookie.spec.ts › should remove cookie with expires far in the past [pass] -library/global-fetch-cookie.spec.ts › should remove cookie with negative max-age [pass] -library/global-fetch-cookie.spec.ts › should remove expired cookies [pass] -library/global-fetch-cookie.spec.ts › should send cookies from storage state [pass] -library/global-fetch-cookie.spec.ts › should send not expired cookies [pass] -library/global-fetch-cookie.spec.ts › should send secure cookie over http for localhost [pass] -library/global-fetch-cookie.spec.ts › should send secure cookie over https [pass] -library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header [pass] -library/global-fetch-cookie.spec.ts › should store cookie from Set-Cookie header even if it contains equal signs [pass] -library/global-fetch-cookie.spec.ts › should work with empty storage state [pass] -library/global-fetch-cookie.spec.ts › storage state should round-trip through file [pass] -library/global-fetch.spec.ts › delete should work @smoke [pass] -library/global-fetch.spec.ts › fetch should work @smoke [pass] -library/global-fetch.spec.ts › get should work @smoke [pass] -library/global-fetch.spec.ts › head should work @smoke [pass] -library/global-fetch.spec.ts › patch should work @smoke [pass] -library/global-fetch.spec.ts › post should work @smoke [pass] -library/global-fetch.spec.ts › put should work @smoke [pass] -library/global-fetch.spec.ts › should abort redirected requests when context is disposed [pass] -library/global-fetch.spec.ts › should abort requests when context is disposed [pass] -library/global-fetch.spec.ts › should accept already serialized data as Buffer when content-type is application/json [pass] -library/global-fetch.spec.ts › should be able to construct with context options [pass] -library/global-fetch.spec.ts › should dispose global request [pass] -library/global-fetch.spec.ts › should have nice toString [pass] -library/global-fetch.spec.ts › should json stringify array body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify bool (false) body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify bool body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify literal string undefined body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify null body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify number (falsey) body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify number body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify object body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify string (falsey) body when content-type is application/json [pass] -library/global-fetch.spec.ts › should json stringify string body when content-type is application/json [pass] -library/global-fetch.spec.ts › should keep headers capitalization [pass] -library/global-fetch.spec.ts › should not double stringify array body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify bool (false) body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify bool body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify literal string undefined body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify null body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify number (falsey) body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify number body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify object body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify string (falsey) body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not double stringify string body when content-type is application/json [pass] -library/global-fetch.spec.ts › should not fail on empty body with encoding [pass] -library/global-fetch.spec.ts › should not follow redirects when maxRedirects is set to 0 [pass] -library/global-fetch.spec.ts › should propagate extra http headers with redirects [pass] -library/global-fetch.spec.ts › should propagate ignoreHTTPSErrors on redirects [pass] -library/global-fetch.spec.ts › should remove content-length from redirected post requests [pass] -library/global-fetch.spec.ts › should resolve url relative to global baseURL option [pass] -library/global-fetch.spec.ts › should retry ECONNRESET [pass] -library/global-fetch.spec.ts › should return body for failing requests [pass] -library/global-fetch.spec.ts › should return empty body [pass] -library/global-fetch.spec.ts › should return error with correct credentials and mismatching hostname [pass] -library/global-fetch.spec.ts › should return error with correct credentials and mismatching port [pass] -library/global-fetch.spec.ts › should return error with correct credentials and mismatching scheme [pass] -library/global-fetch.spec.ts › should return error with wrong credentials [pass] -library/global-fetch.spec.ts › should serialize post data on the client [pass] -library/global-fetch.spec.ts › should set playwright as user-agent [pass] -library/global-fetch.spec.ts › should support HTTPCredentials.send [pass] -library/global-fetch.spec.ts › should support WWW-Authenticate: Basic [pass] -library/global-fetch.spec.ts › should support global httpCredentials option [pass] -library/global-fetch.spec.ts › should support global ignoreHTTPSErrors option [pass] -library/global-fetch.spec.ts › should support global timeout option [pass] -library/global-fetch.spec.ts › should support global userAgent option [pass] -library/global-fetch.spec.ts › should throw after dispose [pass] -library/global-fetch.spec.ts › should throw an error when maxRedirects is exceeded [pass] -library/global-fetch.spec.ts › should throw an error when maxRedirects is less than 0 [pass] -library/global-fetch.spec.ts › should work with correct credentials and matching origin [pass] -library/global-fetch.spec.ts › should work with correct credentials and matching origin case insensitive [pass] -library/har.spec.ts › should attach content [fail] -library/har.spec.ts › should calculate time [pass] -library/har.spec.ts › should contain http2 for http2 requests [fail] -library/har.spec.ts › should filter by glob [pass] -library/har.spec.ts › should filter by regexp [pass] -library/har.spec.ts › should filter favicon and favicon redirects [unknown] -library/har.spec.ts › should have -1 _transferSize when its a failed request [pass] -library/har.spec.ts › should have browser [fail] -library/har.spec.ts › should have connection details [fail] -library/har.spec.ts › should have connection details for failed requests [fail] -library/har.spec.ts › should have connection details for redirects [fail] -library/har.spec.ts › should have different hars for concurrent contexts [fail] -library/har.spec.ts › should have pages [pass] -library/har.spec.ts › should have pages in persistent context [fail] -library/har.spec.ts › should have popup requests [fail] -library/har.spec.ts › should have security details [fail] -library/har.spec.ts › should have version and creator [pass] -library/har.spec.ts › should include API request [pass] -library/har.spec.ts › should include binary postData [fail] -library/har.spec.ts › should include content @smoke [fail] -library/har.spec.ts › should include cookies [pass] -library/har.spec.ts › should include form params [fail] -library/har.spec.ts › should include postData [fail] -library/har.spec.ts › should include query params [pass] -library/har.spec.ts › should include redirectURL [pass] -library/har.spec.ts › should include request [pass] -library/har.spec.ts › should include response [pass] -library/har.spec.ts › should include secure set-cookies [fail] -library/har.spec.ts › should include set-cookies [fail] -library/har.spec.ts › should include set-cookies with comma [fail] -library/har.spec.ts › should include sizes [fail] -library/har.spec.ts › should not contain internal pages [pass] -library/har.spec.ts › should not hang on resources served from cache [fail] -library/har.spec.ts › should not hang on slow chunked response [fail] -library/har.spec.ts › should omit content [pass] -library/har.spec.ts › should omit content legacy [pass] -library/har.spec.ts › should record failed request headers [pass] -library/har.spec.ts › should record failed request overrides [timeout] -library/har.spec.ts › should record request overrides [timeout] -library/har.spec.ts › should report the correct _transferSize with PNG files [fail] -library/har.spec.ts › should report the correct request body size [pass] -library/har.spec.ts › should report the correct request body size when the bodySize is 0 [pass] -library/har.spec.ts › should report the correct response body size when the bodySize is 0 [pass] -library/har.spec.ts › should return receive time [pass] -library/har.spec.ts › should return security details directly from response [fail] -library/har.spec.ts › should return server address directly from response [fail] -library/har.spec.ts › should skip invalid Expires [pass] -library/har.spec.ts › should throw without path [pass] -library/har.spec.ts › should use attach mode for zip extension [fail] -library/har.spec.ts › should work with gzip compression [fail] -library/headful.spec.ts › Page.bringToFront should work [fail] -library/headful.spec.ts › headless and headful should use same default fonts [fail] -library/headful.spec.ts › should click background tab [fail] -library/headful.spec.ts › should click bottom row w/ infobar in OOPIF [fail] -library/headful.spec.ts › should click in OOPIF [fail] -library/headful.spec.ts › should click when viewport size is larger than screen [fail] -library/headful.spec.ts › should close browser after context menu was triggered [pass] -library/headful.spec.ts › should close browser with beforeunload page [fail] -library/headful.spec.ts › should close browsercontext with pending beforeunload dialog [fail] -library/headful.spec.ts › should dispatch click events to oversized viewports [pass] -library/headful.spec.ts › should have default url when launching browser @smoke [fail] -library/headful.spec.ts › should not block third party SameSite=None cookies [fail] -library/headful.spec.ts › should not crash when creating second context [pass] -library/headful.spec.ts › should not override viewport size when passed null [pass] -library/headful.spec.ts › should(not) block third party cookies [fail] -library/hit-target.spec.ts › should block all events when hit target is wrong [pass] -library/hit-target.spec.ts › should block all events when hit target is wrong and element detaches [pass] -library/hit-target.spec.ts › should block click when mousedown fails [pass] -library/hit-target.spec.ts › should click an element inside closed shadow root [fail] -library/hit-target.spec.ts › should click in custom element [fail] -library/hit-target.spec.ts › should click in iframe with padding [fail] -library/hit-target.spec.ts › should click in iframe with padding 2 [fail] -library/hit-target.spec.ts › should click into frame inside closed shadow root [fail] -library/hit-target.spec.ts › should click the button again after document.write [pass] -library/hit-target.spec.ts › should click when element detaches in mousedown [pass] -library/hit-target.spec.ts › should detect overlaid element in a transformed iframe [fail] -library/hit-target.spec.ts › should detect overlay from another shadow root [fail] -library/hit-target.spec.ts › should not block programmatic events [pass] -library/hit-target.spec.ts › should not click an element overlaying iframe with the target [fail] -library/hit-target.spec.ts › should not click iframe overlaying the target [fail] -library/hit-target.spec.ts › should work with block inside inline [fail] -library/hit-target.spec.ts › should work with block inside inline in shadow dom [fail] -library/hit-target.spec.ts › should work with block-block-block inside inline-inline [fail] -library/hit-target.spec.ts › should work with drag and drop that moves the element under cursor [pass] -library/hit-target.spec.ts › should work with mui select [pass] -library/ignorehttpserrors.spec.ts › serviceWorker should intercept document request [fail] -library/ignorehttpserrors.spec.ts › should fail with WebSocket if not ignored [pass] -library/ignorehttpserrors.spec.ts › should isolate contexts [fail] -library/ignorehttpserrors.spec.ts › should work @smoke [fail] -library/ignorehttpserrors.spec.ts › should work with WebSocket [fail] -library/ignorehttpserrors.spec.ts › should work with mixed content [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should assert navigation [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should await popup [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should check [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should check a radio button [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should check with keyboard [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should click [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should click after same-document navigation [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should click button with nested div [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should emit single keyup on ArrowDown [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill [contentEditable] [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill japanese text [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should fill textarea with new lines at the end [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore AltGraph [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should ignore programmatic events [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should make a positioned click on a canvas [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should middle click [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should not target selector preview by text regexp [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should not throw csp directive violation errors [pass] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should press [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should record ArrowDown [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after performAction [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should record omnibox navigations after recordAction [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should record slider [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should select [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should select with size attribute [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should uncheck [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should update selected element after pressing Tab [fail] -library/inspector/cli-codegen-1.spec.ts › cli codegen › should work with TrustedTypes [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › click should emit events in order [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should --save-trace [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should check input with chaining id [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should clear files [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain close page [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain open page [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should contain second page [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should download files [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should fill tricky characters [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle dialogs [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should handle history.postData [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should not clash pages [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should not lead to an error if html gets clicked [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should record navigations after identical pushState [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should record open in a new tab with url [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should reset hover model on action when element detaches [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should save assets via SIGINT [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should update active model on action [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should update hover model on action [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload a single file [fail] -library/inspector/cli-codegen-2.spec.ts › cli codegen › should upload multiple files [fail] -library/inspector/cli-codegen-2.spec.ts › should --test-id-attribute [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled input [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert value on disabled select [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should assert visibility [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.first [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should click locator.nth [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume contextmenu events, despite a custom context menu [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should consume pointer events [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with id attribute [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with name attribute [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with special characters in name attribute [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with testId [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate frame locators with title attribute [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByAltText [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByLabel without regex [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByPlaceholder [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate getByTestId [fail] -library/inspector/cli-codegen-3.spec.ts › cli codegen › should generate role locators undef frame locators [fail] -library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in mstest if no options were passed [fail] -library/inspector/cli-codegen-csharp.spec.ts › should not print context options method override in nunit if no options were passed [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in mstest [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print a valid basic program in nunit [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in mstest if options were passed [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print context options method override in nunit if options were passed [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print load/save storageState [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options for custom settings [fail] -library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device [unknown] -library/inspector/cli-codegen-csharp.spec.ts › should print the correct context options when using a device and additional options [unknown] -library/inspector/cli-codegen-csharp.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-csharp.spec.ts › should work with --save-har [fail] -library/inspector/cli-codegen-java.spec.ts › should print a valid basic program in junit [fail] -library/inspector/cli-codegen-java.spec.ts › should print load/save storage_state [fail] -library/inspector/cli-codegen-java.spec.ts › should print the correct context options for custom settings [fail] -library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device [unknown] -library/inspector/cli-codegen-java.spec.ts › should print the correct context options when using a device and additional options [unknown] -library/inspector/cli-codegen-java.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-java.spec.ts › should print the correct imports in junit [fail] -library/inspector/cli-codegen-java.spec.ts › should work with --save-har [fail] -library/inspector/cli-codegen-javascript.spec.ts › should print load/save storageState [fail] -library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options for custom settings [fail] -library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device [unknown] -library/inspector/cli-codegen-javascript.spec.ts › should print the correct context options when using a device and additional options [unknown] -library/inspector/cli-codegen-javascript.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-javascript.spec.ts › should save the codegen output to a file if specified [fail] -library/inspector/cli-codegen-pytest.spec.ts › should print the correct context options when using a device and lang [unknown] -library/inspector/cli-codegen-pytest.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-pytest.spec.ts › should save the codegen output to a file if specified [fail] -library/inspector/cli-codegen-python-async.spec.ts › should print load/save storage_state [fail] -library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options for custom settings [fail] -library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device [unknown] -library/inspector/cli-codegen-python-async.spec.ts › should print the correct context options when using a device and additional options [unknown] -library/inspector/cli-codegen-python-async.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-python-async.spec.ts › should save the codegen output to a file if specified [fail] -library/inspector/cli-codegen-python-async.spec.ts › should work with --save-har [fail] -library/inspector/cli-codegen-python.spec.ts › should print load/save storage_state [fail] -library/inspector/cli-codegen-python.spec.ts › should print the correct context options for custom settings [fail] -library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device [unknown] -library/inspector/cli-codegen-python.spec.ts › should print the correct context options when using a device and additional options [unknown] -library/inspector/cli-codegen-python.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-python.spec.ts › should save the codegen output to a file if specified [fail] -library/inspector/cli-codegen-test.spec.ts › should print load storageState [fail] -library/inspector/cli-codegen-test.spec.ts › should print the correct context options for custom settings [fail] -library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device [unknown] -library/inspector/cli-codegen-test.spec.ts › should print the correct context options when using a device and additional options [unknown] -library/inspector/cli-codegen-test.spec.ts › should print the correct imports and context options [fail] -library/inspector/cli-codegen-test.spec.ts › should work with --save-har [fail] -library/inspector/console-api.spec.ts › expected properties on playwright object [pass] -library/inspector/console-api.spec.ts › should support locator.and() [fail] -library/inspector/console-api.spec.ts › should support locator.or() [fail] -library/inspector/console-api.spec.ts › should support playwright.$, playwright.$$ [pass] -library/inspector/console-api.spec.ts › should support playwright.getBy* [fail] -library/inspector/console-api.spec.ts › should support playwright.locator({ has }) [fail] -library/inspector/console-api.spec.ts › should support playwright.locator({ hasNot }) [fail] -library/inspector/console-api.spec.ts › should support playwright.locator.value [fail] -library/inspector/console-api.spec.ts › should support playwright.locator.values [fail] -library/inspector/console-api.spec.ts › should support playwright.selector [pass] -library/inspector/pause.spec.ts › pause › should hide internal calls [pass] -library/inspector/pause.spec.ts › pause › should highlight locators with custom testId [fail] -library/inspector/pause.spec.ts › pause › should highlight on explore [fail] -library/inspector/pause.spec.ts › pause › should highlight on explore (csharp) [fail] -library/inspector/pause.spec.ts › pause › should highlight pointer, only in main frame [fail] -library/inspector/pause.spec.ts › pause › should highlight waitForEvent [fail] -library/inspector/pause.spec.ts › pause › should not prevent key events [fail] -library/inspector/pause.spec.ts › pause › should pause after a navigation [pass] -library/inspector/pause.spec.ts › pause › should pause and resume the script [pass] -library/inspector/pause.spec.ts › pause › should pause and resume the script with keyboard shortcut [pass] -library/inspector/pause.spec.ts › pause › should pause on context close [pass] -library/inspector/pause.spec.ts › pause › should pause on next pause [pass] -library/inspector/pause.spec.ts › pause › should pause on page close [pass] -library/inspector/pause.spec.ts › pause › should populate log [fail] -library/inspector/pause.spec.ts › pause › should populate log with error [fail] -library/inspector/pause.spec.ts › pause › should populate log with error in waitForEvent [fail] -library/inspector/pause.spec.ts › pause › should populate log with waitForEvent [fail] -library/inspector/pause.spec.ts › pause › should resume from console [fail] -library/inspector/pause.spec.ts › pause › should show expect.toHaveText [fail] -library/inspector/pause.spec.ts › pause › should show source [pass] -library/inspector/pause.spec.ts › pause › should skip input when resuming [fail] -library/inspector/pause.spec.ts › pause › should step [fail] -library/inspector/pause.spec.ts › pause › should step with keyboard shortcut [fail] -library/inspector/pause.spec.ts › should not reset timeouts [pass] -library/inspector/pause.spec.ts › should resume when closing inspector [pass] -library/launcher.spec.ts › should have a devices object [pass] -library/launcher.spec.ts › should have an errors object [pass] -library/launcher.spec.ts › should kill browser process on timeout after close [pass] -library/launcher.spec.ts › should throw a friendly error if its headed and there is no xserver on linux running [fail] -library/locator-generator.spec.ts › asLocator internal:and [pass] -library/locator-generator.spec.ts › asLocator internal:chain [pass] -library/locator-generator.spec.ts › asLocator internal:or [pass] -library/locator-generator.spec.ts › asLocator xpath [pass] -library/locator-generator.spec.ts › generate multiple locators [pass] -library/locator-generator.spec.ts › parse locators strictly [pass] -library/locator-generator.spec.ts › parseLocator css [pass] -library/locator-generator.spec.ts › parseLocator quotes [pass] -library/locator-generator.spec.ts › reverse engineer frameLocator [pass] -library/locator-generator.spec.ts › reverse engineer getByRole [pass] -library/locator-generator.spec.ts › reverse engineer has [pass] -library/locator-generator.spec.ts › reverse engineer has + hasText [pass] -library/locator-generator.spec.ts › reverse engineer hasNot [pass] -library/locator-generator.spec.ts › reverse engineer hasNotText [pass] -library/locator-generator.spec.ts › reverse engineer hasText [pass] -library/locator-generator.spec.ts › reverse engineer ignore-case locators [pass] -library/locator-generator.spec.ts › reverse engineer internal:has-text locators [fail] -library/locator-generator.spec.ts › reverse engineer locators [pass] -library/locator-generator.spec.ts › reverse engineer locators with regex [pass] -library/locator-generator.spec.ts › reverse engineer ordered locators [pass] -library/logger.spec.ts › should log @smoke [pass] -library/logger.spec.ts › should log context-level [fail] -library/modernizr.spec.ts › Mobile Safari [unknown] -library/modernizr.spec.ts › Safari Desktop [unknown] -library/page-clock.frozen.spec.ts › clock should be frozen [unknown] -library/page-clock.frozen.spec.ts › clock should be realtime [unknown] -library/page-clock.spec.ts › Date.now › check Date.now is an integer [pass] -library/page-clock.spec.ts › Date.now › check Date.now is an integer (2) [pass] -library/page-clock.spec.ts › fastForward › ignores timers which wouldn't be run [pass] -library/page-clock.spec.ts › fastForward › pushes back execution time for skipped timers [fail] -library/page-clock.spec.ts › fastForward › supports string time arguments [fail] -library/page-clock.spec.ts › popup › should not run time before popup on pause [fail] -library/page-clock.spec.ts › popup › should run time before popup [pass] -library/page-clock.spec.ts › popup › should tick after popup [fail] -library/page-clock.spec.ts › popup › should tick before popup [fail] -library/page-clock.spec.ts › runFor › creates updated Date while ticking [fail] -library/page-clock.spec.ts › runFor › does not trigger without sufficient delay [pass] -library/page-clock.spec.ts › runFor › passes 1 minute [fail] -library/page-clock.spec.ts › runFor › passes 2 hours, 34 minutes and 10 seconds [fail] -library/page-clock.spec.ts › runFor › passes 8 seconds [fail] -library/page-clock.spec.ts › runFor › returns the current now value [pass] -library/page-clock.spec.ts › runFor › throws for invalid format [pass] -library/page-clock.spec.ts › runFor › triggers after sufficient delay [fail] -library/page-clock.spec.ts › runFor › triggers event when some throw [fail] -library/page-clock.spec.ts › runFor › triggers immediately without specified delay [fail] -library/page-clock.spec.ts › runFor › triggers multiple simultaneous timers [fail] -library/page-clock.spec.ts › runFor › triggers simultaneous timers [fail] -library/page-clock.spec.ts › runFor › waits after setTimeout was called [fail] -library/page-clock.spec.ts › setFixedTime › allows installing fake timers after settings time [fail] -library/page-clock.spec.ts › setFixedTime › allows setting time multiple times [pass] -library/page-clock.spec.ts › setFixedTime › does not fake methods [pass] -library/page-clock.spec.ts › setFixedTime › fixed time is not affected by clock manipulation [pass] -library/page-clock.spec.ts › stubTimers › fakes Date constructor [pass] -library/page-clock.spec.ts › stubTimers › global fake setTimeout should return id [pass] -library/page-clock.spec.ts › stubTimers › replaces global clearInterval [pass] -library/page-clock.spec.ts › stubTimers › replaces global clearTimeout [pass] -library/page-clock.spec.ts › stubTimers › replaces global performance.now [pass] -library/page-clock.spec.ts › stubTimers › replaces global performance.timeOrigin [pass] -library/page-clock.spec.ts › stubTimers › replaces global setInterval [fail] -library/page-clock.spec.ts › stubTimers › replaces global setTimeout [fail] -library/page-clock.spec.ts › stubTimers › sets initial timestamp [pass] -library/page-clock.spec.ts › stubTimers › should throw for invalid date [pass] -library/page-clock.spec.ts › while on pause › fastForward should not run nested immediate [fail] -library/page-clock.spec.ts › while on pause › runFor should not run nested immediate [fail] -library/page-clock.spec.ts › while on pause › runFor should not run nested immediate from microtask [fail] -library/page-clock.spec.ts › while running › should fastForward [pass] -library/page-clock.spec.ts › while running › should fastForwardTo [pass] -library/page-clock.spec.ts › while running › should pause [pass] -library/page-clock.spec.ts › while running › should pause and fastForward [pass] -library/page-clock.spec.ts › while running › should progress time [pass] -library/page-clock.spec.ts › while running › should runFor [pass] -library/page-clock.spec.ts › while running › should set system time on pause [pass] -library/page-event-crash.spec.ts › should be able to close context when page crashes [fail] -library/page-event-crash.spec.ts › should cancel navigation when page crashes [fail] -library/page-event-crash.spec.ts › should cancel waitForEvent when page crashes [fail] -library/page-event-crash.spec.ts › should emit crash event when page crashes [fail] -library/page-event-crash.spec.ts › should throw on any action after page crashes [fail] -library/pdf.spec.ts › should be able to generate outline [unknown] -library/pdf.spec.ts › should be able to save file [unknown] -library/permissions.spec.ts › permissions › should accumulate when adding [fail] -library/permissions.spec.ts › permissions › should be prompt by default [pass] -library/permissions.spec.ts › permissions › should clear permissions [fail] -library/permissions.spec.ts › permissions › should deny permission when not listed [fail] -library/permissions.spec.ts › permissions › should fail when bad permission is given [fail] -library/permissions.spec.ts › permissions › should grant geolocation permission when origin is listed [fail] -library/permissions.spec.ts › permissions › should grant notifications permission when listed [fail] -library/permissions.spec.ts › permissions › should grant permission when creating context [fail] -library/permissions.spec.ts › permissions › should grant permission when listed for all domains [fail] -library/permissions.spec.ts › permissions › should isolate permissions between browser contexts [fail] -library/permissions.spec.ts › permissions › should prompt for geolocation permission when origin is not listed [pass] -library/permissions.spec.ts › permissions › should reset permissions [fail] -library/permissions.spec.ts › permissions › should trigger permission onchange [fail] -library/permissions.spec.ts › should support clipboard read [fail] -library/permissions.spec.ts › storage access [unknown] -library/popup.spec.ts › BrowserContext.addInitScript should apply to a cross-process popup [fail] -library/popup.spec.ts › BrowserContext.addInitScript should apply to an in-process popup [fail] -library/popup.spec.ts › should expose function from browser context [fail] -library/popup.spec.ts › should inherit extra headers from browser context [fail] -library/popup.spec.ts › should inherit http credentials from browser context [pass] -library/popup.spec.ts › should inherit offline from browser context [fail] -library/popup.spec.ts › should inherit touch support from browser context [fail] -library/popup.spec.ts › should inherit user agent from browser context @smoke [fail] -library/popup.spec.ts › should inherit viewport size from browser context [fail] -library/popup.spec.ts › should not dispatch binding on a closed page [fail] -library/popup.spec.ts › should not throttle rAF in the opener page [timeout] -library/popup.spec.ts › should not throw when click closes popup [timeout] -library/popup.spec.ts › should respect routes from browser context [fail] -library/popup.spec.ts › should respect routes from browser context when using window.open [fail] -library/popup.spec.ts › should use viewport size from window features [timeout] -library/proxy-pattern.spec.ts › socks proxy patter matcher [pass] -library/proxy.spec.ts › does launch without a port [pass] -library/proxy.spec.ts › should authenticate [pass] -library/proxy.spec.ts › should exclude patterns [fail] -library/proxy.spec.ts › should proxy local network requests › by default › link-local [pass] -library/proxy.spec.ts › should proxy local network requests › by default › localhost [fail] -library/proxy.spec.ts › should proxy local network requests › by default › loopback address [fail] -library/proxy.spec.ts › should proxy local network requests › with other bypasses › link-local [pass] -library/proxy.spec.ts › should proxy local network requests › with other bypasses › localhost [fail] -library/proxy.spec.ts › should proxy local network requests › with other bypasses › loopback address [fail] -library/proxy.spec.ts › should throw for bad server value [pass] -library/proxy.spec.ts › should use SOCKS proxy for websocket requests [pass] -library/proxy.spec.ts › should use proxy @smoke [pass] -library/proxy.spec.ts › should use proxy for second page [pass] -library/proxy.spec.ts › should use proxy with emulated user agent [unknown] -library/proxy.spec.ts › should use socks proxy [pass] -library/proxy.spec.ts › should use socks proxy in second page [pass] -library/proxy.spec.ts › should work with IP:PORT notion [pass] -library/proxy.spec.ts › should work with authenticate followed by redirect [pass] -library/resource-timing.spec.ts › should work @smoke [pass] -library/resource-timing.spec.ts › should work for SSL [fail] -library/resource-timing.spec.ts › should work for redirect [pass] -library/resource-timing.spec.ts › should work for subresource [pass] -library/resource-timing.spec.ts › should work when serving from memory cache [fail] -library/role-utils.spec.ts › accessible name nested treeitem [fail] -library/role-utils.spec.ts › accessible name with slots [fail] -library/role-utils.spec.ts › axe-core accessible-text [fail] -library/role-utils.spec.ts › axe-core implicit-role [fail] -library/role-utils.spec.ts › control embedded in a label [fail] -library/role-utils.spec.ts › control embedded in a target element [fail] -library/role-utils.spec.ts › display:contents should be visible when contents are visible [fail] -library/role-utils.spec.ts › label/labelled-by aria-hidden with descendants [fail] -library/role-utils.spec.ts › native controls [fail] -library/role-utils.spec.ts › native controls labelled-by [fail] -library/role-utils.spec.ts › own aria-label concatenated with aria-labelledby [fail] -library/role-utils.spec.ts › should ignore stylesheet from hidden aria-labelledby subtree [fail] -library/role-utils.spec.ts › should not include hidden pseudo into accessible name [fail] -library/role-utils.spec.ts › should work with form and tricky input names [fail] -library/role-utils.spec.ts › svg role=presentation [fail] -library/role-utils.spec.ts › svg title [fail] -library/role-utils.spec.ts › wpt accname #0 [pass] -library/role-utils.spec.ts › wpt accname #1 [pass] -library/role-utils.spec.ts › wpt accname #2 [fail] -library/role-utils.spec.ts › wpt accname #3 [pass] -library/role-utils.spec.ts › wpt accname non-manual [pass] -library/screenshot.spec.ts › element screenshot › element screenshot should work with a mobile viewport [fail] -library/screenshot.spec.ts › element screenshot › element screenshot should work with device scale factor [fail] -library/screenshot.spec.ts › element screenshot › element screenshots should handle vh units [fail] -library/screenshot.spec.ts › element screenshot › page screenshot should capture css transform with device pixels [fail] -library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor [fail] -library/screenshot.spec.ts › element screenshot › should capture full element when larger than viewport with device scale factor and scale:css [fail] -library/screenshot.spec.ts › element screenshot › should restore default viewport after fullPage screenshot [fail] -library/screenshot.spec.ts › element screenshot › should restore viewport after element screenshot and exception [fail] -library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and exception [pass] -library/screenshot.spec.ts › element screenshot › should restore viewport after page screenshot and timeout [fail] -library/screenshot.spec.ts › element screenshot › should take element screenshot when default viewport is null and restore back [fail] -library/screenshot.spec.ts › element screenshot › should take fullPage screenshots when default viewport is null [fail] -library/screenshot.spec.ts › element screenshot › should take screenshots when default viewport is null [fail] -library/screenshot.spec.ts › element screenshot › should work if the main resource hangs [fail] -library/screenshot.spec.ts › page screenshot › should handle vh units [fail] -library/screenshot.spec.ts › page screenshot › should run in parallel in multiple pages [fail] -library/screenshot.spec.ts › page screenshot › should throw if screenshot size is too large with device scale factor [fail] -library/screenshot.spec.ts › page screenshot › should work with a mobile viewport [fail] -library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and clip [fail] -library/screenshot.spec.ts › page screenshot › should work with a mobile viewport and fullPage [fail] -library/screenshot.spec.ts › page screenshot › should work with device scale factor [fail] -library/screenshot.spec.ts › page screenshot › should work with device scale factor and clip [fail] -library/screenshot.spec.ts › page screenshot › should work with device scale factor and scale:css [fail] -library/screenshot.spec.ts › page screenshot › should work with device scale factor, clip and scale:css [fail] -library/screenshot.spec.ts › page screenshot › should work with large size [fail] -library/selector-generator.spec.ts › selector generator › should accept valid aria-label for candidate consideration [fail] -library/selector-generator.spec.ts › selector generator › should accept valid data-test-id for candidate consideration [fail] -library/selector-generator.spec.ts › selector generator › should chain text after parent [fail] -library/selector-generator.spec.ts › selector generator › should escape text with quote [fail] -library/selector-generator.spec.ts › selector generator › should escape text with slash [fail] -library/selector-generator.spec.ts › selector generator › should find text in shadow dom [fail] -library/selector-generator.spec.ts › selector generator › should generate exact label when necessary [fail] -library/selector-generator.spec.ts › selector generator › should generate exact placeholder when necessary [fail] -library/selector-generator.spec.ts › selector generator › should generate exact role when necessary [fail] -library/selector-generator.spec.ts › selector generator › should generate exact text when necessary [fail] -library/selector-generator.spec.ts › selector generator › should generate exact title when necessary [fail] -library/selector-generator.spec.ts › selector generator › should generate label selector [fail] -library/selector-generator.spec.ts › selector generator › should generate multiple: noId [fail] -library/selector-generator.spec.ts › selector generator › should generate multiple: noId noText [fail] -library/selector-generator.spec.ts › selector generator › should generate multiple: noText in role [fail] -library/selector-generator.spec.ts › selector generator › should generate multiple: noText in text [fail] -library/selector-generator.spec.ts › selector generator › should generate relative selector [fail] -library/selector-generator.spec.ts › selector generator › should generate text and normalize whitespace [fail] -library/selector-generator.spec.ts › selector generator › should generate text for [fail] -library/selector-generator.spec.ts › selector generator › should generate title selector [fail] -library/selector-generator.spec.ts › selector generator › should handle first non-unique data-testid [fail] -library/selector-generator.spec.ts › selector generator › should handle second non-unique data-testid [fail] -library/selector-generator.spec.ts › selector generator › should ignore empty aria-label for candidate consideration [fail] -library/selector-generator.spec.ts › selector generator › should ignore empty data-test-id for candidate consideration [fail] -library/selector-generator.spec.ts › selector generator › should ignore empty role for candidate consideration [fail] -library/selector-generator.spec.ts › selector generator › should match in deep shadow dom [fail] -library/selector-generator.spec.ts › selector generator › should match in shadow dom [fail] -library/selector-generator.spec.ts › selector generator › should not accept invalid role for candidate consideration [fail] -library/selector-generator.spec.ts › selector generator › should not escape spaces inside named attr selectors [fail] -library/selector-generator.spec.ts › selector generator › should not escape text with >> [fail] -library/selector-generator.spec.ts › selector generator › should not improve guid text [fail] -library/selector-generator.spec.ts › selector generator › should not prefer zero-sized button over inner span [fail] -library/selector-generator.spec.ts › selector generator › should not use generated id [fail] -library/selector-generator.spec.ts › selector generator › should not use input[value] [fail] -library/selector-generator.spec.ts › selector generator › should not use text for select [fail] -library/selector-generator.spec.ts › selector generator › should prefer button over inner span [fail] -library/selector-generator.spec.ts › selector generator › should prefer data-testid [fail] -library/selector-generator.spec.ts › selector generator › should prefer role other input[type] [fail] -library/selector-generator.spec.ts › selector generator › should prefer role=button over inner span [fail] -library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › name [fail] -library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › placeholder [fail] -library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › role [fail] -library/selector-generator.spec.ts › selector generator › should prioritise attributes correctly › type [fail] -library/selector-generator.spec.ts › selector generator › should properly join child selectors under nested ordinals [fail] -library/selector-generator.spec.ts › selector generator › should separate selectors by >> [fail] -library/selector-generator.spec.ts › selector generator › should trim long text [fail] -library/selector-generator.spec.ts › selector generator › should trim text [fail] -library/selector-generator.spec.ts › selector generator › should try to improve label text by shortening [fail] -library/selector-generator.spec.ts › selector generator › should try to improve role name [fail] -library/selector-generator.spec.ts › selector generator › should try to improve text [fail] -library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [fail] -library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [fail] -library/selector-generator.spec.ts › selector generator › should use internal:has-text [fail] -library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [fail] -library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [fail] -library/selector-generator.spec.ts › selector generator › should use nested ordinals [fail] -library/selector-generator.spec.ts › selector generator › should use ordinal for identical nodes [fail] -library/selector-generator.spec.ts › selector generator › should use parent text [fail] -library/selector-generator.spec.ts › selector generator › should use readable id [fail] -library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [fail] -library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] -library/selector-generator.spec.ts › selector generator › should work with tricky attributes [fail] -library/selector-generator.spec.ts › selector generator › should work without CSS.escape [fail] -library/selectors-register.spec.ts › should handle errors [pass] -library/selectors-register.spec.ts › should not rely on engines working from the root [fail] -library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] -library/selectors-register.spec.ts › should work [fail] -library/selectors-register.spec.ts › should work in main and isolated world [fail] -library/selectors-register.spec.ts › should work when registered on global [fail] -library/selectors-register.spec.ts › should work with path [fail] -library/shared-worker.spec.ts › should survive shared worker restart [pass] -library/signals.spec.ts › should close the browser when the node process closes [timeout] -library/signals.spec.ts › should remove temp dir on process.exit [timeout] -library/signals.spec.ts › signals › should close the browser on SIGHUP [timeout] -library/signals.spec.ts › signals › should close the browser on SIGINT [timeout] -library/signals.spec.ts › signals › should close the browser on SIGTERM [timeout] -library/signals.spec.ts › signals › should kill the browser on SIGINT + SIGTERM [timeout] -library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIGINT [timeout] -library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] -library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] -library/signals.spec.ts › signals › should report browser close signal 2 [timeout] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo check [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo click [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo fill [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo focus [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo goto [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo hover [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo press [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo type [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo check [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo click [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo fill [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo focus [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo goto [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo hover [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo press [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo reload [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo type [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [fail] -library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [fail] -library/snapshotter.spec.ts › snapshots › should capture frame [pass] -library/snapshotter.spec.ts › snapshots › should capture iframe [fail] -library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [pass] -library/snapshotter.spec.ts › snapshots › should capture resources [fail] -library/snapshotter.spec.ts › snapshots › should capture snapshot target [fail] -library/snapshotter.spec.ts › snapshots › should collect multiple [fail] -library/snapshotter.spec.ts › snapshots › should collect on attribute change [fail] -library/snapshotter.spec.ts › snapshots › should collect snapshot [fail] -library/snapshotter.spec.ts › snapshots › should have a custom doctype [fail] -library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [fail] -library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] -library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [fail] -library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [fail] -library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [fail] -library/snapshotter.spec.ts › snapshots › should respect attr removal [fail] -library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [fail] -library/snapshotter.spec.ts › snapshots › should respect node removal [fail] -library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] -library/tap.spec.ts › locators › should send all of the correct events [fail] -library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] -library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] -library/tap.spec.ts › should not wait for a navigation caused by a tap [fail] -library/tap.spec.ts › should send all of the correct events @smoke [fail] -library/tap.spec.ts › should send well formed touch points [fail] -library/tap.spec.ts › should wait until an element is visible to tap it [fail] -library/tap.spec.ts › should work with modifiers [fail] -library/tap.spec.ts › trial run should not tap [fail] -library/trace-viewer.spec.ts › should allow hiding route actions [unknown] -library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [unknown] -library/trace-viewer.spec.ts › should capture data-url svg iframe [unknown] -library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [fail] -library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [unknown] -library/trace-viewer.spec.ts › should contain action info [unknown] -library/trace-viewer.spec.ts › should contain adopted style sheets [unknown] -library/trace-viewer.spec.ts › should display language-specific locators [unknown] -library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [fail] -library/trace-viewer.spec.ts › should filter network requests by resource type [unknown] -library/trace-viewer.spec.ts › should filter network requests by url [unknown] -library/trace-viewer.spec.ts › should follow redirects [fail] -library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [unknown] -library/trace-viewer.spec.ts › should handle file URIs [unknown] -library/trace-viewer.spec.ts › should handle multiple headers [fail] -library/trace-viewer.spec.ts › should handle src=blob [unknown] -library/trace-viewer.spec.ts › should have correct snapshot size [unknown] -library/trace-viewer.spec.ts › should have correct stack trace [fail] -library/trace-viewer.spec.ts › should have network request overrides [unknown] -library/trace-viewer.spec.ts › should have network request overrides 2 [fail] -library/trace-viewer.spec.ts › should have network requests [unknown] -library/trace-viewer.spec.ts › should highlight expect failure [unknown] -library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] -library/trace-viewer.spec.ts › should highlight target element in shadow dom [fail] -library/trace-viewer.spec.ts › should highlight target elements [unknown] -library/trace-viewer.spec.ts › should ignore 304 responses [unknown] -library/trace-viewer.spec.ts › should include metainfo [unknown] -library/trace-viewer.spec.ts › should include requestUrl in route.abort [unknown] -library/trace-viewer.spec.ts › should include requestUrl in route.continue [fail] -library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [unknown] -library/trace-viewer.spec.ts › should not crash with broken locator [unknown] -library/trace-viewer.spec.ts › should open console errors on click [unknown] -library/trace-viewer.spec.ts › should open simple trace viewer [fail] -library/trace-viewer.spec.ts › should open snapshot in new browser context [unknown] -library/trace-viewer.spec.ts › should open trace viewer on specific host [unknown] -library/trace-viewer.spec.ts › should open trace-1.31 [unknown] -library/trace-viewer.spec.ts › should open trace-1.37 [unknown] -library/trace-viewer.spec.ts › should open two trace files [unknown] -library/trace-viewer.spec.ts › should open two trace files of the same test [fail] -library/trace-viewer.spec.ts › should open two trace viewers [unknown] -library/trace-viewer.spec.ts › should pick locator [unknown] -library/trace-viewer.spec.ts › should pick locator in iframe [unknown] -library/trace-viewer.spec.ts › should popup snapshot [unknown] -library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] -library/trace-viewer.spec.ts › should preserve currentSrc [fail] -library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [unknown] -library/trace-viewer.spec.ts › should register custom elements [unknown] -library/trace-viewer.spec.ts › should remove noscript by default [unknown] -library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [fail] -library/trace-viewer.spec.ts › should render console [unknown] -library/trace-viewer.spec.ts › should render network bars [fail] -library/trace-viewer.spec.ts › should restore control values [unknown] -library/trace-viewer.spec.ts › should restore scroll positions [fail] -library/trace-viewer.spec.ts › should serve css without content-type [fail] -library/trace-viewer.spec.ts › should serve overridden request [unknown] -library/trace-viewer.spec.ts › should show action source [unknown] -library/trace-viewer.spec.ts › should show baseURL in metadata pane [unknown] -library/trace-viewer.spec.ts › should show correct request start time [fail] -library/trace-viewer.spec.ts › should show empty trace viewer [fail] -library/trace-viewer.spec.ts › should show font preview [fail] -library/trace-viewer.spec.ts › should show null as a param [unknown] -library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [fail] -library/trace-viewer.spec.ts › should show params and return value [fail] -library/trace-viewer.spec.ts › should show similar actions from library-only trace [unknown] -library/trace-viewer.spec.ts › should show snapshot URL [unknown] -library/trace-viewer.spec.ts › should update highlight when typing [fail] -library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [unknown] -library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [fail] -library/trace-viewer.spec.ts › should work with meta CSP [unknown] -library/trace-viewer.spec.ts › should work with nesting CSS selectors [unknown] -library/tracing.spec.ts › should collect sources [fail] -library/tracing.spec.ts › should collect trace with resources, but no js [fail] -library/tracing.spec.ts › should collect two traces [fail] -library/tracing.spec.ts › should exclude internal pages [pass] -library/tracing.spec.ts › should export trace concurrently to second navigation [pass] -library/tracing.spec.ts › should flush console events on tracing stop [pass] -library/tracing.spec.ts › should hide internal stack frames [fail] -library/tracing.spec.ts › should hide internal stack frames in expect [fail] -library/tracing.spec.ts › should ignore iframes in head [pass] -library/tracing.spec.ts › should include context API requests [pass] -library/tracing.spec.ts › should include interrupted actions [fail] -library/tracing.spec.ts › should not collect snapshots by default [fail] -library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] -library/tracing.spec.ts › should not emit after w/o before [pass] -library/tracing.spec.ts › should not flush console events [pass] -library/tracing.spec.ts › should not hang for clicks that open dialogs [fail] -library/tracing.spec.ts › should not include buffers in the trace [fail] -library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] -library/tracing.spec.ts › should not stall on dialogs [pass] -library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] -library/tracing.spec.ts › should overwrite existing file [fail] -library/tracing.spec.ts › should produce screencast frames crop [fail] -library/tracing.spec.ts › should produce screencast frames fit [fail] -library/tracing.spec.ts › should produce screencast frames scale [fail] -library/tracing.spec.ts › should record global request trace [pass] -library/tracing.spec.ts › should record network failures [pass] -library/tracing.spec.ts › should respect tracesDir and name [fail] -library/tracing.spec.ts › should store global request traces separately [pass] -library/tracing.spec.ts › should store postData for global request [pass] -library/tracing.spec.ts › should survive browser.close with auto-created traces dir [pass] -library/tracing.spec.ts › should throw when starting with different options [pass] -library/tracing.spec.ts › should throw when stopping without start [pass] -library/tracing.spec.ts › should use the correct apiName for event driven callbacks [pass] -library/tracing.spec.ts › should work with multiple chunks [fail] -library/unroute-behavior.spec.ts › context.close should not wait for active route handlers on the owned pages [pass] -library/unroute-behavior.spec.ts › context.unroute should not wait for pending handlers to complete [timeout] -library/unroute-behavior.spec.ts › context.unrouteAll removes all handlers [fail] -library/unroute-behavior.spec.ts › context.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [timeout] -library/unroute-behavior.spec.ts › context.unrouteAll should wait for pending handlers to complete [timeout] -library/unroute-behavior.spec.ts › page.close does not wait for active route handlers [fail] -library/unroute-behavior.spec.ts › page.close should not wait for active route handlers on the owning context [pass] -library/unroute-behavior.spec.ts › page.unroute should not wait for pending handlers to complete [pass] -library/unroute-behavior.spec.ts › page.unrouteAll removes all routes [pass] -library/unroute-behavior.spec.ts › page.unrouteAll should not wait for pending handlers to complete if behavior is ignoreErrors [pass] -library/unroute-behavior.spec.ts › page.unrouteAll should wait for pending handlers to complete [fail] -library/unroute-behavior.spec.ts › route.continue should not throw if page has been closed [pass] -library/unroute-behavior.spec.ts › route.fallback should not throw if page has been closed [pass] -library/unroute-behavior.spec.ts › route.fulfill should not throw if page has been closed [pass] -library/video.spec.ts › screencast › saveAs should throw when no video frames [timeout] -library/video.spec.ts › screencast › should be 800x450 by default [timeout] -library/video.spec.ts › screencast › should be 800x600 with null viewport [timeout] -library/video.spec.ts › screencast › should capture css transformation [timeout] -library/video.spec.ts › screencast › should capture full viewport [fail] -library/video.spec.ts › screencast › should capture full viewport on hidpi [fail] -library/video.spec.ts › screencast › should capture navigation [timeout] -library/video.spec.ts › screencast › should capture static page [timeout] -library/video.spec.ts › screencast › should capture static page in persistent context @smoke [fail] -library/video.spec.ts › screencast › should continue recording main page after popup closes [fail] -library/video.spec.ts › screencast › should delete video [timeout] -library/video.spec.ts › screencast › should emulate an iphone [timeout] -library/video.spec.ts › screencast › should expose video path [timeout] -library/video.spec.ts › screencast › should expose video path blank page [fail] -library/video.spec.ts › screencast › should expose video path blank popup [timeout] -library/video.spec.ts › screencast › should not create video for internal pages [unknown] -library/video.spec.ts › screencast › should scale frames down to the requested size [timeout] -library/video.spec.ts › screencast › should throw if browser dies [fail] -library/video.spec.ts › screencast › should throw on browser close [fail] -library/video.spec.ts › screencast › should throw without recordVideo.dir [pass] -library/video.spec.ts › screencast › should use viewport scaled down to fit into 800x800 as default size [timeout] -library/video.spec.ts › screencast › should wait for video to finish if page was closed [fail] -library/video.spec.ts › screencast › should work for popups [timeout] -library/video.spec.ts › screencast › should work with old options [timeout] -library/video.spec.ts › screencast › should work with relative path for recordVideo.dir [timeout] -library/video.spec.ts › screencast › should work with video+trace [timeout] -library/video.spec.ts › screencast › should work with weird screen resolution [timeout] -library/video.spec.ts › screencast › videoSize should require videosPath [pass] -library/video.spec.ts › should saveAs video [timeout] -library/web-socket.spec.ts › should emit binary frame events [timeout] -library/web-socket.spec.ts › should emit close events [timeout] -library/web-socket.spec.ts › should emit error [timeout] -library/web-socket.spec.ts › should emit frame events [timeout] -library/web-socket.spec.ts › should filter out the close events when the server closes with a message [timeout] -library/web-socket.spec.ts › should not have stray error events [timeout] -library/web-socket.spec.ts › should pass self as argument to close event [timeout] -library/web-socket.spec.ts › should reject waitForEvent on page close [timeout] -library/web-socket.spec.ts › should reject waitForEvent on socket close [timeout] -library/web-socket.spec.ts › should turn off when offline [unknown] -library/web-socket.spec.ts › should work @smoke [pass] \ No newline at end of file diff --git a/tests/bidi/expectations/bidi-firefox-beta-page.txt b/tests/bidi/expectations/bidi-firefox-beta-page.txt deleted file mode 100644 index 85489527fa98c..0000000000000 --- a/tests/bidi/expectations/bidi-firefox-beta-page.txt +++ /dev/null @@ -1,1971 +0,0 @@ -page/elementhandle-bounding-box.spec.ts › should force a layout [fail] -page/elementhandle-bounding-box.spec.ts › should get frame box [fail] -page/elementhandle-bounding-box.spec.ts › should handle nested frames [fail] -page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [fail] -page/elementhandle-bounding-box.spec.ts › should return null for invisible elements [fail] -page/elementhandle-bounding-box.spec.ts › should work [fail] -page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [fail] -page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [fail] -page/elementhandle-click.spec.ts › should double click the button [fail] -page/elementhandle-click.spec.ts › should throw for
elements with force [fail] -page/elementhandle-click.spec.ts › should throw for detached nodes [pass] -page/elementhandle-click.spec.ts › should throw for hidden nodes with force [pass] -page/elementhandle-click.spec.ts › should throw for recursively hidden nodes with force [pass] -page/elementhandle-click.spec.ts › should work @smoke [pass] -page/elementhandle-click.spec.ts › should work for Shadow DOM v1 [pass] -page/elementhandle-click.spec.ts › should work for TextNodes [fail] -page/elementhandle-click.spec.ts › should work with Node removed [pass] -page/elementhandle-content-frame.spec.ts › should return null for document.documentElement [pass] -page/elementhandle-content-frame.spec.ts › should return null for non-iframes [pass] -page/elementhandle-content-frame.spec.ts › should work [pass] -page/elementhandle-content-frame.spec.ts › should work for cross-frame evaluations [fail] -page/elementhandle-content-frame.spec.ts › should work for cross-process iframes [pass] -page/elementhandle-convenience.spec.ts › getAttribute should work [pass] -page/elementhandle-convenience.spec.ts › innerHTML should work [pass] -page/elementhandle-convenience.spec.ts › innerText should throw [fail] -page/elementhandle-convenience.spec.ts › innerText should work [pass] -page/elementhandle-convenience.spec.ts › inputValue should work [fail] -page/elementhandle-convenience.spec.ts › isChecked should work [fail] -page/elementhandle-convenience.spec.ts › isEditable should work [fail] -page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work [fail] -page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work with [fail] -page/page-fill.spec.ts › should throw on incorrect color value [fail] -page/page-fill.spec.ts › should throw on incorrect date [fail] -page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] -page/page-fill.spec.ts › should throw on incorrect month [unknown] -page/page-fill.spec.ts › should throw on incorrect range value [fail] -page/page-fill.spec.ts › should throw on incorrect time [fail] -page/page-fill.spec.ts › should throw on incorrect week [unknown] -page/page-fill.spec.ts › should throw on unsupported inputs [pass] -page/page-focus.spec.ts › clicking checkbox should activate it [unknown] -page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [fail] -page/page-focus.spec.ts › should emit blur event [fail] -page/page-focus.spec.ts › should emit focus event [fail] -page/page-focus.spec.ts › should traverse focus [fail] -page/page-focus.spec.ts › should traverse focus in all directions [fail] -page/page-focus.spec.ts › should traverse only form elements [flaky] -page/page-focus.spec.ts › should work @smoke [fail] -page/page-goto.spec.ts › js redirect overrides url bar navigation [pass] -page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] -page/page-goto.spec.ts › should capture cross-process iframe navigation request [pass] -page/page-goto.spec.ts › should capture iframe navigation request [pass] -page/page-goto.spec.ts › should disable timeout when its set to 0 [pass] -page/page-goto.spec.ts › should fail when canceled by another navigation [fail] -page/page-goto.spec.ts › should fail when exceeding browser context navigation timeout [pass] -page/page-goto.spec.ts › should fail when exceeding browser context timeout [fail] -page/page-goto.spec.ts › should fail when exceeding default maximum navigation timeout [pass] -page/page-goto.spec.ts › should fail when exceeding default maximum timeout [pass] -page/page-goto.spec.ts › should fail when exceeding maximum navigation timeout [pass] -page/page-goto.spec.ts › should fail when main resources failed to load [pass] -page/page-goto.spec.ts › should fail when navigating and show the url at the error message [fail] -page/page-goto.spec.ts › should fail when navigating to bad SSL [fail] -page/page-goto.spec.ts › should fail when navigating to bad SSL after redirects [fail] -page/page-goto.spec.ts › should fail when navigating to bad url [fail] -page/page-goto.spec.ts › should fail when replaced by another navigation [fail] -page/page-goto.spec.ts › should fail when server returns 204 [timeout] -page/page-goto.spec.ts › should navigate to URL with hash and fire requests without hash [pass] -page/page-goto.spec.ts › should navigate to about:blank [pass] -page/page-goto.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] -page/page-goto.spec.ts › should navigate to empty page with domcontentloaded [pass] -page/page-goto.spec.ts › should not crash when RTCPeerConnection is used [pass] -page/page-goto.spec.ts › should not crash when navigating to bad SSL after a cross origin navigation [pass] -page/page-goto.spec.ts › should not leak listeners during 20 waitForNavigation [pass] -page/page-goto.spec.ts › should not leak listeners during bad navigation [pass] -page/page-goto.spec.ts › should not leak listeners during navigation [pass] -page/page-goto.spec.ts › should not resolve goto upon window.stop() [pass] -page/page-goto.spec.ts › should not throw if networkidle0 is passed as an option [pass] -page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] -page/page-goto.spec.ts › should override referrer-policy [fail] -page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] -page/page-goto.spec.ts › should properly wait for load [pass] -page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] -page/page-goto.spec.ts › should report raw buffer for main resource [fail] -page/page-goto.spec.ts › should return from goto if new navigation is started [fail] -page/page-goto.spec.ts › should return last response in redirect chain [pass] -page/page-goto.spec.ts › should return response when page changes its URL after load [pass] -page/page-goto.spec.ts › should return url with basic auth info [pass] -page/page-goto.spec.ts › should return when navigation is committed if commit is specified [fail] -page/page-goto.spec.ts › should send referer [fail] -page/page-goto.spec.ts › should send referer of cross-origin URL [fail] -page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [fail] -page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] -page/page-goto.spec.ts › should use http for no protocol [pass] -page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] -page/page-goto.spec.ts › should work @smoke [pass] -page/page-goto.spec.ts › should work cross-process [pass] -page/page-goto.spec.ts › should work when navigating to 404 [pass] -page/page-goto.spec.ts › should work when navigating to data url [pass] -page/page-goto.spec.ts › should work when navigating to valid url [pass] -page/page-goto.spec.ts › should work when page calls history API in beforeunload [fail] -page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy [pass] -page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy after redirect [pass] -page/page-goto.spec.ts › should work with Cross-Origin-Opener-Policy and interception [pass] -page/page-goto.spec.ts › should work with anchor navigation [timeout] -page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] -page/page-goto.spec.ts › should work with file URL [pass] -page/page-goto.spec.ts › should work with file URL with subframes [fail] -page/page-goto.spec.ts › should work with lazy loading iframes [fail] -page/page-goto.spec.ts › should work with redirects [fail] -page/page-goto.spec.ts › should work with self requesting page [pass] -page/page-goto.spec.ts › should work with subframes return 204 [pass] -page/page-goto.spec.ts › should work with subframes return 204 with domcontentloaded [pass] -page/page-history.spec.ts › goBack/goForward should work with bfcache-able pages [fail] -page/page-history.spec.ts › page.goBack during renderer-initiated navigation [fail] -page/page-history.spec.ts › page.goBack should work @smoke [fail] -page/page-history.spec.ts › page.goBack should work for file urls [fail] -page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] -page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] -page/page-history.spec.ts › page.reload during renderer-initiated navigation [fail] -page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] -page/page-history.spec.ts › page.reload should work [pass] -page/page-history.spec.ts › page.reload should work on a page with a hash [pass] -page/page-history.spec.ts › page.reload should work on a page with a hash at the end [pass] -page/page-history.spec.ts › page.reload should work with cross-origin redirect [pass] -page/page-history.spec.ts › page.reload should work with data url [pass] -page/page-history.spec.ts › page.reload should work with same origin redirect [pass] -page/page-history.spec.ts › regression test for issue 20791 [pass] -page/page-history.spec.ts › should reload proper page [pass] -page/page-keyboard.spec.ts › insertText should only emit input event [fail] -page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [fail] -page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] -page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [fail] -page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [fail] -page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] -page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] -page/page-keyboard.spec.ts › should handle selectAll [pass] -page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] -page/page-keyboard.spec.ts › should move around the selection in a contenteditable [fail] -page/page-keyboard.spec.ts › should move to the start of the document [unknown] -page/page-keyboard.spec.ts › should move with the arrow keys [pass] -page/page-keyboard.spec.ts › should not type canceled events [pass] -page/page-keyboard.spec.ts › should press Enter [fail] -page/page-keyboard.spec.ts › should press plus [fail] -page/page-keyboard.spec.ts › should press shift plus [fail] -page/page-keyboard.spec.ts › should press the meta key [pass] -page/page-keyboard.spec.ts › should report multiple modifiers [fail] -page/page-keyboard.spec.ts › should report shiftKey [pass] -page/page-keyboard.spec.ts › should scroll with PageDown [pass] -page/page-keyboard.spec.ts › should send a character with ElementHandle.press [pass] -page/page-keyboard.spec.ts › should send a character with insertText [fail] -page/page-keyboard.spec.ts › should send proper codes while typing [pass] -page/page-keyboard.spec.ts › should send proper codes while typing with shift [pass] -page/page-keyboard.spec.ts › should shift raw codes [pass] -page/page-keyboard.spec.ts › should specify location [fail] -page/page-keyboard.spec.ts › should specify repeat property [pass] -page/page-keyboard.spec.ts › should support MacOS shortcuts [unknown] -page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] -page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] -page/page-keyboard.spec.ts › should support simple copy-pasting [fail] -page/page-keyboard.spec.ts › should support simple cut-pasting [fail] -page/page-keyboard.spec.ts › should support undo-redo [fail] -page/page-keyboard.spec.ts › should throw on unknown keys [pass] -page/page-keyboard.spec.ts › should type after context menu was opened [pass] -page/page-keyboard.spec.ts › should type all kinds of characters [pass] -page/page-keyboard.spec.ts › should type emoji [pass] -page/page-keyboard.spec.ts › should type emoji into an iframe [pass] -page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] -page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [fail] -page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [fail] -page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [fail] -page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] -page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] -page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [fail] -page/page-leaks.spec.ts › click should not leak [fail] -page/page-leaks.spec.ts › expect should not leak [fail] -page/page-leaks.spec.ts › fill should not leak [fail] -page/page-leaks.spec.ts › waitFor should not leak [fail] -page/page-listeners.spec.ts › should not throw with ignoreErrors [pass] -page/page-listeners.spec.ts › should wait [pass] -page/page-listeners.spec.ts › wait should throw [pass] -page/page-mouse.spec.ts › down and up should generate click [pass] -page/page-mouse.spec.ts › should always round down [fail] -page/page-mouse.spec.ts › should click the document @smoke [pass] -page/page-mouse.spec.ts › should dblclick the div [fail] -page/page-mouse.spec.ts › should dispatch mouse move after context menu was opened [pass] -page/page-mouse.spec.ts › should not crash on mouse drag with any button [pass] -page/page-mouse.spec.ts › should pointerdown the div with a custom button [fail] -page/page-mouse.spec.ts › should report correct buttons property [pass] -page/page-mouse.spec.ts › should select the text with mouse [pass] -page/page-mouse.spec.ts › should set modifier keys on click [pass] -page/page-mouse.spec.ts › should trigger hover state [pass] -page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] -page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] -page/page-mouse.spec.ts › should tween mouse movement [pass] -page/page-navigation.spec.ts › should work with _blank target [pass] -page/page-navigation.spec.ts › should work with _blank target in form [fail] -page/page-navigation.spec.ts › should work with cross-process _blank target [pass] -page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] -page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] -page/page-network-idle.spec.ts › should wait for networkidle from the popup [fail] -page/page-network-idle.spec.ts › should wait for networkidle in setContent [fail] -page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [fail] -page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [fail] -page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] -page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] -page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [fail] -page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [fail] -page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] -page/page-network-idle.spec.ts › should work after repeated navigations in the same page [pass] -page/page-network-request.spec.ts › page.reload return 304 status code [pass] -page/page-network-request.spec.ts › should get the same headers as the server [fail] -page/page-network-request.spec.ts › should get the same headers as the server CORS [fail] -page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] -page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] -page/page-network-request.spec.ts › should handle mixed-content blocked requests [flaky] -page/page-network-request.spec.ts › should not allow to access frame on popup main request [fail] -page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] -page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] -page/page-network-request.spec.ts › should not work for a redirect and interception [pass] -page/page-network-request.spec.ts › should override post data content type [pass] -page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded [fail] -page/page-network-request.spec.ts › should parse the data if content-type is application/x-www-form-urlencoded; charset=UTF-8 [fail] -page/page-network-request.spec.ts › should parse the json post data [fail] -page/page-network-request.spec.ts › should report all cookies in one header [pass] -page/page-network-request.spec.ts › should report raw headers [fail] -page/page-network-request.spec.ts › should report raw response headers in redirects [pass] -page/page-network-request.spec.ts › should return event source [fail] -page/page-network-request.spec.ts › should return headers [pass] -page/page-network-request.spec.ts › should return multipart/form-data [fail] -page/page-network-request.spec.ts › should return navigation bit [pass] -page/page-network-request.spec.ts › should return navigation bit when navigating to image [pass] -page/page-network-request.spec.ts › should return postData [fail] -page/page-network-request.spec.ts › should work for a redirect [pass] -page/page-network-request.spec.ts › should work for fetch requests @smoke [pass] -page/page-network-request.spec.ts › should work for main frame navigation request [pass] -page/page-network-request.spec.ts › should work for subframe navigation request [pass] -page/page-network-request.spec.ts › should work with binary post data [fail] -page/page-network-request.spec.ts › should work with binary post data and interception [fail] -page/page-network-response.spec.ts › should behave the same way for headers and allHeaders [pass] -page/page-network-response.spec.ts › should bypass disk cache when context interception is enabled [fail] -page/page-network-response.spec.ts › should bypass disk cache when page interception is enabled [pass] -page/page-network-response.spec.ts › should provide a Response with a file URL [fail] -page/page-network-response.spec.ts › should reject response.finished if context closes [timeout] -page/page-network-response.spec.ts › should reject response.finished if page closes [pass] -page/page-network-response.spec.ts › should report all headers [fail] -page/page-network-response.spec.ts › should report if request was fromServiceWorker [fail] -page/page-network-response.spec.ts › should report multiple set-cookie headers [fail] -page/page-network-response.spec.ts › should return body [fail] -page/page-network-response.spec.ts › should return body for prefetch script [fail] -page/page-network-response.spec.ts › should return body with compression [fail] -page/page-network-response.spec.ts › should return headers after route.fulfill [pass] -page/page-network-response.spec.ts › should return json [fail] -page/page-network-response.spec.ts › should return multiple header value [pass] -page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [pass] -page/page-network-response.spec.ts › should return status text [pass] -page/page-network-response.spec.ts › should return text [fail] -page/page-network-response.spec.ts › should return uncompressed text [fail] -page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] -page/page-network-response.spec.ts › should wait until response completes [fail] -page/page-network-response.spec.ts › should work @smoke [pass] -page/page-network-sizes.spec.ts › should handle redirects [pass] -page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 with content [pass] -page/page-network-sizes.spec.ts › should have the correct responseBodySize [pass] -page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] -page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [pass] -page/page-network-sizes.spec.ts › should return sizes without hanging [pass] -page/page-network-sizes.spec.ts › should set bodySize and headersSize [fail] -page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] -page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] -page/page-network-sizes.spec.ts › should set bodySize, headersSize, and transferSize [pass] -page/page-network-sizes.spec.ts › should throw for failed requests [pass] -page/page-network-sizes.spec.ts › should work with 200 status code [pass] -page/page-network-sizes.spec.ts › should work with 401 status code [pass] -page/page-network-sizes.spec.ts › should work with 404 status code [pass] -page/page-network-sizes.spec.ts › should work with 500 status code [fail] -page/page-object-count.spec.ts › should count objects [flaky] -page/page-request-continue.spec.ts › continue should delete headers on redirects [pass] -page/page-request-continue.spec.ts › continue should not change multipart/form-data body [fail] -page/page-request-continue.spec.ts › continue should propagate headers to redirects [pass] -page/page-request-continue.spec.ts › post data › should amend binary post data [fail] -page/page-request-continue.spec.ts › post data › should amend longer post data [pass] -page/page-request-continue.spec.ts › post data › should amend method and post data [pass] -page/page-request-continue.spec.ts › post data › should amend post data [pass] -page/page-request-continue.spec.ts › post data › should amend utf8 post data [pass] -page/page-request-continue.spec.ts › post data › should compute content-length from post data [fail] -page/page-request-continue.spec.ts › post data › should use content-type from original request [pass] -page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] -page/page-request-continue.spec.ts › should amend HTTP headers [pass] -page/page-request-continue.spec.ts › should amend method [pass] -page/page-request-continue.spec.ts › should amend method on main request [pass] -page/page-request-continue.spec.ts › should continue preload link requests [pass] -page/page-request-continue.spec.ts › should delete header with undefined value [pass] -page/page-request-continue.spec.ts › should delete the origin header [pass] -page/page-request-continue.spec.ts › should intercept css variable with background url [fail] -page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [pass] -page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [timeout] -page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] -page/page-request-continue.spec.ts › should not throw when continuing while page is closing [pass] -page/page-request-continue.spec.ts › should override method along with url [fail] -page/page-request-continue.spec.ts › should override request url [timeout] -page/page-request-continue.spec.ts › should work [pass] -page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [fail] -page/page-request-fallback.spec.ts › post data › should amend binary post data [fail] -page/page-request-fallback.spec.ts › post data › should amend json post data [pass] -page/page-request-fallback.spec.ts › post data › should amend post data [pass] -page/page-request-fallback.spec.ts › should amend HTTP headers [pass] -page/page-request-fallback.spec.ts › should amend method [pass] -page/page-request-fallback.spec.ts › should chain once [fail] -page/page-request-fallback.spec.ts › should delete header with undefined value [pass] -page/page-request-fallback.spec.ts › should fall back [pass] -page/page-request-fallback.spec.ts › should fall back after exception [pass] -page/page-request-fallback.spec.ts › should fall back async [fail] -page/page-request-fallback.spec.ts › should not chain abort [fail] -page/page-request-fallback.spec.ts › should not chain fulfill [fail] -page/page-request-fallback.spec.ts › should override request url [fail] -page/page-request-fallback.spec.ts › should work [pass] -page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [pass] -page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] -page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] -page/page-request-fulfill.spec.ts › should fetch original request and fulfill [pass] -page/page-request-fulfill.spec.ts › should fulfill json [fail] -page/page-request-fulfill.spec.ts › should fulfill preload link requests [pass] -page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [timeout] -page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] -page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] -page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] -page/page-request-fulfill.spec.ts › should fulfill with gzip and readback [timeout] -page/page-request-fulfill.spec.ts › should fulfill with har response [fail] -page/page-request-fulfill.spec.ts › should fulfill with multiple set-cookie [fail] -page/page-request-fulfill.spec.ts › should fulfill with unuassigned status codes [pass] -page/page-request-fulfill.spec.ts › should include the origin header [pass] -page/page-request-fulfill.spec.ts › should not go to the network for fulfilled requests body [fail] -page/page-request-fulfill.spec.ts › should not modify the headers sent to the server [pass] -page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [timeout] -page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [pass] -page/page-request-fulfill.spec.ts › should work [pass] -page/page-request-fulfill.spec.ts › should work with buffer as body [fail] -page/page-request-fulfill.spec.ts › should work with file path [fail] -page/page-request-fulfill.spec.ts › should work with status code 422 [pass] -page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] -page/page-request-intercept.spec.ts › should fulfill intercepted response [fail] -page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [pass] -page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] -page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] -page/page-request-intercept.spec.ts › should fulfill with any response [fail] -page/page-request-intercept.spec.ts › should give access to the intercepted response [fail] -page/page-request-intercept.spec.ts › should give access to the intercepted response body [pass] -page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [fail] -page/page-request-intercept.spec.ts › should intercept with post data override [pass] -page/page-request-intercept.spec.ts › should intercept with url override [fail] -page/page-request-intercept.spec.ts › should not follow redirects when maxRedirects is set to 0 in route.fetch [pass] -page/page-request-intercept.spec.ts › should override with defaults when intercepted response not provided [fail] -page/page-request-intercept.spec.ts › should support fulfill after intercept [fail] -page/page-request-intercept.spec.ts › should support timeout option in route.fetch [fail] -page/page-route.spec.ts › route.abort should throw if called twice [pass] -page/page-route.spec.ts › route.continue should throw if called twice [pass] -page/page-route.spec.ts › route.fallback should throw if called twice [fail] -page/page-route.spec.ts › route.fulfill should throw if called twice [fail] -page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] -page/page-route.spec.ts › should allow null origin for about:blank [fail] -page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [pass] -page/page-route.spec.ts › should be able to remove headers [fail] -page/page-route.spec.ts › should be abortable [pass] -page/page-route.spec.ts › should be abortable with custom error codes [fail] -page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] -page/page-route.spec.ts › should contain raw request header [pass] -page/page-route.spec.ts › should contain raw response header [pass] -page/page-route.spec.ts › should contain raw response header after fulfill [pass] -page/page-route.spec.ts › should contain referer header [pass] -page/page-route.spec.ts › should fail navigation when aborting main resource [fail] -page/page-route.spec.ts › should fulfill with redirect status [pass] -page/page-route.spec.ts › should intercept @smoke [fail] -page/page-route.spec.ts › should intercept main resource during cross-process navigation [pass] -page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] -page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [pass] -page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [fail] -page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] -page/page-route.spec.ts › should not fulfill with redirect status [fail] -page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] -page/page-route.spec.ts › should not throw if request was cancelled by the page [fail] -page/page-route.spec.ts › should not work with redirects [fail] -page/page-route.spec.ts › should override cookie header [fail] -page/page-route.spec.ts › should pause intercepted XHR until continue [pass] -page/page-route.spec.ts › should pause intercepted fetch request until continue [pass] -page/page-route.spec.ts › should properly return navigation response when URL has cookies [fail] -page/page-route.spec.ts › should reject cors with disallowed credentials [fail] -page/page-route.spec.ts › should respect cors overrides [fail] -page/page-route.spec.ts › should send referer [fail] -page/page-route.spec.ts › should show custom HTTP headers [fail] -page/page-route.spec.ts › should support ? in glob pattern [pass] -page/page-route.spec.ts › should support async handler w/ times [pass] -page/page-route.spec.ts › should support cors for different methods [fail] -page/page-route.spec.ts › should support cors with GET [pass] -page/page-route.spec.ts › should support cors with POST [fail] -page/page-route.spec.ts › should support cors with credentials [fail] -page/page-route.spec.ts › should support the times parameter with route matching [pass] -page/page-route.spec.ts › should unroute [fail] -page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [pass] -page/page-route.spec.ts › should work when POST is redirected with 302 [fail] -page/page-route.spec.ts › should work when header manipulation headers with redirect [pass] -page/page-route.spec.ts › should work with badly encoded server [pass] -page/page-route.spec.ts › should work with custom referer headers [fail] -page/page-route.spec.ts › should work with encoded server [fail] -page/page-route.spec.ts › should work with encoded server - 2 [fail] -page/page-route.spec.ts › should work with equal requests [pass] -page/page-route.spec.ts › should work with redirect inside sync XHR [fail] -page/page-route.spec.ts › should work with redirects for subresources [fail] -page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [fail] -page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [fail] -page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [fail] -page/page-screenshot.spec.ts › page screenshot animations › should stop animations that happen right before screenshot [fail] -page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for INfinite css animation [fail] -page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for css transitions [fail] -page/page-screenshot.spec.ts › page screenshot animations › should trigger particular events for finite css animation [fail] -page/page-screenshot.spec.ts › page screenshot animations › should wait for fonts to load [fail] -page/page-screenshot.spec.ts › page screenshot should capture css transform [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should hide elements based on attr [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should mask in parallel [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should mask inside iframe [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should mask multiple elements [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should remove elements based on attr [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should remove mask after screenshot [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] -page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [fail] -page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] -page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [fail] -page/page-screenshot.spec.ts › page screenshot › path option should work [fail] -page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] -page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] -page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] -page/page-screenshot.spec.ts › page screenshot › should capture blinking caret in shadow dom [fail] -page/page-screenshot.spec.ts › page screenshot › should capture canvas changes [fail] -page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] -page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] -page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] -page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] -page/page-screenshot.spec.ts › page screenshot › should not issue resize event [fail] -page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] -page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] -page/page-screenshot.spec.ts › page screenshot › should restore viewport after fullPage screenshot [fail] -page/page-screenshot.spec.ts › page screenshot › should run in parallel [fail] -page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots [fail] -page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots and mask elements outside of it [fail] -page/page-screenshot.spec.ts › page screenshot › should take fullPage screenshots during navigation [fail] -page/page-screenshot.spec.ts › page screenshot › should throw on clip outside the viewport [pass] -page/page-screenshot.spec.ts › page screenshot › should work @smoke [fail] -page/page-screenshot.spec.ts › page screenshot › should work for canvas [fail] -page/page-screenshot.spec.ts › page screenshot › should work for translateZ [fail] -page/page-screenshot.spec.ts › page screenshot › should work for webgl [fail] -page/page-screenshot.spec.ts › page screenshot › should work while navigating [fail] -page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] -page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] -page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] -page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] -page/page-screenshot.spec.ts › should capture css box-shadow [fail] -page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] -page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [fail] -page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] -page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] -page/page-select-option.spec.ts › should fall back to selecting by label [pass] -page/page-select-option.spec.ts › should not allow null items [pass] -page/page-select-option.spec.ts › should not select single option when some attributes do not match [pass] -page/page-select-option.spec.ts › should not throw when select causes navigation [pass] -page/page-select-option.spec.ts › should respect event bubbling [pass] -page/page-select-option.spec.ts › should return [] on no matched values [pass] -page/page-select-option.spec.ts › should return [] on no values [pass] -page/page-select-option.spec.ts › should return an array of matched values [pass] -page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] -page/page-select-option.spec.ts › should select multiple options [pass] -page/page-select-option.spec.ts › should select multiple options with attributes [pass] -page/page-select-option.spec.ts › should select only first option [pass] -page/page-select-option.spec.ts › should select single option @smoke [pass] -page/page-select-option.spec.ts › should select single option by handle [pass] -page/page-select-option.spec.ts › should select single option by index [pass] -page/page-select-option.spec.ts › should select single option by label [pass] -page/page-select-option.spec.ts › should select single option by multiple attributes [pass] -page/page-select-option.spec.ts › should select single option by value [pass] -page/page-select-option.spec.ts › should throw if passed wrong types [fail] -page/page-select-option.spec.ts › should throw when element is not a [fail] @@ -1691,8 +1706,8 @@ library/selector-generator.spec.ts › selector generator › should try to impr library/selector-generator.spec.ts › selector generator › should try to improve role name [fail] library/selector-generator.spec.ts › selector generator › should try to improve text [fail] library/selector-generator.spec.ts › selector generator › should try to improve text by shortening [fail] -library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [fail] -library/selector-generator.spec.ts › selector generator › should use internal:has-text [fail] +library/selector-generator.spec.ts › selector generator › should use data-testid in strict errors [pass] +library/selector-generator.spec.ts › selector generator › should use internal:has-text [pass] library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp [fail] library/selector-generator.spec.ts › selector generator › should use internal:has-text with regexp with a quote [fail] library/selector-generator.spec.ts › selector generator › should use nested ordinals [fail] @@ -1700,16 +1715,16 @@ library/selector-generator.spec.ts › selector generator › should use ordinal library/selector-generator.spec.ts › selector generator › should use parent text [fail] library/selector-generator.spec.ts › selector generator › should use readable id [fail] library/selector-generator.spec.ts › selector generator › should use the name attributes for elements that can have it [fail] -library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [fail] +library/selector-generator.spec.ts › selector generator › should work in dynamic iframes without navigation [pass] library/selector-generator.spec.ts › selector generator › should work with tricky attributes [fail] library/selector-generator.spec.ts › selector generator › should work without CSS.escape [fail] library/selectors-register.spec.ts › should handle errors [pass] -library/selectors-register.spec.ts › should not rely on engines working from the root [fail] +library/selectors-register.spec.ts › should not rely on engines working from the root [pass] library/selectors-register.spec.ts › should throw a nice error if the selector returns a bad value [pass] -library/selectors-register.spec.ts › should work [fail] -library/selectors-register.spec.ts › should work in main and isolated world [fail] -library/selectors-register.spec.ts › should work when registered on global [fail] -library/selectors-register.spec.ts › should work with path [fail] +library/selectors-register.spec.ts › should work [pass] +library/selectors-register.spec.ts › should work in main and isolated world [pass] +library/selectors-register.spec.ts › should work when registered on global [pass] +library/selectors-register.spec.ts › should work with path [pass] library/shared-worker.spec.ts › should survive shared worker restart [pass] library/signals.spec.ts › should close the browser when the node process closes [timeout] library/signals.spec.ts › should remove temp dir on process.exit [timeout] @@ -1721,64 +1736,64 @@ library/signals.spec.ts › signals › should kill the browser on SIGTERM + SIG library/signals.spec.ts › signals › should kill the browser on double SIGINT and remove temp dir [timeout] library/signals.spec.ts › signals › should not prevent default SIGTERM handling after browser close [timeout] library/signals.spec.ts › signals › should report browser close signal 2 [timeout] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo check [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo click [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dblclick [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo dispatchEvent [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo fill [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo focus [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo hover [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo press [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo selectOption [pass] library/slowmo.spec.ts › slowMo › ElementHandle SlowMo setInputFiles [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [fail] -library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [fail] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo type [pass] +library/slowmo.spec.ts › slowMo › ElementHandle SlowMo uncheck [pass] library/slowmo.spec.ts › slowMo › Frame SlowMo check [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo click [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo fill [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo focus [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo goto [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo hover [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo press [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo click [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo dblclick [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo dispatchEvent [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo fill [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo focus [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo goto [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo hover [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo press [pass] +library/slowmo.spec.ts › slowMo › Frame SlowMo selectOption [pass] library/slowmo.spec.ts › slowMo › Frame SlowMo setInputFiles [fail] -library/slowmo.spec.ts › slowMo › Frame SlowMo type [fail] +library/slowmo.spec.ts › slowMo › Frame SlowMo type [pass] library/slowmo.spec.ts › slowMo › Frame SlowMo uncheck [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo check [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo click [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo fill [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo focus [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo goto [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo hover [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo press [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo reload [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo check [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo click [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo dblclick [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo dispatchEvent [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo fill [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo focus [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo goto [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo hover [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo press [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo reload [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo selectOption [pass] library/slowmo.spec.ts › slowMo › Page SlowMo setInputFiles [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo type [fail] -library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [fail] -library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [fail] +library/slowmo.spec.ts › slowMo › Page SlowMo type [pass] +library/slowmo.spec.ts › slowMo › Page SlowMo uncheck [pass] +library/snapshotter.spec.ts › snapshots › empty adopted style sheets should not prevent node refs [pass] library/snapshotter.spec.ts › snapshots › should capture frame [pass] library/snapshotter.spec.ts › snapshots › should capture iframe [pass] library/snapshotter.spec.ts › snapshots › should capture iframe with srcdoc [pass] -library/snapshotter.spec.ts › snapshots › should capture resources [fail] +library/snapshotter.spec.ts › snapshots › should capture resources [pass] library/snapshotter.spec.ts › snapshots › should capture snapshot target [fail] -library/snapshotter.spec.ts › snapshots › should collect multiple [fail] -library/snapshotter.spec.ts › snapshots › should collect on attribute change [fail] -library/snapshotter.spec.ts › snapshots › should collect snapshot [fail] -library/snapshotter.spec.ts › snapshots › should have a custom doctype [fail] +library/snapshotter.spec.ts › snapshots › should collect multiple [pass] +library/snapshotter.spec.ts › snapshots › should collect on attribute change [pass] +library/snapshotter.spec.ts › snapshots › should collect snapshot [pass] +library/snapshotter.spec.ts › snapshots › should have a custom doctype [pass] library/snapshotter.spec.ts › snapshots › should not navigate on anchor clicks [fail] library/snapshotter.spec.ts › snapshots › should preserve BASE and other content on reset [pass] -library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [fail] -library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [fail] -library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [fail] -library/snapshotter.spec.ts › snapshots › should respect attr removal [fail] -library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [fail] -library/snapshotter.spec.ts › snapshots › should respect node removal [fail] -library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [fail] +library/snapshotter.spec.ts › snapshots › should replace meta charset attr that specifies charset [pass] +library/snapshotter.spec.ts › snapshots › should replace meta content attr that specifies charset [pass] +library/snapshotter.spec.ts › snapshots › should respect CSSOM change through CSSGroupingRule [pass] +library/snapshotter.spec.ts › snapshots › should respect attr removal [pass] +library/snapshotter.spec.ts › snapshots › should respect inline CSSOM change [pass] +library/snapshotter.spec.ts › snapshots › should respect node removal [pass] +library/snapshotter.spec.ts › snapshots › should respect subresource CSSOM change [pass] library/tap.spec.ts › locators › should send all of the correct events [fail] library/tap.spec.ts › should not send mouse events touchstart is canceled [fail] library/tap.spec.ts › should not send mouse events when touchend is canceled [fail] @@ -1790,94 +1805,95 @@ library/tap.spec.ts › should work with modifiers [fail] library/tap.spec.ts › trial run should not tap [fail] library/trace-viewer.spec.ts › should allow hiding route actions [unknown] library/trace-viewer.spec.ts › should allow showing screenshots instead of snapshots [unknown] -library/trace-viewer.spec.ts › should capture data-url svg iframe [unknown] -library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [unknown] -library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [unknown] -library/trace-viewer.spec.ts › should contain action info [fail] -library/trace-viewer.spec.ts › should contain adopted style sheets [fail] -library/trace-viewer.spec.ts › should display language-specific locators [unknown] -library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [unknown] -library/trace-viewer.spec.ts › should filter network requests by resource type [fail] -library/trace-viewer.spec.ts › should filter network requests by url [unknown] -library/trace-viewer.spec.ts › should follow redirects [unknown] +library/trace-viewer.spec.ts › should capture data-url svg iframe [fail] +library/trace-viewer.spec.ts › should capture iframe with sandbox attribute [pass] +library/trace-viewer.spec.ts › should complain about newer version of trace in old viewer [pass] +library/trace-viewer.spec.ts › should contain action info [pass] +library/trace-viewer.spec.ts › should contain adopted style sheets [pass] +library/trace-viewer.spec.ts › should display language-specific locators [pass] +library/trace-viewer.spec.ts › should display waitForLoadState even if did not wait for it [pass] +library/trace-viewer.spec.ts › should filter network requests by resource type [pass] +library/trace-viewer.spec.ts › should filter network requests by url [pass] +library/trace-viewer.spec.ts › should follow redirects [fail] library/trace-viewer.spec.ts › should handle case where neither snapshots nor screenshots exist [fail] library/trace-viewer.spec.ts › should handle file URIs [fail] -library/trace-viewer.spec.ts › should handle multiple headers [unknown] -library/trace-viewer.spec.ts › should handle src=blob [unknown] +library/trace-viewer.spec.ts › should handle multiple headers [fail] +library/trace-viewer.spec.ts › should handle src=blob [fail] library/trace-viewer.spec.ts › should have correct snapshot size [fail] library/trace-viewer.spec.ts › should have correct stack trace [unknown] library/trace-viewer.spec.ts › should have network request overrides [fail] library/trace-viewer.spec.ts › should have network request overrides 2 [unknown] library/trace-viewer.spec.ts › should have network requests [unknown] -library/trace-viewer.spec.ts › should highlight expect failure [unknown] -library/trace-viewer.spec.ts › should highlight locator in iframe while typing [unknown] -library/trace-viewer.spec.ts › should highlight target element in shadow dom [unknown] -library/trace-viewer.spec.ts › should highlight target elements [fail] -library/trace-viewer.spec.ts › should ignore 304 responses [unknown] -library/trace-viewer.spec.ts › should include metainfo [unknown] +library/trace-viewer.spec.ts › should highlight expect failure [pass] +library/trace-viewer.spec.ts › should highlight locator in iframe while typing [fail] +library/trace-viewer.spec.ts › should highlight target element in shadow dom [pass] +library/trace-viewer.spec.ts › should highlight target elements [pass] +library/trace-viewer.spec.ts › should ignore 304 responses [fail] +library/trace-viewer.spec.ts › should include metainfo [pass] library/trace-viewer.spec.ts › should include requestUrl in route.abort [unknown] library/trace-viewer.spec.ts › should include requestUrl in route.continue [unknown] library/trace-viewer.spec.ts › should include requestUrl in route.fulfill [unknown] -library/trace-viewer.spec.ts › should not crash with broken locator [fail] +library/trace-viewer.spec.ts › should not crash with broken locator [pass] +library/trace-viewer.spec.ts › should not record route actions [pass] library/trace-viewer.spec.ts › should open console errors on click [fail] -library/trace-viewer.spec.ts › should open simple trace viewer [fail] -library/trace-viewer.spec.ts › should open snapshot in new browser context [unknown] +library/trace-viewer.spec.ts › should open simple trace viewer [pass] +library/trace-viewer.spec.ts › should open snapshot in new browser context [pass] library/trace-viewer.spec.ts › should open trace viewer on specific host [unknown] -library/trace-viewer.spec.ts › should open trace-1.31 [unknown] -library/trace-viewer.spec.ts › should open trace-1.37 [fail] -library/trace-viewer.spec.ts › should open two trace files [fail] -library/trace-viewer.spec.ts › should open two trace files of the same test [unknown] +library/trace-viewer.spec.ts › should open trace-1.31 [pass] +library/trace-viewer.spec.ts › should open trace-1.37 [pass] +library/trace-viewer.spec.ts › should open two trace files [pass] +library/trace-viewer.spec.ts › should open two trace files of the same test [pass] library/trace-viewer.spec.ts › should open two trace viewers [unknown] -library/trace-viewer.spec.ts › should pick locator [fail] +library/trace-viewer.spec.ts › should pick locator [pass] library/trace-viewer.spec.ts › should pick locator in iframe [fail] -library/trace-viewer.spec.ts › should popup snapshot [fail] -library/trace-viewer.spec.ts › should prefer later resource request with the same method [unknown] -library/trace-viewer.spec.ts › should preserve currentSrc [unknown] -library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [unknown] -library/trace-viewer.spec.ts › should properly synchronize local and remote time [unknown] -library/trace-viewer.spec.ts › should register custom elements [unknown] -library/trace-viewer.spec.ts › should remove noscript by default [fail] -library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [unknown] -library/trace-viewer.spec.ts › should render console [unknown] -library/trace-viewer.spec.ts › should render network bars [unknown] -library/trace-viewer.spec.ts › should restore control values [unknown] -library/trace-viewer.spec.ts › should restore scroll positions [unknown] -library/trace-viewer.spec.ts › should serve css without content-type [unknown] +library/trace-viewer.spec.ts › should popup snapshot [pass] +library/trace-viewer.spec.ts › should prefer later resource request with the same method [fail] +library/trace-viewer.spec.ts › should preserve currentSrc [fail] +library/trace-viewer.spec.ts › should preserve noscript when javascript is disabled [pass] +library/trace-viewer.spec.ts › should properly synchronize local and remote time [pass] +library/trace-viewer.spec.ts › should register custom elements [pass] +library/trace-viewer.spec.ts › should remove noscript by default [pass] +library/trace-viewer.spec.ts › should remove noscript when javaScriptEnabled is set to true [pass] +library/trace-viewer.spec.ts › should render console [fail] +library/trace-viewer.spec.ts › should render network bars [pass] +library/trace-viewer.spec.ts › should restore control values [fail] +library/trace-viewer.spec.ts › should restore scroll positions [pass] +library/trace-viewer.spec.ts › should serve css without content-type [timeout] library/trace-viewer.spec.ts › should serve overridden request [fail] -library/trace-viewer.spec.ts › should show action source [fail] -library/trace-viewer.spec.ts › should show baseURL in metadata pane [fail] -library/trace-viewer.spec.ts › should show correct request start time [unknown] +library/trace-viewer.spec.ts › should show action source [pass] +library/trace-viewer.spec.ts › should show baseURL in metadata pane [pass] +library/trace-viewer.spec.ts › should show correct request start time [fail] library/trace-viewer.spec.ts › should show empty trace viewer [fail] -library/trace-viewer.spec.ts › should show font preview [unknown] +library/trace-viewer.spec.ts › should show font preview [fail] library/trace-viewer.spec.ts › should show null as a param [unknown] -library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [unknown] +library/trace-viewer.spec.ts › should show only one pointer with multilevel iframes [pass] library/trace-viewer.spec.ts › should show params and return value [unknown] -library/trace-viewer.spec.ts › should show similar actions from library-only trace [fail] +library/trace-viewer.spec.ts › should show similar actions from library-only trace [pass] library/trace-viewer.spec.ts › should show snapshot URL [unknown] -library/trace-viewer.spec.ts › should update highlight when typing [unknown] -library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [unknown] -library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [unknown] +library/trace-viewer.spec.ts › should update highlight when typing [pass] +library/trace-viewer.spec.ts › should work with adopted style sheets and all: unset [pass] +library/trace-viewer.spec.ts › should work with adopted style sheets and replace/replaceSync [pass] library/trace-viewer.spec.ts › should work with meta CSP [fail] -library/trace-viewer.spec.ts › should work with nesting CSS selectors [fail] +library/trace-viewer.spec.ts › should work with nesting CSS selectors [pass] library/tracing.spec.ts › should collect sources [fail] library/tracing.spec.ts › should collect trace with resources, but no js [fail] -library/tracing.spec.ts › should collect two traces [fail] +library/tracing.spec.ts › should collect two traces [pass] library/tracing.spec.ts › should exclude internal pages [pass] library/tracing.spec.ts › should export trace concurrently to second navigation [pass] library/tracing.spec.ts › should flush console events on tracing stop [pass] -library/tracing.spec.ts › should hide internal stack frames [fail] -library/tracing.spec.ts › should hide internal stack frames in expect [fail] +library/tracing.spec.ts › should hide internal stack frames [pass] +library/tracing.spec.ts › should hide internal stack frames in expect [pass] library/tracing.spec.ts › should ignore iframes in head [pass] library/tracing.spec.ts › should include context API requests [pass] -library/tracing.spec.ts › should include interrupted actions [fail] -library/tracing.spec.ts › should not collect snapshots by default [fail] +library/tracing.spec.ts › should include interrupted actions [pass] +library/tracing.spec.ts › should not collect snapshots by default [pass] library/tracing.spec.ts › should not crash when browser closes mid-trace [pass] library/tracing.spec.ts › should not emit after w/o before [pass] library/tracing.spec.ts › should not flush console events [pass] -library/tracing.spec.ts › should not hang for clicks that open dialogs [fail] +library/tracing.spec.ts › should not hang for clicks that open dialogs [pass] library/tracing.spec.ts › should not include buffers in the trace [pass] library/tracing.spec.ts › should not include trace resources from the previous chunks [fail] -library/tracing.spec.ts › should not stall on dialogs [fail] +library/tracing.spec.ts › should not stall on dialogs [pass] library/tracing.spec.ts › should not throw when stopping without start but not exporting [pass] library/tracing.spec.ts › should overwrite existing file [fail] library/tracing.spec.ts › should produce screencast frames crop [fail] diff --git a/tests/bidi/expectations/bidi-firefox-nightly-page.txt b/tests/bidi/expectations/bidi-firefox-nightly-page.txt index 366d8fdf367ad..f7e42922276b0 100644 --- a/tests/bidi/expectations/bidi-firefox-nightly-page.txt +++ b/tests/bidi/expectations/bidi-firefox-nightly-page.txt @@ -1,13 +1,13 @@ -page/elementhandle-bounding-box.spec.ts › should force a layout [fail] -page/elementhandle-bounding-box.spec.ts › should get frame box [fail] +page/elementhandle-bounding-box.spec.ts › should force a layout [pass] +page/elementhandle-bounding-box.spec.ts › should get frame box [pass] page/elementhandle-bounding-box.spec.ts › should handle nested frames [fail] -page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [fail] +page/elementhandle-bounding-box.spec.ts › should handle scroll offset and click [pass] page/elementhandle-bounding-box.spec.ts › should return null for invisible elements [fail] page/elementhandle-bounding-box.spec.ts › should work [fail] -page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [fail] -page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [fail] +page/elementhandle-bounding-box.spec.ts › should work when inline box child is outside of viewport [pass] +page/elementhandle-bounding-box.spec.ts › should work with SVG nodes [pass] page/elementhandle-click.spec.ts › should double click the button [fail] -page/elementhandle-click.spec.ts › should throw for
elements with force [fail] +page/elementhandle-click.spec.ts › should throw for
elements with force [pass] page/elementhandle-click.spec.ts › should throw for detached nodes [pass] page/elementhandle-click.spec.ts › should throw for hidden nodes with force [pass] page/elementhandle-click.spec.ts › should throw for recursively hidden nodes with force [pass] @@ -22,35 +22,35 @@ page/elementhandle-content-frame.spec.ts › should work for cross-frame evaluat page/elementhandle-content-frame.spec.ts › should work for cross-process iframes [pass] page/elementhandle-convenience.spec.ts › getAttribute should work [pass] page/elementhandle-convenience.spec.ts › innerHTML should work [pass] -page/elementhandle-convenience.spec.ts › innerText should throw [fail] +page/elementhandle-convenience.spec.ts › innerText should throw [pass] page/elementhandle-convenience.spec.ts › innerText should work [pass] page/elementhandle-convenience.spec.ts › inputValue should work [pass] -page/elementhandle-convenience.spec.ts › isChecked should work [fail] -page/elementhandle-convenience.spec.ts › isEditable should work [fail] -page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work [fail] -page/elementhandle-convenience.spec.ts › isEnabled and isDisabled should work with option/optgroup correctly [pass] +page/elementhandle-convenience.spec.ts › isVisible and isHidden should work [pass] +page/elementhandle-convenience.spec.ts › isVisible should not throw when the DOM element is not connected [pass] page/elementhandle-convenience.spec.ts › should have a nice preview [pass] -page/elementhandle-convenience.spec.ts › should have a nice preview for non-ascii attributes/children [fail] +page/elementhandle-convenience.spec.ts › should have a nice preview for non-ascii attributes/children [pass] page/elementhandle-convenience.spec.ts › textContent should work [pass] page/elementhandle-convenience.spec.ts › textContent should work on ShadowRoot [fail] -page/elementhandle-eval-on-selector.spec.ts › should not throw in case of missing selector for all [fail] -page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree [fail] -page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree for all [fail] -page/elementhandle-eval-on-selector.spec.ts › should throw in case of missing selector [fail] -page/elementhandle-eval-on-selector.spec.ts › should work [fail] -page/elementhandle-eval-on-selector.spec.ts › should work for all [fail] -page/elementhandle-misc.spec.ts › should allow disposing twice [fail] -page/elementhandle-misc.spec.ts › should check the box [fail] -page/elementhandle-misc.spec.ts › should check the box using setChecked [fail] +page/elementhandle-eval-on-selector.spec.ts › should not throw in case of missing selector for all [pass] +page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree [pass] +page/elementhandle-eval-on-selector.spec.ts › should retrieve content from subtree for all [pass] +page/elementhandle-eval-on-selector.spec.ts › should throw in case of missing selector [pass] +page/elementhandle-eval-on-selector.spec.ts › should work [pass] +page/elementhandle-eval-on-selector.spec.ts › should work for all [pass] +page/elementhandle-misc.spec.ts › should allow disposing twice [pass] +page/elementhandle-misc.spec.ts › should check the box [pass] +page/elementhandle-misc.spec.ts › should check the box using setChecked [pass] page/elementhandle-misc.spec.ts › should fill input [pass] page/elementhandle-misc.spec.ts › should fill input when Node is removed [pass] page/elementhandle-misc.spec.ts › should focus a button [pass] page/elementhandle-misc.spec.ts › should hover [pass] page/elementhandle-misc.spec.ts › should hover when Node is removed [pass] page/elementhandle-misc.spec.ts › should select single option [pass] -page/elementhandle-misc.spec.ts › should uncheck the box [fail] +page/elementhandle-misc.spec.ts › should uncheck the box [pass] page/elementhandle-owner-frame.spec.ts › should work [fail] page/elementhandle-owner-frame.spec.ts › should work for adopted elements [fail] page/elementhandle-owner-frame.spec.ts › should work for cross-frame evaluations [fail] @@ -58,29 +58,29 @@ page/elementhandle-owner-frame.spec.ts › should work for cross-process iframes page/elementhandle-owner-frame.spec.ts › should work for detached elements [fail] page/elementhandle-owner-frame.spec.ts › should work for document [fail] page/elementhandle-owner-frame.spec.ts › should work for iframe elements [fail] -page/elementhandle-press.spec.ts › should not modify selection when focused [fail] -page/elementhandle-press.spec.ts › should not select existing value [fail] -page/elementhandle-press.spec.ts › should reset selection when not focused [fail] -page/elementhandle-press.spec.ts › should work [fail] -page/elementhandle-press.spec.ts › should work with number input [fail] -page/elementhandle-query-selector.spec.ts › should query existing element [fail] +page/elementhandle-press.spec.ts › should not modify selection when focused [pass] +page/elementhandle-press.spec.ts › should not select existing value [pass] +page/elementhandle-press.spec.ts › should reset selection when not focused [pass] +page/elementhandle-press.spec.ts › should work [pass] +page/elementhandle-press.spec.ts › should work with number input [pass] +page/elementhandle-query-selector.spec.ts › should query existing element [pass] page/elementhandle-query-selector.spec.ts › should query existing elements [fail] page/elementhandle-query-selector.spec.ts › should return empty array for non-existing elements [fail] -page/elementhandle-query-selector.spec.ts › should return null for non-existing element [fail] +page/elementhandle-query-selector.spec.ts › should return null for non-existing element [pass] page/elementhandle-query-selector.spec.ts › should work for adopted elements [timeout] page/elementhandle-query-selector.spec.ts › xpath should query existing element [fail] page/elementhandle-query-selector.spec.ts › xpath should return null for non-existing element [fail] page/elementhandle-screenshot.spec.ts › element screenshot › path option should create subdirectories [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport [fail] page/elementhandle-screenshot.spec.ts › element screenshot › should capture full element when larger than viewport in parallel [fail] -page/elementhandle-screenshot.spec.ts › element screenshot › should fail to screenshot a detached element [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should fail to screenshot a detached element [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should not issue resize event [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should prefer type over extension [fail] page/elementhandle-screenshot.spec.ts › element screenshot › should scroll 15000px into view [fail] -page/elementhandle-screenshot.spec.ts › element screenshot › should scroll element into view [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should scroll element into view [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should take into account padding and border [fail] -page/elementhandle-screenshot.spec.ts › element screenshot › should take screenshot of disabled button [fail] -page/elementhandle-screenshot.spec.ts › element screenshot › should timeout waiting for visible [fail] +page/elementhandle-screenshot.spec.ts › element screenshot › should take screenshot of disabled button [pass] +page/elementhandle-screenshot.spec.ts › element screenshot › should timeout waiting for visible [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should wait for element to stop moving [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should wait for visible [pass] page/elementhandle-screenshot.spec.ts › element screenshot › should work [fail] @@ -92,250 +92,250 @@ page/elementhandle-scroll-into-view.spec.ts › should scroll display:contents i page/elementhandle-scroll-into-view.spec.ts › should throw for detached element [fail] page/elementhandle-scroll-into-view.spec.ts › should timeout waiting for visible [fail] page/elementhandle-scroll-into-view.spec.ts › should wait for display:none to become visible [fail] -page/elementhandle-scroll-into-view.spec.ts › should wait for element to stop moving [fail] +page/elementhandle-scroll-into-view.spec.ts › should wait for element to stop moving [pass] page/elementhandle-scroll-into-view.spec.ts › should wait for nested display:none to become visible [fail] page/elementhandle-scroll-into-view.spec.ts › should work @smoke [pass] -page/elementhandle-scroll-into-view.spec.ts › should work for visibility:hidden element [fail] -page/elementhandle-scroll-into-view.spec.ts › should work for zero-sized element [fail] +page/elementhandle-scroll-into-view.spec.ts › should work for visibility:hidden element [pass] +page/elementhandle-scroll-into-view.spec.ts › should work for zero-sized element [pass] page/elementhandle-select-text.spec.ts › should select input [fail] page/elementhandle-select-text.spec.ts › should select plain div [pass] page/elementhandle-select-text.spec.ts › should select textarea [fail] page/elementhandle-select-text.spec.ts › should timeout waiting for invisible element [pass] page/elementhandle-select-text.spec.ts › should wait for visible [pass] -page/elementhandle-type.spec.ts › should not modify selection when focused [fail] -page/elementhandle-type.spec.ts › should not select existing value [fail] -page/elementhandle-type.spec.ts › should reset selection when not focused [fail] -page/elementhandle-type.spec.ts › should work [fail] -page/elementhandle-type.spec.ts › should work with number input [fail] -page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for enabled when detached [fail] -page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for visible when detached [fail] -page/elementhandle-wait-for-element-state.spec.ts › should timeout waiting for visible [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for already hidden [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for already visible [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for aria enabled button [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for button with an aria-disabled parent [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for editable input [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden [fail] -page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden when detached [fail] +page/elementhandle-type.spec.ts › should not modify selection when focused [pass] +page/elementhandle-type.spec.ts › should not select existing value [pass] +page/elementhandle-type.spec.ts › should reset selection when not focused [pass] +page/elementhandle-type.spec.ts › should work [pass] +page/elementhandle-type.spec.ts › should work with number input [pass] +page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for enabled when detached [pass] +page/elementhandle-wait-for-element-state.spec.ts › should throw waiting for visible when detached [pass] +page/elementhandle-wait-for-element-state.spec.ts › should timeout waiting for visible [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for already hidden [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for already visible [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for aria enabled button [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for button with an aria-disabled parent [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for editable input [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden [pass] +page/elementhandle-wait-for-element-state.spec.ts › should wait for hidden when detached [pass] page/elementhandle-wait-for-element-state.spec.ts › should wait for stable position [pass] -page/elementhandle-wait-for-element-state.spec.ts › should wait for visible [fail] -page/eval-on-selector-all.spec.ts › should auto-detect css selector [fail] -page/eval-on-selector-all.spec.ts › should return complex values [fail] -page/eval-on-selector-all.spec.ts › should support * capture [fail] -page/eval-on-selector-all.spec.ts › should support * capture when multiple paths match [fail] -page/eval-on-selector-all.spec.ts › should support >> syntax [fail] -page/eval-on-selector-all.spec.ts › should work with bogus Array.from [fail] -page/eval-on-selector-all.spec.ts › should work with css selector [fail] -page/eval-on-selector-all.spec.ts › should work with text selector [fail] -page/eval-on-selector-all.spec.ts › should work with xpath selector [fail] -page/eval-on-selector.spec.ts › should accept ElementHandles as arguments [fail] -page/eval-on-selector.spec.ts › should accept arguments [fail] -page/eval-on-selector.spec.ts › should auto-detect css selector [fail] -page/eval-on-selector.spec.ts › should auto-detect css selector with attributes [fail] -page/eval-on-selector.spec.ts › should auto-detect nested selectors [fail] -page/eval-on-selector.spec.ts › should not stop at first failure with >> syntax [fail] -page/eval-on-selector.spec.ts › should return complex values [fail] -page/eval-on-selector.spec.ts › should support * capture [fail] -page/eval-on-selector.spec.ts › should support >> syntax [fail] -page/eval-on-selector.spec.ts › should support >> syntax with different engines [fail] +page/elementhandle-wait-for-element-state.spec.ts › should wait for visible [pass] +page/eval-on-selector-all.spec.ts › should auto-detect css selector [pass] +page/eval-on-selector-all.spec.ts › should return complex values [pass] +page/eval-on-selector-all.spec.ts › should support * capture [pass] +page/eval-on-selector-all.spec.ts › should support * capture when multiple paths match [pass] +page/eval-on-selector-all.spec.ts › should support >> syntax [pass] +page/eval-on-selector-all.spec.ts › should work with bogus Array.from [pass] +page/eval-on-selector-all.spec.ts › should work with css selector [pass] +page/eval-on-selector-all.spec.ts › should work with text selector [pass] +page/eval-on-selector-all.spec.ts › should work with xpath selector [pass] +page/eval-on-selector.spec.ts › should accept ElementHandles as arguments [pass] +page/eval-on-selector.spec.ts › should accept arguments [pass] +page/eval-on-selector.spec.ts › should auto-detect css selector [pass] +page/eval-on-selector.spec.ts › should auto-detect css selector with attributes [pass] +page/eval-on-selector.spec.ts › should auto-detect nested selectors [pass] +page/eval-on-selector.spec.ts › should not stop at first failure with >> syntax [pass] +page/eval-on-selector.spec.ts › should return complex values [pass] +page/eval-on-selector.spec.ts › should support * capture [pass] +page/eval-on-selector.spec.ts › should support >> syntax [pass] +page/eval-on-selector.spec.ts › should support >> syntax with different engines [pass] page/eval-on-selector.spec.ts › should support spaces with >> syntax [pass] page/eval-on-selector.spec.ts › should throw error if no element is found [pass] page/eval-on-selector.spec.ts › should throw on malformed * capture [pass] page/eval-on-selector.spec.ts › should throw on multiple * captures [pass] -page/eval-on-selector.spec.ts › should work with css selector [fail] -page/eval-on-selector.spec.ts › should work with data-test selector [fail] -page/eval-on-selector.spec.ts › should work with data-test-id selector [fail] -page/eval-on-selector.spec.ts › should work with data-testid selector [fail] -page/eval-on-selector.spec.ts › should work with id selector [fail] -page/eval-on-selector.spec.ts › should work with quotes in css attributes [fail] -page/eval-on-selector.spec.ts › should work with quotes in css attributes when missing [fail] -page/eval-on-selector.spec.ts › should work with spaces in css attributes [fail] -page/eval-on-selector.spec.ts › should work with spaces in css attributes when missing [fail] -page/eval-on-selector.spec.ts › should work with text selector [fail] -page/eval-on-selector.spec.ts › should work with text selector in quotes [fail] -page/eval-on-selector.spec.ts › should work with xpath selector [fail] -page/expect-boolean.spec.ts › not.toBeDisabled div [fail] -page/expect-boolean.spec.ts › not.toBeEmpty [fail] +page/eval-on-selector.spec.ts › should work with css selector [pass] +page/eval-on-selector.spec.ts › should work with data-test selector [pass] +page/eval-on-selector.spec.ts › should work with data-test-id selector [pass] +page/eval-on-selector.spec.ts › should work with data-testid selector [pass] +page/eval-on-selector.spec.ts › should work with id selector [pass] +page/eval-on-selector.spec.ts › should work with quotes in css attributes [pass] +page/eval-on-selector.spec.ts › should work with quotes in css attributes when missing [pass] +page/eval-on-selector.spec.ts › should work with spaces in css attributes [pass] +page/eval-on-selector.spec.ts › should work with spaces in css attributes when missing [pass] +page/eval-on-selector.spec.ts › should work with text selector [pass] +page/eval-on-selector.spec.ts › should work with text selector in quotes [pass] +page/eval-on-selector.spec.ts › should work with xpath selector [pass] +page/expect-boolean.spec.ts › not.toBeDisabled div [pass] +page/expect-boolean.spec.ts › not.toBeEmpty [pass] page/expect-boolean.spec.ts › not.toBeOK [pass] page/expect-boolean.spec.ts › should print selector syntax error [pass] page/expect-boolean.spec.ts › should print unknown engine error [pass] -page/expect-boolean.spec.ts › toBeAttached › default [fail] -page/expect-boolean.spec.ts › toBeAttached › eventually [fail] -page/expect-boolean.spec.ts › toBeAttached › eventually with not [fail] -page/expect-boolean.spec.ts › toBeAttached › fail [fail] -page/expect-boolean.spec.ts › toBeAttached › fail with not [fail] +page/expect-boolean.spec.ts › toBeAttached › default [pass] +page/expect-boolean.spec.ts › toBeAttached › eventually [pass] +page/expect-boolean.spec.ts › toBeAttached › eventually with not [pass] +page/expect-boolean.spec.ts › toBeAttached › fail [pass] +page/expect-boolean.spec.ts › toBeAttached › fail with not [pass] page/expect-boolean.spec.ts › toBeAttached › over navigation [pass] -page/expect-boolean.spec.ts › toBeAttached › with attached:false [fail] -page/expect-boolean.spec.ts › toBeAttached › with attached:true [fail] -page/expect-boolean.spec.ts › toBeAttached › with frameLocator [fail] -page/expect-boolean.spec.ts › toBeAttached › with hidden element [fail] -page/expect-boolean.spec.ts › toBeAttached › with impossible timeout [fail] -page/expect-boolean.spec.ts › toBeAttached › with impossible timeout .not [fail] -page/expect-boolean.spec.ts › toBeAttached › with not [fail] -page/expect-boolean.spec.ts › toBeAttached › with not and attached:false [fail] -page/expect-boolean.spec.ts › toBeChecked with value [fail] -page/expect-boolean.spec.ts › toBeChecked › default [fail] -page/expect-boolean.spec.ts › toBeChecked › fail [fail] -page/expect-boolean.spec.ts › toBeChecked › fail missing [fail] -page/expect-boolean.spec.ts › toBeChecked › fail with checked:false [fail] +page/expect-boolean.spec.ts › toBeAttached › with attached:false [pass] +page/expect-boolean.spec.ts › toBeAttached › with attached:true [pass] +page/expect-boolean.spec.ts › toBeAttached › with frameLocator [pass] +page/expect-boolean.spec.ts › toBeAttached › with hidden element [pass] +page/expect-boolean.spec.ts › toBeAttached › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeAttached › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeAttached › with not [pass] +page/expect-boolean.spec.ts › toBeAttached › with not and attached:false [pass] +page/expect-boolean.spec.ts › toBeChecked with value [pass] +page/expect-boolean.spec.ts › toBeChecked › default [pass] +page/expect-boolean.spec.ts › toBeChecked › fail [pass] +page/expect-boolean.spec.ts › toBeChecked › fail missing [pass] +page/expect-boolean.spec.ts › toBeChecked › fail with checked:false [pass] page/expect-boolean.spec.ts › toBeChecked › fail with not [fail] -page/expect-boolean.spec.ts › toBeChecked › friendly log [fail] -page/expect-boolean.spec.ts › toBeChecked › with checked:false [fail] -page/expect-boolean.spec.ts › toBeChecked › with checked:true [fail] -page/expect-boolean.spec.ts › toBeChecked › with impossible timeout [fail] -page/expect-boolean.spec.ts › toBeChecked › with impossible timeout .not [fail] +page/expect-boolean.spec.ts › toBeChecked › friendly log [pass] +page/expect-boolean.spec.ts › toBeChecked › with checked:false [pass] +page/expect-boolean.spec.ts › toBeChecked › with checked:true [pass] +page/expect-boolean.spec.ts › toBeChecked › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeChecked › with impossible timeout .not [pass] page/expect-boolean.spec.ts › toBeChecked › with not [fail] -page/expect-boolean.spec.ts › toBeChecked › with not and checked:false [fail] -page/expect-boolean.spec.ts › toBeChecked › with role [fail] -page/expect-boolean.spec.ts › toBeDisabled with value [fail] -page/expect-boolean.spec.ts › toBeEditable › default [fail] -page/expect-boolean.spec.ts › toBeEditable › with editable:false [fail] -page/expect-boolean.spec.ts › toBeEditable › with editable:true [fail] -page/expect-boolean.spec.ts › toBeEditable › with not [fail] +page/expect-boolean.spec.ts › toBeChecked › with not and checked:false [pass] +page/expect-boolean.spec.ts › toBeChecked › with role [pass] +page/expect-boolean.spec.ts › toBeDisabled with value [pass] +page/expect-boolean.spec.ts › toBeEditable › default [pass] +page/expect-boolean.spec.ts › toBeEditable › with editable:false [pass] +page/expect-boolean.spec.ts › toBeEditable › with editable:true [pass] +page/expect-boolean.spec.ts › toBeEditable › with not [pass] page/expect-boolean.spec.ts › toBeEditable › with not and editable:false [fail] -page/expect-boolean.spec.ts › toBeEmpty div [fail] -page/expect-boolean.spec.ts › toBeEmpty input [fail] -page/expect-boolean.spec.ts › toBeEnabled › default [fail] -page/expect-boolean.spec.ts › toBeEnabled › eventually [fail] -page/expect-boolean.spec.ts › toBeEnabled › eventually with not [fail] -page/expect-boolean.spec.ts › toBeEnabled › failed [fail] -page/expect-boolean.spec.ts › toBeEnabled › toBeDisabled [fail] -page/expect-boolean.spec.ts › toBeEnabled › with enabled:false [fail] -page/expect-boolean.spec.ts › toBeEnabled › with enabled:true [fail] -page/expect-boolean.spec.ts › toBeEnabled › with not and enabled:false [fail] -page/expect-boolean.spec.ts › toBeFocused [fail] -page/expect-boolean.spec.ts › toBeFocused with shadow elements [fail] +page/expect-boolean.spec.ts › toBeEmpty div [pass] +page/expect-boolean.spec.ts › toBeEmpty input [pass] +page/expect-boolean.spec.ts › toBeEnabled › default [pass] +page/expect-boolean.spec.ts › toBeEnabled › eventually [pass] +page/expect-boolean.spec.ts › toBeEnabled › eventually with not [pass] +page/expect-boolean.spec.ts › toBeEnabled › failed [pass] +page/expect-boolean.spec.ts › toBeEnabled › toBeDisabled [pass] +page/expect-boolean.spec.ts › toBeEnabled › with enabled:false [pass] +page/expect-boolean.spec.ts › toBeEnabled › with enabled:true [pass] +page/expect-boolean.spec.ts › toBeEnabled › with not and enabled:false [pass] +page/expect-boolean.spec.ts › toBeFocused [pass] +page/expect-boolean.spec.ts › toBeFocused with shadow elements [pass] page/expect-boolean.spec.ts › toBeHidden with value [fail] -page/expect-boolean.spec.ts › toBeHidden › default [fail] -page/expect-boolean.spec.ts › toBeHidden › eventually [fail] -page/expect-boolean.spec.ts › toBeHidden › eventually with not [fail] -page/expect-boolean.spec.ts › toBeHidden › fail [fail] -page/expect-boolean.spec.ts › toBeHidden › fail with not [fail] -page/expect-boolean.spec.ts › toBeHidden › fail with not when nothing matching [fail] -page/expect-boolean.spec.ts › toBeHidden › when nothing matches [fail] -page/expect-boolean.spec.ts › toBeHidden › with impossible timeout [fail] -page/expect-boolean.spec.ts › toBeHidden › with impossible timeout .not [fail] -page/expect-boolean.spec.ts › toBeHidden › with not [fail] +page/expect-boolean.spec.ts › toBeHidden › default [pass] +page/expect-boolean.spec.ts › toBeHidden › eventually [pass] +page/expect-boolean.spec.ts › toBeHidden › eventually with not [pass] +page/expect-boolean.spec.ts › toBeHidden › fail [pass] +page/expect-boolean.spec.ts › toBeHidden › fail with not [pass] +page/expect-boolean.spec.ts › toBeHidden › fail with not when nothing matching [pass] +page/expect-boolean.spec.ts › toBeHidden › when nothing matches [pass] +page/expect-boolean.spec.ts › toBeHidden › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeHidden › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeHidden › with not [pass] page/expect-boolean.spec.ts › toBeOK [pass] page/expect-boolean.spec.ts › toBeOK fail with invalid argument [pass] page/expect-boolean.spec.ts › toBeOK fail with promise [pass] page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › image content type [pass] page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › no content type [pass] page/expect-boolean.spec.ts › toBeOK should print response with text content type when fails › text content type [pass] -page/expect-boolean.spec.ts › toBeVisible › default [fail] -page/expect-boolean.spec.ts › toBeVisible › eventually [fail] -page/expect-boolean.spec.ts › toBeVisible › eventually with not [fail] -page/expect-boolean.spec.ts › toBeVisible › fail [fail] -page/expect-boolean.spec.ts › toBeVisible › fail with not [fail] +page/expect-boolean.spec.ts › toBeVisible › default [pass] +page/expect-boolean.spec.ts › toBeVisible › eventually [pass] +page/expect-boolean.spec.ts › toBeVisible › eventually with not [pass] +page/expect-boolean.spec.ts › toBeVisible › fail [pass] +page/expect-boolean.spec.ts › toBeVisible › fail with not [pass] page/expect-boolean.spec.ts › toBeVisible › over navigation [pass] -page/expect-boolean.spec.ts › toBeVisible › with frameLocator [fail] -page/expect-boolean.spec.ts › toBeVisible › with frameLocator 2 [fail] -page/expect-boolean.spec.ts › toBeVisible › with impossible timeout [fail] -page/expect-boolean.spec.ts › toBeVisible › with impossible timeout .not [fail] -page/expect-boolean.spec.ts › toBeVisible › with not [fail] -page/expect-boolean.spec.ts › toBeVisible › with not and visible:false [fail] -page/expect-boolean.spec.ts › toBeVisible › with visible:false [fail] -page/expect-boolean.spec.ts › toBeVisible › with visible:true [fail] -page/expect-matcher-result.spec.ts › toBeChecked({ checked: false }) should have expected: false [fail] -page/expect-matcher-result.spec.ts › toBeTruthy-based assertions should have matcher result [fail] -page/expect-matcher-result.spec.ts › toEqual-based assertions should have matcher result [fail] +page/expect-boolean.spec.ts › toBeVisible › with frameLocator [pass] +page/expect-boolean.spec.ts › toBeVisible › with frameLocator 2 [pass] +page/expect-boolean.spec.ts › toBeVisible › with impossible timeout [pass] +page/expect-boolean.spec.ts › toBeVisible › with impossible timeout .not [pass] +page/expect-boolean.spec.ts › toBeVisible › with not [pass] +page/expect-boolean.spec.ts › toBeVisible › with not and visible:false [pass] +page/expect-boolean.spec.ts › toBeVisible › with visible:false [pass] +page/expect-boolean.spec.ts › toBeVisible › with visible:true [pass] +page/expect-matcher-result.spec.ts › toBeChecked({ checked: false }) should have expected: false [pass] +page/expect-matcher-result.spec.ts › toBeTruthy-based assertions should have matcher result [pass] +page/expect-matcher-result.spec.ts › toEqual-based assertions should have matcher result [pass] page/expect-matcher-result.spec.ts › toHaveScreenshot should populate matcherResult [fail] -page/expect-matcher-result.spec.ts › toMatchText-based assertions should have matcher result [fail] +page/expect-matcher-result.spec.ts › toMatchText-based assertions should have matcher result [pass] page/expect-misc.spec.ts › toBeInViewport › should have good stack [pass] -page/expect-misc.spec.ts › toBeInViewport › should report intersection even if fully covered by other element [fail] -page/expect-misc.spec.ts › toBeInViewport › should respect ratio option [fail] -page/expect-misc.spec.ts › toBeInViewport › should work [fail] -page/expect-misc.spec.ts › toHaveAccessibleDescription [fail] -page/expect-misc.spec.ts › toHaveAccessibleName [fail] -page/expect-misc.spec.ts › toHaveAttribute › pass [fail] -page/expect-misc.spec.ts › toHaveAttribute › should match attribute without value [fail] -page/expect-misc.spec.ts › toHaveAttribute › should match boolean attribute [fail] -page/expect-misc.spec.ts › toHaveAttribute › should not match missing attribute [fail] -page/expect-misc.spec.ts › toHaveAttribute › should support boolean attribute with options [fail] -page/expect-misc.spec.ts › toHaveAttribute › support ignoreCase [fail] -page/expect-misc.spec.ts › toHaveCSS › custom css properties [fail] -page/expect-misc.spec.ts › toHaveCSS › pass [fail] -page/expect-misc.spec.ts › toHaveClass › fail [fail] -page/expect-misc.spec.ts › toHaveClass › fail with array [fail] -page/expect-misc.spec.ts › toHaveClass › pass [fail] -page/expect-misc.spec.ts › toHaveClass › pass with SVGs [fail] -page/expect-misc.spec.ts › toHaveClass › pass with array [fail] -page/expect-misc.spec.ts › toHaveCount should not produce logs twice [fail] -page/expect-misc.spec.ts › toHaveCount › eventually pass non-zero [fail] -page/expect-misc.spec.ts › toHaveCount › eventually pass not non-zero [fail] -page/expect-misc.spec.ts › toHaveCount › eventually pass zero [fail] -page/expect-misc.spec.ts › toHaveCount › fail zero [fail] -page/expect-misc.spec.ts › toHaveCount › fail zero 2 [fail] -page/expect-misc.spec.ts › toHaveCount › pass zero [fail] -page/expect-misc.spec.ts › toHaveCount › toHaveCount pass [fail] -page/expect-misc.spec.ts › toHaveId › pass [fail] -page/expect-misc.spec.ts › toHaveJSProperty › fail [fail] -page/expect-misc.spec.ts › toHaveJSProperty › fail boolean [fail] -page/expect-misc.spec.ts › toHaveJSProperty › fail boolean 2 [fail] -page/expect-misc.spec.ts › toHaveJSProperty › fail nested [fail] -page/expect-misc.spec.ts › toHaveJSProperty › fail number [fail] -page/expect-misc.spec.ts › toHaveJSProperty › fail string [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass boolean [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass boolean 2 [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass nested [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass null [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass number [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass string [fail] -page/expect-misc.spec.ts › toHaveJSProperty › pass undefined [fail] -page/expect-misc.spec.ts › toHaveRole [fail] -page/expect-misc.spec.ts › toHaveText should not produce logs twice [fail] -page/expect-misc.spec.ts › toHaveText that does not match should not produce logs twice [fail] -page/expect-misc.spec.ts › toHaveTitle › fail [fail] -page/expect-misc.spec.ts › toHaveTitle › pass [fail] +page/expect-misc.spec.ts › toBeInViewport › should report intersection even if fully covered by other element [pass] +page/expect-misc.spec.ts › toBeInViewport › should respect ratio option [pass] +page/expect-misc.spec.ts › toBeInViewport › should work [pass] +page/expect-misc.spec.ts › toHaveAccessibleDescription [pass] +page/expect-misc.spec.ts › toHaveAccessibleName [pass] +page/expect-misc.spec.ts › toHaveAttribute › pass [pass] +page/expect-misc.spec.ts › toHaveAttribute › should match attribute without value [pass] +page/expect-misc.spec.ts › toHaveAttribute › should match boolean attribute [pass] +page/expect-misc.spec.ts › toHaveAttribute › should not match missing attribute [pass] +page/expect-misc.spec.ts › toHaveAttribute › should support boolean attribute with options [pass] +page/expect-misc.spec.ts › toHaveAttribute › support ignoreCase [pass] +page/expect-misc.spec.ts › toHaveCSS › custom css properties [pass] +page/expect-misc.spec.ts › toHaveCSS › pass [pass] +page/expect-misc.spec.ts › toHaveClass › fail [pass] +page/expect-misc.spec.ts › toHaveClass › fail with array [pass] +page/expect-misc.spec.ts › toHaveClass › pass [pass] +page/expect-misc.spec.ts › toHaveClass › pass with SVGs [pass] +page/expect-misc.spec.ts › toHaveClass › pass with array [pass] +page/expect-misc.spec.ts › toHaveCount should not produce logs twice [pass] +page/expect-misc.spec.ts › toHaveCount › eventually pass non-zero [pass] +page/expect-misc.spec.ts › toHaveCount › eventually pass not non-zero [pass] +page/expect-misc.spec.ts › toHaveCount › eventually pass zero [pass] +page/expect-misc.spec.ts › toHaveCount › fail zero [pass] +page/expect-misc.spec.ts › toHaveCount › fail zero 2 [pass] +page/expect-misc.spec.ts › toHaveCount › pass zero [pass] +page/expect-misc.spec.ts › toHaveCount › toHaveCount pass [pass] +page/expect-misc.spec.ts › toHaveId › pass [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail boolean [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail boolean 2 [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail nested [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail number [pass] +page/expect-misc.spec.ts › toHaveJSProperty › fail string [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass boolean [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass boolean 2 [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass nested [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass null [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass number [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass string [pass] +page/expect-misc.spec.ts › toHaveJSProperty › pass undefined [pass] +page/expect-misc.spec.ts › toHaveRole [pass] +page/expect-misc.spec.ts › toHaveText should not produce logs twice [pass] +page/expect-misc.spec.ts › toHaveText that does not match should not produce logs twice [pass] +page/expect-misc.spec.ts › toHaveTitle › fail [pass] +page/expect-misc.spec.ts › toHaveTitle › pass [pass] page/expect-misc.spec.ts › toHaveURL › fail [pass] page/expect-misc.spec.ts › toHaveURL › pass [pass] page/expect-misc.spec.ts › toHaveURL › support ignoreCase [pass] page/expect-timeout.spec.ts › should have timeout error name [pass] page/expect-timeout.spec.ts › should not print timed out error message when page closes [fail] -page/expect-timeout.spec.ts › should not throw when navigating during first locator handler check [fail] -page/expect-timeout.spec.ts › should not throw when navigating during one-shot check [fail] -page/expect-timeout.spec.ts › should print timed out error message [fail] -page/expect-timeout.spec.ts › should print timed out error message when value does not match [fail] -page/expect-timeout.spec.ts › should print timed out error message when value does not match with impossible timeout [fail] -page/expect-timeout.spec.ts › should print timed out error message with impossible timeout [fail] -page/expect-timeout.spec.ts › should timeout during first locator handler check [fail] -page/expect-to-have-text.spec.ts › not.toHaveText › fail [fail] -page/expect-to-have-text.spec.ts › not.toHaveText › pass [fail] -page/expect-to-have-text.spec.ts › not.toHaveText › should work when selector does not match [fail] -page/expect-to-have-text.spec.ts › toContainText with array › fail [fail] -page/expect-to-have-text.spec.ts › toContainText with array › pass [fail] -page/expect-to-have-text.spec.ts › toContainText with regex › fail [fail] -page/expect-to-have-text.spec.ts › toContainText with regex › pass [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › fail [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › fail on not+empty [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › fail on repeating array matchers [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › pass [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › pass empty [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › pass eventually empty [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › pass lazy [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › pass not empty [fail] -page/expect-to-have-text.spec.ts › toHaveText with array › pass on empty [fail] -page/expect-to-have-text.spec.ts › toHaveText with regex › fail [fail] -page/expect-to-have-text.spec.ts › toHaveText with regex › pass [fail] +page/expect-timeout.spec.ts › should not throw when navigating during first locator handler check [pass] +page/expect-timeout.spec.ts › should not throw when navigating during one-shot check [pass] +page/expect-timeout.spec.ts › should print timed out error message [pass] +page/expect-timeout.spec.ts › should print timed out error message when value does not match [pass] +page/expect-timeout.spec.ts › should print timed out error message when value does not match with impossible timeout [pass] +page/expect-timeout.spec.ts › should print timed out error message with impossible timeout [pass] +page/expect-timeout.spec.ts › should timeout during first locator handler check [pass] +page/expect-to-have-text.spec.ts › not.toHaveText › fail [pass] +page/expect-to-have-text.spec.ts › not.toHaveText › pass [pass] +page/expect-to-have-text.spec.ts › not.toHaveText › should work when selector does not match [pass] +page/expect-to-have-text.spec.ts › toContainText with array › fail [pass] +page/expect-to-have-text.spec.ts › toContainText with array › pass [pass] +page/expect-to-have-text.spec.ts › toContainText with regex › fail [pass] +page/expect-to-have-text.spec.ts › toContainText with regex › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › fail [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › fail on not+empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › fail on repeating array matchers [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass eventually empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass lazy [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass not empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with array › pass on empty [pass] +page/expect-to-have-text.spec.ts › toHaveText with regex › fail [pass] +page/expect-to-have-text.spec.ts › toHaveText with regex › pass [pass] page/expect-to-have-text.spec.ts › toHaveText with text › fail [fail] -page/expect-to-have-text.spec.ts › toHaveText with text › fail with impossible timeout [fail] -page/expect-to-have-text.spec.ts › toHaveText with text › in shadow dom [fail] -page/expect-to-have-text.spec.ts › toHaveText with text › pass [fail] -page/expect-to-have-text.spec.ts › toHaveText with text › pass contain [fail] -page/expect-to-have-text.spec.ts › toHaveText with text › pass eventually [fail] -page/expect-to-have-text.spec.ts › toHaveText with text › with userInnerText [fail] -page/expect-to-have-value.spec.ts › should support failure [fail] -page/expect-to-have-value.spec.ts › should work [fail] -page/expect-to-have-value.spec.ts › should work with label [fail] -page/expect-to-have-value.spec.ts › should work with regex [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › exact match with text failure [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when items not selected [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when multiple not specified [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when not a select element [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › follows labels [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with regex [fail] -page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with text [fail] +page/expect-to-have-text.spec.ts › toHaveText with text › fail with impossible timeout [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › in shadow dom [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › pass [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › pass contain [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › pass eventually [pass] +page/expect-to-have-text.spec.ts › toHaveText with text › with userInnerText [pass] +page/expect-to-have-value.spec.ts › should support failure [pass] +page/expect-to-have-value.spec.ts › should work [pass] +page/expect-to-have-value.spec.ts › should work with label [pass] +page/expect-to-have-value.spec.ts › should work with regex [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › exact match with text failure [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when items not selected [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when multiple not specified [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › fails when not a select element [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › follows labels [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with regex [pass] +page/expect-to-have-value.spec.ts › toHaveValues with multi-select › works with text [pass] page/frame-evaluate.spec.ts › evaluateHandle should work [pass] page/frame-evaluate.spec.ts › should allow cross-frame element handles [fail] page/frame-evaluate.spec.ts › should be isolated between frames [pass] @@ -382,10 +382,10 @@ page/interception.spec.ts › should not break remote worker importScripts [pass page/interception.spec.ts › should work with glob [pass] page/interception.spec.ts › should work with navigation @smoke [pass] page/interception.spec.ts › should work with regular expression passed from a different context [fail] -page/jshandle-as-element.spec.ts › should return ElementHandle for TextNodes [fail] +page/jshandle-as-element.spec.ts › should return ElementHandle for TextNodes [pass] page/jshandle-as-element.spec.ts › should return null for non-elements [pass] page/jshandle-as-element.spec.ts › should work @smoke [pass] -page/jshandle-as-element.spec.ts › should work with nullified Node [fail] +page/jshandle-as-element.spec.ts › should work with nullified Node [pass] page/jshandle-evaluate.spec.ts › should work with expression [fail] page/jshandle-evaluate.spec.ts › should work with function @smoke [pass] page/jshandle-json-value.spec.ts › should handle circular objects [pass] @@ -404,37 +404,37 @@ page/jshandle-to-string.spec.ts › should work for primitives [pass] page/jshandle-to-string.spec.ts › should work for promises [fail] page/jshandle-to-string.spec.ts › should work with different subtypes @smoke [fail] page/jshandle-to-string.spec.ts › should work with previewable subtypes [fail] -page/locator-click.spec.ts › should click if the target element is removed in pointerdown event [fail] -page/locator-click.spec.ts › should click if the target element is removed in pointerup event [fail] +page/locator-click.spec.ts › should click if the target element is removed in pointerdown event [pass] +page/locator-click.spec.ts › should click if the target element is removed in pointerup event [pass] page/locator-click.spec.ts › should double click the button [fail] page/locator-click.spec.ts › should work @smoke [pass] page/locator-click.spec.ts › should work for TextNodes [fail] page/locator-click.spec.ts › should work with Node removed [pass] -page/locator-convenience.spec.ts › allInnerTexts should work [fail] -page/locator-convenience.spec.ts › allTextContents should work [fail] +page/locator-convenience.spec.ts › allInnerTexts should work [pass] +page/locator-convenience.spec.ts › allTextContents should work [pass] page/locator-convenience.spec.ts › getAttribute should work [pass] page/locator-convenience.spec.ts › innerHTML should work [pass] -page/locator-convenience.spec.ts › innerText should produce log [fail] -page/locator-convenience.spec.ts › innerText should throw [fail] +page/locator-convenience.spec.ts › innerText should produce log [pass] +page/locator-convenience.spec.ts › innerText should throw [pass] page/locator-convenience.spec.ts › innerText should work [pass] page/locator-convenience.spec.ts › inputValue should work [pass] -page/locator-convenience.spec.ts › isChecked should work [fail] -page/locator-convenience.spec.ts › isChecked should work for indeterminate input [fail] +page/locator-convenience.spec.ts › isChecked should work [pass] +page/locator-convenience.spec.ts › isChecked should work for indeterminate input [pass] page/locator-convenience.spec.ts › isEditable should work [fail] -page/locator-convenience.spec.ts › isEnabled and isDisabled should work [fail] +page/locator-convenience.spec.ts › isEnabled and isDisabled should work [pass] page/locator-convenience.spec.ts › should have a nice preview [pass] -page/locator-convenience.spec.ts › should return page [fail] +page/locator-convenience.spec.ts › should return page [pass] page/locator-convenience.spec.ts › textContent should work [pass] -page/locator-element-handle.spec.ts › should query existing element @smoke [fail] +page/locator-element-handle.spec.ts › should query existing element @smoke [pass] page/locator-element-handle.spec.ts › should query existing elements [fail] page/locator-element-handle.spec.ts › should return empty array for non-existing elements [fail] -page/locator-element-handle.spec.ts › xpath should query existing element [fail] +page/locator-element-handle.spec.ts › xpath should query existing element [pass] page/locator-element-handle.spec.ts › xpath should return null for non-existing element [fail] -page/locator-evaluate.spec.ts › should not throw in case of missing selector for all [fail] -page/locator-evaluate.spec.ts › should retrieve content from subtree [fail] -page/locator-evaluate.spec.ts › should retrieve content from subtree for all [fail] -page/locator-evaluate.spec.ts › should work @smoke [fail] -page/locator-evaluate.spec.ts › should work for all [fail] +page/locator-evaluate.spec.ts › should not throw in case of missing selector for all [pass] +page/locator-evaluate.spec.ts › should retrieve content from subtree [pass] +page/locator-evaluate.spec.ts › should retrieve content from subtree for all [pass] +page/locator-evaluate.spec.ts › should work @smoke [pass] +page/locator-evaluate.spec.ts › should work for all [pass] page/locator-frame.spec.ts › click should survive frame reattach [pass] page/locator-frame.spec.ts › click should survive iframe navigation [pass] page/locator-frame.spec.ts › frameLocator.owner should work [pass] @@ -444,7 +444,7 @@ page/locator-frame.spec.ts › locator.frameLocator should not throw on first/la page/locator-frame.spec.ts › locator.frameLocator should throw on ambiguity [pass] page/locator-frame.spec.ts › locator.frameLocator should work for iframe [pass] page/locator-frame.spec.ts › should click in lazy iframe [pass] -page/locator-frame.spec.ts › should non work for non-frame [fail] +page/locator-frame.spec.ts › should non work for non-frame [pass] page/locator-frame.spec.ts › should not wait for frame [pass] page/locator-frame.spec.ts › should not wait for frame 2 [pass] page/locator-frame.spec.ts › should not wait for frame 3 [pass] @@ -457,65 +457,65 @@ page/locator-frame.spec.ts › should work for nested iframe [pass] page/locator-frame.spec.ts › should work with COEP/COOP/CORP isolated iframe [fail] page/locator-frame.spec.ts › wait for hidden should succeed when frame is not in dom [pass] page/locator-frame.spec.ts › waitFor should survive frame reattach [pass] -page/locator-highlight.spec.ts › should highlight locator [fail] +page/locator-highlight.spec.ts › should highlight locator [pass] page/locator-is-visible.spec.ts › isVisible and isHidden should work [fail] page/locator-is-visible.spec.ts › isVisible and isHidden should work with details [fail] page/locator-is-visible.spec.ts › isVisible during navigation should not throw [fail] -page/locator-is-visible.spec.ts › isVisible inside a button [fail] -page/locator-is-visible.spec.ts › isVisible inside a role=button [fail] +page/locator-is-visible.spec.ts › isVisible inside a button [pass] +page/locator-is-visible.spec.ts › isVisible inside a role=button [pass] page/locator-is-visible.spec.ts › isVisible should be true for element outside view [fail] -page/locator-is-visible.spec.ts › isVisible should be true for opacity:0 [fail] +page/locator-is-visible.spec.ts › isVisible should be true for opacity:0 [pass] page/locator-is-visible.spec.ts › isVisible with invalid selector should throw [pass] -page/locator-list.spec.ts › locator.all should work [fail] -page/locator-misc-1.spec.ts › focus should respect strictness [fail] -page/locator-misc-1.spec.ts › should check the box [fail] -page/locator-misc-1.spec.ts › should check the box using setChecked [fail] +page/locator-list.spec.ts › locator.all should work [pass] +page/locator-misc-1.spec.ts › focus should respect strictness [pass] +page/locator-misc-1.spec.ts › should check the box [pass] +page/locator-misc-1.spec.ts › should check the box using setChecked [pass] page/locator-misc-1.spec.ts › should clear input [pass] page/locator-misc-1.spec.ts › should dispatch click event via ElementHandles [pass] page/locator-misc-1.spec.ts › should fill input [pass] -page/locator-misc-1.spec.ts › should fill input when Node is removed [fail] +page/locator-misc-1.spec.ts › should fill input when Node is removed [pass] page/locator-misc-1.spec.ts › should focus and blur a button [pass] page/locator-misc-1.spec.ts › should hover @smoke [pass] page/locator-misc-1.spec.ts › should hover when Node is removed [pass] page/locator-misc-1.spec.ts › should select single option [pass] page/locator-misc-1.spec.ts › should uncheck the box [fail] page/locator-misc-1.spec.ts › should upload the file [fail] -page/locator-misc-2.spec.ts › Locator.locator() and FrameLocator.locator() should accept locator [fail] +page/locator-misc-2.spec.ts › Locator.locator() and FrameLocator.locator() should accept locator [pass] page/locator-misc-2.spec.ts › locator.count should work with deleted Map in main world [pass] -page/locator-misc-2.spec.ts › should combine visible with other selectors [fail] -page/locator-misc-2.spec.ts › should press @smoke [fail] -page/locator-misc-2.spec.ts › should pressSequentially [fail] +page/locator-misc-2.spec.ts › should combine visible with other selectors [pass] +page/locator-misc-2.spec.ts › should press @smoke [pass] +page/locator-misc-2.spec.ts › should pressSequentially [pass] page/locator-misc-2.spec.ts › should return bounding box [fail] page/locator-misc-2.spec.ts › should scroll into view [pass] -page/locator-misc-2.spec.ts › should scroll zero-sized element into view [fail] +page/locator-misc-2.spec.ts › should scroll zero-sized element into view [pass] page/locator-misc-2.spec.ts › should select textarea [fail] page/locator-misc-2.spec.ts › should take screenshot [fail] -page/locator-misc-2.spec.ts › should type [fail] +page/locator-misc-2.spec.ts › should type [pass] page/locator-misc-2.spec.ts › should waitFor [fail] -page/locator-misc-2.spec.ts › should waitFor hidden [fail] -page/locator-query.spec.ts › alias methods coverage [fail] -page/locator-query.spec.ts › should allow some, but not all nested frameLocators [fail] +page/locator-misc-2.spec.ts › should waitFor hidden [pass] +page/locator-query.spec.ts › alias methods coverage [pass] +page/locator-query.spec.ts › should allow some, but not all nested frameLocators [pass] page/locator-query.spec.ts › should enforce same frame for has/leftOf/rightOf/above/below/near [pass] -page/locator-query.spec.ts › should filter by case-insensitive regex in a child [fail] -page/locator-query.spec.ts › should filter by case-insensitive regex in multiple children [fail] -page/locator-query.spec.ts › should filter by regex [fail] -page/locator-query.spec.ts › should filter by regex and regexp flags [fail] -page/locator-query.spec.ts › should filter by regex with a single quote [fail] -page/locator-query.spec.ts › should filter by regex with quotes [fail] -page/locator-query.spec.ts › should filter by regex with special symbols [fail] -page/locator-query.spec.ts › should filter by text [fail] -page/locator-query.spec.ts › should filter by text 2 [fail] -page/locator-query.spec.ts › should filter by text with quotes [fail] -page/locator-query.spec.ts › should respect first() and last() @smoke [fail] -page/locator-query.spec.ts › should respect nth() [fail] -page/locator-query.spec.ts › should support has:locator [fail] -page/locator-query.spec.ts › should support locator.and [fail] -page/locator-query.spec.ts › should support locator.filter [fail] -page/locator-query.spec.ts › should support locator.locator with and/or [fail] -page/locator-query.spec.ts › should support locator.or [fail] -page/locator-query.spec.ts › should throw on capture w/ nth() [fail] -page/locator-query.spec.ts › should throw on due to strictness [fail] -page/locator-query.spec.ts › should throw on due to strictness 2 [fail] +page/locator-query.spec.ts › should filter by case-insensitive regex in a child [pass] +page/locator-query.spec.ts › should filter by case-insensitive regex in multiple children [pass] +page/locator-query.spec.ts › should filter by regex [pass] +page/locator-query.spec.ts › should filter by regex and regexp flags [pass] +page/locator-query.spec.ts › should filter by regex with a single quote [pass] +page/locator-query.spec.ts › should filter by regex with quotes [pass] +page/locator-query.spec.ts › should filter by regex with special symbols [pass] +page/locator-query.spec.ts › should filter by text [pass] +page/locator-query.spec.ts › should filter by text 2 [pass] +page/locator-query.spec.ts › should filter by text with quotes [pass] +page/locator-query.spec.ts › should respect first() and last() @smoke [pass] +page/locator-query.spec.ts › should respect nth() [pass] +page/locator-query.spec.ts › should support has:locator [pass] +page/locator-query.spec.ts › should support locator.and [pass] +page/locator-query.spec.ts › should support locator.filter [pass] +page/locator-query.spec.ts › should support locator.locator with and/or [pass] +page/locator-query.spec.ts › should support locator.or [pass] +page/locator-query.spec.ts › should throw on capture w/ nth() [pass] +page/locator-query.spec.ts › should throw on due to strictness [pass] +page/locator-query.spec.ts › should throw on due to strictness 2 [pass] page/matchers.misc.spec.ts › should outlive frame navigation [pass] page/matchers.misc.spec.ts › should print no-locator-resolved error when locator matcher did not resolve to any element [pass] page/network-post-data.spec.ts › should get post data for file/blob [fail] @@ -586,42 +586,45 @@ page/page-add-style-tag.spec.ts › should throw an error if loading from url fa page/page-add-style-tag.spec.ts › should throw an error if no options are provided [pass] page/page-add-style-tag.spec.ts › should throw when added with URL to the CSP page [pass] page/page-add-style-tag.spec.ts › should throw when added with content to the CSP page [pass] -page/page-add-style-tag.spec.ts › should work with a path [fail] +page/page-add-style-tag.spec.ts › should work with a path [pass] page/page-add-style-tag.spec.ts › should work with a url @smoke [pass] page/page-add-style-tag.spec.ts › should work with content [pass] -page/page-autowaiting-basic.spec.ts › should await cross-process navigation when clicking anchor [fail] -page/page-autowaiting-basic.spec.ts › should await form-get on click [fail] -page/page-autowaiting-basic.spec.ts › should await form-post on click [fail] -page/page-autowaiting-basic.spec.ts › should await navigation when clicking anchor [fail] -page/page-autowaiting-basic.spec.ts › should not stall on JS navigation link [fail] -page/page-autowaiting-basic.spec.ts › should report navigation in the log when clicking anchor [fail] -page/page-autowaiting-basic.spec.ts › should work with dblclick without noWaitAfter when navigation is stalled [fail] +page/page-autowaiting-basic.spec.ts › should await cross-process navigation when clicking anchor [pass] +page/page-autowaiting-basic.spec.ts › should await form-get on click [pass] +page/page-autowaiting-basic.spec.ts › should await form-post on click [pass] +page/page-autowaiting-basic.spec.ts › should await navigation when clicking anchor [pass] +page/page-autowaiting-basic.spec.ts › should not stall on JS navigation link [pass] +page/page-autowaiting-basic.spec.ts › should report navigation in the log when clicking anchor [pass] +page/page-autowaiting-basic.spec.ts › should work with dblclick without noWaitAfter when navigation is stalled [pass] page/page-autowaiting-basic.spec.ts › should work with goto following click [fail] -page/page-autowaiting-basic.spec.ts › should work with noWaitAfter: true [fail] +page/page-autowaiting-basic.spec.ts › should work with noWaitAfter: true [pass] page/page-autowaiting-basic.spec.ts › should work with waitForLoadState(load) [fail] page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank [pass] page/page-autowaiting-no-hang.spec.ts › assigning location to about:blank after non-about:blank [pass] page/page-autowaiting-no-hang.spec.ts › calling window.open and window.close [fail] page/page-autowaiting-no-hang.spec.ts › calling window.stop async [pass] page/page-autowaiting-no-hang.spec.ts › calling window.stop sync [pass] -page/page-autowaiting-no-hang.spec.ts › clicking on links which do not commit navigation [fail] +page/page-autowaiting-no-hang.spec.ts › clicking in the middle of navigation that aborts [pass] +page/page-autowaiting-no-hang.spec.ts › clicking in the middle of navigation that commits [fail] +page/page-autowaiting-no-hang.spec.ts › clicking on links which do not commit navigation [pass] +page/page-autowaiting-no-hang.spec.ts › goBack in the middle of navigation that commits [pass] page/page-autowaiting-no-hang.spec.ts › opening a popup [pass] page/page-basic.spec.ts › async stacks should work [pass] page/page-basic.spec.ts › frame.press should work [fail] -page/page-basic.spec.ts › has navigator.webdriver set to true [fail] +page/page-basic.spec.ts › has navigator.webdriver set to true [pass] page/page-basic.spec.ts › page.close should work with page.close [pass] page/page-basic.spec.ts › page.close should work with window.close [timeout] page/page-basic.spec.ts › page.frame should respect name [fail] -page/page-basic.spec.ts › page.frame should respect url [fail] +page/page-basic.spec.ts › page.frame should respect url [pass] page/page-basic.spec.ts › page.press should work [pass] -page/page-basic.spec.ts › page.press should work for Enter [fail] +page/page-basic.spec.ts › page.press should work for Enter [pass] page/page-basic.spec.ts › page.title should return the page title [pass] page/page-basic.spec.ts › page.url should include hashes [pass] page/page-basic.spec.ts › page.url should work [pass] page/page-basic.spec.ts › should be callable twice [pass] page/page-basic.spec.ts › should fail with error upon disconnect [pass] page/page-basic.spec.ts › should fire domcontentloaded when expected [pass] -page/page-basic.spec.ts › should fire load when expected [fail] +page/page-basic.spec.ts › should fire load when expected [pass] page/page-basic.spec.ts › should have sane user agent [fail] page/page-basic.spec.ts › should iterate over page properties [pass] page/page-basic.spec.ts › should pass page to close event [pass] @@ -632,22 +635,22 @@ page/page-basic.spec.ts › should reject all promises when page is closed [pass page/page-basic.spec.ts › should return null if parent page has been closed [timeout] page/page-basic.spec.ts › should set the page close state [pass] page/page-basic.spec.ts › should terminate network waiters [pass] -page/page-check.spec.ts › should check radio [fail] +page/page-check.spec.ts › should check radio [pass] page/page-check.spec.ts › should check radio by aria role [fail] -page/page-check.spec.ts › should check the box @smoke [fail] -page/page-check.spec.ts › should check the box by aria role [fail] -page/page-check.spec.ts › should check the box inside a button [fail] -page/page-check.spec.ts › should check the box using setChecked [fail] -page/page-check.spec.ts › should check the label with position [fail] -page/page-check.spec.ts › should not check the checked box [fail] -page/page-check.spec.ts › should not uncheck the unchecked box [fail] -page/page-check.spec.ts › should throw when not a checkbox [fail] -page/page-check.spec.ts › should throw when not a checkbox 2 [fail] -page/page-check.spec.ts › should uncheck radio by aria role [fail] -page/page-check.spec.ts › should uncheck the box [fail] -page/page-check.spec.ts › should uncheck the box by aria role [fail] -page/page-check.spec.ts › trial run should not check [fail] -page/page-check.spec.ts › trial run should not uncheck [fail] +page/page-check.spec.ts › should check the box @smoke [pass] +page/page-check.spec.ts › should check the box by aria role [pass] +page/page-check.spec.ts › should check the box inside a button [pass] +page/page-check.spec.ts › should check the box using setChecked [pass] +page/page-check.spec.ts › should check the label with position [pass] +page/page-check.spec.ts › should not check the checked box [pass] +page/page-check.spec.ts › should not uncheck the unchecked box [pass] +page/page-check.spec.ts › should throw when not a checkbox [pass] +page/page-check.spec.ts › should throw when not a checkbox 2 [pass] +page/page-check.spec.ts › should uncheck radio by aria role [pass] +page/page-check.spec.ts › should uncheck the box [pass] +page/page-check.spec.ts › should uncheck the box by aria role [pass] +page/page-check.spec.ts › trial run should not check [pass] +page/page-check.spec.ts › trial run should not uncheck [pass] page/page-click-during-navigation.spec.ts › should not fail with internal error upon navigation [pass] page/page-click-react.spec.ts › should not retarget the handle when element is recycled [unknown] page/page-click-react.spec.ts › should not retarget when element changes on hover [pass] @@ -655,19 +658,19 @@ page/page-click-react.spec.ts › should not retarget when element is recycled o page/page-click-react.spec.ts › should report that selector does not match anymore [unknown] page/page-click-react.spec.ts › should retarget when element is recycled before enabled check [unknown] page/page-click-react.spec.ts › should retarget when element is recycled during hit testing [unknown] -page/page-click-react.spec.ts › should timeout when click opens alert [fail] -page/page-click-scroll.spec.ts › should not crash when force-clicking hidden input [fail] -page/page-click-scroll.spec.ts › should not hit scroll bar [fail] +page/page-click-react.spec.ts › should timeout when click opens alert [pass] +page/page-click-scroll.spec.ts › should not crash when force-clicking hidden input [pass] +page/page-click-scroll.spec.ts › should not hit scroll bar [pass] page/page-click-scroll.spec.ts › should scroll into view display:contents [fail] page/page-click-scroll.spec.ts › should scroll into view display:contents with a child [fail] page/page-click-scroll.spec.ts › should scroll into view display:contents with position [fail] -page/page-click-scroll.spec.ts › should scroll into view element in iframe [fail] -page/page-click-scroll.spec.ts › should scroll into view span element [fail] +page/page-click-scroll.spec.ts › should scroll into view element in iframe [pass] +page/page-click-scroll.spec.ts › should scroll into view span element [pass] page/page-click-timeout-1.spec.ts › should avoid side effects after timeout [pass] -page/page-click-timeout-1.spec.ts › should timeout waiting for button to be enabled [fail] +page/page-click-timeout-1.spec.ts › should timeout waiting for button to be enabled [pass] page/page-click-timeout-2.spec.ts › should timeout waiting for display:none to be gone [pass] page/page-click-timeout-2.spec.ts › should timeout waiting for visibility:hidden to be gone [pass] -page/page-click-timeout-3.spec.ts › should fail when element jumps during hit testing [fail] +page/page-click-timeout-3.spec.ts › should fail when element jumps during hit testing [pass] page/page-click-timeout-3.spec.ts › should report wrong hit target subtree [pass] page/page-click-timeout-3.spec.ts › should still click when force but hit target is obscured [pass] page/page-click-timeout-3.spec.ts › should timeout waiting for hit target [pass] @@ -678,44 +681,44 @@ page/page-click.spec.ts › should click a button in scrolling container with of page/page-click.spec.ts › should click a button that is overlaid by a permission popup [fail] page/page-click.spec.ts › should click a partially obscured button [pass] page/page-click.spec.ts › should click a rotated button [pass] -page/page-click.spec.ts › should click a very large button with offset [fail] -page/page-click.spec.ts › should click an offscreen element when scroll-behavior is smooth [fail] +page/page-click.spec.ts › should click a very large button with offset [pass] +page/page-click.spec.ts › should click an offscreen element when scroll-behavior is smooth [pass] page/page-click.spec.ts › should click button inside frameset [pass] -page/page-click.spec.ts › should click disabled div [fail] -page/page-click.spec.ts › should click if opened select covers the button [fail] +page/page-click.spec.ts › should click disabled div [pass] +page/page-click.spec.ts › should click if opened select covers the button [pass] page/page-click.spec.ts › should click in a nested transformed iframe [fail] page/page-click.spec.ts › should click in a transformed iframe [fail] page/page-click.spec.ts › should click in a transformed iframe with force [fail] -page/page-click.spec.ts › should click in an iframe with border [fail] -page/page-click.spec.ts › should click in an iframe with border 2 [fail] -page/page-click.spec.ts › should click links which cause navigation [fail] +page/page-click.spec.ts › should click in an iframe with border [pass] +page/page-click.spec.ts › should click in an iframe with border 2 [pass] +page/page-click.spec.ts › should click links which cause navigation [pass] page/page-click.spec.ts › should click offscreen buttons [pass] page/page-click.spec.ts › should click on a span with an inline element inside [fail] page/page-click.spec.ts › should click on checkbox input and toggle [pass] page/page-click.spec.ts › should click on checkbox label and toggle [pass] -page/page-click.spec.ts › should click svg [fail] -page/page-click.spec.ts › should click the 1x1 div [fail] +page/page-click.spec.ts › should click svg [pass] +page/page-click.spec.ts › should click the 1x1 div [pass] page/page-click.spec.ts › should click the button @smoke [pass] page/page-click.spec.ts › should click the button after a cross origin navigation [pass] page/page-click.spec.ts › should click the button after navigation [pass] -page/page-click.spec.ts › should click the button behind sticky header [fail] +page/page-click.spec.ts › should click the button behind sticky header [pass] page/page-click.spec.ts › should click the button if window.Node is removed [pass] -page/page-click.spec.ts › should click the button inside an iframe [fail] +page/page-click.spec.ts › should click the button inside an iframe [pass] page/page-click.spec.ts › should click the button when window.innerWidth is corrupted [pass] page/page-click.spec.ts › should click the button with em border with offset [pass] page/page-click.spec.ts › should click the button with fixed position inside an iframe [fail] page/page-click.spec.ts › should click the button with px border with offset [pass] -page/page-click.spec.ts › should click when one of inline box children is outside of viewport [fail] +page/page-click.spec.ts › should click when one of inline box children is outside of viewport [pass] page/page-click.spec.ts › should click wrapped links [pass] -page/page-click.spec.ts › should click zero-sized input by label [fail] -page/page-click.spec.ts › should climb dom for inner label with pointer-events:none [fail] -page/page-click.spec.ts › should climb up to [role=button] [fail] -page/page-click.spec.ts › should climb up to a [role=link] [fail] -page/page-click.spec.ts › should climb up to a anchor [fail] -page/page-click.spec.ts › should dispatch microtasks in order [fail] +page/page-click.spec.ts › should click zero-sized input by label [pass] +page/page-click.spec.ts › should climb dom for inner label with pointer-events:none [pass] +page/page-click.spec.ts › should climb up to [role=button] [pass] +page/page-click.spec.ts › should climb up to a [role=link] [pass] +page/page-click.spec.ts › should climb up to a anchor [pass] +page/page-click.spec.ts › should dispatch microtasks in order [pass] page/page-click.spec.ts › should double click the button [fail] page/page-click.spec.ts › should fail when element detaches after animation [pass] -page/page-click.spec.ts › should fail when element is animating from outside the viewport with force [fail] +page/page-click.spec.ts › should fail when element is animating from outside the viewport with force [pass] page/page-click.spec.ts › should fail when obscured and not waiting for hit target [pass] page/page-click.spec.ts › should fire contextmenu event on right click [pass] page/page-click.spec.ts › should fire contextmenu event on right click in correct order [fail] @@ -732,13 +735,13 @@ page/page-click.spec.ts › should scroll and click the button [pass] page/page-click.spec.ts › should scroll and click the button with smooth scroll behavior [pass] page/page-click.spec.ts › should select the text by triple clicking [fail] page/page-click.spec.ts › should update modifiers correctly [pass] -page/page-click.spec.ts › should wait for BUTTON to be clickable when it has pointer-events:none [fail] -page/page-click.spec.ts › should wait for LABEL to be clickable when it has pointer-events:none [fail] +page/page-click.spec.ts › should wait for BUTTON to be clickable when it has pointer-events:none [pass] +page/page-click.spec.ts › should wait for LABEL to be clickable when it has pointer-events:none [pass] page/page-click.spec.ts › should wait for becoming hit target [pass] page/page-click.spec.ts › should wait for becoming hit target with trial run [pass] -page/page-click.spec.ts › should wait for button to be enabled [fail] -page/page-click.spec.ts › should wait for input to be enabled [fail] -page/page-click.spec.ts › should wait for select to be enabled [fail] +page/page-click.spec.ts › should wait for button to be enabled [pass] +page/page-click.spec.ts › should wait for input to be enabled [pass] +page/page-click.spec.ts › should wait for select to be enabled [pass] page/page-click.spec.ts › should wait for stable position [pass] page/page-click.spec.ts › should waitFor display:none to be gone [pass] page/page-click.spec.ts › should waitFor visibility:hidden to be gone [pass] @@ -747,38 +750,38 @@ page/page-click.spec.ts › should waitFor visible when parent is hidden [pass] page/page-click.spec.ts › trial run should not click [pass] page/page-click.spec.ts › trial run should not double click [pass] page/page-click.spec.ts › trial run should work with short timeout [pass] -page/page-close.spec.ts › should close page with active dialog [fail] -page/page-close.spec.ts › should not accept dialog after close [fail] +page/page-close.spec.ts › should close page with active dialog [pass] +page/page-close.spec.ts › should not accept dialog after close [pass] page/page-dialog.spec.ts › should accept the confirm prompt [pass] page/page-dialog.spec.ts › should allow accepting prompts @smoke [pass] -page/page-dialog.spec.ts › should auto-dismiss the alert without listeners [fail] +page/page-dialog.spec.ts › should auto-dismiss the alert without listeners [pass] page/page-dialog.spec.ts › should auto-dismiss the prompt without listeners [pass] page/page-dialog.spec.ts › should be able to close context with open alert [pass] page/page-dialog.spec.ts › should dismiss the confirm prompt [pass] page/page-dialog.spec.ts › should dismiss the prompt [pass] page/page-dialog.spec.ts › should fire [pass] -page/page-dialog.spec.ts › should handle multiple alerts [fail] -page/page-dialog.spec.ts › should handle multiple confirms [fail] -page/page-dispatchevent.spec.ts › should be atomic [fail] +page/page-dialog.spec.ts › should handle multiple alerts [pass] +page/page-dialog.spec.ts › should handle multiple confirms [pass] +page/page-dispatchevent.spec.ts › should be atomic [pass] page/page-dispatchevent.spec.ts › should dispatch absolute device orientation event [pass] page/page-dispatchevent.spec.ts › should dispatch click after a cross origin navigation [pass] page/page-dispatchevent.spec.ts › should dispatch click after navigation [pass] page/page-dispatchevent.spec.ts › should dispatch click event @smoke [pass] page/page-dispatchevent.spec.ts › should dispatch click event properties [pass] page/page-dispatchevent.spec.ts › should dispatch click event via ElementHandles [pass] -page/page-dispatchevent.spec.ts › should dispatch click on a span with an inline element inside [fail] -page/page-dispatchevent.spec.ts › should dispatch click svg [fail] +page/page-dispatchevent.spec.ts › should dispatch click on a span with an inline element inside [pass] +page/page-dispatchevent.spec.ts › should dispatch click svg [pass] page/page-dispatchevent.spec.ts › should dispatch click when node is added in shadow dom [pass] page/page-dispatchevent.spec.ts › should dispatch device motion event [pass] page/page-dispatchevent.spec.ts › should dispatch device orientation event [pass] page/page-dispatchevent.spec.ts › should dispatch drag drop events [pass] page/page-dispatchevent.spec.ts › should dispatch drag drop events via ElementHandles [pass] page/page-dispatchevent.spec.ts › should dispatch wheel event [pass] -page/page-dispatchevent.spec.ts › should not fail when element is blocked on hover [fail] +page/page-dispatchevent.spec.ts › should not fail when element is blocked on hover [pass] page/page-dispatchevent.spec.ts › should throw if argument is from different frame [pass] page/page-drag.spec.ts › Drag and drop › iframe › should drag into an iframe [unknown] page/page-drag.spec.ts › Drag and drop › iframe › should drag out of an iframe [unknown] -page/page-drag.spec.ts › Drag and drop › should allow specifying the position [fail] +page/page-drag.spec.ts › Drag and drop › should allow specifying the position [pass] page/page-drag.spec.ts › Drag and drop › should be able to drag the mouse in a frame [pass] page/page-drag.spec.ts › Drag and drop › should cancel on escape [fail] page/page-drag.spec.ts › Drag and drop › should not send dragover on the first mousemove [unknown] @@ -794,7 +797,7 @@ page/page-drag.spec.ts › Drag and drop › should work with the helper method page/page-drag.spec.ts › should handle custom dataTransfer [fail] page/page-drag.spec.ts › should report event.buttons [pass] page/page-drag.spec.ts › should work if not doing a drag [pass] -page/page-drag.spec.ts › what happens when dragging element is destroyed [fail] +page/page-drag.spec.ts › what happens when dragging element is destroyed [pass] page/page-emulate-media.spec.ts › should change the actual colors in css [fail] page/page-emulate-media.spec.ts › should default to light [fail] page/page-emulate-media.spec.ts › should emulate colorScheme should work @smoke [fail] @@ -816,14 +819,14 @@ page/page-evaluate-handle.spec.ts › should accept same nested object multiple page/page-evaluate-handle.spec.ts › should pass configurable args [pass] page/page-evaluate-handle.spec.ts › should work [pass] page/page-evaluate-handle.spec.ts › should work with primitives [pass] -page/page-evaluate-no-stall.spec.ts › should throw when no main execution context [fail] +page/page-evaluate-no-stall.spec.ts › should throw when no main execution context [pass] page/page-evaluate-no-stall.spec.ts › should throw while pending navigation [pass] page/page-evaluate-no-stall.spec.ts › should work [pass] page/page-evaluate.spec.ts › should accept "undefined" as one of multiple parameters [pass] page/page-evaluate.spec.ts › should accept a string [pass] page/page-evaluate.spec.ts › should accept a string with comments [pass] page/page-evaluate.spec.ts › should accept a string with semi colons [pass] -page/page-evaluate.spec.ts › should accept element handle as an argument [fail] +page/page-evaluate.spec.ts › should accept element handle as an argument [pass] page/page-evaluate.spec.ts › should alias Window, Document and Node [pass] page/page-evaluate.spec.ts › should await promise [pass] page/page-evaluate.spec.ts › should await promise from popup [pass] @@ -875,14 +878,14 @@ page/page-evaluate.spec.ts › should support thrown numbers as error messages [ page/page-evaluate.spec.ts › should support thrown strings as error messages [pass] page/page-evaluate.spec.ts › should throw a nice error after a navigation [pass] page/page-evaluate.spec.ts › should throw error with detailed information on exception inside promise [pass] -page/page-evaluate.spec.ts › should throw if underlying element was disposed [fail] +page/page-evaluate.spec.ts › should throw if underlying element was disposed [pass] page/page-evaluate.spec.ts › should throw when evaluation triggers reload [pass] page/page-evaluate.spec.ts › should throw when frame is detached [pass] page/page-evaluate.spec.ts › should throw when passed more than one parameter [pass] page/page-evaluate.spec.ts › should transfer -0 [pass] page/page-evaluate.spec.ts › should transfer -Infinity [pass] -page/page-evaluate.spec.ts › should transfer 100Mb of data from page to node.js [fail] -page/page-evaluate.spec.ts › should transfer Infinity [fail] +page/page-evaluate.spec.ts › should transfer 100Mb of data from page to node.js [pass] +page/page-evaluate.spec.ts › should transfer Infinity [pass] page/page-evaluate.spec.ts › should transfer NaN [pass] page/page-evaluate.spec.ts › should transfer arrays [pass] page/page-evaluate.spec.ts › should transfer arrays as arrays, not objects [pass] @@ -892,7 +895,7 @@ page/page-evaluate.spec.ts › should work @smoke [pass] page/page-evaluate.spec.ts › should work even when JSON is set to null [pass] page/page-evaluate.spec.ts › should work for circular object [pass] page/page-evaluate.spec.ts › should work from-inside an exposed function [pass] -page/page-evaluate.spec.ts › should work right after a cross-origin navigation [fail] +page/page-evaluate.spec.ts › should work right after a cross-origin navigation [pass] page/page-evaluate.spec.ts › should work right after framenavigated [fail] page/page-evaluate.spec.ts › should work with Array.from/map [pass] page/page-evaluate.spec.ts › should work with CSP [fail] @@ -945,15 +948,16 @@ page/page-event-popup.spec.ts › should emit for immediately closed popups 2 [f page/page-event-popup.spec.ts › should not treat navigations as new popups [fail] page/page-event-popup.spec.ts › should report popup opened from iframes [fail] page/page-event-popup.spec.ts › should work @smoke [timeout] -page/page-event-popup.spec.ts › should work with clicking target=_blank [fail] -page/page-event-popup.spec.ts › should work with clicking target=_blank and rel=noopener [fail] +page/page-event-popup.spec.ts › should work with clicking target=_blank [pass] +page/page-event-popup.spec.ts › should work with clicking target=_blank and rel=noopener [pass] page/page-event-popup.spec.ts › should work with empty url [pass] -page/page-event-popup.spec.ts › should work with fake-clicking target=_blank and rel=noopener [fail] +page/page-event-popup.spec.ts › should work with fake-clicking target=_blank and rel=noopener [pass] page/page-event-popup.spec.ts › should work with noopener and about:blank [pass] page/page-event-popup.spec.ts › should work with noopener and no url [fail] page/page-event-popup.spec.ts › should work with noopener and url [pass] page/page-event-popup.spec.ts › should work with window features [pass] page/page-event-request.spec.ts › main resource xhr should have type xhr [fail] +page/page-event-request.spec.ts › should finish 204 request [pass] page/page-event-request.spec.ts › should fire for fetches [pass] page/page-event-request.spec.ts › should fire for iframes [pass] page/page-event-request.spec.ts › should fire for navigation requests [pass] @@ -964,7 +968,7 @@ page/page-event-request.spec.ts › should report requests and responses handled page/page-event-request.spec.ts › should report requests and responses handled by service worker with routing [fail] page/page-event-request.spec.ts › should return response body when Cross-Origin-Opener-Policy is set [fail] page/page-expose-function.spec.ts › exposeBinding should work @smoke [pass] -page/page-expose-function.spec.ts › exposeBinding(handle) should work with element handles [fail] +page/page-expose-function.spec.ts › exposeBinding(handle) should work with element handles [pass] page/page-expose-function.spec.ts › exposeBindingHandle should not throw during navigation [pass] page/page-expose-function.spec.ts › exposeBindingHandle should throw for multiple arguments [pass] page/page-expose-function.spec.ts › exposeBindingHandle should work [pass] @@ -986,58 +990,60 @@ page/page-expose-function.spec.ts › should work with busted Array.prototype.ma page/page-expose-function.spec.ts › should work with complex objects [pass] page/page-expose-function.spec.ts › should work with handles and complex objects [pass] page/page-expose-function.spec.ts › should work with overridden console object [pass] -page/page-expose-function.spec.ts › should work with setContent [fail] -page/page-fill.spec.ts › fill back to back [fail] -page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - color [fail] -page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - date [fail] -page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - datetime-local [fail] +page/page-expose-function.spec.ts › should work with setContent [pass] +page/page-fill.spec.ts › fill back to back [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - color [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - date [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - datetime-local [pass] page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - month [unknown] -page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - range [fail] -page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - time [fail] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - range [pass] +page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - time [pass] page/page-fill.spec.ts › input event.composed should be true and cross shadow dom boundary - week [unknown] page/page-fill.spec.ts › should be able to clear using fill() [pass] -page/page-fill.spec.ts › should be able to fill exponent into the input[type=number] [fail] -page/page-fill.spec.ts › should be able to fill input[type=number] with empty string [fail] -page/page-fill.spec.ts › should be able to fill the body [fail] -page/page-fill.spec.ts › should be able to fill the input[type=number] [fail] -page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [fail] -page/page-fill.spec.ts › should fill color input [fail] +page/page-fill.spec.ts › should be able to fill exponent into the input[type=number] [pass] +page/page-fill.spec.ts › should be able to fill input[type=number] with empty string [pass] +page/page-fill.spec.ts › should be able to fill the body [pass] +page/page-fill.spec.ts › should be able to fill the input[type=number] [pass] +page/page-fill.spec.ts › should be able to fill when focus is in the wrong frame [pass] +page/page-fill.spec.ts › should fill color input [pass] page/page-fill.spec.ts › should fill contenteditable [pass] page/page-fill.spec.ts › should fill contenteditable with new lines [fail] -page/page-fill.spec.ts › should fill date input after clicking [fail] -page/page-fill.spec.ts › should fill datetime-local input [fail] +page/page-fill.spec.ts › should fill date input after clicking [pass] +page/page-fill.spec.ts › should fill datetime-local input [pass] page/page-fill.spec.ts › should fill different input types [pass] page/page-fill.spec.ts › should fill elements with existing value and selection [pass] -page/page-fill.spec.ts › should fill fixed position input [fail] +page/page-fill.spec.ts › should fill fixed position input [pass] page/page-fill.spec.ts › should fill input [pass] -page/page-fill.spec.ts › should fill month input [fail] -page/page-fill.spec.ts › should fill range input [fail] +page/page-fill.spec.ts › should fill month input [pass] +page/page-fill.spec.ts › should fill range input [pass] page/page-fill.spec.ts › should fill textarea @smoke [pass] -page/page-fill.spec.ts › should fill time input [fail] -page/page-fill.spec.ts › should fill week input [fail] -page/page-fill.spec.ts › should not be able to fill text into the input[type=number] [fail] -page/page-fill.spec.ts › should not throw when fill causes navigation [fail] +page/page-fill.spec.ts › should fill time input [pass] +page/page-fill.spec.ts › should fill week input [pass] +page/page-fill.spec.ts › should not be able to fill text into the input[type=number] [pass] +page/page-fill.spec.ts › should not throw when fill causes navigation [pass] page/page-fill.spec.ts › should retry on disabled element [pass] page/page-fill.spec.ts › should retry on invisible element [pass] page/page-fill.spec.ts › should retry on readonly element [pass] page/page-fill.spec.ts › should throw if passed a non-string value [pass] page/page-fill.spec.ts › should throw nice error without injected script stack when element is not an [fail] -page/page-fill.spec.ts › should throw on incorrect color value [fail] -page/page-fill.spec.ts › should throw on incorrect date [fail] +page/page-fill.spec.ts › should throw on incorrect color value [pass] +page/page-fill.spec.ts › should throw on incorrect date [pass] page/page-fill.spec.ts › should throw on incorrect datetime-local [unknown] page/page-fill.spec.ts › should throw on incorrect month [unknown] -page/page-fill.spec.ts › should throw on incorrect range value [fail] -page/page-fill.spec.ts › should throw on incorrect time [fail] +page/page-fill.spec.ts › should throw on incorrect range value [pass] +page/page-fill.spec.ts › should throw on incorrect time [pass] page/page-fill.spec.ts › should throw on incorrect week [unknown] page/page-fill.spec.ts › should throw on unsupported inputs [pass] page/page-focus.spec.ts › clicking checkbox should activate it [unknown] -page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [fail] -page/page-focus.spec.ts › should emit blur event [fail] -page/page-focus.spec.ts › should emit focus event [fail] -page/page-focus.spec.ts › should traverse focus [fail] -page/page-focus.spec.ts › should traverse focus in all directions [fail] +page/page-focus.spec.ts › keeps focus on element when attempting to focus a non-focusable element [pass] +page/page-focus.spec.ts › should emit blur event [pass] +page/page-focus.spec.ts › should emit focus event [pass] +page/page-focus.spec.ts › should traverse focus [pass] +page/page-focus.spec.ts › should traverse focus in all directions [pass] page/page-focus.spec.ts › should traverse only form elements [unknown] -page/page-focus.spec.ts › should work @smoke [fail] +page/page-focus.spec.ts › should work @smoke [pass] +page/page-focus.spec.ts › tab should cycle between document elements and browser [unknown] +page/page-focus.spec.ts › tab should cycle between single input and browser [unknown] page/page-force-gc.spec.ts › should work [fail] page/page-goto.spec.ts › js redirect overrides url bar navigation [pass] page/page-goto.spec.ts › should be able to navigate to a page controlled by service worker [pass] @@ -1071,7 +1077,7 @@ page/page-goto.spec.ts › should not throw if networkidle0 is passed as an opti page/page-goto.spec.ts › should not throw unhandled rejections on invalid url [pass] page/page-goto.spec.ts › should override referrer-policy [fail] page/page-goto.spec.ts › should prioritize default navigation timeout over default timeout [pass] -page/page-goto.spec.ts › should properly wait for load [fail] +page/page-goto.spec.ts › should properly wait for load [pass] page/page-goto.spec.ts › should reject referer option when setExtraHTTPHeaders provides referer [pass] page/page-goto.spec.ts › should report raw buffer for main resource [fail] page/page-goto.spec.ts › should return from goto if new navigation is started [pass] @@ -1082,7 +1088,7 @@ page/page-goto.spec.ts › should return when navigation is committed if commit page/page-goto.spec.ts › should send referer [fail] page/page-goto.spec.ts › should send referer of cross-origin URL [fail] page/page-goto.spec.ts › should succeed on url bar navigation when there is pending navigation [pass] -page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [fail] +page/page-goto.spec.ts › should throw if networkidle2 is passed as an option [pass] page/page-goto.spec.ts › should use http for no protocol [pass] page/page-goto.spec.ts › should wait for load when iframe attaches and detaches [pass] page/page-goto.spec.ts › should work @smoke [pass] @@ -1098,7 +1104,7 @@ page/page-goto.spec.ts › should work with anchor navigation [timeout] page/page-goto.spec.ts › should work with cross-process that fails before committing [pass] page/page-goto.spec.ts › should work with file URL [pass] page/page-goto.spec.ts › should work with file URL with subframes [pass] -page/page-goto.spec.ts › should work with lazy loading iframes [fail] +page/page-goto.spec.ts › should work with lazy loading iframes [pass] page/page-goto.spec.ts › should work with redirects [pass] page/page-goto.spec.ts › should work with self requesting page [pass] page/page-goto.spec.ts › should work with subframes return 204 [pass] @@ -1108,8 +1114,8 @@ page/page-history.spec.ts › page.goBack during renderer-initiated navigation [ page/page-history.spec.ts › page.goBack should work @smoke [pass] page/page-history.spec.ts › page.goBack should work for file urls [fail] page/page-history.spec.ts › page.goBack should work with HistoryAPI [fail] -page/page-history.spec.ts › page.goForward during renderer-initiated navigation [fail] -page/page-history.spec.ts › page.reload during renderer-initiated navigation [fail] +page/page-history.spec.ts › page.goForward during renderer-initiated navigation [pass] +page/page-history.spec.ts › page.reload during renderer-initiated navigation [pass] page/page-history.spec.ts › page.reload should not resolve with same-document navigation [fail] page/page-history.spec.ts › page.reload should work [pass] page/page-history.spec.ts › page.reload should work on a page with a hash [pass] @@ -1120,15 +1126,15 @@ page/page-history.spec.ts › page.reload should work with same origin redirect page/page-history.spec.ts › regression test for issue 20791 [pass] page/page-history.spec.ts › should reload proper page [timeout] page/page-keyboard.spec.ts › insertText should only emit input event [fail] -page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [fail] +page/page-keyboard.spec.ts › pressing Meta should not result in any text insertion on any platform [pass] page/page-keyboard.spec.ts › should be able to prevent selectAll [pass] -page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [fail] -page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [fail] +page/page-keyboard.spec.ts › should dispatch a click event on a button when Enter gets pressed [pass] +page/page-keyboard.spec.ts › should dispatch a click event on a button when Space gets pressed [pass] page/page-keyboard.spec.ts › should dispatch insertText after context menu was opened [pass] page/page-keyboard.spec.ts › should expose keyIdentifier in webkit [unknown] page/page-keyboard.spec.ts › should handle selectAll [pass] page/page-keyboard.spec.ts › should have correct Keydown/Keyup order when pressing Escape key [pass] -page/page-keyboard.spec.ts › should move around the selection in a contenteditable [fail] +page/page-keyboard.spec.ts › should move around the selection in a contenteditable [pass] page/page-keyboard.spec.ts › should move to the start of the document [unknown] page/page-keyboard.spec.ts › should move with the arrow keys [pass] page/page-keyboard.spec.ts › should not type canceled events [pass] @@ -1149,21 +1155,21 @@ page/page-keyboard.spec.ts › should specify repeat property [pass] page/page-keyboard.spec.ts › should support MacOS shortcuts [unknown] page/page-keyboard.spec.ts › should support multiple plus-separated modifiers [pass] page/page-keyboard.spec.ts › should support plus-separated modifiers [pass] -page/page-keyboard.spec.ts › should support simple copy-pasting [fail] -page/page-keyboard.spec.ts › should support simple cut-pasting [fail] -page/page-keyboard.spec.ts › should support undo-redo [fail] +page/page-keyboard.spec.ts › should support simple copy-pasting [pass] +page/page-keyboard.spec.ts › should support simple cut-pasting [pass] +page/page-keyboard.spec.ts › should support undo-redo [pass] page/page-keyboard.spec.ts › should throw on unknown keys [pass] page/page-keyboard.spec.ts › should type after context menu was opened [pass] page/page-keyboard.spec.ts › should type all kinds of characters [pass] page/page-keyboard.spec.ts › should type emoji [pass] page/page-keyboard.spec.ts › should type emoji into an iframe [pass] page/page-keyboard.spec.ts › should type into a textarea @smoke [pass] -page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [fail] -page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [fail] -page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [fail] +page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom [pass] +page/page-keyboard.spec.ts › should type repeatedly in contenteditable in shadow dom with nested elements [pass] +page/page-keyboard.spec.ts › should type repeatedly in input in shadow dom [pass] page/page-keyboard.spec.ts › should work after a cross origin navigation [pass] page/page-keyboard.spec.ts › should work with keyboard events with empty.html [pass] -page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [fail] +page/page-keyboard.spec.ts › type to non-focusable element should maintain old focus [pass] page/page-leaks.spec.ts › click should not leak [fail] page/page-leaks.spec.ts › expect should not leak [fail] page/page-leaks.spec.ts › fill should not leak [fail] @@ -1186,18 +1192,18 @@ page/page-mouse.spec.ts › should trigger hover state on disabled button [pass] page/page-mouse.spec.ts › should trigger hover state with removed window.Node [pass] page/page-mouse.spec.ts › should tween mouse movement [pass] page/page-navigation.spec.ts › should work with _blank target [pass] -page/page-navigation.spec.ts › should work with _blank target in form [fail] +page/page-navigation.spec.ts › should work with _blank target in form [pass] page/page-navigation.spec.ts › should work with cross-process _blank target [pass] page/page-network-idle.spec.ts › should navigate to empty page with networkidle [pass] page/page-network-idle.spec.ts › should wait for networkidle from the child frame [pass] page/page-network-idle.spec.ts › should wait for networkidle from the popup [fail] -page/page-network-idle.spec.ts › should wait for networkidle in setContent [fail] -page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [fail] -page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [fail] +page/page-network-idle.spec.ts › should wait for networkidle in setContent [pass] +page/page-network-idle.spec.ts › should wait for networkidle in setContent from the child frame [pass] +page/page-network-idle.spec.ts › should wait for networkidle in setContent with request from previous navigation [pass] page/page-network-idle.spec.ts › should wait for networkidle in waitForNavigation [pass] page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation [pass] page/page-network-idle.spec.ts › should wait for networkidle to succeed navigation with request from previous navigation [fail] -page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [fail] +page/page-network-idle.spec.ts › should wait for networkidle when iframe attaches and detaches [pass] page/page-network-idle.spec.ts › should wait for networkidle when navigating iframe [pass] page/page-network-idle.spec.ts › should work after repeated navigations in the same page [pass] page/page-network-request.spec.ts › page.reload return 304 status code [pass] @@ -1206,7 +1212,7 @@ page/page-network-request.spec.ts › should get the same headers as the server page/page-network-request.spec.ts › should get |undefined| with postData() when there is no post data [pass] page/page-network-request.spec.ts › should get |undefined| with postDataJSON() when there is no post data [pass] page/page-network-request.spec.ts › should handle mixed-content blocked requests [unknown] -page/page-network-request.spec.ts › should not allow to access frame on popup main request [fail] +page/page-network-request.spec.ts › should not allow to access frame on popup main request [pass] page/page-network-request.spec.ts › should not get preflight CORS requests when intercepting [fail] page/page-network-request.spec.ts › should not return allHeaders() until they are available [fail] page/page-network-request.spec.ts › should not work for a redirect and interception [pass] @@ -1243,9 +1249,9 @@ page/page-network-response.spec.ts › should return body for prefetch script [f page/page-network-response.spec.ts › should return body with compression [fail] page/page-network-response.spec.ts › should return headers after route.fulfill [pass] page/page-network-response.spec.ts › should return json [fail] -page/page-network-response.spec.ts › should return multiple header value [fail] +page/page-network-response.spec.ts › should return multiple header value [pass] page/page-network-response.spec.ts › should return set-cookie header after route.fulfill [pass] -page/page-network-response.spec.ts › should return status text [fail] +page/page-network-response.spec.ts › should return status text [pass] page/page-network-response.spec.ts › should return text [fail] page/page-network-response.spec.ts › should return uncompressed text [fail] page/page-network-response.spec.ts › should throw when requesting body of redirected response [pass] @@ -1256,7 +1262,7 @@ page/page-network-sizes.spec.ts › should have correct responseBodySize for 404 page/page-network-sizes.spec.ts › should have the correct responseBodySize [pass] page/page-network-sizes.spec.ts › should have the correct responseBodySize for chunked request [fail] page/page-network-sizes.spec.ts › should have the correct responseBodySize with gzip compression [pass] -page/page-network-sizes.spec.ts › should return sizes without hanging [fail] +page/page-network-sizes.spec.ts › should return sizes without hanging [pass] page/page-network-sizes.spec.ts › should set bodySize and headersSize [pass] page/page-network-sizes.spec.ts › should set bodySize to 0 if there was no body [pass] page/page-network-sizes.spec.ts › should set bodySize to 0 when there was no response body [pass] @@ -1270,28 +1276,28 @@ page/page-object-count.spec.ts › should count objects [unknown] page/page-request-continue.spec.ts › continue should delete headers on redirects [fail] page/page-request-continue.spec.ts › continue should not change multipart/form-data body [pass] page/page-request-continue.spec.ts › continue should propagate headers to redirects [fail] -page/page-request-continue.spec.ts › post data › should amend binary post data [fail] +page/page-request-continue.spec.ts › post data › should amend binary post data [pass] page/page-request-continue.spec.ts › post data › should amend longer post data [pass] page/page-request-continue.spec.ts › post data › should amend method and post data [pass] page/page-request-continue.spec.ts › post data › should amend post data [pass] -page/page-request-continue.spec.ts › post data › should amend utf8 post data [fail] +page/page-request-continue.spec.ts › post data › should amend utf8 post data [pass] page/page-request-continue.spec.ts › post data › should compute content-length from post data [pass] page/page-request-continue.spec.ts › post data › should use content-type from original request [pass] page/page-request-continue.spec.ts › redirected requests should report overridden headers [fail] page/page-request-continue.spec.ts › should amend HTTP headers [pass] page/page-request-continue.spec.ts › should amend method [pass] -page/page-request-continue.spec.ts › should amend method on main request [fail] +page/page-request-continue.spec.ts › should amend method on main request [pass] page/page-request-continue.spec.ts › should continue preload link requests [pass] page/page-request-continue.spec.ts › should delete header with undefined value [pass] page/page-request-continue.spec.ts › should delete the origin header [pass] -page/page-request-continue.spec.ts › should intercept css variable with background url [fail] +page/page-request-continue.spec.ts › should intercept css variable with background url [pass] page/page-request-continue.spec.ts › should not allow changing protocol when overriding url [pass] page/page-request-continue.spec.ts › should not throw if request was cancelled by the page [timeout] -page/page-request-continue.spec.ts › should not throw when continuing after page is closed [fail] +page/page-request-continue.spec.ts › should not throw when continuing after page is closed [pass] page/page-request-continue.spec.ts › should not throw when continuing while page is closing [fail] page/page-request-continue.spec.ts › should override method along with url [timeout] page/page-request-continue.spec.ts › should override request url [timeout] -page/page-request-continue.spec.ts › should work [fail] +page/page-request-continue.spec.ts › should work [pass] page/page-request-continue.spec.ts › should work with Cross-Origin-Opener-Policy [pass] page/page-request-fallback.spec.ts › post data › should amend binary post data [pass] page/page-request-fallback.spec.ts › post data › should amend json post data [pass] @@ -1300,7 +1306,7 @@ page/page-request-fallback.spec.ts › should amend HTTP headers [pass] page/page-request-fallback.spec.ts › should amend method [fail] page/page-request-fallback.spec.ts › should chain once [fail] page/page-request-fallback.spec.ts › should delete header with undefined value [pass] -page/page-request-fallback.spec.ts › should fall back [fail] +page/page-request-fallback.spec.ts › should fall back [pass] page/page-request-fallback.spec.ts › should fall back after exception [pass] page/page-request-fallback.spec.ts › should fall back async [pass] page/page-request-fallback.spec.ts › should not chain abort [pass] @@ -1310,10 +1316,10 @@ page/page-request-fallback.spec.ts › should work [pass] page/page-request-fulfill.spec.ts › headerValue should return set-cookie from intercepted response [pass] page/page-request-fulfill.spec.ts › should allow mocking binary responses [fail] page/page-request-fulfill.spec.ts › should allow mocking svg with charset [fail] -page/page-request-fulfill.spec.ts › should fetch original request and fulfill [fail] +page/page-request-fulfill.spec.ts › should fetch original request and fulfill [pass] page/page-request-fulfill.spec.ts › should fulfill json [pass] -page/page-request-fulfill.spec.ts › should fulfill preload link requests [fail] -page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [fail] +page/page-request-fulfill.spec.ts › should fulfill preload link requests [pass] +page/page-request-fulfill.spec.ts › should fulfill with fetch response that has multiple set-cookie [pass] page/page-request-fulfill.spec.ts › should fulfill with fetch result [fail] page/page-request-fulfill.spec.ts › should fulfill with fetch result and overrides [fail] page/page-request-fulfill.spec.ts › should fulfill with global fetch result [fail] @@ -1327,17 +1333,18 @@ page/page-request-fulfill.spec.ts › should not modify the headers sent to the page/page-request-fulfill.spec.ts › should not throw if request was cancelled by the page [fail] page/page-request-fulfill.spec.ts › should stringify intercepted request response headers [pass] page/page-request-fulfill.spec.ts › should work [pass] -page/page-request-fulfill.spec.ts › should work with buffer as body [fail] +page/page-request-fulfill.spec.ts › should work with buffer as body [pass] page/page-request-fulfill.spec.ts › should work with file path [pass] page/page-request-fulfill.spec.ts › should work with status code 422 [pass] +page/page-request-gc.spec.ts › should work [fail] page/page-request-intercept.spec.ts › request.postData is not null when fetching FormData with a Blob [fail] page/page-request-intercept.spec.ts › should fulfill intercepted response [pass] page/page-request-intercept.spec.ts › should fulfill intercepted response using alias [pass] -page/page-request-intercept.spec.ts › should fulfill popup main request using alias [fail] +page/page-request-intercept.spec.ts › should fulfill popup main request using alias [pass] page/page-request-intercept.spec.ts › should fulfill response with empty body [fail] page/page-request-intercept.spec.ts › should fulfill with any response [fail] page/page-request-intercept.spec.ts › should give access to the intercepted response [pass] -page/page-request-intercept.spec.ts › should give access to the intercepted response body [fail] +page/page-request-intercept.spec.ts › should give access to the intercepted response body [pass] page/page-request-intercept.spec.ts › should intercept multipart/form-data request body [unknown] page/page-request-intercept.spec.ts › should intercept with post data override [pass] page/page-request-intercept.spec.ts › should intercept with url override [fail] @@ -1348,7 +1355,7 @@ page/page-request-intercept.spec.ts › should support timeout option in route.f page/page-route.spec.ts › route.abort should throw if called twice [pass] page/page-route.spec.ts › route.continue should throw if called twice [pass] page/page-route.spec.ts › route.fallback should throw if called twice [pass] -page/page-route.spec.ts › route.fulfill should throw if called twice [fail] +page/page-route.spec.ts › route.fulfill should throw if called twice [pass] page/page-route.spec.ts › should add Access-Control-Allow-Origin by default when fulfill [fail] page/page-route.spec.ts › should allow null origin for about:blank [fail] page/page-route.spec.ts › should be able to fetch dataURL and not fire dataURL requests [fail] @@ -1359,50 +1366,50 @@ page/page-route.spec.ts › should chain fallback w/ dynamic URL [fail] page/page-route.spec.ts › should contain raw request header [pass] page/page-route.spec.ts › should contain raw response header [pass] page/page-route.spec.ts › should contain raw response header after fulfill [pass] -page/page-route.spec.ts › should contain referer header [fail] +page/page-route.spec.ts › should contain referer header [pass] page/page-route.spec.ts › should fail navigation when aborting main resource [fail] -page/page-route.spec.ts › should fulfill with redirect status [fail] +page/page-route.spec.ts › should fulfill with redirect status [pass] page/page-route.spec.ts › should intercept @smoke [fail] page/page-route.spec.ts › should intercept main resource during cross-process navigation [pass] page/page-route.spec.ts › should intercept when postData is more than 1MB [fail] page/page-route.spec.ts › should navigate to URL with hash and and fire requests without hash [pass] page/page-route.spec.ts › should navigate to dataURL and not fire dataURL requests [pass] page/page-route.spec.ts › should not auto-intercept non-preflight OPTIONS [fail] -page/page-route.spec.ts › should not fulfill with redirect status [unknown] +page/page-route.spec.ts › should not fulfill with redirect status [fail] page/page-route.spec.ts › should not throw "Invalid Interception Id" if the request was cancelled [fail] page/page-route.spec.ts › should not throw if request was cancelled by the page [timeout] page/page-route.spec.ts › should not work with redirects [fail] -page/page-route.spec.ts › should override cookie header [fail] -page/page-route.spec.ts › should pause intercepted XHR until continue [fail] +page/page-route.spec.ts › should override cookie header [pass] +page/page-route.spec.ts › should pause intercepted XHR until continue [pass] page/page-route.spec.ts › should pause intercepted fetch request until continue [pass] page/page-route.spec.ts › should properly return navigation response when URL has cookies [pass] page/page-route.spec.ts › should reject cors with disallowed credentials [fail] page/page-route.spec.ts › should respect cors overrides [fail] page/page-route.spec.ts › should send referer [fail] page/page-route.spec.ts › should show custom HTTP headers [fail] -page/page-route.spec.ts › should support ? in glob pattern [fail] +page/page-route.spec.ts › should support ? in glob pattern [pass] page/page-route.spec.ts › should support async handler w/ times [pass] page/page-route.spec.ts › should support cors for different methods [fail] page/page-route.spec.ts › should support cors with GET [pass] page/page-route.spec.ts › should support cors with POST [fail] page/page-route.spec.ts › should support cors with credentials [fail] -page/page-route.spec.ts › should support the times parameter with route matching [fail] +page/page-route.spec.ts › should support the times parameter with route matching [pass] page/page-route.spec.ts › should unroute [pass] page/page-route.spec.ts › should work if handler with times parameter was removed from another handler [pass] -page/page-route.spec.ts › should work when POST is redirected with 302 [fail] -page/page-route.spec.ts › should work when header manipulation headers with redirect [fail] +page/page-route.spec.ts › should work when POST is redirected with 302 [pass] +page/page-route.spec.ts › should work when header manipulation headers with redirect [pass] page/page-route.spec.ts › should work with badly encoded server [pass] page/page-route.spec.ts › should work with custom referer headers [fail] -page/page-route.spec.ts › should work with encoded server [fail] +page/page-route.spec.ts › should work with encoded server [pass] page/page-route.spec.ts › should work with encoded server - 2 [fail] -page/page-route.spec.ts › should work with equal requests [fail] +page/page-route.spec.ts › should work with equal requests [pass] page/page-route.spec.ts › should work with redirect inside sync XHR [pass] page/page-route.spec.ts › should work with redirects for subresources [fail] page/page-screenshot.spec.ts › page screenshot animations › should capture screenshots after layoutchanges in transitionend event [pass] page/page-screenshot.spec.ts › page screenshot animations › should fire transitionend for finite transitions [pass] page/page-screenshot.spec.ts › page screenshot animations › should not capture css animations in shadow DOM [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [fail] -page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [fail] +page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite css animation [pass] +page/page-screenshot.spec.ts › page screenshot animations › should not capture infinite web animations [pass] page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] page/page-screenshot.spec.ts › page screenshot animations › should not change animation with playbackRate equal to 0 [pass] page/page-screenshot.spec.ts › page screenshot animations › should resume infinite animations [pass] @@ -1421,13 +1428,13 @@ page/page-screenshot.spec.ts › page screenshot › mask option › should remo page/page-screenshot.spec.ts › page screenshot › mask option › should work [fail] page/page-screenshot.spec.ts › page screenshot › mask option › should work when mask color is not pink #F0F [fail] page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe has stalled navigation [fail] -page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [fail] +page/page-screenshot.spec.ts › page screenshot › mask option › should work when subframe used document.open after a weird url [pass] page/page-screenshot.spec.ts › page screenshot › mask option › should work with elementhandle [fail] page/page-screenshot.spec.ts › page screenshot › mask option › should work with locator [fail] page/page-screenshot.spec.ts › page screenshot › path option should create subdirectories [pass] page/page-screenshot.spec.ts › page screenshot › path option should detect jpeg [fail] page/page-screenshot.spec.ts › page screenshot › path option should throw for unsupported mime type [pass] -page/page-screenshot.spec.ts › page screenshot › path option should work [fail] +page/page-screenshot.spec.ts › page screenshot › path option should work [pass] page/page-screenshot.spec.ts › page screenshot › quality option should throw for png [pass] page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] page/page-screenshot.spec.ts › page screenshot › should capture blinking caret if explicitly asked for [fail] @@ -1436,7 +1443,7 @@ page/page-screenshot.spec.ts › page screenshot › should capture canvas chang page/page-screenshot.spec.ts › page screenshot › should clip elements to the viewport [fail] page/page-screenshot.spec.ts › page screenshot › should clip rect [fail] page/page-screenshot.spec.ts › page screenshot › should clip rect with fullPage [fail] -page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [fail] +page/page-screenshot.spec.ts › page screenshot › should not capture blinking caret by default [pass] page/page-screenshot.spec.ts › page screenshot › should not issue resize event [pass] page/page-screenshot.spec.ts › page screenshot › should prefer type over extension [fail] page/page-screenshot.spec.ts › page screenshot › should render white background on jpeg file [fail] @@ -1454,10 +1461,10 @@ page/page-screenshot.spec.ts › page screenshot › should work while navigatin page/page-screenshot.spec.ts › page screenshot › should work with Array deleted [fail] page/page-screenshot.spec.ts › page screenshot › should work with iframe in shadow [fail] page/page-screenshot.spec.ts › page screenshot › should work with odd clip size on Retina displays [fail] -page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [fail] +page/page-screenshot.spec.ts › page screenshot › zero quality option should throw for png [pass] page/page-screenshot.spec.ts › should capture css box-shadow [fail] -page/page-screenshot.spec.ts › should throw if screenshot size is too large [fail] -page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [fail] +page/page-screenshot.spec.ts › should throw if screenshot size is too large [pass] +page/page-select-option.spec.ts › input event.composed should be true and cross shadow dom boundary [pass] page/page-select-option.spec.ts › should deselect all options when passed no values for a multiple select [pass] page/page-select-option.spec.ts › should deselect all options when passed no values for a select without multiple [pass] page/page-select-option.spec.ts › should fall back to selecting by label [pass] @@ -1467,7 +1474,7 @@ page/page-select-option.spec.ts › should not throw when select causes navigati page/page-select-option.spec.ts › should respect event bubbling [pass] page/page-select-option.spec.ts › should return [] on no matched values [pass] page/page-select-option.spec.ts › should return [] on no values [pass] -page/page-select-option.spec.ts › should return an array of matched values [fail] +page/page-select-option.spec.ts › should return an array of matched values [pass] page/page-select-option.spec.ts › should return an array of one element when multiple is not set [pass] page/page-select-option.spec.ts › should select multiple options [pass] page/page-select-option.spec.ts › should select multiple options with attributes [pass] @@ -1478,28 +1485,28 @@ page/page-select-option.spec.ts › should select single option by index [pass] page/page-select-option.spec.ts › should select single option by label [pass] page/page-select-option.spec.ts › should select single option by multiple attributes [pass] page/page-select-option.spec.ts › should select single option by value [pass] -page/page-select-option.spec.ts › should throw if passed wrong types [fail] +page/page-select-option.spec.ts › should throw if passed wrong types [pass] page/page-select-option.spec.ts › should throw when element is not a `); - - const locator = await recorder.hoverOverElement('select'); - expect(locator).toBe(`locator('#age')`); - await clickMultipleSelectOption(page.getByRole('option', { name: '1' })); - - const [message, sources] = await Promise.all([ - page.waitForEvent('console', msg => msg.type() !== 'error' && msg.text().includes('2')), - recorder.waitForOutput('JavaScript', 'selectOption(['), - clickMultipleSelectOption(page.getByRole('option', { name: '2' }), true) - ]); - - expect(sources.get('JavaScript')!.text).toContain(` - await page.locator('#age').selectOption(['1', '2']);`); - - expect(sources.get('Java')!.text).toContain(` - page.locator("#age").selectOption(new String[] {"1", "2"});`); - - expect(sources.get('Python')!.text).toContain(` - page.locator("#age").select_option(["1", "2"])`); - - expect(sources.get('Python Async')!.text).toContain(` - await page.locator("#age").select_option(["1", "2"])`); - - expect(sources.get('C#')!.text).toContain(` -await page.Locator("#age").SelectOptionAsync(new[] { "1", "2" });`); - - expect(message.text()).toBe('[1,2]'); - }); - - test('should unselect with multiple attribute', async ({ openRecorder }) => { - const { page, recorder } = await openRecorder(); - - await recorder.setContentAndWait(``); - const locator = await recorder.hoverOverElement('select'); - expect(locator).toBe(`locator('#age')`); - await clickMultipleSelectOption(page.getByRole('option', { name: '1' })); - - const [message, sources] = await Promise.all([ - page.waitForEvent('console', msg => msg.type() !== 'error' && msg.text() === '[]'), - recorder.waitForOutput('JavaScript', 'selectOption(['), - clickMultipleSelectOption(page.getByRole('option', { name: '1' }), true) - ]); - - expect(sources.get('JavaScript')!.text).toContain(` - await page.locator('#age').selectOption([]);`); - - expect(sources.get('Java')!.text).toContain(` - page.locator("#age").selectOption(new String[0]);`); - - expect(sources.get('Python')!.text).toContain(` - page.locator("#age").select_option([])`); - - expect(sources.get('Python Async')!.text).toContain(` - await page.locator("#age").select_option([])`); - - expect(sources.get('C#')!.text).toContain(` -await page.Locator("#age").SelectOptionAsync(new[] { });`); - - expect(message.text()).toBe('[]'); - }); - test('should await popup', async ({ openRecorder }) => { const { page, recorder } = await openRecorder(); await recorder.setContentAndWait('link'); From e4b0d5e6dd05d774c4d7dea239d7dc20571c083b Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Fri, 11 Oct 2024 07:33:59 -0700 Subject: [PATCH 295/805] feat(chromium): roll to r1142 (#33062) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 4 +- packages/playwright-core/browsers.json | 4 +- .../src/server/deviceDescriptorsSource.json | 96 +++++++++---------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 6df15c2024cdc..e865883de96b8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-130.0.6723.31-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-130.0.6723.44-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 130.0.6723.31 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 130.0.6723.44 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 131.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 8cfd41cd8cffb..7921a260352f8 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,9 +3,9 @@ "browsers": [ { "name": "chromium", - "revision": "1141", + "revision": "1142", "installByDefault": true, - "browserVersion": "130.0.6723.31" + "browserVersion": "130.0.6723.44" }, { "name": "chromium-tip-of-tree", diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index 1b0a015346334..6609089642a6e 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -110,7 +110,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S5": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -121,7 +121,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -132,7 +132,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 360, "height": 740 @@ -143,7 +143,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 740, "height": 360 @@ -154,7 +154,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 320, "height": 658 @@ -165,7 +165,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+ landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 658, "height": 320 @@ -176,7 +176,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "viewport": { "width": 712, "height": 1138 @@ -187,7 +187,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -1098,7 +1098,7 @@ "defaultBrowserType": "webkit" }, "LG Optimus L70": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,7 @@ "defaultBrowserType": "chromium" }, "LG Optimus L70 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,7 @@ "defaultBrowserType": "webkit" }, "Pixel 2": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36 Edg/130.0.6723.31", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36 Edg/130.0.6723.44", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.31 Safari/537.36 Edg/130.0.6723.31", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36 Edg/130.0.6723.44", "screen": { "width": 1920, "height": 1080 From 699f51b227d98d6d6e912f9490828337d1011340 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:18:06 -0700 Subject: [PATCH 296/805] feat(webkit): roll to r2091 (#33070) --- packages/playwright-core/browsers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 7921a260352f8..3dbbeee56198f 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -27,7 +27,7 @@ }, { "name": "webkit", - "revision": "2090", + "revision": "2091", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", From 0a63427c778ba447e870fe1ade72fee35c483fe1 Mon Sep 17 00:00:00 2001 From: Fumiaki MATSUSHIMA Date: Sun, 13 Oct 2024 20:16:01 +0900 Subject: [PATCH 297/805] fix(codegen): fix unselect issue (#33076) --- packages/playwright-core/src/server/codegen/java.ts | 2 +- packages/playwright-core/src/server/codegen/javascript.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/src/server/codegen/java.ts b/packages/playwright-core/src/server/codegen/java.ts index 507a040bcec66..5b417c6c3a82d 100644 --- a/packages/playwright-core/src/server/codegen/java.ts +++ b/packages/playwright-core/src/server/codegen/java.ts @@ -122,7 +122,7 @@ export class JavaLanguageGenerator implements LanguageGenerator { case 'navigate': return `${subject}.navigate(${quote(action.url)});`; case 'select': - return `${subject}.${this._asLocator(action.selector, inFrameLocator)}.selectOption(${formatSelectOption(action.options.length > 1 ? action.options : action.options[0])});`; + return `${subject}.${this._asLocator(action.selector, inFrameLocator)}.selectOption(${formatSelectOption(action.options.length === 1 ? action.options[0] : action.options)});`; case 'assertText': return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).${action.substring ? 'containsText' : 'hasText'}(${quote(action.text)});`; case 'assertChecked': diff --git a/packages/playwright-core/src/server/codegen/javascript.ts b/packages/playwright-core/src/server/codegen/javascript.ts index 558670cd47842..b68a8104a86e2 100644 --- a/packages/playwright-core/src/server/codegen/javascript.ts +++ b/packages/playwright-core/src/server/codegen/javascript.ts @@ -106,7 +106,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { case 'navigate': return `await ${subject}.goto(${quote(action.url)});`; case 'select': - return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length > 1 ? action.options : action.options[0])});`; + return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length === 1 ? action.options[0] : action.options)});`; case 'assertText': return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? 'toContainText' : 'toHaveText'}(${quote(action.text)});`; case 'assertChecked': From 4c2d62a8816bb606e1e73b1c82fa39aa13406a70 Mon Sep 17 00:00:00 2001 From: Remigiusz Dudek Date: Mon, 14 Oct 2024 14:16:19 +0200 Subject: [PATCH 298/805] feat(html-reporter): recognize video attachment by the contentType (#33074) Closes https://github.com/microsoft/playwright/issues/33073. --------- Signed-off-by: Remigiusz Dudek Co-authored-by: Dmitry Gozman --- packages/html-reporter/src/testResultView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/html-reporter/src/testResultView.tsx b/packages/html-reporter/src/testResultView.tsx index 273703a0c7064..48a24a2391f27 100644 --- a/packages/html-reporter/src/testResultView.tsx +++ b/packages/html-reporter/src/testResultView.tsx @@ -70,7 +70,7 @@ export const TestResultView: React.FC<{ const { screenshots, videos, traces, otherAttachments, diffs, errors, htmls } = React.useMemo(() => { const attachments = result?.attachments || []; const screenshots = new Set(attachments.filter(a => a.contentType.startsWith('image/'))); - const videos = attachments.filter(a => a.name === 'video'); + const videos = attachments.filter(a => a.contentType.startsWith('video/')); const traces = attachments.filter(a => a.name === 'trace'); const htmls = attachments.filter(a => a.contentType.startsWith('text/html')); const otherAttachments = new Set(attachments); From 9fcf60464d983b70b3cafea3e230e4e6e4f92c15 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 14 Oct 2024 16:32:11 +0200 Subject: [PATCH 299/805] chore: various v1.48.0 roll fixes for .NET (#33096) --- docs/src/api/class-websocketroute.md | 14 ++++++++++---- docs/src/api/params.md | 2 +- utils/doclint/dotnetXmlDocumentation.js | 13 ++++++++----- utils/doclint/generateDotnetApi.js | 5 +++-- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/src/api/class-websocketroute.md b/docs/src/api/class-websocketroute.md index e5347b07b1448..f977050481120 100644 --- a/docs/src/api/class-websocketroute.md +++ b/docs/src/api/class-websocketroute.md @@ -256,19 +256,25 @@ By default, closing one side of the connection, either in the page or on the ser ### param: WebSocketRoute.onClose.handler * since: v1.48 * langs: js, python -- `handler` <[function]\([number]|[undefined], [string]|[undefined]\): [Promise|any]> +- `handler` <[function]\([int]|[undefined], [string]|[undefined]\): [Promise|any]> Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason). ### param: WebSocketRoute.onClose.handler * since: v1.48 -* langs: java, csharp -- `handler` <[function]\([null]|[number], [null]|[string]\)> +* langs: java +- `handler` <[function]\([null]|[int], [null]|[string]\)> Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason). +### param: WebSocketRoute.onClose.handler +* since: v1.48 +* langs: csharp +- `handler` <[function]\([int?], [string]\)> + +Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason). -## async method: WebSocketRoute.onMessage +## method: WebSocketRoute.onMessage * since: v1.48 This method allows to handle messages that are sent by the WebSocket, either from the page or from the server. diff --git a/docs/src/api/params.md b/docs/src/api/params.md index 63693030bbe60..9b8d3de31b81f 100644 --- a/docs/src/api/params.md +++ b/docs/src/api/params.md @@ -363,7 +363,7 @@ Target URL. ## js-fetch-option-params * langs: js -- `params` <[Object]<[string], [string]|[number]|[boolean]>|[URLSearchParams]|[string]> +- `params` <[Object]<[string], [string]|[float]|[boolean]>|[URLSearchParams]|[string]> Query parameters to be sent with the URL. diff --git a/utils/doclint/dotnetXmlDocumentation.js b/utils/doclint/dotnetXmlDocumentation.js index 66fae02c12977..4b500c0781581 100644 --- a/utils/doclint/dotnetXmlDocumentation.js +++ b/utils/doclint/dotnetXmlDocumentation.js @@ -16,7 +16,7 @@ // @ts-check const Documentation = require('./documentation'); -const { visitAll } = require('../markdown'); +const { visitAll, render } = require('../markdown'); /** * @param {Documentation.MarkdownNode[]} nodes * @param {number} maxColumns @@ -64,7 +64,10 @@ function _innerRenderNodes(nodes, maxColumns = 80, wrapParagraphs = true) { } else if (node.type === 'li') { _wrapInNode('item>/g, '>'); if (i < lines.length - 1) - line = line + "
"; + line = line + '
'; out.push(line); i++; } @@ -163,4 +166,4 @@ function renderTextOnly(nodes, maxColumns = 80) { return result.summary; } -module.exports = { renderXmlDoc, renderTextOnly } \ No newline at end of file +module.exports = { renderXmlDoc, renderTextOnly }; \ No newline at end of file diff --git a/utils/doclint/generateDotnetApi.js b/utils/doclint/generateDotnetApi.js index 006d6e494c6d2..2e82f92d0ad3a 100644 --- a/utils/doclint/generateDotnetApi.js +++ b/utils/doclint/generateDotnetApi.js @@ -520,7 +520,8 @@ function renderMethod(member, parent, name, options, out) { && !name.startsWith('Get') && name !== 'CreateFormData' && !name.startsWith('PostDataJSON') - && !name.startsWith('As')) { + && !name.startsWith('As') + && name !== 'ConnectToServer') { if (!member.async) { if (member.spec && !options.nodocs) out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth)); @@ -718,7 +719,7 @@ function translateType(type, parent, generateNameCallback = t => t.name, optiona if (type.expression === '[null]|[Error]') return 'void'; - if (type.name == 'Promise' && type.templates?.[0].name === 'any') + if (type.name === 'Promise' && type.templates?.[0].name === 'any') return 'Task'; if (type.union) { From a8df750a48fcad562b5f42e05ea554a07f80a377 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 14 Oct 2024 17:22:29 +0200 Subject: [PATCH 300/805] fix(har): account for reused sockets (#33087) Closes https://github.com/microsoft/playwright/issues/32960 If the socket is reused, the connect and DNS timings are set to -1, because that timing doesn't apply to the current request. The time between request start and the socket being free is counted as `blocked`. --- packages/playwright-core/src/server/fetch.ts | 11 +++++++++-- tests/library/har.spec.ts | 13 +++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/src/server/fetch.ts b/packages/playwright-core/src/server/fetch.ts index 243e89cf1c9f4..f231c907c0827 100644 --- a/packages/playwright-core/src/server/fetch.ts +++ b/packages/playwright-core/src/server/fetch.ts @@ -302,6 +302,7 @@ export abstract class APIRequestContext extends SdkObject { const requestOptions = { ...options, agent }; const startAt = monotonicTime(); + let reusedSocketAt: number | undefined; let dnsLookupAt: number | undefined; let tcpConnectionAt: number | undefined; let tlsHandshakeAt: number | undefined; @@ -319,14 +320,15 @@ export abstract class APIRequestContext extends SdkObject { const notifyRequestFinished = (body?: Buffer) => { const endAt = monotonicTime(); // spec: http://www.softwareishard.com/blog/har-12-spec/#timings + const connectEnd = tlsHandshakeAt ?? tcpConnectionAt; const timings: har.Timings = { send: requestFinishAt! - startAt, wait: responseAt - requestFinishAt!, receive: endAt - responseAt, dns: dnsLookupAt ? dnsLookupAt - startAt : -1, - connect: (tlsHandshakeAt ?? tcpConnectionAt!) - startAt, // "If [ssl] is defined then the time is also included in the connect field " + connect: connectEnd ? connectEnd - startAt : -1, // "If [ssl] is defined then the time is also included in the connect field " ssl: tlsHandshakeAt ? tlsHandshakeAt - tcpConnectionAt! : -1, - blocked: -1, + blocked: reusedSocketAt ? reusedSocketAt - startAt : -1, }; const requestFinishedEvent: APIRequestFinishedEvent = { @@ -489,6 +491,11 @@ export abstract class APIRequestContext extends SdkObject { request.on('close', () => eventsHelper.removeEventListeners(listeners)); request.on('socket', socket => { + if (request.reusedSocket) { + reusedSocketAt = monotonicTime(); + return; + } + // happy eyeballs don't emit lookup and connect events, so we use our custom ones const happyEyeBallsTimings = timingForSocket(socket); dnsLookupAt = happyEyeBallsTimings.dnsLookupAt; diff --git a/tests/library/har.spec.ts b/tests/library/har.spec.ts index a5d4a6fa0ea2f..92358608e9e3e 100644 --- a/tests/library/har.spec.ts +++ b/tests/library/har.spec.ts @@ -877,6 +877,19 @@ it('should include timings when using socks proxy', async ({ contextFactory, ser expect(log.entries[0].timings.connect).toBeGreaterThan(0); }); +it('should not have connect and dns timings when socket is reused', async ({ contextFactory, server }, testInfo) => { + const { page, getLog } = await pageWithHar(contextFactory, testInfo); + await page.request.get(server.EMPTY_PAGE); + await page.request.get(server.EMPTY_PAGE); + + const log = await getLog(); + expect(log.entries).toHaveLength(2); + const request2 = log.entries[1]; + expect.soft(request2.timings.connect).toBe(-1); + expect.soft(request2.timings.dns).toBe(-1); + expect.soft(request2.timings.blocked).toBeGreaterThan(0); +}); + it('should include redirects from API request', async ({ contextFactory, server }, testInfo) => { server.setRedirect('/redirect-me', '/simple.json'); const { page, getLog } = await pageWithHar(contextFactory, testInfo); From c7fbeddaf479b1c0b6ce93e7ad72ac8141a91781 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:21:49 -0700 Subject: [PATCH 301/805] feat(webkit): roll to r2092 (#33078) --- packages/playwright-core/browsers.json | 2 +- tests/library/modernizr.spec.ts | 4 ++-- tests/page/page-screenshot.spec.ts | 5 +++-- ...nshot-canvas-with-accurate-corners-webkit.png | Bin 0 -> 2249 bytes 4 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 tests/page/page-screenshot.spec.ts-snapshots/screenshot-canvas-with-accurate-corners-webkit.png diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 3dbbeee56198f..53fedf1923822 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -27,7 +27,7 @@ }, { "name": "webkit", - "revision": "2091", + "revision": "2092", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", diff --git a/tests/library/modernizr.spec.ts b/tests/library/modernizr.spec.ts index d74afaedb25ab..7e3fc49f6f1d8 100644 --- a/tests/library/modernizr.spec.ts +++ b/tests/library/modernizr.spec.ts @@ -57,7 +57,7 @@ it('Safari Desktop', async ({ browser, browserName, platform, server, headless } expected.publickeycredential = false; expected.mediastream = false; if (headless) - expected.todataurljpeg = false; + expected.todataurlwebp = true; // GHA delete actual.variablefonts; @@ -124,7 +124,7 @@ it('Mobile Safari', async ({ playwright, browser, browserName, platform, server, expected.publickeycredential = false; expected.mediastream = false; if (headless) - expected.todataurljpeg = false; + expected.todataurlwebp = true; // GHA delete actual.variablefonts; diff --git a/tests/page/page-screenshot.spec.ts b/tests/page/page-screenshot.spec.ts index 07e53e4a711f6..879307aa916f3 100644 --- a/tests/page/page-screenshot.spec.ts +++ b/tests/page/page-screenshot.spec.ts @@ -280,12 +280,13 @@ it.describe('page screenshot', () => { expect(screenshot).toMatchSnapshot('screenshot-clip-odd-size.png'); }); - it('should work for canvas', async ({ page, server, isElectron, isMac, macVersion, browserName, headless }) => { + it('should work for canvas', async ({ page, server, isElectron, isMac, isLinux, macVersion, browserName, headless }) => { it.fixme(isElectron && isMac, 'Fails on the bots'); await page.setViewportSize({ width: 500, height: 500 }); await page.goto(server.PREFIX + '/screenshots/canvas.html'); const screenshot = await page.screenshot(); - if (!headless && browserName === 'chromium' && isMac && os.arch() === 'arm64' && macVersion >= 14) + if ((!headless && browserName === 'chromium' && isMac && os.arch() === 'arm64' && macVersion >= 14) || + (browserName === 'webkit' && isLinux)) expect(screenshot).toMatchSnapshot('screenshot-canvas-with-accurate-corners.png'); else expect(screenshot).toMatchSnapshot('screenshot-canvas.png'); diff --git a/tests/page/page-screenshot.spec.ts-snapshots/screenshot-canvas-with-accurate-corners-webkit.png b/tests/page/page-screenshot.spec.ts-snapshots/screenshot-canvas-with-accurate-corners-webkit.png new file mode 100644 index 0000000000000000000000000000000000000000..8c38aaeeb6eda4607758f97cc07b6007c0bff3c3 GIT binary patch literal 2249 zcmeAS@N?(olHy`uVBq!ia0y~yVEh8Y9Be?5)7S2I0V&4fAa^H*b?0PW0y!+jPM#qg zKv2Vx(!s#MQS9mB7*a9k?JdVXDMJz0KdiizR>NlsY?CKf7Tz2)pShtJHJ z_aUhI{bgYWi!;cEPr85Mf7$-~{{9s!UVp6u+HHTvouzi|F;~m!_ZfbiIu2xS&D(za zCFlL1>dOoV9{*_LV_;yLZqLlHZ_{(pt-r5#upj@x{%6VbPyZPoNLw+ma6qw&{?VNa*bXc&bfTWy zK<>$2Yihh)o#8-qF%=D_Mc|E^Nxg_44a?E698CkmBMmg%w|uW%zF~pPFJN Date: Mon, 14 Oct 2024 13:25:30 -0700 Subject: [PATCH 302/805] chore(bidi): remove assertion from response dispatch (#33100) After the context has been disposed we can't route any callbacks to it because it is not in the map, so the assertion doesn't make sense as it always ends up in the top level session. Fixes the following error: ``` pw:browser Closing websocket due to failed onmessage callback. eventData={"type":"success","id":32,"result":{}} e=Assertion error Error: Assertion error pw:browser at assert (/home/yurys/playwright/packages/playwright-core/src/utils/debug.ts:21:11) pw:browser at BidiSession.dispatchMessage (/home/yurys/playwright/packages/playwright-core/src/server/bidi/bidiConnection.ts:229:13) pw:browser at BidiConnection.call [as _dispatchMessage] (/home/yurys/playwright/packages/playwright-core/src/server/bidi/bidiConnection.ts:93:25) ``` --- packages/playwright-core/src/server/bidi/bidiConnection.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/playwright-core/src/server/bidi/bidiConnection.ts b/packages/playwright-core/src/server/bidi/bidiConnection.ts index f34881594022b..48472bf748212 100644 --- a/packages/playwright-core/src/server/bidi/bidiConnection.ts +++ b/packages/playwright-core/src/server/bidi/bidiConnection.ts @@ -15,7 +15,6 @@ */ import { EventEmitter } from 'events'; -import { assert } from '../../utils'; import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport'; import type { RecentLogsCollector } from '../../utils/debugLogger'; import { debugLogger } from '../../utils/debugLogger'; @@ -224,7 +223,6 @@ export class BidiSession extends EventEmitter { } } else if (object.id) { // Response might come after session has been disposed and rejected all callbacks. - assert(this.isDisposed()); } else { Promise.resolve().then(() => this.emit(object.method, object.params)); } From ecd147ce436f674348b6e92a50fe82bc0ef27b0f Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 14 Oct 2024 13:46:06 -0700 Subject: [PATCH 303/805] fix(test runner): when sharding with beforeAll, use shards total instead of workers (#33083) Otherwise, we might split the `beforeAll`-grouped test group into `workers` parts instead of `shard.total` parts as the user would expect. Fixes #33077. --- packages/playwright/src/runner/loadUtils.ts | 7 +++- packages/playwright/src/runner/testGroups.ts | 4 +- tests/playwright-test/shard.spec.ts | 40 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/packages/playwright/src/runner/loadUtils.ts b/packages/playwright/src/runner/loadUtils.ts index 63a230750741e..e2c6d0c530951 100644 --- a/packages/playwright/src/runner/loadUtils.ts +++ b/packages/playwright/src/runner/loadUtils.ts @@ -176,8 +176,11 @@ export async function createRootSuite(testRun: TestRun, errors: TestError[], sho if (config.config.shard) { // Create test groups for top-level projects. const testGroups: TestGroup[] = []; - for (const projectSuite of rootSuite.suites) - testGroups.push(...createTestGroups(projectSuite, config.config.workers)); + for (const projectSuite of rootSuite.suites) { + // Split beforeAll-grouped tests into "config.shard.total" groups when needed. + // Later on, we'll re-split them between workers by using "config.workers" instead. + testGroups.push(...createTestGroups(projectSuite, config.config.shard.total)); + } // Shard test groups. const testGroupsInThisShard = filterForShard(config.config.shard, testGroups); diff --git a/packages/playwright/src/runner/testGroups.ts b/packages/playwright/src/runner/testGroups.ts index 5a70bc84cc0d7..5743c7044bcb5 100644 --- a/packages/playwright/src/runner/testGroups.ts +++ b/packages/playwright/src/runner/testGroups.ts @@ -24,7 +24,7 @@ export type TestGroup = { tests: TestCase[]; }; -export function createTestGroups(projectSuite: Suite, workers: number): TestGroup[] { +export function createTestGroups(projectSuite: Suite, expectedParallelism: number): TestGroup[] { // This function groups tests that can be run together. // Tests cannot be run together when: // - They belong to different projects - requires different workers. @@ -116,7 +116,7 @@ export function createTestGroups(projectSuite: Suite, workers: number): TestGrou result.push(...withRequireFile.parallel.values()); // Tests with beforeAll/afterAll should try to share workers as much as possible. - const parallelWithHooksGroupSize = Math.ceil(withRequireFile.parallelWithHooks.tests.length / workers); + const parallelWithHooksGroupSize = Math.ceil(withRequireFile.parallelWithHooks.tests.length / expectedParallelism); let lastGroup: TestGroup | undefined; for (const test of withRequireFile.parallelWithHooks.tests) { if (!lastGroup || lastGroup.tests.length >= parallelWithHooksGroupSize) { diff --git a/tests/playwright-test/shard.spec.ts b/tests/playwright-test/shard.spec.ts index e82a434f5233a..f73462c1f4f59 100644 --- a/tests/playwright-test/shard.spec.ts +++ b/tests/playwright-test/shard.spec.ts @@ -284,3 +284,43 @@ test('should not shard mode:default suites', async ({ runInlineTest }) => { expect(result.outputLines).toEqual(['beforeAll2', 'test4', 'test5']); } }); + +test('should shard tests with beforeAll based on shards total instead of workers', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33077' }, +}, async ({ runInlineTest }) => { + const tests = { + 'a.spec.ts': ` + import { test } from '@playwright/test'; + + test.describe.configure({ mode: 'parallel' }); + test.beforeAll(() => { + console.log('\\n%%beforeAll'); + }); + + for (let i = 1; i <= 8; i++) { + test('test ' + i, async ({ }) => { + console.log('\\n%%test' + i); + }); + } + `, + }; + + { + const result = await runInlineTest(tests, { shard: '1/4', workers: 1 }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(2); + expect(result.outputLines).toEqual(['beforeAll', 'test1', 'test2']); + } + { + const result = await runInlineTest(tests, { shard: '2/4', workers: 1 }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(2); + expect(result.outputLines).toEqual(['beforeAll', 'test3', 'test4']); + } + { + const result = await runInlineTest(tests, { shard: '7/8', workers: 6 }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + expect(result.outputLines).toEqual(['beforeAll', 'test7']); + } +}); From 6cfcbe0d6d7447f8129b083c828d187846773fb6 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 14 Oct 2024 14:04:24 -0700 Subject: [PATCH 304/805] chore: fix codegen selector while debugging (#33099) Fixes #33052 --- .../playwright-core/src/server/recorder.ts | 3 ++- .../src/server/recorder/recorderApp.ts | 6 ++--- .../src/server/recorder/recorderFrontend.ts | 2 +- .../server/recorder/recorderInTraceViewer.ts | 4 ++-- packages/recorder/src/recorder.tsx | 18 +++++++------- packages/recorder/src/recorderTypes.ts | 2 +- packages/web/src/components/sourceChooser.tsx | 24 +++++++++++-------- packages/web/src/components/toolbarButton.tsx | 3 +++ tests/library/inspector/pause.spec.ts | 16 +++++++++++++ 9 files changed, 50 insertions(+), 28 deletions(-) diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 4aab712b9bd64..386e4dece6f1d 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -140,6 +140,7 @@ export class Recorder implements InstrumentationListener, IRecorder { this._contextRecorder.on(ContextRecorder.Events.Change, (data: { sources: Source[], actions: actions.ActionInContext[] }) => { this._recorderSources = data.sources; recorderApp.setActions(data.actions, data.sources); + recorderApp.setRunningFile(undefined); this._pushAllSources(); }); @@ -299,7 +300,7 @@ export class Recorder implements InstrumentationListener, IRecorder { } this._pushAllSources(); if (fileToSelect) - this._recorderApp?.setFile(fileToSelect); + this._recorderApp?.setRunningFile(fileToSelect); } private _pushAllSources() { diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index 30149f9816ca2..3f9a636579efe 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -34,7 +34,7 @@ export class EmptyRecorderApp extends EventEmitter implements IRecorderApp { async close(): Promise {} async setPaused(paused: boolean): Promise {} async setMode(mode: Mode): Promise {} - async setFile(file: string): Promise {} + async setRunningFile(file: string | undefined): Promise {} async setSelector(selector: string, userGesture?: boolean): Promise {} async updateCallLogs(callLogs: CallLog[]): Promise {} async setSources(sources: Source[]): Promise {} @@ -131,9 +131,9 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { }).toString(), { isFunction: true }, mode).catch(() => {}); } - async setFile(file: string): Promise { + async setRunningFile(file: string | undefined): Promise { await this._page.mainFrame().evaluateExpression(((file: string) => { - window.playwrightSetFile(file); + window.playwrightSetRunningFile(file); }).toString(), { isFunction: true }, file).catch(() => {}); } diff --git a/packages/playwright-core/src/server/recorder/recorderFrontend.ts b/packages/playwright-core/src/server/recorder/recorderFrontend.ts index 97df1d3ceb6c4..9bf48022a7087 100644 --- a/packages/playwright-core/src/server/recorder/recorderFrontend.ts +++ b/packages/playwright-core/src/server/recorder/recorderFrontend.ts @@ -28,7 +28,7 @@ export interface IRecorderApp extends EventEmitter { close(): Promise; setPaused(paused: boolean): Promise; setMode(mode: Mode): Promise; - setFile(file: string): Promise; + setRunningFile(file: string | undefined): Promise; setSelector(selector: string, userGesture?: boolean): Promise; updateCallLogs(callLogs: CallLog[]): Promise; setSources(sources: Source[]): Promise; diff --git a/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts b/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts index ab67fe562cf7f..e11ef1283a80f 100644 --- a/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts +++ b/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts @@ -66,8 +66,8 @@ export class RecorderInTraceViewer extends EventEmitter implements IRecorderApp this._transport.deliverEvent('setMode', { mode }); } - async setFile(file: string): Promise { - this._transport.deliverEvent('setFileIfNeeded', { file }); + async setRunningFile(file: string | undefined): Promise { + this._transport.deliverEvent('setRunningFile', { file }); } async setSelector(selector: string, userGesture?: boolean): Promise { diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx index 9d5c0feebac94..19b7bc12a70ad 100644 --- a/packages/recorder/src/recorder.tsx +++ b/packages/recorder/src/recorder.tsx @@ -41,13 +41,11 @@ export const Recorder: React.FC = ({ log, mode, }) => { - const [fileId, setFileId] = React.useState(); + const [selectedFileId, setSelectedFileId] = React.useState(); + const [runningFileId, setRunningFileId] = React.useState(); const [selectedTab, setSelectedTab] = React.useState('log'); - React.useEffect(() => { - if (!fileId && sources.length > 0) - setFileId(sources[0].id); - }, [fileId, sources]); + const fileId = selectedFileId || runningFileId || sources[0]?.id; const source = React.useMemo(() => { if (fileId) { @@ -66,7 +64,7 @@ export const Recorder: React.FC = ({ setLocator(asLocator(language, selector)); }; - window.playwrightSetFile = setFileId; + window.playwrightSetRunningFile = setRunningFileId; const messagesEndRef = React.useRef(null); React.useLayoutEffect(() => { @@ -134,19 +132,19 @@ export const Recorder: React.FC = ({ { copy(source.text); }}> - { + { window.dispatch({ event: 'resume' }); }}> - { + { window.dispatch({ event: 'pause' }); }}> - { + { window.dispatch({ event: 'step' }); }}>
Target:
{ - setFileId(fileId); + setSelectedFileId(fileId); window.dispatch({ event: 'fileChanged', params: { file: fileId } }); }} /> { diff --git a/packages/recorder/src/recorderTypes.ts b/packages/recorder/src/recorderTypes.ts index a5791e2306522..dd379f7ccd7ee 100644 --- a/packages/recorder/src/recorderTypes.ts +++ b/packages/recorder/src/recorderTypes.ts @@ -96,7 +96,7 @@ declare global { playwrightSetSources: (sources: Source[]) => void; playwrightSetOverlayVisible: (visible: boolean) => void; playwrightUpdateLogs: (callLogs: CallLog[]) => void; - playwrightSetFile: (file: string) => void; + playwrightSetRunningFile: (file: string | undefined) => void; playwrightSetSelector: (selector: string, focus?: boolean) => void; playwrightSourcesEchoForTest: Source[]; dispatch(data: any): Promise; diff --git a/packages/web/src/components/sourceChooser.tsx b/packages/web/src/components/sourceChooser.tsx index 0645480a03c65..22b91c61a511b 100644 --- a/packages/web/src/components/sourceChooser.tsx +++ b/packages/web/src/components/sourceChooser.tsx @@ -22,7 +22,7 @@ export const SourceChooser: React.FC<{ fileId: string | undefined, setFileId: (fileId: string) => void, }> = ({ sources, fileId, setFileId }) => { - return { setFileId(event.target.selectedOptions[0].value); }}>{renderSourceOptions(sources)}; }; @@ -33,17 +33,21 @@ function renderSourceOptions(sources: Source[]): React.ReactNode { ); - const hasGroup = sources.some(s => s.group); - if (hasGroup) { - const groups = new Set(sources.map(s => s.group)); - return [...groups].filter(Boolean).map(group => ( - - {sources.filter(s => s.group === group).map(source => renderOption(source))} - - )); + const sourcesByGroups = new Map(); + for (const source of sources) { + let list = sourcesByGroups.get(source.group || 'Debugger'); + if (!list) { + list = []; + sourcesByGroups.set(source.group || 'Debugger', list); + } + list.push(source); } - return sources.map(source => renderOption(source)); + return [...sourcesByGroups.entries()].map(([group, sources]) => ( + + {sources.filter(s => (s.group || 'Debugger') === group).map(source => renderOption(source))} + + )); } export function emptySource(): Source { diff --git a/packages/web/src/components/toolbarButton.tsx b/packages/web/src/components/toolbarButton.tsx index 00b9babd59940..184642b395e7f 100644 --- a/packages/web/src/components/toolbarButton.tsx +++ b/packages/web/src/components/toolbarButton.tsx @@ -28,6 +28,7 @@ export interface ToolbarButtonProps { style?: React.CSSProperties, testId?: string, className?: string, + ariaLabel?: string, } export const ToolbarButton: React.FC> = ({ @@ -40,6 +41,7 @@ export const ToolbarButton: React.FC style, testId, className, + ariaLabel, }) => { return `; - case 'link': return `${escapedTextContent}`; - case 'textbox': return ``; - } - return `
${escapedTextContent}
`; -} diff --git a/packages/playwright/ThirdPartyNotices.txt b/packages/playwright/ThirdPartyNotices.txt index f2bb64d661c29..46c2f60cd2ffe 100644 --- a/packages/playwright/ThirdPartyNotices.txt +++ b/packages/playwright/ThirdPartyNotices.txt @@ -155,6 +155,7 @@ This project incorporates components from the projects listed below. The origina - undici-types@6.19.8 (https://github.com/nodejs/undici) - update-browserslist-db@1.0.13 (https://github.com/browserslist/update-db) - yallist@3.1.1 (https://github.com/isaacs/yallist) +- yaml@2.5.1 (https://github.com/eemeli/yaml) %% @ampproject/remapping@2.2.1 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -4397,8 +4398,26 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ========================================= END OF yallist@3.1.1 AND INFORMATION +%% yaml@2.5.1 NOTICES AND INFORMATION BEGIN HERE +========================================= +Copyright Eemeli Aro + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +========================================= +END OF yaml@2.5.1 AND INFORMATION + SUMMARY BEGIN HERE ========================================= -Total Packages: 151 +Total Packages: 152 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright/bundles/expect/src/expectBundleImpl.ts b/packages/playwright/bundles/expect/src/expectBundleImpl.ts index dbfd169353d9b..875b48e614a43 100644 --- a/packages/playwright/bundles/expect/src/expectBundleImpl.ts +++ b/packages/playwright/bundles/expect/src/expectBundleImpl.ts @@ -40,6 +40,7 @@ export const matcherUtils = { }; export { + EXPECTED_COLOR, INVERTED_COLOR, RECEIVED_COLOR, printReceived, diff --git a/packages/playwright/bundles/utils/package-lock.json b/packages/playwright/bundles/utils/package-lock.json index fcf9f972feb31..90df9a258bd57 100644 --- a/packages/playwright/bundles/utils/package-lock.json +++ b/packages/playwright/bundles/utils/package-lock.json @@ -13,7 +13,8 @@ "json5": "2.2.3", "pirates": "4.0.4", "source-map-support": "0.5.21", - "stoppable": "1.1.0" + "stoppable": "1.1.0", + "yaml": "^2.5.1" }, "devDependencies": { "@types/source-map-support": "^0.5.4", @@ -280,6 +281,17 @@ "engines": { "node": ">=8.0" } + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } } }, "dependencies": { @@ -464,6 +476,11 @@ "requires": { "is-number": "^7.0.0" } + }, + "yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" } } } diff --git a/packages/playwright/bundles/utils/package.json b/packages/playwright/bundles/utils/package.json index 69477909c5337..dc807c0d95202 100644 --- a/packages/playwright/bundles/utils/package.json +++ b/packages/playwright/bundles/utils/package.json @@ -14,7 +14,8 @@ "json5": "2.2.3", "pirates": "4.0.4", "source-map-support": "0.5.21", - "stoppable": "1.1.0" + "stoppable": "1.1.0", + "yaml": "^2.5.1" }, "devDependencies": { "@types/source-map-support": "^0.5.4", diff --git a/packages/playwright/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright/bundles/utils/src/utilsBundleImpl.ts index 7c29c301a8924..76cf961ab7c55 100644 --- a/packages/playwright/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright/bundles/utils/src/utilsBundleImpl.ts @@ -31,3 +31,6 @@ export const enquirer = enquirerLibrary; import chokidarLibrary from 'chokidar'; export const chokidar = chokidarLibrary; + +import yamlLibrary from 'yaml'; +export const yaml = yamlLibrary; diff --git a/packages/playwright/src/matchers/DEPS.list b/packages/playwright/src/matchers/DEPS.list index 59b704628dfe0..de39c6b5453af 100644 --- a/packages/playwright/src/matchers/DEPS.list +++ b/packages/playwright/src/matchers/DEPS.list @@ -1,4 +1,5 @@ [*] ../common/ ../util.ts +../utilsBundle.ts ../worker/testInfo.ts diff --git a/packages/playwright/src/matchers/expect.ts b/packages/playwright/src/matchers/expect.ts index 16300607d9961..0d276d4101ab0 100644 --- a/packages/playwright/src/matchers/expect.ts +++ b/packages/playwright/src/matchers/expect.ts @@ -62,6 +62,7 @@ import { import { zones } from 'playwright-core/lib/utils'; import { TestInfoImpl } from '../worker/testInfo'; import { ExpectError, isExpectError } from './matcherHint'; +import { toMatchAriaSnapshot } from './toMatchAriaSnapshot'; // #region // Mirrored from https://github.com/facebook/jest/blob/f13abff8df9a0e1148baf3584bcde6d1b479edc7/packages/expect/src/print.ts @@ -236,6 +237,7 @@ const customAsyncMatchers = { toHaveValue, toHaveValues, toHaveScreenshot, + toMatchAriaSnapshot, toPass, }; diff --git a/packages/playwright/src/matchers/matchers.ts b/packages/playwright/src/matchers/matchers.ts index 3ca9180ae26b3..c0319e371f0bc 100644 --- a/packages/playwright/src/matchers/matchers.ts +++ b/packages/playwright/src/matchers/matchers.ts @@ -27,7 +27,7 @@ import { TestInfoImpl } from '../worker/testInfo'; import type { ExpectMatcherState } from '../../types/test'; import { takeFirst } from '../common/config'; -interface LocatorEx extends Locator { +export interface LocatorEx extends Locator { _expect(expression: string, options: Omit & { expectedValue?: any }): Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }>; } diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts new file mode 100644 index 0000000000000..949e44af6fd3d --- /dev/null +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -0,0 +1,134 @@ +/** + * Copyright Microsoft Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import type { LocatorEx } from './matchers'; +import type { ExpectMatcherState } from '../../types/test'; +import { kNoElementsFoundError, matcherHint, type MatcherResult } from './matcherHint'; +import type { AriaTemplateNode } from 'playwright-core/lib/server/injected/ariaSnapshot'; +import { yaml } from '../utilsBundle'; +import { colors } from 'playwright-core/lib/utilsBundle'; +import { EXPECTED_COLOR } from '../common/expectBundle'; +import { callLogText } from '../util'; +import { printReceivedStringContainExpectedSubstring } from './expect'; + +export async function toMatchAriaSnapshot( + this: ExpectMatcherState, + receiver: LocatorEx, + expected: string, + options: { timeout?: number, matchSubstring?: boolean } = {}, +): Promise> { + const matcherName = 'toMatchAriaSnapshot'; + + const matcherOptions = { + isNot: this.isNot, + promise: this.promise, + }; + + if (typeof expected !== 'string') { + throw new Error([ + matcherHint(this, receiver, matcherName, receiver, expected, matcherOptions), + `${colors.bold('Matcher error')}: ${EXPECTED_COLOR('expected',)} value must be a string`, + this.utils.printWithType('Expected', expected, this.utils.printExpected) + ].join('\n\n')); + } + + const ariaTree = toAriaTree(expected) as AriaTemplateNode; + const timeout = options.timeout ?? this.timeout; + const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: ariaTree, isNot: this.isNot, timeout }); + + const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined); + const notFound = received === kNoElementsFoundError; + const message = () => { + if (pass) { + if (notFound) + return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); + const printedReceived = printReceivedStringContainExpectedSubstring(received, received.indexOf(expected), expected.length); + return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived string: ${printedReceived}` + callLogText(log); + } else { + const labelExpected = `Expected`; + if (notFound) + return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); + return messagePrefix + this.utils.printDiffOrStringify(expected, received, labelExpected, 'Received string', false) + callLogText(log); + } + }; + + return { + name: matcherName, + expected, + message, + pass, + actual: received, + log, + timeout: timedOut ? timeout : undefined, + }; +} + +function parseKey(key: string): AriaTemplateNode { + if (!key) + return { role: '' }; + + const match = key.match(/^([a-z]+)(?:\s+(?:"([^"]*)"|\/([^\/]*)\/))?$/); + + if (!match) + throw new Error(`Invalid key ${key}`); + + const role = match[1]; + if (role && role !== 'text' && !allRoles.includes(role)) + throw new Error(`Invalid role ${role}`); + + if (match[2]) + return { role, name: match[2] }; + if (match[3]) + return { role, name: new RegExp(match[3]) }; + return { role }; +} + +function valueOrRegex(value: string): string | RegExp { + return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : value; +} + +type YamlNode = Record | string>; + +function toAriaTree(text: string): AriaTemplateNode { + const convert = (object: YamlNode | string): AriaTemplateNode | RegExp | string => { + const key = typeof object === 'string' ? object : Object.keys(object)[0]; + const value = typeof object === 'string' ? undefined : object[key]; + const parsed = parseKey(key); + if (parsed.role === 'text') { + if (typeof value !== 'string') + throw new Error(`Generic role must have a text value`); + return valueOrRegex(value as string); + } + if (Array.isArray(value)) + parsed.children = value.map(convert); + else if (value) + parsed.children = [valueOrRegex(value)]; + return parsed; + }; + const fragment = yaml.parse(text) as YamlNode[]; + return convert({ '': fragment }) as AriaTemplateNode; +} + +const allRoles = [ + 'alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'command', + 'complementary', 'composite', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', + 'gridcell', 'group', 'heading', 'img', 'input', 'insertion', 'landmark', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'marquee', 'math', 'meter', 'menu', + 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none', 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', + 'range', 'region', 'roletype', 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'section', 'sectionhead', 'select', 'separator', 'slider', + 'spinbutton', 'status', 'strong', 'structure', 'subscript', 'superscript', 'switch', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', + 'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem', 'widget', 'window' +]; diff --git a/packages/playwright/src/utilsBundle.ts b/packages/playwright/src/utilsBundle.ts index 072e16bb037d6..5ded7993b7f70 100644 --- a/packages/playwright/src/utilsBundle.ts +++ b/packages/playwright/src/utilsBundle.ts @@ -20,3 +20,4 @@ export const sourceMapSupport: typeof import('../bundles/utils/node_modules/@typ export const stoppable: typeof import('../bundles/utils/node_modules/@types/stoppable') = require('./utilsBundleImpl').stoppable; export const enquirer: typeof import('../bundles/utils/node_modules/enquirer') = require('./utilsBundleImpl').enquirer; export const chokidar: typeof import('../bundles/utils/node_modules/chokidar') = require('./utilsBundleImpl').chokidar; +export const yaml: typeof import('../bundles/utils/node_modules/yaml') = require('./utilsBundleImpl').yaml; diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index a1128c519ed9d..3f1179e34fa03 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -7638,6 +7638,31 @@ interface LocatorAssertions { timeout?: number; }): Promise; + /** + * Asserts that the target element matches the given accessibility snapshot. + * + * **Usage** + * + * ```js + * import { role as x } from '@playwright/test'; + * // ... + * await page.goto('https://demo.playwright.dev/todomvc/'); + * await expect(page.locator('body')).toMatchAriaSnapshot(` + * - heading "todos" + * - textbox "What needs to be done?" + * `); + * ``` + * + * @param expected + * @param options + */ + toMatchAriaSnapshot(expected: string, options?: { + /** + * Time to retry the assertion for in milliseconds. Defaults to `timeout` in `TestConfig.expect`. + */ + timeout?: number; + }): Promise; + /** * Makes the assertion check for the opposite condition. For example, this code tests that the Locator doesn't contain * text `"error"`: diff --git a/tests/library/inspector/console-api.spec.ts b/tests/library/inspector/console-api.spec.ts index 51d2262bf8fbd..0305f5c5e3222 100644 --- a/tests/library/inspector/console-api.spec.ts +++ b/tests/library/inspector/console-api.spec.ts @@ -107,6 +107,7 @@ it('expected properties on playwright object', async ({ page }) => { 'inspect', 'selector', 'generateLocator', + 'ariaSnapshot', 'resume', 'locator', 'getByTestId', diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts new file mode 100644 index 0000000000000..d1e0d7b91ef07 --- /dev/null +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -0,0 +1,179 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { stripAnsi } from 'tests/config/utils'; +import { test, expect } from './pageTest'; + +test('should match', async ({ page }) => { + await page.setContent(`

title

`); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "title" + `); +}); + +test('should match in list', async ({ page }) => { + await page.setContent(` +

title

+

title 2

+ `); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "title" + `); +}); + +test('should match list with accessible name', async ({ page }) => { + await page.setContent(` +
    +
  • one
  • +
  • two
  • +
+ `); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - list "my list": + - listitem: one + - listitem: two + `); +}); + +test('should match deep item', async ({ page }) => { + await page.setContent(` +
+

title

+

title 2

+
+ `); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "title" + `); +}); + +test('should match complex', async ({ page }) => { + await page.setContent(` + + `); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - list: + - listitem: + - link "link" + `); +}); + +test('should match regex', async ({ page }) => { + await page.setContent(`

Issues 12

`); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading /Issues \\d+/ + `); +}); + +test('should allow text nodes', async ({ page }) => { + await page.setContent(` +

Microsoft

+
Open source projects and samples from Microsoft
+ `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "Microsoft" + - text: Open source projects and samples from Microsoft + `); +}); + +test('integration test', async ({ page, browserName }) => { + test.fixme(browserName === 'webkit'); + await page.setContent(` +

Microsoft

+
Open source projects and samples from Microsoft
+ `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "Microsoft" + - text: Open source projects and samples from Microsoft + - list: + - listitem: + - group: Verified + - listitem: + - link "Sponsor" + `); +}); + +test('integration test 2', async ({ page }) => { + await page.setContent(` +
+
+

todos

+ +
+
`); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "todos" + - textbox "What needs to be done?" + `); +}); + +test('expected formatter', async ({ page }) => { + await page.setContent(` +
+
+

todos

+ +
+
`); + const error = await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading "todos" + - textbox "Wrong text" + `, { timeout: 1 }).catch(e => e); + expect(stripAnsi(error.message)).toContain(`- Expected - 3 ++ Received string + 3 + +- ++ - : ++ - banner: + - heading "todos" +- - textbox "Wrong text" +- ++ - textbox "What needs to be done?"`); +}); diff --git a/utils/doclint/linting-code-snippets/cli.js b/utils/doclint/linting-code-snippets/cli.js index 146646a1f0312..5d3200aa9e383 100644 --- a/utils/doclint/linting-code-snippets/cli.js +++ b/utils/doclint/linting-code-snippets/cli.js @@ -152,6 +152,7 @@ class JSLintingService extends LintingService { 'notice/notice': 'off', '@typescript-eslint/no-unused-vars': 'off', 'max-len': ['error', { code: 100 }], + 'react/react-in-jsx-scope': 'off', }, } }); From 2c05d294a8ea599e3db4f4bc55047e64bb3a2bd0 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 14 Oct 2024 15:55:21 -0700 Subject: [PATCH 306/805] chore: fix webkit visibility check in aria matcher (#33102) --- .../src/server/injected/ariaSnapshot.ts | 8 ++------ tests/page/to-match-aria-snapshot.spec.ts | 14 +++++++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index b573569f8f0b1..8e08ae70160d0 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -16,7 +16,7 @@ import { escapeWithQuotes } from '@isomorphic/stringUtils'; import { beginAriaCaches, endAriaCaches, getAriaRole, getElementAccessibleName, isElementIgnoredForAria } from './roleUtils'; -import { isElementVisible } from './domUtils'; +import { isElementVisible, isElementStyleVisibilityVisible } from './domUtils'; type AriaNode = { role: string; @@ -59,11 +59,7 @@ export function generateAriaTree(rootElement: Element): AriaNode { return; const visible = isElementVisible(element); - const hasVisibleChildren = element.checkVisibility({ - opacityProperty: true, - visibilityProperty: true, - contentVisibilityAuto: true - }); + const hasVisibleChildren = isElementStyleVisibilityVisible(element); if (!hasVisibleChildren) return; diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index d1e0d7b91ef07..826f8cc90e9af 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -94,8 +94,20 @@ test('should allow text nodes', async ({ page }) => { `); }); +test('details visibility', async ({ page, browserName }) => { + await page.setContent(` +
+ Summary +
Details
+
+ `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - group: Summary + `); +}); + test('integration test', async ({ page, browserName }) => { - test.fixme(browserName === 'webkit'); await page.setContent(`

Microsoft

Open source projects and samples from Microsoft
From 8a275e5a5bd6b49d1e7fb8cc330884434375c4ea Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 15 Oct 2024 02:07:03 -0700 Subject: [PATCH 307/805] docs: improve docs for WebSocketRoute (#33097) --- docs/src/api/class-websocketroute.md | 73 ++++++++++++- docs/src/mock.md | 119 ++++++++++++++++++++++ docs/src/network.md | 6 +- packages/playwright-core/types/types.d.ts | 14 ++- 4 files changed, 204 insertions(+), 8 deletions(-) diff --git a/docs/src/api/class-websocketroute.md b/docs/src/api/class-websocketroute.md index f977050481120..b827db25dd6e7 100644 --- a/docs/src/api/class-websocketroute.md +++ b/docs/src/api/class-websocketroute.md @@ -8,7 +8,7 @@ Whenever a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSoc By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over the WebSocket. Here is an example that responds to a `"request"` with a `"response"`. ```js -await page.routeWebSocket('/ws', ws => { +await page.routeWebSocket('wss://example.com/ws', ws => { ws.onMessage(message => { if (message === 'request') ws.send('response'); @@ -17,7 +17,7 @@ await page.routeWebSocket('/ws', ws => { ``` ```java -page.routeWebSocket("/ws", ws -> { +page.routeWebSocket("wss://example.com/ws", ws -> { ws.onMessage(message -> { if ("request".equals(message)) ws.send("response"); @@ -30,7 +30,7 @@ def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): if message == "request": ws.send("response") -await page.route_web_socket("/ws", lambda ws: ws.on_message( +await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( lambda message: message_handler(ws, message) )) ``` @@ -40,13 +40,13 @@ def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): if message == "request": ws.send("response") -page.route_web_socket("/ws", lambda ws: ws.on_message( +page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( lambda message: message_handler(ws, message) )) ``` ```csharp -await page.RouteWebSocketAsync("/ws", ws => { +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { ws.OnMessage(message => { if (message == "request") ws.Send("response"); @@ -56,6 +56,69 @@ await page.RouteWebSocketAsync("/ws", ws => { Since we do not call [`method: WebSocketRoute.connectToServer`] inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically. +Here is another example that handles JSON messages: + +```js +await page.routeWebSocket('wss://example.com/ws', ws => { + ws.onMessage(message => { + const json = JSON.parse(message); + if (json.request === 'question') + ws.send(JSON.stringify({ response: 'answer' })); + }); +}); +``` + +```java +page.routeWebSocket("wss://example.com/ws", ws -> { + ws.onMessage(message -> { + JsonObject json = new JsonParser().parse(message).getAsJsonObject(); + if ("question".equals(json.get("request").getAsString())) { + Map result = new HashMap(); + result.put("response", "answer"); + ws.send(gson.toJson(result)); + } + }); +}); +``` + +```python async +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + json_message = json.loads(message) + if json_message["request"] == "question": + ws.send(json.dumps({ "response": "answer" })) + +await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + +```python sync +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + json_message = json.loads(message) + if json_message["request"] == "question": + ws.send(json.dumps({ "response": "answer" })) + +page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + +```csharp +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { + ws.OnMessage(message => { + using var jsonDoc = JsonDocument.Parse(message); + JsonElement root = jsonDoc.RootElement; + if (root.TryGetProperty("request", out JsonElement requestElement) && requestElement.GetString() == "question") + { + var response = new Dictionary { ["response"] = "answer" }; + string jsonResponse = JsonSerializer.Serialize(response); + ws.Send(jsonResponse); + } + }); +}); +``` + + **Intercepting** Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [`method: WebSocketRoute.connectToServer`] returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages. diff --git a/docs/src/mock.md b/docs/src/mock.md index 5c87e91d5b15e..468690904abe3 100644 --- a/docs/src/mock.md +++ b/docs/src/mock.md @@ -435,3 +435,122 @@ pwsh bin/Debug/netX/playwright.ps1 open --save-har=example.har --save-har-glob=" ``` Read more about [advanced networking](./network.md). + +## Mock WebSockets + +The following code will intercept WebSocket connections and mock entire communcation over the WebSocket, instead of connecting to the server. This example responds to a `"request"` with a `"response"`. + +```js +await page.routeWebSocket('wss://example.com/ws', ws => { + ws.onMessage(message => { + if (message === 'request') + ws.send('response'); + }); +}); +``` + +```java +page.routeWebSocket("wss://example.com/ws", ws -> { + ws.onMessage(message -> { + if ("request".equals(message)) + ws.send("response"); + }); +}); +``` + +```python async +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + ws.send("response") + +await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + +```python sync +def message_handler(ws: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + ws.send("response") + +page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( + lambda message: message_handler(ws, message) +)) +``` + +```csharp +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { + ws.OnMessage(message => { + if (message == "request") + ws.Send("response"); + }); +}); +``` + +Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Here is an example that modifies some of the messages sent by the page to the server, and leaves the rest unmodified. + +```js +await page.routeWebSocket('wss://example.com/ws', ws => { + const server = ws.connectToServer(); + ws.onMessage(message => { + if (message === 'request') + server.send('request2'); + else + server.send(message); + }); +}); +``` + +```java +page.routeWebSocket("wss://example.com/ws", ws -> { + WebSocketRoute server = ws.connectToServer(); + ws.onMessage(message -> { + if ("request".equals(message)) + server.send("request2"); + else + server.send(message); + }); +}); +``` + +```python async +def message_handler(server: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + server.send("request2") + else: + server.send(message) + +def handler(ws: WebSocketRoute): + server = ws.connect_to_server() + ws.on_message(lambda message: message_handler(server, message)) + +await page.route_web_socket("wss://example.com/ws", handler) +``` + +```python sync +def message_handler(server: WebSocketRoute, message: Union[str, bytes]): + if message == "request": + server.send("request2") + else: + server.send(message) + +def handler(ws: WebSocketRoute): + server = ws.connect_to_server() + ws.on_message(lambda message: message_handler(server, message)) + +page.route_web_socket("wss://example.com/ws", handler) +``` + +```csharp +await page.RouteWebSocketAsync("wss://example.com/ws", ws => { + var server = ws.ConnectToServer(); + ws.OnMessage(message => { + if (message == "request") + server.Send("request2"); + else + server.Send(message); + }); +}); +``` + +For more details, see [WebSocketRoute]. diff --git a/docs/src/network.md b/docs/src/network.md index 33c012d9b5d11..97c637a806f2d 100644 --- a/docs/src/network.md +++ b/docs/src/network.md @@ -10,7 +10,7 @@ Playwright provides APIs to **monitor** and **modify** browser network traffic, ## Mock APIs -Check out our [API mocking guide](./mock.md) to learn more on how to +Check out our [API mocking guide](./mock.md) to learn more on how to - mock API requests and never hit the API - perform the API request and modify the response - use HAR files to mock network requests. @@ -723,7 +723,9 @@ Important notes: ## WebSockets -Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection out of the box. Every time a WebSocket is created, the [`event: Page.webSocket`] event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: +Playwright supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) inspection, mocking and modifying out of the box. See our [API mocking guide](./mock.md#mock-websockets) to learn how to mock WebSockets. + +Every time a WebSocket is created, the [`event: Page.webSocket`] event is fired. This event contains the [WebSocket] instance for further web socket frames inspection: ```js page.on('websocket', ws => { diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index abf92c0141aa6..7d1d736a13167 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -15356,7 +15356,7 @@ export interface CDPSession { * the WebSocket. Here is an example that responds to a `"request"` with a `"response"`. * * ```js - * await page.routeWebSocket('/ws', ws => { + * await page.routeWebSocket('wss://example.com/ws', ws => { * ws.onMessage(message => { * if (message === 'request') * ws.send('response'); @@ -15369,6 +15369,18 @@ export interface CDPSession { * inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket * inside the page automatically. * + * Here is another example that handles JSON messages: + * + * ```js + * await page.routeWebSocket('wss://example.com/ws', ws => { + * ws.onMessage(message => { + * const json = JSON.parse(message); + * if (json.request === 'question') + * ws.send(JSON.stringify({ response: 'answer' })); + * }); + * }); + * ``` + * * **Intercepting** * * Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block From 17837e564d1f1b975fcab7893708b6917b7340cf Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 15 Oct 2024 02:08:27 -0700 Subject: [PATCH 308/805] fix(routeWebSocket): make sure ws url without trailing slash is supported (#33095) --- .../src/server/injected/webSocketMock.ts | 1 + tests/library/route-web-socket.spec.ts | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/packages/playwright-core/src/server/injected/webSocketMock.ts b/packages/playwright-core/src/server/injected/webSocketMock.ts index 69d6bc0585994..7a4742bac3085 100644 --- a/packages/playwright-core/src/server/injected/webSocketMock.ts +++ b/packages/playwright-core/src/server/injected/webSocketMock.ts @@ -143,6 +143,7 @@ export function inject(globalThis: GlobalThis) { this.url = typeof url === 'string' ? url : url.href; try { + this.url = new URL(url).href; this._origin = new URL(url).origin; } catch { } diff --git a/tests/library/route-web-socket.spec.ts b/tests/library/route-web-socket.spec.ts index 46a75cdefb339..6af0cb4bc0a0d 100644 --- a/tests/library/route-web-socket.spec.ts +++ b/tests/library/route-web-socket.spec.ts @@ -508,3 +508,27 @@ test('should throw when connecting twice', async ({ page, server }) => { const error = await promise; expect(error.message).toContain('Already connected to the server'); }); + +test('should work with no trailing slash', async ({ page, server }) => { + const log: string[] = []; + // No trailing slash! + await page.routeWebSocket('ws://localhost:' + server.PORT, ws => { + ws.onMessage(message => { + log.push(message as string); + ws.send('response'); + }); + }); + + await page.goto('about:blank'); + await page.evaluate(({ port }) => { + window.log = []; + // No trailing slash! + window.ws = new WebSocket('ws://localhost:' + port); + window.ws.addEventListener('message', event => window.log.push(event.data)); + }, { port: server.PORT }); + + await expect.poll(() => page.evaluate(() => window.ws.readyState)).toBe(1); + await page.evaluate(() => window.ws.send('query')); + await expect.poll(() => log).toEqual(['query']); + expect(await page.evaluate(() => window.log)).toEqual(['response']); +}); From 59a50cf59603850c645830a17ccb05178eb96f50 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 15 Oct 2024 02:13:19 -0700 Subject: [PATCH 309/805] fix(chromium): disable PlzDedicatedWorker again (#33110) --- .../src/server/chromium/chromiumSwitches.ts | 3 ++- tests/page/interception.spec.ts | 1 + tests/page/workers.spec.ts | 14 +++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/src/server/chromium/chromiumSwitches.ts b/packages/playwright-core/src/server/chromium/chromiumSwitches.ts index 01df7a66ace0b..4774c13ed7152 100644 --- a/packages/playwright-core/src/server/chromium/chromiumSwitches.ts +++ b/packages/playwright-core/src/server/chromium/chromiumSwitches.ts @@ -37,7 +37,8 @@ export const chromiumSwitches = [ // PaintHolding - https://github.com/microsoft/playwright/issues/28023 // ThirdPartyStoragePartitioning - https://github.com/microsoft/playwright/issues/32230 // LensOverlay - Hides the Lens feature in the URL address bar. Its not working in unofficial builds. - '--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding,ThirdPartyStoragePartitioning,LensOverlay', + // PlzDedicatedWorker - https://github.com/microsoft/playwright/issues/31747 + '--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades,PaintHolding,ThirdPartyStoragePartitioning,LensOverlay,PlzDedicatedWorker', '--allow-pre-commit-input', '--disable-hang-monitor', '--disable-ipc-flooding-protection', diff --git a/tests/page/interception.spec.ts b/tests/page/interception.spec.ts index 9447a80fcd1ef..eef67e8b37c1f 100644 --- a/tests/page/interception.spec.ts +++ b/tests/page/interception.spec.ts @@ -126,6 +126,7 @@ it('should intercept worker requests when enabled after worker creation', { }, async ({ page, server, isAndroid, browserName, browserMajorVersion }) => { it.skip(isAndroid); it.skip(browserName === 'chromium' && browserMajorVersion < 130, 'fixed in Chromium 130'); + it.fixme(browserName === 'chromium', 'requires PlzDedicatedWorker to be enabled'); await page.goto(server.EMPTY_PAGE); server.setRoute('/data_for_worker', (req, res) => res.end('failed to intercept')); diff --git a/tests/page/workers.spec.ts b/tests/page/workers.spec.ts index 327a2ed45daba..3ca56a686667d 100644 --- a/tests/page/workers.spec.ts +++ b/tests/page/workers.spec.ts @@ -167,7 +167,6 @@ it('should report network activity', async function({ page, server, browserName, it('should report network activity on worker creation', async function({ page, server, browserName, browserMajorVersion }) { it.skip(browserName === 'firefox' && browserMajorVersion < 114, 'https://github.com/microsoft/playwright/issues/21760'); - // Chromium needs waitForDebugger enabled for this one. await page.goto(server.EMPTY_PAGE); const url = server.PREFIX + '/one-style.css'; const requestPromise = page.waitForRequest(url); @@ -182,6 +181,19 @@ it('should report network activity on worker creation', async function({ page, s expect(response.ok()).toBe(true); }); +it('should report worker script as network request', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33107' }, +}, async function({ page, server }) { + await page.goto(server.EMPTY_PAGE); + const [request1, request2] = await Promise.all([ + page.waitForEvent('request', r => r.url().includes('worker.js')), + page.waitForEvent('requestfinished', r => r.url().includes('worker.js')), + page.evaluate(() => (window as any).w = new Worker('/worker/worker.js')), + ]); + expect.soft(request1.url()).toBe(server.PREFIX + '/worker/worker.js'); + expect.soft(request1).toBe(request2); +}); + it('should dispatch console messages when page has workers', async function({ page, server }) { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/15550' }); await page.goto(server.EMPTY_PAGE); From 615f1dbd635f9d5b8217dad9eac16c9651c2fe4c Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Tue, 15 Oct 2024 08:51:57 -0700 Subject: [PATCH 310/805] feat(chromium-tip-of-tree): roll to r1269 (#33117) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 53fedf1923822..a579acc36557a 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -9,9 +9,9 @@ }, { "name": "chromium-tip-of-tree", - "revision": "1268", + "revision": "1269", "installByDefault": false, - "browserVersion": "131.0.6768.0" + "browserVersion": "131.0.6778.0" }, { "name": "firefox", From d40425ea589c7644ffdefa85427b3c726151ef9a Mon Sep 17 00:00:00 2001 From: Anand M Cherian <63868951+Anand-M-Cherian@users.noreply.github.com> Date: Wed, 16 Oct 2024 01:15:03 +0530 Subject: [PATCH 311/805] docs: update to "Matching one of the two alternative locators" section (#33079) Signed-off-by: Anand M Cherian <63868951+Anand-M-Cherian@users.noreply.github.com> Co-authored-by: Dmitry Gozman --- docs/src/locators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/locators.md b/docs/src/locators.md index 0aa918e53c998..648a654177d17 100644 --- a/docs/src/locators.md +++ b/docs/src/locators.md @@ -1218,7 +1218,7 @@ var button = page.GetByRole(AriaRole.Button).And(page.GetByTitle("Subscribe")); ### Matching one of the two alternative locators -If you'd like to target one of the two or more elements, and you don't know which one it will be, use [`method: Locator.or`] to create a locator that matches all of the alternatives. +If you'd like to target one of the two or more elements, and you don't know which one it will be, use [`method: Locator.or`] to create a locator that matches any one or both of the alternatives. For example, consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly. From 23b1012c704ad7d4c479be1bc5144d1ce6986fad Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 15 Oct 2024 13:34:08 -0700 Subject: [PATCH 312/805] chore: fix ff test for codegen (#33122) --- tests/library/inspector/pause.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/library/inspector/pause.spec.ts b/tests/library/inspector/pause.spec.ts index 405fffbe5b0c6..12b7ed940fd7a 100644 --- a/tests/library/inspector/pause.spec.ts +++ b/tests/library/inspector/pause.spec.ts @@ -483,6 +483,7 @@ it.describe('pause', () => { }); it('should record from debugger', async ({ page, recorderPageGetter }) => { + await page.setContent(''); const scriptPromise = (async () => { await page.pause(); })(); From 4b1fbde2adbfc3d9c9160d2b46671eb0c47c506e Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 15 Oct 2024 13:38:55 -0700 Subject: [PATCH 313/805] chore: generate match snapshot (#33105) --- .../src/server/codegen/csharp.ts | 2 + .../src/server/codegen/java.ts | 2 + .../src/server/codegen/javascript.ts | 19 +++++- .../src/server/codegen/python.ts | 2 + .../src/server/injected/ariaSnapshot.ts | 25 ++++---- .../src/server/injected/highlight.css | 5 ++ .../src/server/injected/injectedScript.ts | 6 +- .../src/server/injected/recorder/clipPaths.ts | 2 +- .../server/injected/recorder/icons/gist.svg | 1 + .../src/server/injected/recorder/recorder.ts | 59 ++++++++++++++++--- .../playwright-core/src/server/recorder.ts | 2 +- .../src/utils/isomorphic/recorderUtils.ts | 9 +++ packages/recorder/src/actions.ts | 12 +++- packages/recorder/src/recorder.tsx | 1 + packages/recorder/src/recorderTypes.ts | 3 +- tests/page/to-match-aria-snapshot.spec.ts | 15 +++-- utils/generate_clip_paths.js | 1 + 17 files changed, 132 insertions(+), 34 deletions(-) create mode 100644 packages/playwright-core/src/server/injected/recorder/icons/gist.svg diff --git a/packages/playwright-core/src/server/codegen/csharp.ts b/packages/playwright-core/src/server/codegen/csharp.ts index 8e6561f04ee8e..2e4526d0a2dd3 100644 --- a/packages/playwright-core/src/server/codegen/csharp.ts +++ b/packages/playwright-core/src/server/codegen/csharp.ts @@ -146,6 +146,8 @@ export class CSharpLanguageGenerator implements LanguageGenerator { const assertion = action.value ? `ToHaveValueAsync(${quote(action.value)})` : `ToBeEmptyAsync()`; return `await Expect(${subject}.${this._asLocator(action.selector)}).${assertion};`; } + case 'assertSnapshot': + return `await Expect(${subject}.${this._asLocator(action.selector)}).ToMatchAriaSnapshotAsync(${quote(action.snapshot)});`; } } diff --git a/packages/playwright-core/src/server/codegen/java.ts b/packages/playwright-core/src/server/codegen/java.ts index 5b417c6c3a82d..c6d41e607b384 100644 --- a/packages/playwright-core/src/server/codegen/java.ts +++ b/packages/playwright-core/src/server/codegen/java.ts @@ -133,6 +133,8 @@ export class JavaLanguageGenerator implements LanguageGenerator { const assertion = action.value ? `hasValue(${quote(action.value)})` : `isEmpty()`; return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).${assertion};`; } + case 'assertSnapshot': + return `assertThat(${subject}.${this._asLocator(action.selector, inFrameLocator)}).matchesAriaSnapshot(${quote(action.snapshot)});`; } } diff --git a/packages/playwright-core/src/server/codegen/javascript.ts b/packages/playwright-core/src/server/codegen/javascript.ts index b68a8104a86e2..c0e62d9df3020 100644 --- a/packages/playwright-core/src/server/codegen/javascript.ts +++ b/packages/playwright-core/src/server/codegen/javascript.ts @@ -117,6 +117,8 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator { const assertion = action.value ? `toHaveValue(${quote(action.value)})` : `toBeEmpty()`; return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).${assertion};`; } + case 'assertSnapshot': + return `${this._isTest ? '' : '// '}await expect(${subject}.${this._asLocator(action.selector)}).toMatchAriaSnapshot(${quoteMultiline(action.snapshot)});`; } } @@ -228,11 +230,13 @@ export class JavaScriptFormatter { } prepend(text: string) { - this._lines = text.trim().split('\n').map(line => line.trim()).concat(this._lines); + const trim = isMultilineString(text) ? (line: string) => line : (line: string) => line.trim(); + this._lines = text.trim().split('\n').map(trim).concat(this._lines); } add(text: string) { - this._lines.push(...text.trim().split('\n').map(line => line.trim())); + const trim = isMultilineString(text) ? (line: string) => line : (line: string) => line.trim(); + this._lines.push(...text.trim().split('\n').map(trim)); } newLine() { @@ -269,3 +273,14 @@ function wrapWithStep(description: string | undefined, body: string) { ${body} });` : body; } + +export function quoteMultiline(text: string, indent = ' ') { + const lines = text.split('\n'); + if (lines.length === 1) + return '`' + text.replace(/`/g, '\\`').replace(/\${/g, '\\${') + '`'; + return '`\n' + lines.map(line => indent + line.replace(/`/g, '\\`').replace(/\${/g, '\\${')).join('\n') + `\n${indent}\``; +} + +function isMultilineString(text: string) { + return text.match(/`[\S\s]*`/)?.[0].includes('\n'); +} diff --git a/packages/playwright-core/src/server/codegen/python.ts b/packages/playwright-core/src/server/codegen/python.ts index 38894695bcf49..50afe1b1a5225 100644 --- a/packages/playwright-core/src/server/codegen/python.ts +++ b/packages/playwright-core/src/server/codegen/python.ts @@ -126,6 +126,8 @@ export class PythonLanguageGenerator implements LanguageGenerator { const assertion = action.value ? `to_have_value(${quote(action.value)})` : `to_be_empty()`; return `expect(${subject}.${this._asLocator(action.selector)}).${assertion};`; } + case 'assertSnapshot': + return `expect(${subject}.${this._asLocator(action.selector)}).to_match_aria_snapshot(${quote(action.snapshot)})`; } } diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 8e08ae70160d0..22ec9b5c42273 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -90,8 +90,7 @@ export function generateAriaTree(rootElement: Element): AriaNode { } beginAriaCaches(); - const result = toAriaNode(rootElement); - const ariaRoot = result?.ariaNode || { role: '' }; + const ariaRoot: AriaNode = { role: '' }; try { visit(ariaRoot, rootElement); } finally { @@ -218,7 +217,11 @@ function nodeMatches(root: AriaNode, template: AriaTemplateNode): boolean { export function renderAriaTree(ariaNode: AriaNode): string { const lines: string[] = []; - const visit = (ariaNode: AriaNode, indent: string) => { + const visit = (ariaNode: AriaNode | string, indent: string) => { + if (typeof ariaNode === 'string') { + lines.push(indent + '- text: ' + escapeYamlString(ariaNode)); + return; + } let line = `${indent}- ${ariaNode.role}`; if (ariaNode.name) line += ` ${escapeWithQuotes(ariaNode.name, '"')}`; @@ -231,14 +234,16 @@ export function renderAriaTree(ariaNode: AriaNode): string { return; } lines.push(line + (ariaNode.children ? ':' : '')); - for (const child of ariaNode.children || []) { - if (typeof child === 'string') - lines.push(indent + ' - text: ' + escapeYamlString(child)); - else - visit(child, indent + ' '); - } + for (const child of ariaNode.children || []) + visit(child, indent + ' '); }; - visit(ariaNode, ''); + if (ariaNode.role === '') { + // Render fragment. + for (const child of ariaNode.children || []) + visit(child, ''); + } else { + visit(ariaNode, ''); + } return lines.join('\n'); } diff --git a/packages/playwright-core/src/server/injected/highlight.css b/packages/playwright-core/src/server/injected/highlight.css index 83123011bc5b8..096f9311611c4 100644 --- a/packages/playwright-core/src/server/injected/highlight.css +++ b/packages/playwright-core/src/server/injected/highlight.css @@ -220,6 +220,11 @@ x-pw-tool-item.value > x-div { clip-path: url(#icon-symbol-constant); } +x-pw-tool-item.snapshot > x-div { + /* codicon: eye */ + clip-path: url(#icon-gist); +} + x-pw-tool-item.accept > x-div { clip-path: url(#icon-check); } diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 0f3308fe7c7f9..66a18848db964 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -34,7 +34,7 @@ import { kLayoutSelectorNames, type LayoutSelectorName, layoutSelectorScore } fr import { asLocator } from '../../utils/isomorphic/locatorGenerators'; import type { Language } from '../../utils/isomorphic/locatorGenerators'; import { cacheNormalizedWhitespaces, normalizeWhiteSpace, trimStringWithEllipsis } from '../../utils/isomorphic/stringUtils'; -import { matchesAriaTree } from './ariaSnapshot'; +import { matchesAriaTree, renderedAriaTree } from './ariaSnapshot'; export type FrameExpectParams = Omit & { expectedValue?: any }; @@ -206,6 +206,10 @@ export class InjectedScript { return new Set(result.map(r => r.element)); } + renderedAriaTree(target: Element): string { + return renderedAriaTree(target); + } + querySelectorAll(selector: ParsedSelector, root: Node): Element[] { if (selector.capture !== undefined) { if (selector.parts.some(part => part.name === 'nth')) diff --git a/packages/playwright-core/src/server/injected/recorder/clipPaths.ts b/packages/playwright-core/src/server/injected/recorder/clipPaths.ts index faa77a63d6779..a1e016542a8fc 100644 --- a/packages/playwright-core/src/server/injected/recorder/clipPaths.ts +++ b/packages/playwright-core/src/server/injected/recorder/clipPaths.ts @@ -27,5 +27,5 @@ import type { SvgJson } from './recorder'; // eslint-disable-next-line key-spacing, object-curly-spacing, comma-spacing, quotes -const svgJson: SvgJson = {"tagName":"svg","children":[{"tagName":"defs","children":[{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-gripper"},"children":[{"tagName":"path","attrs":{"d":"M5 3h2v2H5zm0 4h2v2H5zm0 4h2v2H5zm4-8h2v2H9zm0 4h2v2H9zm0 4h2v2H9z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-circle-large-filled"},"children":[{"tagName":"path","attrs":{"d":"M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-inspect"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-whole-word"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M0 11H1V13H15V11H16V14H15H1H0V11Z"}},{"tagName":"path","attrs":{"d":"M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z"}},{"tagName":"path","attrs":{"d":"M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-eye"},"children":[{"tagName":"path","attrs":{"d":"M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-symbol-constant"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M4 6h8v1H4V6zm8 3H4v1h8V9z"}},{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-check"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M14.431 3.323l-8.47 10-.79-.036-3.35-4.77.818-.574 2.978 4.24 8.051-9.506.764.646z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-close"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M8 8.707l3.646 3.647.708-.707L8.707 8l3.647-3.646-.707-.708L8 7.293 4.354 3.646l-.707.708L7.293 8l-3.646 3.646.707.708L8 8.707z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-pass"},"children":[{"tagName":"path","attrs":{"d":"M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z"}},{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z"}}]}]}]}; +const svgJson: SvgJson = {"tagName":"svg","children":[{"tagName":"defs","children":[{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-gripper"},"children":[{"tagName":"path","attrs":{"d":"M5 3h2v2H5zm0 4h2v2H5zm0 4h2v2H5zm4-8h2v2H9zm0 4h2v2H9zm0 4h2v2H9z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-circle-large-filled"},"children":[{"tagName":"path","attrs":{"d":"M8 1a6.8 6.8 0 0 1 1.86.253 6.899 6.899 0 0 1 3.083 1.805 6.903 6.903 0 0 1 1.804 3.083C14.916 6.738 15 7.357 15 8s-.084 1.262-.253 1.86a6.9 6.9 0 0 1-.704 1.674 7.157 7.157 0 0 1-2.516 2.509 6.966 6.966 0 0 1-1.668.71A6.984 6.984 0 0 1 8 15a6.984 6.984 0 0 1-1.86-.246 7.098 7.098 0 0 1-1.674-.711 7.3 7.3 0 0 1-1.415-1.094 7.295 7.295 0 0 1-1.094-1.415 7.098 7.098 0 0 1-.71-1.675A6.985 6.985 0 0 1 1 8c0-.643.082-1.262.246-1.86a6.968 6.968 0 0 1 .711-1.667 7.156 7.156 0 0 1 2.509-2.516 6.895 6.895 0 0 1 1.675-.704A6.808 6.808 0 0 1 8 1z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-inspect"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M1 3l1-1h12l1 1v6h-1V3H2v8h5v1H2l-1-1V3zm14.707 9.707L9 6v9.414l2.707-2.707h4zM10 13V8.414l3.293 3.293h-2L10 13z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-whole-word"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M0 11H1V13H15V11H16V14H15H1H0V11Z"}},{"tagName":"path","attrs":{"d":"M6.84048 11H5.95963V10.1406H5.93814C5.555 10.7995 4.99104 11.1289 4.24625 11.1289C3.69839 11.1289 3.26871 10.9839 2.95718 10.6938C2.64924 10.4038 2.49527 10.0189 2.49527 9.53906C2.49527 8.51139 3.10041 7.91341 4.3107 7.74512L5.95963 7.51416C5.95963 6.57959 5.58186 6.1123 4.82632 6.1123C4.16389 6.1123 3.56591 6.33789 3.03238 6.78906V5.88672C3.57307 5.54297 4.19612 5.37109 4.90152 5.37109C6.19416 5.37109 6.84048 6.05501 6.84048 7.42285V11ZM5.95963 8.21777L4.63297 8.40039C4.22476 8.45768 3.91682 8.55973 3.70914 8.70654C3.50145 8.84977 3.39761 9.10579 3.39761 9.47461C3.39761 9.74316 3.4925 9.96338 3.68228 10.1353C3.87564 10.3035 4.13166 10.3877 4.45035 10.3877C4.8872 10.3877 5.24706 10.2355 5.52994 9.93115C5.8164 9.62321 5.95963 9.2347 5.95963 8.76562V8.21777Z"}},{"tagName":"path","attrs":{"d":"M9.3475 10.2051H9.32601V11H8.44515V2.85742H9.32601V6.4668H9.3475C9.78076 5.73633 10.4146 5.37109 11.2489 5.37109C11.9543 5.37109 12.5057 5.61816 12.9032 6.1123C13.3042 6.60286 13.5047 7.26172 13.5047 8.08887C13.5047 9.00911 13.2809 9.74674 12.8333 10.3018C12.3857 10.8532 11.7734 11.1289 10.9964 11.1289C10.2695 11.1289 9.71989 10.821 9.3475 10.2051ZM9.32601 7.98682V8.75488C9.32601 9.20964 9.47282 9.59635 9.76644 9.91504C10.0636 10.2301 10.4396 10.3877 10.8944 10.3877C11.4279 10.3877 11.8451 10.1836 12.1458 9.77539C12.4502 9.36719 12.6024 8.79964 12.6024 8.07275C12.6024 7.46045 12.4609 6.98063 12.1781 6.6333C11.8952 6.28597 11.512 6.1123 11.0286 6.1123C10.5166 6.1123 10.1048 6.29134 9.7933 6.64941C9.48177 7.00391 9.32601 7.44971 9.32601 7.98682Z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-eye"},"children":[{"tagName":"path","attrs":{"d":"M7.99993 6.00316C9.47266 6.00316 10.6666 7.19708 10.6666 8.66981C10.6666 10.1426 9.47266 11.3365 7.99993 11.3365C6.52715 11.3365 5.33324 10.1426 5.33324 8.66981C5.33324 7.19708 6.52715 6.00316 7.99993 6.00316ZM7.99993 7.00315C7.07946 7.00315 6.33324 7.74935 6.33324 8.66981C6.33324 9.59028 7.07946 10.3365 7.99993 10.3365C8.9204 10.3365 9.6666 9.59028 9.6666 8.66981C9.6666 7.74935 8.9204 7.00315 7.99993 7.00315ZM7.99993 3.66675C11.0756 3.66675 13.7307 5.76675 14.4673 8.70968C14.5344 8.97755 14.3716 9.24908 14.1037 9.31615C13.8358 9.38315 13.5643 9.22041 13.4973 8.95248C12.8713 6.45205 10.6141 4.66675 7.99993 4.66675C5.38454 4.66675 3.12664 6.45359 2.50182 8.95555C2.43491 9.22341 2.16348 9.38635 1.89557 9.31948C1.62766 9.25255 1.46471 8.98115 1.53162 8.71321C2.26701 5.76856 4.9229 3.66675 7.99993 3.66675Z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-symbol-constant"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M4 6h8v1H4V6zm8 3H4v1h8V9z"}},{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M1 4l1-1h12l1 1v8l-1 1H2l-1-1V4zm1 0v8h12V4H2z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-check"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M14.431 3.323l-8.47 10-.79-.036-3.35-4.77.818-.574 2.978 4.24 8.051-9.506.764.646z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-close"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M8 8.707l3.646 3.647.708-.707L8.707 8l3.647-3.646-.707-.708L8 7.293 4.354 3.646l-.707.708L7.293 8l-3.646 3.646.707.708L8 8.707z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-pass"},"children":[{"tagName":"path","attrs":{"d":"M6.27 10.87h.71l4.56-4.56-.71-.71-4.2 4.21-1.92-1.92L4 8.6l2.27 2.27z"}},{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M8.6 1c1.6.1 3.1.9 4.2 2 1.3 1.4 2 3.1 2 5.1 0 1.6-.6 3.1-1.6 4.4-1 1.2-2.4 2.1-4 2.4-1.6.3-3.2.1-4.6-.7-1.4-.8-2.5-2-3.1-3.5C.9 9.2.8 7.5 1.3 6c.5-1.6 1.4-2.9 2.8-3.8C5.4 1.3 7 .9 8.6 1zm.5 12.9c1.3-.3 2.5-1 3.4-2.1.8-1.1 1.3-2.4 1.2-3.8 0-1.6-.6-3.2-1.7-4.3-1-1-2.2-1.6-3.6-1.7-1.3-.1-2.7.2-3.8 1-1.1.8-1.9 1.9-2.3 3.3-.4 1.3-.4 2.7.2 4 .6 1.3 1.5 2.3 2.7 3 1.2.7 2.6.9 3.9.6z"}}]},{"tagName":"clipPath","attrs":{"width":"16","height":"16","viewBox":"0 0 16 16","fill":"currentColor","id":"icon-gist"},"children":[{"tagName":"path","attrs":{"fill-rule":"evenodd","clip-rule":"evenodd","d":"M10.57 1.14l3.28 3.3.15.36v9.7l-.5.5h-11l-.5-.5v-13l.5-.5h7.72l.35.14zM10 5h3l-3-3v3zM3 2v12h10V6H9.5L9 5.5V2H3zm2.062 7.533l1.817-1.828L6.17 7 4 9.179v.707l2.171 2.174.707-.707-1.816-1.82zM8.8 7.714l.7-.709 2.189 2.175v.709L9.5 12.062l-.705-.709 1.831-1.82L8.8 7.714z"}}]}]}]}; export default svgJson; \ No newline at end of file diff --git a/packages/playwright-core/src/server/injected/recorder/icons/gist.svg b/packages/playwright-core/src/server/injected/recorder/icons/gist.svg new file mode 100644 index 0000000000000..f6d50e43d4f1b --- /dev/null +++ b/packages/playwright-core/src/server/injected/recorder/icons/gist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index cdc29a105063e..d620ca273cd1a 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -608,9 +608,9 @@ class TextAssertionTool implements RecorderTool { private _action: actions.AssertAction | null = null; private _dialog: Dialog; private _textCache = new Map(); - private _kind: 'text' | 'value'; + private _kind: 'text' | 'value' | 'snapshot'; - constructor(recorder: Recorder, kind: 'text' | 'value') { + constructor(recorder: Recorder, kind: 'text' | 'value' | 'snapshot') { this._recorder = recorder; this._kind = kind; this._dialog = new Dialog(recorder); @@ -656,7 +656,7 @@ class TextAssertionTool implements RecorderTool { const target = this._recorder.deepEventTarget(event); if (this._hoverHighlight?.elements[0] === target) return; - if (this._kind === 'text') + if (this._kind === 'text' || this._kind === 'snapshot') this._hoverHighlight = this._recorder.injectedScript.utils.elementText(this._textCache, target).full ? { elements: [target], selector: '' } : null; else this._hoverHighlight = this._elementHasValue(target) ? this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName }) : null; @@ -704,6 +704,18 @@ class TextAssertionTool implements RecorderTool { value: (target as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)).value, }; } + } if (this._kind === 'snapshot') { + this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true }); + this._hoverHighlight.color = '#8acae480'; + // forTextExpect can update the target, re-highlight it. + this._recorder.updateHighlight(this._hoverHighlight, true); + + return { + name: 'assertSnapshot', + selector: this._hoverHighlight.selector, + signals: [], + snapshot: this._recorder.injectedScript.renderedAriaTree(target), + }; } else { this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true }); this._hoverHighlight.color = '#8acae480'; @@ -727,6 +739,8 @@ class TextAssertionTool implements RecorderTool { return String(action.checked); if (action?.name === 'assertValue') return action.value; + if (action?.name === 'assertSnapshot') + return action.snapshot; return ''; } @@ -742,13 +756,19 @@ class TextAssertionTool implements RecorderTool { if (!this._hoverHighlight?.elements[0]) return; this._action = this._generateAction(); - if (!this._action || this._action.name !== 'assertText') - return; + if (this._action?.name === 'assertText') { + this._showTextDialog(this._action); + } else if (this._action?.name === 'assertSnapshot') { + this._recorder.recordAction(this._action); + this._recorder.setMode('recording'); + this._recorder.overlay?.flashToolSucceeded('assertingSnapshot'); + } + } - const action = this._action; + private _showTextDialog(action: actions.AssertTextAction) { const textElement = this._recorder.document.createElement('textarea'); textElement.setAttribute('spellcheck', 'false'); - textElement.value = this._renderValue(this._action); + textElement.value = this._renderValue(action); textElement.classList.add('text-editor'); const updateAndValidate = () => { @@ -796,6 +816,7 @@ class Overlay { private _assertVisibilityToggle: HTMLElement; private _assertTextToggle: HTMLElement; private _assertValuesToggle: HTMLElement; + private _assertSnapshotToggle: HTMLElement; private _offsetX = 0; private _dragState: { offsetX: number, dragStart: { x: number, y: number } } | undefined; private _measure: { width: number, height: number } = { width: 0, height: 0 }; @@ -842,6 +863,12 @@ class Overlay { this._assertValuesToggle.appendChild(this._recorder.document.createElement('x-div')); toolsListElement.appendChild(this._assertValuesToggle); + this._assertSnapshotToggle = this._recorder.document.createElement('x-pw-tool-item'); + this._assertSnapshotToggle.title = 'Assert snapshot'; + this._assertSnapshotToggle.classList.add('snapshot'); + this._assertSnapshotToggle.appendChild(this._recorder.document.createElement('x-div')); + toolsListElement.appendChild(this._assertSnapshotToggle); + this._updateVisualPosition(); this._refreshListeners(); } @@ -865,6 +892,7 @@ class Overlay { 'assertingText': 'recording-inspecting', 'assertingVisibility': 'recording-inspecting', 'assertingValue': 'recording-inspecting', + 'assertingSnapshot': 'recording-inspecting', }; this._recorder.setMode(newMode[this._recorder.state.mode]); }), @@ -880,6 +908,10 @@ class Overlay { if (!this._assertValuesToggle.classList.contains('disabled')) this._recorder.setMode(this._recorder.state.mode === 'assertingValue' ? 'recording' : 'assertingValue'); }), + addEventListener(this._assertSnapshotToggle, 'click', () => { + if (!this._assertSnapshotToggle.classList.contains('disabled')) + this._recorder.setMode(this._recorder.state.mode === 'assertingSnapshot' ? 'recording' : 'assertingSnapshot'); + }), ]; } @@ -902,6 +934,8 @@ class Overlay { this._assertTextToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); this._assertValuesToggle.classList.toggle('active', state.mode === 'assertingValue'); this._assertValuesToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); + this._assertSnapshotToggle.classList.toggle('active', state.mode === 'assertingSnapshot'); + this._assertSnapshotToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); if (this._offsetX !== state.overlay.offsetX) { this._offsetX = state.overlay.offsetX; this._updateVisualPosition(); @@ -912,8 +946,14 @@ class Overlay { this._showOverlay(); } - flashToolSucceeded(tool: 'assertingVisibility' | 'assertingValue') { - const element = tool === 'assertingVisibility' ? this._assertVisibilityToggle : this._assertValuesToggle; + flashToolSucceeded(tool: 'assertingVisibility' | 'assertingSnapshot' | 'assertingValue') { + let element: Element; + if (tool === 'assertingVisibility') + element = this._assertVisibilityToggle; + else if (tool === 'assertingSnapshot') + element = this._assertSnapshotToggle; + else + element = this._assertValuesToggle; element.classList.add('succeeded'); this._recorder.injectedScript.builtinSetTimeout(() => element.classList.remove('succeeded'), 2000); } @@ -1004,6 +1044,7 @@ export class Recorder { 'assertingText': new TextAssertionTool(this, 'text'), 'assertingVisibility': new InspectTool(this, true), 'assertingValue': new TextAssertionTool(this, 'value'), + 'assertingSnapshot': new TextAssertionTool(this, 'snapshot'), }; this._currentTool = this._tools.none; if (injectedScript.window.top === injectedScript.window) { diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 386e4dece6f1d..c5e133c06908a 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -216,7 +216,7 @@ export class Recorder implements InstrumentationListener, IRecorder { this._highlightedSelector = ''; this._mode = mode; this._recorderApp?.setMode(this._mode); - this._contextRecorder.setEnabled(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue'); + this._contextRecorder.setEnabled(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue' || this._mode === 'assertingSnapshot'); this._debugger.setMuted(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue'); if (this._mode !== 'none' && this._mode !== 'standby' && this._context.pages().length === 1) this._context.pages()[0].bringToFront().catch(() => {}); diff --git a/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts b/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts index 40ce3acd44c47..349afe95a56fd 100644 --- a/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts +++ b/packages/playwright-core/src/utils/isomorphic/recorderUtils.ts @@ -130,6 +130,15 @@ export function traceParamsForAction(actionInContext: recorderActions.ActionInCo }; return { method: 'expect', params }; } + case 'assertSnapshot': { + const params: channels.FrameExpectParams = { + selector, + expression: 'to.match.snapshot', + expectedText: [], + isNot: false, + }; + return { method: 'expect', params }; + } } } diff --git a/packages/recorder/src/actions.ts b/packages/recorder/src/actions.ts index a17e0c172bad3..d4c74b26562ab 100644 --- a/packages/recorder/src/actions.ts +++ b/packages/recorder/src/actions.ts @@ -30,7 +30,8 @@ export type ActionName = 'assertText' | 'assertValue' | 'assertChecked' | - 'assertVisible'; + 'assertVisible' | + 'assertSnapshot'; export type ActionBase = { name: ActionName, @@ -113,8 +114,13 @@ export type AssertVisibleAction = ActionWithSelector & { name: 'assertVisible', }; -export type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageAction | UncheckAction | FillAction | NavigateAction | PressAction | SelectAction | SetInputFilesAction | AssertTextAction | AssertValueAction | AssertCheckedAction | AssertVisibleAction; -export type AssertAction = AssertCheckedAction | AssertValueAction | AssertTextAction | AssertVisibleAction; +export type AssertSnapshotAction = ActionWithSelector & { + name: 'assertSnapshot', + snapshot: string, +}; + +export type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageAction | UncheckAction | FillAction | NavigateAction | PressAction | SelectAction | SetInputFilesAction | AssertTextAction | AssertValueAction | AssertCheckedAction | AssertVisibleAction | AssertSnapshotAction; +export type AssertAction = AssertCheckedAction | AssertValueAction | AssertTextAction | AssertVisibleAction | AssertSnapshotAction; export type PerformOnRecordAction = ClickAction | CheckAction | UncheckAction | PressAction | SelectAction; // Signals. diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx index 19b7bc12a70ad..a8cd2b271987a 100644 --- a/packages/recorder/src/recorder.tsx +++ b/packages/recorder/src/recorder.tsx @@ -116,6 +116,7 @@ export const Recorder: React.FC = ({ 'assertingText': 'recording-inspecting', 'assertingVisibility': 'recording-inspecting', 'assertingValue': 'recording-inspecting', + 'assertingSnapshot': 'recording-inspecting', }[mode]; window.dispatch({ event: 'setMode', params: { mode: newMode } }).catch(() => { }); }}>
diff --git a/packages/recorder/src/recorderTypes.ts b/packages/recorder/src/recorderTypes.ts index dd379f7ccd7ee..a0e04a72836fd 100644 --- a/packages/recorder/src/recorderTypes.ts +++ b/packages/recorder/src/recorderTypes.ts @@ -26,7 +26,8 @@ export type Mode = | 'recording-inspecting' | 'standby' | 'assertingVisibility' - | 'assertingValue'; + | 'assertingValue' + | 'assertingSnapshot'; export type EventData = { event: diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index 826f8cc90e9af..5e58ba94e0ebe 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -78,7 +78,7 @@ test('should match complex', async ({ page }) => { test('should match regex', async ({ page }) => { await page.setContent(`

Issues 12

`); await expect(page.locator('body')).toMatchAriaSnapshot(` - - heading /Issues \\d+/ + - heading ${/Issues \d+/} `); }); @@ -178,14 +178,17 @@ test('expected formatter', async ({ page }) => { - heading "todos" - textbox "Wrong text" `, { timeout: 1 }).catch(e => e); - expect(stripAnsi(error.message)).toContain(`- Expected - 3 + + expect(stripAnsi(error.message)).toContain(` +Locator: locator('body') +- Expected - 4 + Received string + 3 - -+ - : -+ - banner: - - heading "todos" ++ - banner: +- - heading "todos" ++ - heading "todos" - - textbox "Wrong text" - -+ - textbox "What needs to be done?"`); ++ - textbox "What needs to be done?"`); }); diff --git a/utils/generate_clip_paths.js b/utils/generate_clip_paths.js index cbef6ece9d027..83d26a905c7f1 100644 --- a/utils/generate_clip_paths.js +++ b/utils/generate_clip_paths.js @@ -64,6 +64,7 @@ const iconNames = [ 'check', 'close', 'pass', + 'gist', ]; (async () => { From b421bd8b0da0477c13684597e18c811dcfc71519 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 15 Oct 2024 15:21:45 -0700 Subject: [PATCH 314/805] chore: add a basic snapshot generator test (#33123) --- docs/src/api/class-locatorassertions.md | 39 ++++++++-- .../playwright-core/ThirdPartyNotices.txt | 21 +++++- .../bundles/utils/package-lock.json | 19 ++++- .../bundles/utils/package.json | 1 + .../bundles/utils/src/utilsBundleImpl.ts | 3 + .../src/server/ariaSnapshot.ts | 74 +++++++++++++++++++ .../src/server/dispatchers/frameDispatcher.ts | 5 +- .../src/server/injected/recorder/recorder.ts | 2 +- packages/playwright-core/src/utilsBundle.ts | 1 + packages/playwright/ThirdPartyNotices.txt | 21 +----- .../bundles/utils/package-lock.json | 19 +---- .../playwright/bundles/utils/package.json | 3 +- .../bundles/utils/src/utilsBundleImpl.ts | 3 - .../src/matchers/toMatchAriaSnapshot.ts | 61 +-------------- packages/playwright/src/utilsBundle.ts | 1 - packages/playwright/types/test.d.ts | 2 - .../inspector/cli-codegen-aria.spec.ts | 42 +++++++++++ tests/library/inspector/inspectorTest.ts | 9 +++ 18 files changed, 211 insertions(+), 115 deletions(-) create mode 100644 packages/playwright-core/src/server/ariaSnapshot.ts create mode 100644 tests/library/inspector/cli-codegen-aria.spec.ts diff --git a/docs/src/api/class-locatorassertions.md b/docs/src/api/class-locatorassertions.md index 46f8f610e0f87..b48b3fce7ed3b 100644 --- a/docs/src/api/class-locatorassertions.md +++ b/docs/src/api/class-locatorassertions.md @@ -2106,15 +2106,14 @@ Expected options currently selected. ## async method: LocatorAssertions.toMatchAriaSnapshot * since: v1.49 -* langs: js +* langs: + - alias-java: matchesAriaSnapshot Asserts that the target element matches the given accessibility snapshot. **Usage** ```js -import { role as x } from '@playwright/test'; -// ... await page.goto('https://demo.playwright.dev/todomvc/'); await expect(page.locator('body')).toMatchAriaSnapshot(` - heading "todos" @@ -2122,11 +2121,41 @@ await expect(page.locator('body')).toMatchAriaSnapshot(` `); ``` +```python async +await page.goto('https://demo.playwright.dev/todomvc/') +await expect(page.locator('body')).to_match_aria_snapshot(''' + - heading "todos" + - textbox "What needs to be done?" +''') +``` + +```python sync +page.goto('https://demo.playwright.dev/todomvc/') +expect(page.locator('body')).to_match_aria_snapshot(''' + - heading "todos" + - textbox "What needs to be done?" +''') +``` + +```csharp +await page.GotoAsync("https://demo.playwright.dev/todomvc/"); +await Expect(page.Locator("body")).ToMatchAriaSnapshotAsync(@" + - heading ""todos"" + - textbox ""What needs to be done?"" +"); +``` + +```java +page.navigate("https://demo.playwright.dev/todomvc/"); +assertThat(page.locator("body")).matchesAriaSnapshot(""" + - heading "todos" + - textbox "What needs to be done?" +"""); +``` + ### param: LocatorAssertions.toMatchAriaSnapshot.expected * since: v1.49 -* langs: js - `expected` ### option: LocatorAssertions.toMatchAriaSnapshot.timeout = %%-js-assertions-timeout-%% * since: v1.49 -* langs: js diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index a5d4ca7d0b7dc..23e3cff257ceb 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -48,6 +48,7 @@ This project incorporates components from the projects listed below. The origina - stack-utils@2.0.5 (https://github.com/tapjs/stack-utils) - wrappy@1.0.2 (https://github.com/npm/wrappy) - ws@8.17.1 (https://github.com/websockets/ws) +- yaml@2.6.0 (https://github.com/eemeli/yaml) - yauzl@2.10.0 (https://github.com/thejoshwolfe/yauzl) - yazl@2.5.1 (https://github.com/thejoshwolfe/yazl) @@ -1121,6 +1122,24 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= END OF ws@8.17.1 AND INFORMATION +%% yaml@2.6.0 NOTICES AND INFORMATION BEGIN HERE +========================================= +Copyright Eemeli Aro + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +========================================= +END OF yaml@2.6.0 AND INFORMATION + %% yauzl@2.10.0 NOTICES AND INFORMATION BEGIN HERE ========================================= The MIT License (MIT) @@ -1175,6 +1194,6 @@ END OF yazl@2.5.1 AND INFORMATION SUMMARY BEGIN HERE ========================================= -Total Packages: 46 +Total Packages: 47 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index 0e5e761433bf0..f786cb4db7bd5 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -25,7 +25,8 @@ "signal-exit": "3.0.7", "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", - "ws": "8.17.1" + "ws": "8.17.1", + "yaml": "^2.5.1" }, "devDependencies": { "@types/debug": "^4.1.7", @@ -432,6 +433,17 @@ "optional": true } } + }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } } }, "dependencies": { @@ -726,6 +738,11 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "requires": {} + }, + "yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==" } } } diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index 06637adabee9a..005e32fbe6a62 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -26,6 +26,7 @@ "signal-exit": "3.0.7", "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", + "yaml": "^2.5.1", "ws": "8.17.1" }, "devDependencies": { diff --git a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts index dcb37906290f0..975e291bb5dbc 100644 --- a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts @@ -54,6 +54,9 @@ export { SocksProxyAgent } from 'socks-proxy-agent'; import StackUtilsLibrary from 'stack-utils'; export const StackUtils = StackUtilsLibrary; +import yamlLibrary from 'yaml'; +export const yaml = yamlLibrary; + // @ts-ignore import wsLibrary, { WebSocketServer, Receiver, Sender } from 'ws'; export const ws = wsLibrary; diff --git a/packages/playwright-core/src/server/ariaSnapshot.ts b/packages/playwright-core/src/server/ariaSnapshot.ts new file mode 100644 index 0000000000000..6f89dd21cfc80 --- /dev/null +++ b/packages/playwright-core/src/server/ariaSnapshot.ts @@ -0,0 +1,74 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { AriaTemplateNode } from './injected/ariaSnapshot'; +import { yaml } from '../utilsBundle'; + +export function parseAriaSnapshot(text: string): AriaTemplateNode { + type YamlNode = Record | string>; + + const parseKey = (key: string): AriaTemplateNode => { + if (!key) + return { role: '' }; + + const match = key.match(/^([a-z]+)(?:\s+(?:"([^"]*)"|\/([^\/]*)\/))?$/); + + if (!match) + throw new Error(`Invalid key ${key}`); + + const role = match[1]; + if (role && role !== 'text' && !allRoles.includes(role)) + throw new Error(`Invalid role ${role}`); + + if (match[2]) + return { role, name: match[2] }; + if (match[3]) + return { role, name: new RegExp(match[3]) }; + return { role }; + }; + + const valueOrRegex = (value: string): string | RegExp => { + return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : value; + }; + + const convert = (object: YamlNode | string): AriaTemplateNode | RegExp | string => { + const key = typeof object === 'string' ? object : Object.keys(object)[0]; + const value = typeof object === 'string' ? undefined : object[key]; + const parsed = parseKey(key); + if (parsed.role === 'text') { + if (typeof value !== 'string') + throw new Error(`Generic role must have a text value`); + return valueOrRegex(value as string); + } + if (Array.isArray(value)) + parsed.children = value.map(convert); + else if (value) + parsed.children = [valueOrRegex(value)]; + return parsed; + }; + const fragment = yaml.parse(text) as YamlNode[]; + return convert({ '': fragment }) as AriaTemplateNode; +} + +const allRoles = [ + 'alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'command', + 'complementary', 'composite', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', + 'gridcell', 'group', 'heading', 'img', 'input', 'insertion', 'landmark', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'marquee', 'math', 'meter', 'menu', + 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none', 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', + 'range', 'region', 'roletype', 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'section', 'sectionhead', 'select', 'separator', 'slider', + 'spinbutton', 'status', 'strong', 'structure', 'subscript', 'superscript', 'switch', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', + 'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem', 'widget', 'window' +]; diff --git a/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts b/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts index 6dcb9a7220fcd..d058085cb71b2 100644 --- a/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts @@ -26,6 +26,7 @@ import type { CallMetadata } from '../instrumentation'; import type { BrowserContextDispatcher } from './browserContextDispatcher'; import type { PageDispatcher } from './pageDispatcher'; import { debugAssert } from '../../utils'; +import { parseAriaSnapshot } from '../ariaSnapshot'; export class FrameDispatcher extends Dispatcher implements channels.FrameChannel { _type_Frame = true; @@ -258,7 +259,9 @@ export class FrameDispatcher extends Dispatcher { metadata.potentiallyClosesScope = true; - const expectedValue = params.expectedValue ? parseArgument(params.expectedValue) : undefined; + let expectedValue = params.expectedValue ? parseArgument(params.expectedValue) : undefined; + if (params.expression === 'to.match.aria' && expectedValue) + expectedValue = parseAriaSnapshot(expectedValue); const result = await this._frame.expect(metadata, params.selector, { ...params, expectedValue }); if (result.received !== undefined) result.received = serializeResult(result.received); diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index d620ca273cd1a..fd2cdcdb7cdae 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -704,7 +704,7 @@ class TextAssertionTool implements RecorderTool { value: (target as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)).value, }; } - } if (this._kind === 'snapshot') { + } else if (this._kind === 'snapshot') { this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true }); this._hoverHighlight.color = '#8acae480'; // forTextExpect can update the target, re-highlight it. diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts index a2a62be867e6d..b330491e0cbed 100644 --- a/packages/playwright-core/src/utilsBundle.ts +++ b/packages/playwright-core/src/utilsBundle.ts @@ -31,6 +31,7 @@ export const PNG: typeof import('../bundles/utils/node_modules/@types/pngjs').PN export const program: typeof import('../bundles/utils/node_modules/commander').program = require('./utilsBundleImpl').program; export const progress: typeof import('../bundles/utils/node_modules/@types/progress') = require('./utilsBundleImpl').progress; export const SocksProxyAgent: typeof import('../bundles/utils/node_modules/socks-proxy-agent').SocksProxyAgent = require('./utilsBundleImpl').SocksProxyAgent; +export const yaml: typeof import('../bundles/utils/node_modules/yaml') = require('./utilsBundleImpl').yaml; export const ws: typeof import('../bundles/utils/node_modules/@types/ws') = require('./utilsBundleImpl').ws; export const wsServer: typeof import('../bundles/utils/node_modules/@types/ws').WebSocketServer = require('./utilsBundleImpl').wsServer; export const wsReceiver = require('./utilsBundleImpl').wsReceiver; diff --git a/packages/playwright/ThirdPartyNotices.txt b/packages/playwright/ThirdPartyNotices.txt index 46c2f60cd2ffe..f2bb64d661c29 100644 --- a/packages/playwright/ThirdPartyNotices.txt +++ b/packages/playwright/ThirdPartyNotices.txt @@ -155,7 +155,6 @@ This project incorporates components from the projects listed below. The origina - undici-types@6.19.8 (https://github.com/nodejs/undici) - update-browserslist-db@1.0.13 (https://github.com/browserslist/update-db) - yallist@3.1.1 (https://github.com/isaacs/yallist) -- yaml@2.5.1 (https://github.com/eemeli/yaml) %% @ampproject/remapping@2.2.1 NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -4398,26 +4397,8 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ========================================= END OF yallist@3.1.1 AND INFORMATION -%% yaml@2.5.1 NOTICES AND INFORMATION BEGIN HERE -========================================= -Copyright Eemeli Aro - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -========================================= -END OF yaml@2.5.1 AND INFORMATION - SUMMARY BEGIN HERE ========================================= -Total Packages: 152 +Total Packages: 151 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright/bundles/utils/package-lock.json b/packages/playwright/bundles/utils/package-lock.json index 90df9a258bd57..fcf9f972feb31 100644 --- a/packages/playwright/bundles/utils/package-lock.json +++ b/packages/playwright/bundles/utils/package-lock.json @@ -13,8 +13,7 @@ "json5": "2.2.3", "pirates": "4.0.4", "source-map-support": "0.5.21", - "stoppable": "1.1.0", - "yaml": "^2.5.1" + "stoppable": "1.1.0" }, "devDependencies": { "@types/source-map-support": "^0.5.4", @@ -281,17 +280,6 @@ "engines": { "node": ">=8.0" } - }, - "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } } }, "dependencies": { @@ -476,11 +464,6 @@ "requires": { "is-number": "^7.0.0" } - }, - "yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" } } } diff --git a/packages/playwright/bundles/utils/package.json b/packages/playwright/bundles/utils/package.json index dc807c0d95202..69477909c5337 100644 --- a/packages/playwright/bundles/utils/package.json +++ b/packages/playwright/bundles/utils/package.json @@ -14,8 +14,7 @@ "json5": "2.2.3", "pirates": "4.0.4", "source-map-support": "0.5.21", - "stoppable": "1.1.0", - "yaml": "^2.5.1" + "stoppable": "1.1.0" }, "devDependencies": { "@types/source-map-support": "^0.5.4", diff --git a/packages/playwright/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright/bundles/utils/src/utilsBundleImpl.ts index 76cf961ab7c55..7c29c301a8924 100644 --- a/packages/playwright/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright/bundles/utils/src/utilsBundleImpl.ts @@ -31,6 +31,3 @@ export const enquirer = enquirerLibrary; import chokidarLibrary from 'chokidar'; export const chokidar = chokidarLibrary; - -import yamlLibrary from 'yaml'; -export const yaml = yamlLibrary; diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index 949e44af6fd3d..cd79ccab61718 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -18,8 +18,6 @@ import type { LocatorEx } from './matchers'; import type { ExpectMatcherState } from '../../types/test'; import { kNoElementsFoundError, matcherHint, type MatcherResult } from './matcherHint'; -import type { AriaTemplateNode } from 'playwright-core/lib/server/injected/ariaSnapshot'; -import { yaml } from '../utilsBundle'; import { colors } from 'playwright-core/lib/utilsBundle'; import { EXPECTED_COLOR } from '../common/expectBundle'; import { callLogText } from '../util'; @@ -46,9 +44,8 @@ export async function toMatchAriaSnapshot( ].join('\n\n')); } - const ariaTree = toAriaTree(expected) as AriaTemplateNode; const timeout = options.timeout ?? this.timeout; - const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: ariaTree, isNot: this.isNot, timeout }); + const { matches: pass, received, log, timedOut } = await receiver._expect('to.match.aria', { expectedValue: expected, isNot: this.isNot, timeout }); const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined); const notFound = received === kNoElementsFoundError; @@ -76,59 +73,3 @@ export async function toMatchAriaSnapshot( timeout: timedOut ? timeout : undefined, }; } - -function parseKey(key: string): AriaTemplateNode { - if (!key) - return { role: '' }; - - const match = key.match(/^([a-z]+)(?:\s+(?:"([^"]*)"|\/([^\/]*)\/))?$/); - - if (!match) - throw new Error(`Invalid key ${key}`); - - const role = match[1]; - if (role && role !== 'text' && !allRoles.includes(role)) - throw new Error(`Invalid role ${role}`); - - if (match[2]) - return { role, name: match[2] }; - if (match[3]) - return { role, name: new RegExp(match[3]) }; - return { role }; -} - -function valueOrRegex(value: string): string | RegExp { - return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : value; -} - -type YamlNode = Record | string>; - -function toAriaTree(text: string): AriaTemplateNode { - const convert = (object: YamlNode | string): AriaTemplateNode | RegExp | string => { - const key = typeof object === 'string' ? object : Object.keys(object)[0]; - const value = typeof object === 'string' ? undefined : object[key]; - const parsed = parseKey(key); - if (parsed.role === 'text') { - if (typeof value !== 'string') - throw new Error(`Generic role must have a text value`); - return valueOrRegex(value as string); - } - if (Array.isArray(value)) - parsed.children = value.map(convert); - else if (value) - parsed.children = [valueOrRegex(value)]; - return parsed; - }; - const fragment = yaml.parse(text) as YamlNode[]; - return convert({ '': fragment }) as AriaTemplateNode; -} - -const allRoles = [ - 'alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'command', - 'complementary', 'composite', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', - 'gridcell', 'group', 'heading', 'img', 'input', 'insertion', 'landmark', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'marquee', 'math', 'meter', 'menu', - 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none', 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', - 'range', 'region', 'roletype', 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'section', 'sectionhead', 'select', 'separator', 'slider', - 'spinbutton', 'status', 'strong', 'structure', 'subscript', 'superscript', 'switch', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', - 'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem', 'widget', 'window' -]; diff --git a/packages/playwright/src/utilsBundle.ts b/packages/playwright/src/utilsBundle.ts index 5ded7993b7f70..072e16bb037d6 100644 --- a/packages/playwright/src/utilsBundle.ts +++ b/packages/playwright/src/utilsBundle.ts @@ -20,4 +20,3 @@ export const sourceMapSupport: typeof import('../bundles/utils/node_modules/@typ export const stoppable: typeof import('../bundles/utils/node_modules/@types/stoppable') = require('./utilsBundleImpl').stoppable; export const enquirer: typeof import('../bundles/utils/node_modules/enquirer') = require('./utilsBundleImpl').enquirer; export const chokidar: typeof import('../bundles/utils/node_modules/chokidar') = require('./utilsBundleImpl').chokidar; -export const yaml: typeof import('../bundles/utils/node_modules/yaml') = require('./utilsBundleImpl').yaml; diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 3f1179e34fa03..c96de2091a3f1 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -7644,8 +7644,6 @@ interface LocatorAssertions { * **Usage** * * ```js - * import { role as x } from '@playwright/test'; - * // ... * await page.goto('https://demo.playwright.dev/todomvc/'); * await expect(page.locator('body')).toMatchAriaSnapshot(` * - heading "todos" diff --git a/tests/library/inspector/cli-codegen-aria.spec.ts b/tests/library/inspector/cli-codegen-aria.spec.ts new file mode 100644 index 0000000000000..f99f65fd6f212 --- /dev/null +++ b/tests/library/inspector/cli-codegen-aria.spec.ts @@ -0,0 +1,42 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { test, expect } from './inspectorTest'; + +test.describe(() => { + test.skip(({ mode }) => mode !== 'default'); + test.skip(({ trace, codegenMode }) => trace === 'on' && codegenMode === 'trace-events'); + + test('should generate aria snapshot', async ({ openRecorder }) => { + const { recorder } = await openRecorder(); + await recorder.setContentAndWait(`
`); + + await recorder.page.click('x-pw-tool-item.snapshot'); + await recorder.page.hover('button'); + await recorder.trustedClick(); + + await expect.poll(() => + recorder.text('JavaScript')).toContain(`await expect(page.getByRole('button')).toMatchAriaSnapshot(\`- button "Submit"\`);`); + await expect.poll(() => + recorder.text('Python')).toContain(`expect(page.get_by_role("button")).to_match_aria_snapshot("- button \\"Submit\\"")`); + await expect.poll(() => + recorder.text('Python Async')).toContain(`await expect(page.get_by_role(\"button\")).to_match_aria_snapshot("- button \\"Submit\\"")`); + await expect.poll(() => + recorder.text('Java')).toContain(`assertThat(page.getByRole(AriaRole.BUTTON)).matchesAriaSnapshot("- button \\"Submit\\"");`); + await expect.poll(() => + recorder.text('C#')).toContain(`await Expect(page.GetByRole(AriaRole.Button)).ToMatchAriaSnapshotAsync("- button \\"Submit\\"");`); + }); +}); diff --git a/tests/library/inspector/inspectorTest.ts b/tests/library/inspector/inspectorTest.ts index 524fab1e57a01..3ed700a20819a 100644 --- a/tests/library/inspector/inspectorTest.ts +++ b/tests/library/inspector/inspectorTest.ts @@ -160,6 +160,15 @@ export class Recorder { return this._sources; } + async text(file: string): Promise { + const sources: Source[] = await this.recorderPage.evaluate(() => (window as any).playwrightSourcesEchoForTest || []); + for (const source of sources) { + if (codegenLangId2lang.get(source.id) === file) + return source.text; + } + return ''; + } + async waitForHighlight(action: () => Promise): Promise { await this.page.$$eval('x-pw-highlight', els => els.forEach(e => e.remove())); await this.page.$$eval('x-pw-tooltip', els => els.forEach(e => e.remove())); From b92b855638d1dd409883a49ef1094d52435306bd Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 15 Oct 2024 16:21:55 -0700 Subject: [PATCH 315/805] test: unflake ff debugger test (#33124) --- tests/library/inspector/inspectorTest.ts | 11 +++++++++-- tests/library/inspector/pause.spec.ts | 8 ++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/library/inspector/inspectorTest.ts b/tests/library/inspector/inspectorTest.ts index 3ed700a20819a..d77ad866977a8 100644 --- a/tests/library/inspector/inspectorTest.ts +++ b/tests/library/inspector/inspectorTest.ts @@ -180,6 +180,13 @@ export class Recorder { return this.page.locator('x-pw-tooltip').textContent(); } + async waitForHighlightNoTooltip(action: () => Promise): Promise { + await this.page.$$eval('x-pw-highlight', els => els.forEach(e => e.remove())); + await action(); + await this.page.locator('x-pw-highlight').waitFor(); + return ''; + } + async waitForActionPerformed(): Promise<{ hovered: string | null, active: string | null }> { let callback; const listener = async msg => { @@ -194,8 +201,8 @@ export class Recorder { return new Promise(f => callback = f); } - async hoverOverElement(selector: string, options?: { position?: { x: number, y: number }}): Promise { - return this.waitForHighlight(async () => { + async hoverOverElement(selector: string, options?: { position?: { x: number, y: number }, omitTooltip?: boolean }): Promise { + return (options?.omitTooltip ? this.waitForHighlightNoTooltip : this.waitForHighlight).call(this, async () => { const box = await this.page.locator(selector).first().boundingBox(); const offset = options?.position || { x: box.width / 2, y: box.height / 2 }; await this.page.mouse.move(box.x + offset.x, box.y + offset.y); diff --git a/tests/library/inspector/pause.spec.ts b/tests/library/inspector/pause.spec.ts index 12b7ed940fd7a..647706956f83f 100644 --- a/tests/library/inspector/pause.spec.ts +++ b/tests/library/inspector/pause.spec.ts @@ -15,7 +15,7 @@ */ import type { Page } from 'playwright-core'; -import { test as it, expect } from './inspectorTest'; +import { test as it, expect, Recorder } from './inspectorTest'; import { waitForTestLog } from '../../config/utils'; @@ -491,7 +491,11 @@ it.describe('pause', () => { await expect(recorderPage.getByRole('combobox', { name: 'Source chooser' })).toHaveValue(/pause\.spec\.ts/); await expect(recorderPage.locator('.source-line-paused')).toHaveText(/await page\.pause\(\)/); await recorderPage.getByRole('button', { name: 'Record' }).click(); - await page.locator('body').click(); + + const recorder = new Recorder(page, recorderPage); + await recorder.hoverOverElement('body', { omitTooltip: true }); + await recorder.trustedClick(); + await expect(recorderPage.getByRole('combobox', { name: 'Source chooser' })).toHaveValue('javascript'); await expect(recorderPage.locator('.cm-wrapper')).toContainText(`await page.locator('body').click();`); await recorderPage.getByRole('button', { name: 'Resume' }).click(); From 94321fef1c94f9851b6fcc4304d3844760e986cb Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 15 Oct 2024 18:47:26 -0700 Subject: [PATCH 316/805] chore: implement locator.ariaSnapshot (#33125) --- docs/src/api/class-locator.md | 57 +++++++++++++++++++ .../playwright-core/src/client/locator.ts | 5 ++ .../playwright-core/src/protocol/validator.ts | 7 +++ .../src/server/dispatchers/frameDispatcher.ts | 4 ++ packages/playwright-core/src/server/dom.ts | 4 ++ packages/playwright-core/src/server/frames.ts | 7 +++ .../src/server/injected/consoleApi.ts | 3 +- .../src/server/injected/injectedScript.ts | 6 +- .../src/server/injected/recorder/recorder.ts | 2 +- packages/playwright-core/types/types.d.ts | 51 +++++++++++++++++ packages/protocol/src/channels.ts | 11 ++++ packages/protocol/src/protocol.yml | 7 +++ tests/page/page-aria-snapshot.spec.ts | 40 +++++++++++++ 13 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 tests/page/page-aria-snapshot.spec.ts diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md index 8f0b53e16da7f..ba6dc91353be1 100644 --- a/docs/src/api/class-locator.md +++ b/docs/src/api/class-locator.md @@ -150,6 +150,63 @@ var button = page.GetByRole(AriaRole.Button).And(page.GetByTitle("Subscribe")); Additional locator to match. +## async method: Locator.ariaSnapshot +* since: v1.49 +- returns: <[string]> + +Captures the aria snapshot of the given element. See [`method: LocatorAssertions.toMatchAriaSnapshot`] for the corresponding assertion. + +**Usage** + +```js +await page.getByRole('link').ariaSnapshot(); +``` + +```java +page.getByRole(AriaRole.LINK).ariaSnapshot(); +``` + +```python async +await page.get_by_role("link").aria_snapshot() +``` + +```python sync +page.get_by_role("link").aria_snapshot() +``` + +```csharp +await page.GetByRole(AriaRole.Link).AriaSnapshotAsync(); +``` + +**Details** + +This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of the element and its children. +The snapshot can be used to assert the state of the element in the test, or to compare it to state in the future. + +The ARIA snapshot is represented using [YAML](https://yaml.org/spec/1.2.2/) markup language: +* The keys of the objects are the roles and optional accessible names of the elements. +* The values are either text content or an array of child elements. +* Generic static text can be represented with the `text` key. + +Below is the HTML markup and the respective ARIA snapshot: + +```html +
    +
  • Home
  • +
  • About
  • +
      +``` + +```yml +- list "Links": + - listitem: + - link "Home" + - listitem: + - link "About" +``` + +### option: Locator.ariaSnapshot.timeout = %%-input-timeout-js-%% +* since: v1.49 ## async method: Locator.blur * since: v1.28 diff --git a/packages/playwright-core/src/client/locator.ts b/packages/playwright-core/src/client/locator.ts index b6058e0abb825..1b43db8de732e 100644 --- a/packages/playwright-core/src/client/locator.ts +++ b/packages/playwright-core/src/client/locator.ts @@ -288,6 +288,11 @@ export class Locator implements api.Locator { return await this._withElement((h, timeout) => h.screenshot({ ...options, timeout }), options.timeout); } + async ariaSnapshot(options?: TimeoutOptions): Promise { + const result = await this._frame._channel.ariaSnapshot({ ...options, selector: this._selector }); + return result.snapshot; + } + async scrollIntoViewIfNeeded(options: channels.ElementHandleScrollIntoViewIfNeededOptions = {}) { return await this._withElement((h, timeout) => h.scrollIntoViewIfNeeded({ ...options, timeout }), options.timeout); } diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index d5d91b165de75..24ddf0014c0d1 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -1424,6 +1424,13 @@ scheme.FrameAddStyleTagParams = tObject({ scheme.FrameAddStyleTagResult = tObject({ element: tChannel(['ElementHandle']), }); +scheme.FrameAriaSnapshotParams = tObject({ + selector: tString, + timeout: tOptional(tNumber), +}); +scheme.FrameAriaSnapshotResult = tObject({ + snapshot: tString, +}); scheme.FrameBlurParams = tObject({ selector: tString, strict: tOptional(tBoolean), diff --git a/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts b/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts index d058085cb71b2..2f172df694f34 100644 --- a/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/frameDispatcher.ts @@ -267,4 +267,8 @@ export class FrameDispatcher extends Dispatcher { + return { snapshot: await this._frame.ariaSnapshot(metadata, params.selector, params) }; + } } diff --git a/packages/playwright-core/src/server/dom.ts b/packages/playwright-core/src/server/dom.ts index 76708245d4ab3..4bb301bffdc56 100644 --- a/packages/playwright-core/src/server/dom.ts +++ b/packages/playwright-core/src/server/dom.ts @@ -789,6 +789,10 @@ export class ElementHandle extends js.JSHandle { return this._page._delegate.getBoundingBox(this); } + async ariaSnapshot(): Promise { + return await this.evaluateInUtility(([injected, element]) => injected.ariaSnapshot(element), {}); + } + async screenshot(metadata: CallMetadata, options: ScreenshotOptions & TimeoutOptions = {}): Promise { const controller = new ProgressController(metadata, this); return controller.run( diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 6dc412c235357..597ff359511c3 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -1405,6 +1405,13 @@ export class Frame extends SdkObject { }); } + async ariaSnapshot(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise { + const controller = new ProgressController(metadata, this); + return controller.run(async progress => { + return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, handle => handle.ariaSnapshot()); + }, this._page._timeoutSettings.timeout(options)); + } + async expect(metadata: CallMetadata, selector: string, options: FrameExpectParams): Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }> { const result = await this._expectImpl(metadata, selector, options); // Library mode special case for the expect errors which are return values, not exceptions. diff --git a/packages/playwright-core/src/server/injected/consoleApi.ts b/packages/playwright-core/src/server/injected/consoleApi.ts index 526694745b8bd..0287240493291 100644 --- a/packages/playwright-core/src/server/injected/consoleApi.ts +++ b/packages/playwright-core/src/server/injected/consoleApi.ts @@ -20,7 +20,6 @@ import { escapeForTextSelector } from '../../utils/isomorphic/stringUtils'; import { asLocator } from '../../utils/isomorphic/locatorGenerators'; import type { Language } from '../../utils/isomorphic/locatorGenerators'; import type { InjectedScript } from './injectedScript'; -import { renderedAriaTree } from './ariaSnapshot'; const selectorSymbol = Symbol('selector'); @@ -86,7 +85,7 @@ class ConsoleAPI { inspect: (selector: string) => this._inspect(selector), selector: (element: Element) => this._selector(element), generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language), - ariaSnapshot: (element?: Element) => renderedAriaTree(element || this._injectedScript.document.body), + ariaSnapshot: (element?: Element) => this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body), resume: () => this._resume(), ...new Locator(injectedScript, ''), }; diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 66a18848db964..7abc5850bbcaf 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -206,8 +206,10 @@ export class InjectedScript { return new Set(result.map(r => r.element)); } - renderedAriaTree(target: Element): string { - return renderedAriaTree(target); + ariaSnapshot(node: Node): string { + if (node.nodeType !== Node.ELEMENT_NODE) + throw this.createStacklessError('Can only capture aria snapshot of Element nodes.'); + return renderedAriaTree(node as Element); } querySelectorAll(selector: ParsedSelector, root: Node): Element[] { diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index fd2cdcdb7cdae..c82f55c984487 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -714,7 +714,7 @@ class TextAssertionTool implements RecorderTool { name: 'assertSnapshot', selector: this._hoverHighlight.selector, signals: [], - snapshot: this._recorder.injectedScript.renderedAriaTree(target), + snapshot: this._recorder.injectedScript.ariaSnapshot(target), }; } else { this._hoverHighlight = this._recorder.injectedScript.generateSelector(target, { testIdAttributeName: this._recorder.state.testIdAttributeName, forTextExpect: true }); diff --git a/packages/playwright-core/types/types.d.ts b/packages/playwright-core/types/types.d.ts index 7d1d736a13167..092f75b2636bc 100644 --- a/packages/playwright-core/types/types.d.ts +++ b/packages/playwright-core/types/types.d.ts @@ -12424,6 +12424,57 @@ export interface Locator { */ and(locator: Locator): Locator; + /** + * Captures the aria snapshot of the given element. See + * [expect(locator).toMatchAriaSnapshot(expected[, options])](https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-match-aria-snapshot) + * for the corresponding assertion. + * + * **Usage** + * + * ```js + * await page.getByRole('link').ariaSnapshot(); + * ``` + * + * **Details** + * + * This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of + * the element and its children. The snapshot can be used to assert the state of the element in the test, or to + * compare it to state in the future. + * + * The ARIA snapshot is represented using [YAML](https://yaml.org/spec/1.2.2/) markup language: + * - The keys of the objects are the roles and optional accessible names of the elements. + * - The values are either text content or an array of child elements. + * - Generic static text can be represented with the `text` key. + * + * Below is the HTML markup and the respective ARIA snapshot: + * + * ```html + *
        + *
      • Home
      • + *
      • About
      • + *
          + * ``` + * + * ```yml + * - list "Links": + * - listitem: + * - link "Home" + * - listitem: + * - link "About" + * ``` + * + * @param options + */ + ariaSnapshot(options?: { + /** + * Maximum time in milliseconds. Defaults to `0` - no timeout. The default value can be changed via `actionTimeout` + * option in the config, or by using the + * [browserContext.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-browsercontext#browser-context-set-default-timeout) + * or [page.setDefaultTimeout(timeout)](https://playwright.dev/docs/api/class-page#page-set-default-timeout) methods. + */ + timeout?: number; + }): Promise; + /** * Calls [blur](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur) on the element. * @param options diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index a0d6a30b9faea..5ecc2f4077e07 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -2509,6 +2509,7 @@ export interface FrameChannel extends FrameEventTarget, Channel { evalOnSelectorAll(params: FrameEvalOnSelectorAllParams, metadata?: CallMetadata): Promise; addScriptTag(params: FrameAddScriptTagParams, metadata?: CallMetadata): Promise; addStyleTag(params: FrameAddStyleTagParams, metadata?: CallMetadata): Promise; + ariaSnapshot(params: FrameAriaSnapshotParams, metadata?: CallMetadata): Promise; blur(params: FrameBlurParams, metadata?: CallMetadata): Promise; check(params: FrameCheckParams, metadata?: CallMetadata): Promise; click(params: FrameClickParams, metadata?: CallMetadata): Promise; @@ -2613,6 +2614,16 @@ export type FrameAddStyleTagOptions = { export type FrameAddStyleTagResult = { element: ElementHandleChannel, }; +export type FrameAriaSnapshotParams = { + selector: string, + timeout?: number, +}; +export type FrameAriaSnapshotOptions = { + timeout?: number, +}; +export type FrameAriaSnapshotResult = { + snapshot: string, +}; export type FrameBlurParams = { selector: string, strict?: boolean, diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index a32ebde3d47cf..c91cecbe6cab7 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -1875,6 +1875,13 @@ Frame: flags: snapshot: true + ariaSnapshot: + parameters: + selector: string + timeout: number? + returns: + snapshot: string + blur: parameters: selector: string diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts new file mode 100644 index 0000000000000..766df6d4855f3 --- /dev/null +++ b/tests/page/page-aria-snapshot.spec.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2018 Google Inc. All rights reserved. + * Modifications copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { test as it, expect } from './pageTest'; + +it('should snapshot the check box @smoke', async ({ page }) => { + await page.setContent(``); + expect(await page.locator('body').ariaSnapshot()).toBe('- checkbox'); +}); + +it('should snapshot nested element', async ({ page }) => { + await page.setContent(` +
          + +
          `); + expect(await page.locator('body').ariaSnapshot()).toBe('- checkbox'); +}); + +it('should snapshot fragment', async ({ page }) => { + await page.setContent(` +
          + Link + Link +
          `); + expect(await page.locator('body').ariaSnapshot()).toBe(`- link "Link"\n- link "Link"`); +}); From 183720b56a3e8a502e40bc9ec7d5cf9b4dc36b6e Mon Sep 17 00:00:00 2001 From: Lars Hanisch Date: Wed, 16 Oct 2024 10:15:40 +0200 Subject: [PATCH 317/805] fix(docker): correct Ubuntu Noble name in name template (#33133) --- utils/docker/Dockerfile.noble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/docker/Dockerfile.noble b/utils/docker/Dockerfile.noble index 7236acbbfc4d6..29ca98c4e4f36 100644 --- a/utils/docker/Dockerfile.noble +++ b/utils/docker/Dockerfile.noble @@ -2,7 +2,7 @@ FROM ubuntu:noble ARG DEBIAN_FRONTEND=noninteractive ARG TZ=America/Los_Angeles -ARG DOCKER_IMAGE_NAME_TEMPLATE="mcr.microsoft.com/playwright:v%version%-jammy" +ARG DOCKER_IMAGE_NAME_TEMPLATE="mcr.microsoft.com/playwright:v%version%-noble" ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 From d10a5e56938f8183cc22651eeab4ec7f2610b0ce Mon Sep 17 00:00:00 2001 From: Pengoose Date: Wed, 16 Oct 2024 22:47:23 +0900 Subject: [PATCH 318/805] feat(testType): add support for test.fail.only method (#33001) --- docs/src/test-api/class-test.md | 51 ++++++++ packages/playwright/src/common/testType.ts | 7 +- packages/playwright/types/test.d.ts | 126 +++++++++++++++++-- tests/playwright-test/basic.spec.ts | 69 +++++++++- tests/playwright-test/test-modifiers.spec.ts | 27 ++++ tests/playwright-test/types-2.spec.ts | 2 + utils/generate_types/overrides-test.d.ts | 13 +- 7 files changed, 278 insertions(+), 17 deletions(-) diff --git a/docs/src/test-api/class-test.md b/docs/src/test-api/class-test.md index 31f60b7e9c2c8..7ea05d4c5655d 100644 --- a/docs/src/test-api/class-test.md +++ b/docs/src/test-api/class-test.md @@ -1138,6 +1138,57 @@ Optional description that will be reflected in a test report. +## method: Test.fail.only +* since: v1.49 + +You can use `test.fail.only` to focus on a specific test that is expected to fail. This is particularly useful when debugging a failing test or working on a specific issue. + +To declare a focused "failing" test: +* `test.fail.only(title, body)` +* `test.fail.only(title, details, body)` + +**Usage** + +You can declare a focused failing test, so that Playwright runs only this test and ensures it actually fails. + +```js +import { test, expect } from '@playwright/test'; + +test.fail.only('focused failing test', async ({ page }) => { + // This test is expected to fail +}); +test('not in the focused group', async ({ page }) => { + // This test will not run +}); +``` + +### param: Test.fail.only.title +* since: v1.49 + +- `title` ?<[string]> + +Test title. + +### param: Test.fail.only.details +* since: v1.49 + +- `details` ?<[Object]> + - `tag` ?<[string]|[Array]<[string]>> + - `annotation` ?<[Object]|[Array]<[Object]>> + - `type` <[string]> + - `description` ?<[string]> + +See [`method: Test.describe`] for test details description. + +### param: Test.fail.only.body +* since: v1.49 + +- `body` ?<[function]\([Fixtures], [TestInfo]\)> + +Test body that takes one or two arguments: an object with fixtures and optional [TestInfo]. + + + ## method: Test.fixme * since: v1.10 diff --git a/packages/playwright/src/common/testType.ts b/packages/playwright/src/common/testType.ts index adf6bc3734ed1..f22fd159d86da 100644 --- a/packages/playwright/src/common/testType.ts +++ b/packages/playwright/src/common/testType.ts @@ -52,6 +52,7 @@ export class TestTypeImpl { test.skip = wrapFunctionWithLocation(this._modifier.bind(this, 'skip')); test.fixme = wrapFunctionWithLocation(this._modifier.bind(this, 'fixme')); test.fail = wrapFunctionWithLocation(this._modifier.bind(this, 'fail')); + test.fail.only = wrapFunctionWithLocation(this._createTest.bind(this, 'fail.only')); test.slow = wrapFunctionWithLocation(this._modifier.bind(this, 'slow')); test.setTimeout = wrapFunctionWithLocation(this._setTimeout.bind(this)); test.step = this._step.bind(this); @@ -81,7 +82,7 @@ export class TestTypeImpl { return suite; } - private _createTest(type: 'default' | 'only' | 'skip' | 'fixme' | 'fail', location: Location, title: string, fnOrDetails: Function | TestDetails, fn?: Function) { + private _createTest(type: 'default' | 'only' | 'skip' | 'fixme' | 'fail' | 'fail.only', location: Location, title: string, fnOrDetails: Function | TestDetails, fn?: Function) { throwIfRunningInsideJest(); const suite = this._currentSuite(location, 'test()'); if (!suite) @@ -104,10 +105,12 @@ export class TestTypeImpl { test._tags.push(...validatedDetails.tags); suite._addTest(test); - if (type === 'only') + if (type === 'only' || type === 'fail.only') test._only = true; if (type === 'skip' || type === 'fixme' || type === 'fail') test._staticAnnotations.push({ type }); + else if (type === 'fail.only') + test._staticAnnotations.push({ type: 'fail' }); } private _describe(type: 'default' | 'only' | 'serial' | 'serial.only' | 'parallel' | 'parallel.only' | 'skip' | 'fixme', location: Location, titleOrFn: string | Function, fnOrDetails?: TestDetails | Function, fn?: Function) { diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index c96de2091a3f1..78f8eb7f4f440 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -3625,8 +3625,8 @@ export interface TestType Promise | void): void; - /** + fail: { + /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. * @@ -3702,8 +3702,8 @@ export interface TestType Promise | void): void; - /** + (title: string, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; + /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. * @@ -3779,8 +3779,8 @@ export interface TestType Promise | void): void; + /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. * @@ -3856,8 +3856,8 @@ export interface TestType boolean, description?: string): void; - /** + (condition: boolean, description?: string): void; + /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. * @@ -3933,7 +3933,115 @@ export interface TestType boolean, description?: string): void; + /** + * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful + * for documentation purposes to acknowledge that some functionality is broken until it is fixed. + * + * To declare a "failing" test: + * - `test.fail(title, body)` + * - `test.fail(title, details, body)` + * + * To annotate test as "failing" at runtime: + * - `test.fail(condition, description)` + * - `test.fail(callback, description)` + * - `test.fail()` + * + * **Usage** + * + * You can declare a test as failing, so that Playwright ensures it actually fails. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.fail('not yet ready', async ({ page }) => { + * // ... + * }); + * ``` + * + * If your test fails in some configurations, but not all, you can mark the test as failing inside the test body based + * on some condition. We recommend passing a `description` argument in this case. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('fail in WebKit', async ({ page, browserName }) => { + * test.fail(browserName === 'webkit', 'This feature is not implemented for Mac yet'); + * // ... + * }); + * ``` + * + * You can mark all tests in a file or + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) group as + * "should fail" based on some condition with a single `test.fail(callback, description)` call. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.fail(({ browserName }) => browserName === 'webkit', 'not implemented yet'); + * + * test('fail in WebKit 1', async ({ page }) => { + * // ... + * }); + * test('fail in WebKit 2', async ({ page }) => { + * // ... + * }); + * ``` + * + * You can also call `test.fail()` without arguments inside the test body to always mark the test as failed. We + * recommend declaring a failing test with `test.fail(title, body)` instead. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('less readable', async ({ page }) => { + * test.fail(); + * // ... + * }); + * ``` + * + * @param title Test title. + * @param details See [test.(call)(title[, details, body])](https://playwright.dev/docs/api/class-test#test-call) for test details + * description. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + * @param condition Test is marked as "should fail" when the condition is `true`. + * @param callback A function that returns whether to mark as "should fail", based on test fixtures. Test or tests are marked as + * "should fail" when the return value is `true`. + * @param description Optional description that will be reflected in a test report. + */ + (): void; + /** + * You can use `test.fail.only` to focus on a specific test that is expected to fail. This is particularly useful when + * debugging a failing test or working on a specific issue. + * + * To declare a focused "failing" test: + * - `test.fail.only(title, body)` + * - `test.fail.only(title, details, body)` + * + * **Usage** + * + * You can declare a focused failing test, so that Playwright runs only this test and ensures it actually fails. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.fail.only('focused failing test', async ({ page }) => { + * // This test is expected to fail + * }); + * test('not in the focused group', async ({ page }) => { + * // This test will not run + * }); + * ``` + * + * @param title Test title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for test + * details description. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + */ + only: TestFunction; + } /** * Marks a test as "slow". Slow test will be given triple the default timeout. * diff --git a/tests/playwright-test/basic.spec.ts b/tests/playwright-test/basic.spec.ts index 3b47603c2554a..ce6825c5596a2 100644 --- a/tests/playwright-test/basic.spec.ts +++ b/tests/playwright-test/basic.spec.ts @@ -153,6 +153,10 @@ test('should respect focused tests', async ({ runInlineTest }) => { }); }); + test.fail.only('focused fail.only test', () => { + expect(1 + 1).toBe(3); + }); + test.describe('non-focused describe', () => { test('describe test', () => { expect(1 + 1).toBe(3); @@ -172,13 +176,46 @@ test('should respect focused tests', async ({ runInlineTest }) => { test.only('test4', () => { expect(1 + 1).toBe(2); }); + test.fail.only('test5', () => { + expect(1 + 1).toBe(3); + }); }); ` }); - expect(passed).toBe(5); + expect(passed).toBe(7); expect(exitCode).toBe(0); }); +test('should respect focused tests with test.fail', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'fail-only.spec.ts': ` + import { test, expect } from '@playwright/test'; + + test('test1', () => { + console.log('test1 should not run'); + expect(1 + 1).toBe(2); + }); + + test.fail.only('test2', () => { + console.log('test2 should run and fail'); + expect(1 + 1).toBe(3); + }); + + test('test3', () => { + console.log('test3 should not run'); + expect(1 + 1).toBe(2); + }); + `, + }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + expect(result.failed).toBe(0); + expect(result.skipped).toBe(0); + expect(result.output).toContain('test2 should run and fail'); + expect(result.output).not.toContain('test1 should not run'); + expect(result.output).not.toContain('test3 should not run'); +}); + test('skip should take priority over fail', async ({ runInlineTest }) => { const { passed, skipped, failed } = await runInlineTest({ 'test.spec.ts': ` @@ -550,3 +587,33 @@ test('should support describe.fixme', async ({ runInlineTest }) => { expect(result.skipped).toBe(3); expect(result.output).toContain('heytest4'); }); + +test('should fail when test.fail.only passes unexpectedly', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'fail-only-pass.spec.ts': ` + import { test, expect } from '@playwright/test'; + + test('test1', () => { + console.log('test1 should not run'); + expect(1 + 1).toBe(2); + }); + + test.fail.only('test2', () => { + console.log('test2 should run and pass unexpectedly'); + expect(1 + 1).toBe(2); + }); + + test('test3', () => { + console.log('test3 should not run'); + expect(1 + 1).toBe(2); + }); + `, + }); + expect(result.exitCode).toBe(1); + expect(result.passed).toBe(0); + expect(result.failed).toBe(1); + expect(result.skipped).toBe(0); + expect(result.output).toContain('should run and pass unexpectedly'); + expect(result.output).not.toContain('test1 should not run'); + expect(result.output).not.toContain('test3 should not run'); +}); diff --git a/tests/playwright-test/test-modifiers.spec.ts b/tests/playwright-test/test-modifiers.spec.ts index 0dd41bd0abd59..f7fb9a6ae01a6 100644 --- a/tests/playwright-test/test-modifiers.spec.ts +++ b/tests/playwright-test/test-modifiers.spec.ts @@ -279,6 +279,33 @@ test.describe('test modifier annotations', () => { expectTest('focused fixme by suite', 'skipped', 'skipped', ['fixme']); }); + test('should work with fail.only inside describe.only', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + + test.describe.only("suite", () => { + test.skip('focused skip by suite', () => {}); + test.fixme('focused fixme by suite', () => {}); + test.fail.only('focused fail by suite', () => { expect(1).toBe(2); }); + }); + + test.describe.skip('not focused', () => { + test('no marker', () => {}); + }); + `, + }); + const expectTest = expectTestHelper(result); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + expect(result.failed).toBe(0); + expect(result.skipped).toBe(0); + expectTest('focused skip by suite', 'skipped', 'skipped', ['skip']); + expectTest('focused fixme by suite', 'skipped', 'skipped', ['fixme']); + expectTest('focused fail by suite', 'failed', 'expected', ['fail']); + }); + test('should not multiple on retry', async ({ runInlineTest }) => { const result = await runInlineTest({ 'a.test.ts': ` diff --git a/tests/playwright-test/types-2.spec.ts b/tests/playwright-test/types-2.spec.ts index e61d4870ed5fa..f794e06798382 100644 --- a/tests/playwright-test/types-2.spec.ts +++ b/tests/playwright-test/types-2.spec.ts @@ -33,6 +33,7 @@ test('basics should work', async ({ runTSC }) => { test.skip('my test', async () => {}); test.fixme('my test', async () => {}); test.fail('my test', async () => {}); + test.fail.only('my test', async () => {}); }); test.describe(() => { test('my test', () => {}); @@ -59,6 +60,7 @@ test('basics should work', async ({ runTSC }) => { test.fixme('title', { tag: '@foo' }, () => {}); test.only('title', { tag: '@foo' }, () => {}); test.fail('title', { tag: '@foo' }, () => {}); + test.fail.only('title', { tag: '@foo' }, () => {}); test.describe('title', { tag: '@foo' }, () => {}); test.describe('title', { annotation: { type: 'issue' } }, () => {}); // @ts-expect-error diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index be1fa7ee373d3..54fffb5345851 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -110,11 +110,14 @@ export interface TestType boolean, description?: string): void; - fail(title: string, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; - fail(title: string, details: TestDetails, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; - fail(condition: boolean, description?: string): void; - fail(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; - fail(): void; + fail: { + (title: string, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; + (title: string, details: TestDetails, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; + (condition: boolean, description?: string): void; + (callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; + (): void; + only: TestFunction; + } slow(): void; slow(condition: boolean, description?: string): void; slow(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; From 9848ebec5a760839e226e1ef5ccf7dfb9f45f2d2 Mon Sep 17 00:00:00 2001 From: Debbie O'Brien Date: Wed, 16 Oct 2024 18:36:46 +0200 Subject: [PATCH 319/805] docs: add video to release notes (#33147) --- docs/src/release-notes-js.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/src/release-notes-js.md b/docs/src/release-notes-js.md index b366c43dbd189..f6bd4301637ae 100644 --- a/docs/src/release-notes-js.md +++ b/docs/src/release-notes-js.md @@ -8,6 +8,11 @@ import LiteYouTube from '@site/src/components/LiteYouTube'; ## Version 1.48 + + ### WebSocket routing New methods [`method: Page.routeWebSocket`] and [`method: BrowserContext.routeWebSocket`] allow to intercept, modify and mock WebSocket connections initiated in the page. Below is a simple example that mocks WebSocket communication by responding to a `"request"` with a `"response"`. From 7af9e93304797481e8f8725581b0ead7530f2a56 Mon Sep 17 00:00:00 2001 From: Amaechi Hope <51549388+Honyii@users.noreply.github.com> Date: Thu, 17 Oct 2024 08:11:53 +0100 Subject: [PATCH 320/805] docs(api): fix code snippets for locator ele (#33153) --- docs/src/locators.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/src/locators.md b/docs/src/locators.md index 648a654177d17..c3a2817670caf 100644 --- a/docs/src/locators.md +++ b/docs/src/locators.md @@ -62,11 +62,11 @@ expect(page.get_by_text("Welcome, John!")).to_be_visible() ``` ```csharp -await page.GetByLabel("User Name").FillAsync("John"); +await Page.GetByLabel("User Name").FillAsync("John"); -await page.GetByLabel("Password").FillAsync("secret-password"); +await Page.GetByLabel("Password").FillAsync("secret-password"); -await page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync(); +await Page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync(); await Expect(Page.GetByText("Welcome, John!")).ToBeVisibleAsync(); ``` @@ -101,7 +101,7 @@ page.get_by_role("button", name="Sign in").click() ``` ```csharp -await page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync(); +await Page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }).ClickAsync(); ``` :::note @@ -143,7 +143,7 @@ locator.click() ``` ```csharp -var locator = page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }); +var locator = Page.GetByRole(AriaRole.Button, new() { Name = "Sign in" }); await locator.HoverAsync(); await locator.ClickAsync(); @@ -180,7 +180,7 @@ locator.click() ``` ```csharp -var locator = page +var locator = Page .FrameLocator("#my-frame") .GetByRole(AriaRole.Button, new() { Name = "Sign in" }); @@ -249,11 +249,11 @@ await Expect(Page .GetByRole(AriaRole.Heading, new() { Name = "Sign up" })) .ToBeVisibleAsync(); -await page +await Page .GetByRole(AriaRole.Checkbox, new() { Name = "Subscribe" }) .CheckAsync(); -await page +await Page .GetByRole(AriaRole.Button, new() { NameRegex = new Regex("submit", RegexOptions.IgnoreCase) }) @@ -298,7 +298,7 @@ page.get_by_label("Password").fill("secret") ``` ```csharp -await page.GetByLabel("Password").FillAsync("secret"); +await Page.GetByLabel("Password").FillAsync("secret"); ``` :::note[When to use label locators] @@ -335,7 +335,7 @@ page.get_by_placeholder("name@example.com").fill("playwright@microsoft.com") ``` ```csharp -await page +await Page .GetByPlaceholder("name@example.com") .FillAsync("playwright@microsoft.com"); ``` @@ -468,7 +468,7 @@ page.get_by_alt_text("playwright logo").click() ``` ```csharp -await page.GetByAltText("playwright logo").ClickAsync(); +await Page.GetByAltText("playwright logo").ClickAsync(); ``` :::note[When to use alt locators] @@ -540,7 +540,7 @@ page.get_by_test_id("directions").click() ``` ```csharp -await page.GetByTestId("directions").ClickAsync(); +await Page.GetByTestId("directions").ClickAsync(); ``` :::note[When to use testid locators] @@ -604,7 +604,7 @@ page.get_by_test_id("directions").click() ``` ```csharp -await page.GetByTestId("directions").ClickAsync(); +await Page.GetByTestId("directions").ClickAsync(); ``` ### Locate by CSS or XPath @@ -644,11 +644,11 @@ page.locator("//button").click() ``` ```csharp -await page.Locator("css=button").ClickAsync(); -await page.Locator("xpath=//button").ClickAsync(); +await Page.Locator("css=button").ClickAsync(); +await Page.Locator("xpath=//button").ClickAsync(); -await page.Locator("button").ClickAsync(); -await page.Locator("//button").ClickAsync(); +await Page.Locator("button").ClickAsync(); +await Page.Locator("//button").ClickAsync(); ``` XPath and CSS selectors can be tied to the DOM structure or implementation. These selectors can break when the DOM structure changes. Long CSS or XPath chains below are an example of a **bad practice** that leads to unstable tests: @@ -688,9 +688,9 @@ page.locator('//*[@id="tsf"]/div[2]/div[1]/div[1]/div/div[2]/input').click() ``` ```csharp -await page.Locator("#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input").ClickAsync(); +await Page.Locator("#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > div.a4bIc > input").ClickAsync(); -await page.Locator("//*[@id='tsf']/div[2]/div[1]/div[1]/div/div[2]/input").ClickAsync(); +await Page.Locator("//*[@id='tsf']/div[2]/div[1]/div[1]/div/div[2]/input").ClickAsync(); ``` :::note[When to use this] From 2d150eec25958f28e0b0ba7ae214572f1df7546b Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 17 Oct 2024 03:34:05 -0700 Subject: [PATCH 321/805] fix: correct types for things like `test.describe.only` (#33142) --- packages/playwright/types/test.d.ts | 1272 ++++++++++++++++------ utils/generate_types/index.js | 23 +- utils/generate_types/overrides-test.d.ts | 91 +- utils/generate_types/parseOverrides.js | 6 +- 4 files changed, 1034 insertions(+), 358 deletions(-) diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 78f8eb7f4f440..a989fe69b29f4 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -1857,7 +1857,220 @@ export type TestDetails = { annotation?: TestDetailsAnnotation | TestDetailsAnnotation[]; } -interface SuiteFunction { +type TestBody = (args: TestArgs, testInfo: TestInfo) => Promise | void; +type ConditionBody = (args: TestArgs) => boolean; + +/** + * Playwright Test provides a `test` function to declare tests and `expect` function to write assertions. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * const name = await page.innerText('.navbar__title'); + * expect(name).toBe('Playwright'); + * }); + * ``` + * + */ +export interface TestType { + /** + * Declares a test. + * - `test(title, body)` + * - `test(title, details, body)` + * + * **Usage** + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * ``` + * + * **Tags** + * + * You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note + * that each tag must start with `@` symbol. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', { + * tag: '@smoke', + * }, async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * + * test('another test @smoke', async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * ``` + * + * Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property. + * + * You can also filter tests by their tags during test execution: + * - in the [command line](https://playwright.dev/docs/test-cli#reference); + * - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and + * [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep); + * + * Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests). + * + * **Annotations** + * + * You can annotate tests by providing additional test details. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', { + * annotation: { + * type: 'issue', + * description: 'https://github.com/microsoft/playwright/issues/23180', + * }, + * }, async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * ``` + * + * Test annotations are displayed in the test report, and are available to a custom reporter via + * `TestCase.annotations` property. + * + * You can also add annotations during runtime by manipulating + * [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations). + * + * Learn more about [test annotations](https://playwright.dev/docs/test-annotations). + * @param title Test title. + * @param details Additional test details. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + */ + (title: string, body: TestBody): void; + /** + * Declares a test. + * - `test(title, body)` + * - `test(title, details, body)` + * + * **Usage** + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * ``` + * + * **Tags** + * + * You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note + * that each tag must start with `@` symbol. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', { + * tag: '@smoke', + * }, async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * + * test('another test @smoke', async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * ``` + * + * Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property. + * + * You can also filter tests by their tags during test execution: + * - in the [command line](https://playwright.dev/docs/test-cli#reference); + * - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and + * [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep); + * + * Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests). + * + * **Annotations** + * + * You can annotate tests by providing additional test details. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', { + * annotation: { + * type: 'issue', + * description: 'https://github.com/microsoft/playwright/issues/23180', + * }, + * }, async ({ page }) => { + * await page.goto('https://playwright.dev/'); + * // ... + * }); + * ``` + * + * Test annotations are displayed in the test report, and are available to a custom reporter via + * `TestCase.annotations` property. + * + * You can also add annotations during runtime by manipulating + * [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations). + * + * Learn more about [test annotations](https://playwright.dev/docs/test-annotations). + * @param title Test title. + * @param details Additional test details. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + */ + (title: string, details: TestDetails, body: TestBody): void; + + /** + * Declares a focused test. If there are some focused tests or suites, all of them will be run but nothing else. + * - `test.only(title, body)` + * - `test.only(title, details, body)` + * + * **Usage** + * + * ```js + * test.only('focus this test', async ({ page }) => { + * // Run only focused tests in the entire project. + * }); + * ``` + * + * @param title Test title. + * @param details See [test.(call)(title[, details, body])](https://playwright.dev/docs/api/class-test#test-call) for test details + * description. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + */ + only(title: string, body: TestBody): void; + /** + * Declares a focused test. If there are some focused tests or suites, all of them will be run but nothing else. + * - `test.only(title, body)` + * - `test.only(title, details, body)` + * + * **Usage** + * + * ```js + * test.only('focus this test', async ({ page }) => { + * // Run only focused tests in the entire project. + * }); + * ``` + * + * @param title Test title. + * @param details See [test.(call)(title[, details, body])](https://playwright.dev/docs/api/class-test#test-call) for test details + * description. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + */ + only(title: string, details: TestDetails, body: TestBody): void; + /** * Declares a group of tests. * - `test.describe(title, callback)` @@ -1952,8 +2165,8 @@ interface SuiteFunction { * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Any tests * declared in this callback will belong to the group. */ - (title: string, callback: () => void): void; - /** + describe: { + /** * Declares a group of tests. * - `test.describe(title, callback)` * - `test.describe(callback)` @@ -2047,8 +2260,8 @@ interface SuiteFunction { * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Any tests * declared in this callback will belong to the group. */ - (callback: () => void): void; - /** + (title: string, callback: () => void): void; + /** * Declares a group of tests. * - `test.describe(title, callback)` * - `test.describe(callback)` @@ -2142,232 +2355,38 @@ interface SuiteFunction { * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Any tests * declared in this callback will belong to the group. */ - (title: string, details: TestDetails, callback: () => void): void; -} - -interface TestFunction { - /** - * Declares a test. - * - `test(title, body)` - * - `test(title, details, body)` + (callback: () => void): void; + /** + * Declares a group of tests. + * - `test.describe(title, callback)` + * - `test.describe(callback)` + * - `test.describe(title, details, callback)` * * **Usage** * + * You can declare a group of tests with a title. The title will be visible in the test report as a part of each + * test's title. + * * ```js - * import { test, expect } from '@playwright/test'; + * test.describe('two tests', () => { + * test('one', async ({ page }) => { + * // ... + * }); * - * test('basic test', async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... + * test('two', async ({ page }) => { + * // ... + * }); * }); * ``` * - * **Tags** + * **Anonymous group** * - * You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note - * that each tag must start with `@` symbol. + * You can also declare a test group without a title. This is convenient to give a group of tests a common option with + * [test.use(options)](https://playwright.dev/docs/api/class-test#test-use). * * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', { - * tag: '@smoke', - * }, async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * - * test('another test @smoke', async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * ``` - * - * Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property. - * - * You can also filter tests by their tags during test execution: - * - in the [command line](https://playwright.dev/docs/test-cli#reference); - * - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and - * [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep); - * - * Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests). - * - * **Annotations** - * - * You can annotate tests by providing additional test details. - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', { - * annotation: { - * type: 'issue', - * description: 'https://github.com/microsoft/playwright/issues/23180', - * }, - * }, async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * ``` - * - * Test annotations are displayed in the test report, and are available to a custom reporter via - * `TestCase.annotations` property. - * - * You can also add annotations during runtime by manipulating - * [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations). - * - * Learn more about [test annotations](https://playwright.dev/docs/test-annotations). - * @param title Test title. - * @param details Additional test details. - * @param body Test body that takes one or two arguments: an object with fixtures and optional - * [TestInfo](https://playwright.dev/docs/api/class-testinfo). - */ - (title: string, body: (args: TestArgs, testInfo: TestInfo) => Promise | void): void; - /** - * Declares a test. - * - `test(title, body)` - * - `test(title, details, body)` - * - * **Usage** - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * ``` - * - * **Tags** - * - * You can tag tests by providing additional test details. Alternatively, you can include tags in the test title. Note - * that each tag must start with `@` symbol. - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', { - * tag: '@smoke', - * }, async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * - * test('another test @smoke', async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * ``` - * - * Test tags are displayed in the test report, and are available to a custom reporter via `TestCase.tags` property. - * - * You can also filter tests by their tags during test execution: - * - in the [command line](https://playwright.dev/docs/test-cli#reference); - * - in the config with [testConfig.grep](https://playwright.dev/docs/api/class-testconfig#test-config-grep) and - * [testProject.grep](https://playwright.dev/docs/api/class-testproject#test-project-grep); - * - * Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests). - * - * **Annotations** - * - * You can annotate tests by providing additional test details. - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', { - * annotation: { - * type: 'issue', - * description: 'https://github.com/microsoft/playwright/issues/23180', - * }, - * }, async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * // ... - * }); - * ``` - * - * Test annotations are displayed in the test report, and are available to a custom reporter via - * `TestCase.annotations` property. - * - * You can also add annotations during runtime by manipulating - * [testInfo.annotations](https://playwright.dev/docs/api/class-testinfo#test-info-annotations). - * - * Learn more about [test annotations](https://playwright.dev/docs/test-annotations). - * @param title Test title. - * @param details Additional test details. - * @param body Test body that takes one or two arguments: an object with fixtures and optional - * [TestInfo](https://playwright.dev/docs/api/class-testinfo). - */ - (title: string, details: TestDetails, body: (args: TestArgs, testInfo: TestInfo) => Promise | void): void; -} - -/** - * Playwright Test provides a `test` function to declare tests and `expect` function to write assertions. - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', async ({ page }) => { - * await page.goto('https://playwright.dev/'); - * const name = await page.innerText('.navbar__title'); - * expect(name).toBe('Playwright'); - * }); - * ``` - * - */ -export interface TestType extends TestFunction { - /** - * Declares a focused test. If there are some focused tests or suites, all of them will be run but nothing else. - * - `test.only(title, body)` - * - `test.only(title, details, body)` - * - * **Usage** - * - * ```js - * test.only('focus this test', async ({ page }) => { - * // Run only focused tests in the entire project. - * }); - * ``` - * - * @param title Test title. - * @param details See [test.(call)(title[, details, body])](https://playwright.dev/docs/api/class-test#test-call) for test details - * description. - * @param body Test body that takes one or two arguments: an object with fixtures and optional - * [TestInfo](https://playwright.dev/docs/api/class-testinfo). - */ - only: TestFunction; - /** - * Declares a group of tests. - * - `test.describe(title, callback)` - * - `test.describe(callback)` - * - `test.describe(title, details, callback)` - * - * **Usage** - * - * You can declare a group of tests with a title. The title will be visible in the test report as a part of each - * test's title. - * - * ```js - * test.describe('two tests', () => { - * test('one', async ({ page }) => { - * // ... - * }); - * - * test('two', async ({ page }) => { - * // ... - * }); - * }); - * ``` - * - * **Anonymous group** - * - * You can also declare a test group without a title. This is convenient to give a group of tests a common option with - * [test.use(options)](https://playwright.dev/docs/api/class-test#test-use). - * - * ```js - * test.describe(() => { - * test.use({ colorScheme: 'dark' }); + * test.describe(() => { + * test.use({ colorScheme: 'dark' }); * * test('one', async ({ page }) => { * // ... @@ -2431,7 +2450,44 @@ export interface TestType void): void; + + /** + * Declares a focused group of tests. If there are some focused tests or suites, all of them will be run but nothing + * else. + * - `test.describe.only(title, callback)` + * - `test.describe.only(callback)` + * - `test.describe.only(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.only('focused group', () => { + * test('in the focused group', async ({ page }) => { + * // This test will run + * }); + * }); + * test('not in the focused group', async ({ page }) => { + * // This test will not run + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.only(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.only([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-only). + * Any tests added in this callback will belong to the group. + */ + only(title: string, callback: () => void): void; /** * Declares a focused group of tests. If there are some focused tests or suites, all of them will be run but nothing * else. @@ -2446,16 +2502,500 @@ export interface TestType { * // This test will run * }); - * }); - * test('not in the focused group', async ({ page }) => { - * // This test will not run + * }); + * test('not in the focused group', async ({ page }) => { + * // This test will not run + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.only(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.only([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-only). + * Any tests added in this callback will belong to the group. + */ + only(callback: () => void): void; + /** + * Declares a focused group of tests. If there are some focused tests or suites, all of them will be run but nothing + * else. + * - `test.describe.only(title, callback)` + * - `test.describe.only(callback)` + * - `test.describe.only(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.only('focused group', () => { + * test('in the focused group', async ({ page }) => { + * // This test will run + * }); + * }); + * test('not in the focused group', async ({ page }) => { + * // This test will not run + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.only(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.only([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-only). + * Any tests added in this callback will belong to the group. + */ + only(title: string, details: TestDetails, callback: () => void): void; + + /** + * Declares a skipped test group, similarly to + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in the + * skipped group are never run. + * - `test.describe.skip(title, callback)` + * - `test.describe.skip(title)` + * - `test.describe.skip(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.skip('skipped group', () => { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.skip(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.skip(title[, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-skip). + * Any tests added in this callback will belong to the group, and will not be run. + */ + skip(title: string, callback: () => void): void; + /** + * Declares a skipped test group, similarly to + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in the + * skipped group are never run. + * - `test.describe.skip(title, callback)` + * - `test.describe.skip(title)` + * - `test.describe.skip(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.skip('skipped group', () => { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.skip(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.skip(title[, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-skip). + * Any tests added in this callback will belong to the group, and will not be run. + */ + skip(callback: () => void): void; + /** + * Declares a skipped test group, similarly to + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in the + * skipped group are never run. + * - `test.describe.skip(title, callback)` + * - `test.describe.skip(title)` + * - `test.describe.skip(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.skip('skipped group', () => { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.skip(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.skip(title[, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-skip). + * Any tests added in this callback will belong to the group, and will not be run. + */ + skip(title: string, details: TestDetails, callback: () => void): void; + + /** + * Declares a test group similarly to + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in + * this group are marked as "fixme" and will not be executed. + * - `test.describe.fixme(title, callback)` + * - `test.describe.fixme(callback)` + * - `test.describe.fixme(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.fixme('broken tests that should be fixed', () => { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.fixme(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.fixme([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-fixme). + * Any tests added in this callback will belong to the group, and will not be run. + */ + fixme(title: string, callback: () => void): void; + /** + * Declares a test group similarly to + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in + * this group are marked as "fixme" and will not be executed. + * - `test.describe.fixme(title, callback)` + * - `test.describe.fixme(callback)` + * - `test.describe.fixme(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.fixme('broken tests that should be fixed', () => { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.fixme(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.fixme([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-fixme). + * Any tests added in this callback will belong to the group, and will not be run. + */ + fixme(callback: () => void): void; + /** + * Declares a test group similarly to + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in + * this group are marked as "fixme" and will not be executed. + * - `test.describe.fixme(title, callback)` + * - `test.describe.fixme(callback)` + * - `test.describe.fixme(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.fixme('broken tests that should be fixed', () => { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.fixme(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.fixme([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-fixme). + * Any tests added in this callback will belong to the group, and will not be run. + */ + fixme(title: string, details: TestDetails, callback: () => void): void; + + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a group of tests that should always be run serially. If one of the tests fails, all subsequent tests are + * skipped. All tests in a group are retried together. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial(title, callback)` + * - `test.describe.serial(title)` + * - `test.describe.serial(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.serial('group', () => { + * test('runs first', async ({ page }) => {}); + * test('runs second', async ({ page }) => {}); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.serial(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.serial([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-serial). + * Any tests added in this callback will belong to the group. + */ + serial: { + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a group of tests that should always be run serially. If one of the tests fails, all subsequent tests are + * skipped. All tests in a group are retried together. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial(title, callback)` + * - `test.describe.serial(title)` + * - `test.describe.serial(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.serial('group', () => { + * test('runs first', async ({ page }) => {}); + * test('runs second', async ({ page }) => {}); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.serial(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.serial([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-serial). + * Any tests added in this callback will belong to the group. + */ + (title: string, callback: () => void): void; + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a group of tests that should always be run serially. If one of the tests fails, all subsequent tests are + * skipped. All tests in a group are retried together. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial(title, callback)` + * - `test.describe.serial(title)` + * - `test.describe.serial(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.serial('group', () => { + * test('runs first', async ({ page }) => {}); + * test('runs second', async ({ page }) => {}); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.serial(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.serial([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-serial). + * Any tests added in this callback will belong to the group. + */ + (callback: () => void): void; + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a group of tests that should always be run serially. If one of the tests fails, all subsequent tests are + * skipped. All tests in a group are retried together. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial(title, callback)` + * - `test.describe.serial(title)` + * - `test.describe.serial(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.serial('group', () => { + * test('runs first', async ({ page }) => {}); + * test('runs second', async ({ page }) => {}); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.serial(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.serial([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-serial). + * Any tests added in this callback will belong to the group. + */ + (title: string, details: TestDetails, callback: () => void): void; + + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a focused group of tests that should always be run serially. If one of the tests fails, all subsequent + * tests are skipped. All tests in a group are retried together. If there are some focused tests or suites, all of + * them will be run but nothing else. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial.only(title, callback)` + * - `test.describe.serial.only(title)` + * - `test.describe.serial.only(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.serial.only('group', () => { + * test('runs first', async ({ page }) => { + * }); + * test('runs second', async ({ page }) => { + * }); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.serial.only(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.serial.only(title[, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-serial-only). + * Any tests added in this callback will belong to the group. + */ + only(title: string, callback: () => void): void; + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a focused group of tests that should always be run serially. If one of the tests fails, all subsequent + * tests are skipped. All tests in a group are retried together. If there are some focused tests or suites, all of + * them will be run but nothing else. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial.only(title, callback)` + * - `test.describe.serial.only(title)` + * - `test.describe.serial.only(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.serial.only('group', () => { + * test('runs first', async ({ page }) => { + * }); + * test('runs second', async ({ page }) => { + * }); * }); * ``` * * You can also omit the title. * * ```js - * test.describe.only(() => { + * test.describe.serial.only(() => { * // ... * }); * ``` @@ -2464,24 +3004,32 @@ export interface TestType void): void; + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a focused group of tests that should always be run serially. If one of the tests fails, all subsequent + * tests are skipped. All tests in a group are retried together. If there are some focused tests or suites, all of + * them will be run but nothing else. + * + * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run + * independently. + * + * - `test.describe.serial.only(title, callback)` + * - `test.describe.serial.only(title)` + * - `test.describe.serial.only(title, details, callback)` * * **Usage** * * ```js - * test.describe.skip('skipped group', () => { - * test('example', async ({ page }) => { - * // This test will not run + * test.describe.serial.only('group', () => { + * test('runs first', async ({ page }) => { + * }); + * test('runs second', async ({ page }) => { * }); * }); * ``` @@ -2489,7 +3037,7 @@ export interface TestType { + * test.describe.serial.only(() => { * // ... * }); * ``` @@ -2498,32 +3046,40 @@ export interface TestType void): void; + }; + /** - * Declares a test group similarly to - * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe). Tests in - * this group are marked as "fixme" and will not be executed. - * - `test.describe.fixme(title, callback)` - * - `test.describe.fixme(callback)` - * - `test.describe.fixme(title, details, callback)` + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a group of tests that could be run in parallel. By default, tests in a single test file run one after + * another, but using + * [test.describe.parallel([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel) + * allows them to run in parallel. + * - `test.describe.parallel(title, callback)` + * - `test.describe.parallel(callback)` + * - `test.describe.parallel(title, details, callback)` * * **Usage** * * ```js - * test.describe.fixme('broken tests that should be fixed', () => { - * test('example', async ({ page }) => { - * // This test will not run - * }); + * test.describe.parallel('group', () => { + * test('runs in parallel 1', async ({ page }) => {}); + * test('runs in parallel 2', async ({ page }) => {}); * }); * ``` * + * Note that parallel tests are executed in separate processes and cannot share any state or global variables. Each of + * the parallel tests executes all relevant hooks. + * * You can also omit the title. * * ```js - * test.describe.fixme(() => { + * test.describe.parallel(() => { * // ... * }); * ``` @@ -2532,37 +3088,38 @@ export interface TestType { - * test('runs first', async ({ page }) => {}); - * test('runs second', async ({ page }) => {}); + * test.describe.parallel('group', () => { + * test('runs in parallel 1', async ({ page }) => {}); + * test('runs in parallel 2', async ({ page }) => {}); * }); * ``` * + * Note that parallel tests are executed in separate processes and cannot share any state or global variables. Each of + * the parallel tests executes all relevant hooks. + * * You can also omit the title. * * ```js - * test.describe.serial(() => { + * test.describe.parallel(() => { * // ... * }); * ``` @@ -2571,40 +3128,38 @@ export interface TestType void): void; /** * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for * the preferred way of configuring the execution mode. * - * Declares a focused group of tests that should always be run serially. If one of the tests fails, all subsequent - * tests are skipped. All tests in a group are retried together. If there are some focused tests or suites, all of - * them will be run but nothing else. - * - * **NOTE** Using serial is not recommended. It is usually better to make your tests isolated, so they can be run - * independently. - * - * - `test.describe.serial.only(title, callback)` - * - `test.describe.serial.only(title)` - * - `test.describe.serial.only(title, details, callback)` + * Declares a group of tests that could be run in parallel. By default, tests in a single test file run one after + * another, but using + * [test.describe.parallel([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel) + * allows them to run in parallel. + * - `test.describe.parallel(title, callback)` + * - `test.describe.parallel(callback)` + * - `test.describe.parallel(title, details, callback)` * * **Usage** * * ```js - * test.describe.serial.only('group', () => { - * test('runs first', async ({ page }) => { - * }); - * test('runs second', async ({ page }) => { - * }); + * test.describe.parallel('group', () => { + * test('runs in parallel 1', async ({ page }) => {}); + * test('runs in parallel 2', async ({ page }) => {}); * }); * ``` * + * Note that parallel tests are executed in separate processes and cannot share any state or global variables. Each of + * the parallel tests executes all relevant hooks. + * * You can also omit the title. * * ```js - * test.describe.serial.only(() => { + * test.describe.parallel(() => { * // ... * }); * ``` @@ -2613,12 +3168,11 @@ export interface TestType void): void; + /** * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for * the preferred way of configuring the execution mode. * @@ -2657,7 +3211,80 @@ export interface TestType void): void; + + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a focused group of tests that could be run in parallel. This is similar to + * [test.describe.parallel([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel), + * but focuses the group. If there are some focused tests or suites, all of them will be run but nothing else. + * - `test.describe.parallel.only(title, callback)` + * - `test.describe.parallel.only(callback)` + * - `test.describe.parallel.only(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.parallel.only('group', () => { + * test('runs in parallel 1', async ({ page }) => {}); + * test('runs in parallel 2', async ({ page }) => {}); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.parallel.only(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.parallel.only([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel-only). + * Any tests added in this callback will belong to the group. + */ + only(title: string, callback: () => void): void; + /** + * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for + * the preferred way of configuring the execution mode. + * + * Declares a focused group of tests that could be run in parallel. This is similar to + * [test.describe.parallel([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel), + * but focuses the group. If there are some focused tests or suites, all of them will be run but nothing else. + * - `test.describe.parallel.only(title, callback)` + * - `test.describe.parallel.only(callback)` + * - `test.describe.parallel.only(title, details, callback)` + * + * **Usage** + * + * ```js + * test.describe.parallel.only('group', () => { + * test('runs in parallel 1', async ({ page }) => {}); + * test('runs in parallel 2', async ({ page }) => {}); + * }); + * ``` + * + * You can also omit the title. + * + * ```js + * test.describe.parallel.only(() => { + * // ... + * }); + * ``` + * + * @param title Group title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for + * details description. + * @param callback A callback that is run immediately when calling + * [test.describe.parallel.only([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe-parallel-only). + * Any tests added in this callback will belong to the group. + */ + only(callback: () => void): void; /** * **NOTE** See [test.describe.configure([options])](https://playwright.dev/docs/api/class-test#test-describe-configure) for * the preferred way of configuring the execution mode. @@ -2693,8 +3320,9 @@ export interface TestType void): void; }; + /** * Configures the enclosing scope. Can be executed either on the top level or inside a describe. Configuration applies * to the entire scope, regardless of whether it run before or after the test declaration. @@ -2754,6 +3382,7 @@ export interface TestType void; }; + /** * Skip a test. Playwright will not run the test past the `test.skip()` call. * @@ -2834,7 +3463,7 @@ export interface TestType Promise | void): void; + skip(title: string, body: TestBody): void; /** * Skip a test. Playwright will not run the test past the `test.skip()` call. * @@ -2915,7 +3544,7 @@ export interface TestType Promise | void): void; + skip(title: string, details: TestDetails, body: TestBody): void; /** * Skip a test. Playwright will not run the test past the `test.skip()` call. * @@ -3158,7 +3787,8 @@ export interface TestType boolean, description?: string): void; + skip(callback: ConditionBody, description?: string): void; + /** * Mark a test as "fixme", with the intention to fix it. Playwright will not run the test past the `test.fixme()` * call. @@ -3236,7 +3866,7 @@ export interface TestType Promise | void): void; + fixme(title: string, body: TestBody): void; /** * Mark a test as "fixme", with the intention to fix it. Playwright will not run the test past the `test.fixme()` * call. @@ -3314,7 +3944,7 @@ export interface TestType Promise | void): void; + fixme(title: string, details: TestDetails, body: TestBody): void; /** * Mark a test as "fixme", with the intention to fix it. Playwright will not run the test past the `test.fixme()` * call. @@ -3548,7 +4178,8 @@ export interface TestType boolean, description?: string): void; + fixme(callback: ConditionBody, description?: string): void; + /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. @@ -3702,7 +4333,7 @@ export interface TestType Promise | void): void; + (title: string, body: TestBody): void; /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. @@ -3779,7 +4410,7 @@ export interface TestType Promise | void): void; + (title: string, details: TestDetails, body: TestBody): void; /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. @@ -3933,7 +4564,7 @@ export interface TestType boolean, description?: string): void; + (callback: ConditionBody, description?: string): void; /** * Marks a test as "should fail". Playwright runs this test and ensures that it is actually failing. This is useful * for documentation purposes to acknowledge that some functionality is broken until it is fixed. @@ -4011,6 +4642,37 @@ export interface TestType { + * // This test is expected to fail + * }); + * test('not in the focused group', async ({ page }) => { + * // This test will not run + * }); + * ``` + * + * @param title Test title. + * @param details See [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) for test + * details description. + * @param body Test body that takes one or two arguments: an object with fixtures and optional + * [TestInfo](https://playwright.dev/docs/api/class-testinfo). + */ + only(title: string, body: TestBody): void; /** * You can use `test.fail.only` to focus on a specific test that is expected to fail. This is particularly useful when * debugging a failing test or working on a specific issue. @@ -4040,8 +4702,9 @@ export interface TestType; + only(title: string, details: TestDetails, body: TestBody): void; } + /** * Marks a test as "slow". Slow test will be given triple the default timeout. * @@ -4215,7 +4878,8 @@ export interface TestType boolean, description?: string): void; + slow(callback: ConditionBody, description?: string): void; + /** * Changes the timeout for the test. Zero means no timeout. Learn more about [various timeouts](https://playwright.dev/docs/test-timeouts). * diff --git a/utils/generate_types/index.js b/utils/generate_types/index.js index ae988ac32c168..b3ad1c4f23ce7 100644 --- a/utils/generate_types/index.js +++ b/utils/generate_types/index.js @@ -93,25 +93,8 @@ class TypesGenerator { handledClasses.add(className); return this.writeComment(docClass.comment, '') + '\n'; }, (className, methodName, overloadIndex) => { - if (className === 'SuiteFunction' && methodName === '__call') { - const cls = this.documentation.classes.get('Test'); - if (!cls) - throw new Error(`Unknown class "Test"`); - const method = cls.membersArray.find(m => m.alias === 'describe'); - if (!method) - throw new Error(`Unknown method "Test.describe"`); - return this.memberJSDOC(method, ' ').trimLeft(); - } - if (className === 'TestFunction' && methodName === '__call') { - const cls = this.documentation.classes.get('Test'); - if (!cls) - throw new Error(`Unknown class "Test"`); - const method = cls.membersArray.find(m => m.alias === '(call)'); - if (!method) - throw new Error(`Unknown method "Test.(call)"`); - return this.memberJSDOC(method, ' ').trimLeft(); - } - + if (methodName === '__call') + methodName = '(call)'; const docClass = this.docClassForName(className); let method; if (docClass) { @@ -591,8 +574,6 @@ class TypesGenerator { 'PlaywrightWorkerArgs.playwright', 'PlaywrightWorkerOptions.defaultBrowserType', 'Project', - 'SuiteFunction', - 'TestFunction', ]), doNotExportClassNames: assertionClasses, }); diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 54fffb5345851..ff46ba0e5c2d7 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -75,52 +75,83 @@ export type TestDetails = { annotation?: TestDetailsAnnotation | TestDetailsAnnotation[]; } -interface SuiteFunction { - (title: string, callback: () => void): void; - (callback: () => void): void; - (title: string, details: TestDetails, callback: () => void): void; -} +type TestBody = (args: TestArgs, testInfo: TestInfo) => Promise | void; +type ConditionBody = (args: TestArgs) => boolean; -interface TestFunction { - (title: string, body: (args: TestArgs, testInfo: TestInfo) => Promise | void): void; - (title: string, details: TestDetails, body: (args: TestArgs, testInfo: TestInfo) => Promise | void): void; -} +export interface TestType { + (title: string, body: TestBody): void; + (title: string, details: TestDetails, body: TestBody): void; + + only(title: string, body: TestBody): void; + only(title: string, details: TestDetails, body: TestBody): void; + + describe: { + (title: string, callback: () => void): void; + (callback: () => void): void; + (title: string, details: TestDetails, callback: () => void): void; + + only(title: string, callback: () => void): void; + only(callback: () => void): void; + only(title: string, details: TestDetails, callback: () => void): void; -export interface TestType extends TestFunction { - only: TestFunction; - describe: SuiteFunction & { - only: SuiteFunction; - skip: SuiteFunction; - fixme: SuiteFunction; - serial: SuiteFunction & { - only: SuiteFunction; + skip(title: string, callback: () => void): void; + skip(callback: () => void): void; + skip(title: string, details: TestDetails, callback: () => void): void; + + fixme(title: string, callback: () => void): void; + fixme(callback: () => void): void; + fixme(title: string, details: TestDetails, callback: () => void): void; + + serial: { + (title: string, callback: () => void): void; + (callback: () => void): void; + (title: string, details: TestDetails, callback: () => void): void; + + only(title: string, callback: () => void): void; + only(callback: () => void): void; + only(title: string, details: TestDetails, callback: () => void): void; }; - parallel: SuiteFunction & { - only: SuiteFunction; + + parallel: { + (title: string, callback: () => void): void; + (callback: () => void): void; + (title: string, details: TestDetails, callback: () => void): void; + + only(title: string, callback: () => void): void; + only(callback: () => void): void; + only(title: string, details: TestDetails, callback: () => void): void; }; + configure: (options: { mode?: 'default' | 'parallel' | 'serial', retries?: number, timeout?: number }) => void; }; - skip(title: string, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; - skip(title: string, details: TestDetails, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; + + skip(title: string, body: TestBody): void; + skip(title: string, details: TestDetails, body: TestBody): void; skip(): void; skip(condition: boolean, description?: string): void; - skip(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; - fixme(title: string, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; - fixme(title: string, details: TestDetails, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; + skip(callback: ConditionBody, description?: string): void; + + fixme(title: string, body: TestBody): void; + fixme(title: string, details: TestDetails, body: TestBody): void; fixme(): void; fixme(condition: boolean, description?: string): void; - fixme(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; + fixme(callback: ConditionBody, description?: string): void; + fail: { - (title: string, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; - (title: string, details: TestDetails, body: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | void): void; + (title: string, body: TestBody): void; + (title: string, details: TestDetails, body: TestBody): void; (condition: boolean, description?: string): void; - (callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; + (callback: ConditionBody, description?: string): void; (): void; - only: TestFunction; + + only(title: string, body: TestBody): void; + only(title: string, details: TestDetails, body: TestBody): void; } + slow(): void; slow(condition: boolean, description?: string): void; - slow(callback: (args: TestArgs & WorkerArgs) => boolean, description?: string): void; + slow(callback: ConditionBody, description?: string): void; + setTimeout(timeout: number): void; beforeEach(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; beforeEach(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; diff --git a/utils/generate_types/parseOverrides.js b/utils/generate_types/parseOverrides.js index ad80ea388f233..bb96013842275 100644 --- a/utils/generate_types/parseOverrides.js +++ b/utils/generate_types/parseOverrides.js @@ -101,9 +101,9 @@ async function parseOverrides(filePath, commentForClass, commentForMethod, extra * @param {ts.Node} node */ function visitProperties(className, prefix, node) { - // This function supports structs like "a: { b: string; c: number, (): void }" - // and inserts comments for "a.b", "a.c", a. - if (ts.isPropertySignature(node)) { + // This function supports structs like "a: { b: string; c: number, (): void, d(): void }" + // and inserts comments for "a.b", "a.c", "a", "a.d". + if (ts.isPropertySignature(node) || ts.isMethodSignature(node)) { const name = checker.getSymbolAtLocation(node.name).getName(); const pos = node.getStart(file, false); replacers.push({ From 65983b4bf8a260401a1de4ee670bf016adb7afb3 Mon Sep 17 00:00:00 2001 From: LeoTM <1881059+leotm@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:08:14 +0100 Subject: [PATCH 322/805] chore(docs): remove dead link to install config (#33160) Signed-off-by: LeoTM <1881059+leotm@users.noreply.github.com> --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index e865883de96b8..1d420a87687ee 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ npx playwright install You can optionally install only selected browsers, see [install browsers](https://playwright.dev/docs/cli#install-browsers) for more details. Or you can install no browsers at all and use existing [browser channels](https://playwright.dev/docs/browsers). * [Getting started](https://playwright.dev/docs/intro) -* [Installation configuration](https://playwright.dev/docs/installation) * [API reference](https://playwright.dev/docs/api/class-playwright) ## Capabilities From edb041f9e388e4201964beb49893e812da32a32c Mon Sep 17 00:00:00 2001 From: LeoTM <1881059+leotm@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:12:19 +0100 Subject: [PATCH 323/805] chore(docs): fix documentation url (#33161) Signed-off-by: LeoTM <1881059+leotm@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d420a87687ee..860e11db6567d 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ test('Intercept network requests', async ({ page }) => { ## Resources -* [Documentation](https://playwright.dev/docs/intro) +* [Documentation](https://playwright.dev) * [API reference](https://playwright.dev/docs/api/class-playwright/) * [Contribution guide](CONTRIBUTING.md) * [Changelog](https://github.com/microsoft/playwright/releases) From a2a5b102ab8c421ad3da27a4911b900d3eff648c Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 17 Oct 2024 06:13:17 -0700 Subject: [PATCH 324/805] chore: update CONTRIBUTING.md (#33138) --- CONTRIBUTING.md | 241 +++++++++++++++--------------------------------- 1 file changed, 76 insertions(+), 165 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b25a131d44a54..cb06a17e771a1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,92 +1,77 @@ # Contributing -- [How to Contribute](#how-to-contribute) - * [Getting Code](#getting-code) - * [Code reviews](#code-reviews) - * [Code Style](#code-style) - * [API guidelines](#api-guidelines) - * [Commit Messages](#commit-messages) - * [Writing Documentation](#writing-documentation) - * [Adding New Dependencies](#adding-new-dependencies) - * [Running & Writing Tests](#running--writing-tests) - * [Public API Coverage](#public-api-coverage) -- [Contributor License Agreement](#contributor-license-agreement) - * [Code of Conduct](#code-of-conduct) +## Choose an issue -## How to Contribute +Playwright **requires an issue** for every contribution, except for minor documentation updates. We strongly recommend to pick an issue labeled `open-to-a-pull-request` for your first contribution to the project. -We strongly recommend that you open an issue before beginning any code modifications. This is particularly important if the changes involve complex logic or if the existing code isn't immediately clear. By doing so, we can discuss and agree upon the best approach to address a bug or implement a feature, ensuring that our efforts are aligned. +If you are passioned about a bug/feature, but cannot find an issue describing it, **file an issue first**. This will facilitate the discussion and you might get some early feedback from project maintainers before spending your time on creating a pull request. -### Getting Code - -Make sure you're running Node.js 20 to verify and upgrade NPM do: +## Make a change +Make sure you're running Node.js 20 or later. ```bash node --version -npm --version -npm i -g npm@latest ``` -1. Clone this repository - - ```bash - git clone https://github.com/microsoft/playwright - cd playwright - ``` +Clone the repository. If you plan to send a pull request, it might be better to [fork the repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) first. +```bash +git clone https://github.com/microsoft/playwright +cd playwright +``` -2. Install dependencies +Install dependencies and run the build in watch mode. +```bash +npm ci +npm run watch +npx playwright install +``` - ```bash - npm ci - ``` +Playwright is a multi-package repository that uses npm workspaces. For browser APIs, look at [`packages/playwright-core`](https://github.com/microsoft/playwright/blob/main/packages/playwright-core). For test runner, see [`packages/playwright`](https://github.com/microsoft/playwright/blob/main/packages/playwright). -3. Build Playwright +Note that some files are generated by the build, so the watch process might override your changes if done in the wrong file. For example, TypeScript types for the API are generated from the [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src). - ```bash - npm run build - ``` +Coding style is fully defined in [.eslintrc](https://github.com/microsoft/playwright/blob/main/.eslintrc.js). Before creating a pull request, or at any moment during development, run linter to check all kinds of things: + ```bash + npm run lint + ``` -4. Run tests +Comments should be generally avoided. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory. - This will run a test on line `23` in `page-fill.spec.ts`: +### Write documentation - ```bash - npm run ctest -- page-fill:23 - ``` +Every part of the public API should be documented in [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src), in the same change that adds/changes the API. We use markdown files with custom structure to specify the API. Take a look around for an example. - See [here](#running--writing-tests) for more information about running and writing tests. +Various other files are generated from the API specification. If you are running `npm run watch`, these will be re-generated automatically. -### Code reviews +Larger changes will require updates to the documentation guides as well. This will be made clear during the code review. -All submissions, including submissions by project members, require review. We -use GitHub pull requests for this purpose. Consult -[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more -information on using pull requests. +## Add a test -### Code Style +Playwright requires a test for almost any new or modified functionality. An exception would be a pure refactoring, but chances are you are doing more than that. -- Coding style is fully defined in [.eslintrc](https://github.com/microsoft/playwright/blob/main/.eslintrc.js) -- Comments should be generally avoided. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory. +There are multiple [test suites](https://github.com/microsoft/playwright/blob/main/tests) in Playwright that will be executed on the CI. The two most important that you need to run locally are: -To run code linter, use: +- Library tests cover APIs not related to the test runner. + ```bash + # fast path runs all tests in Chromium + npm run ctest -```bash -npm run eslint -``` + # slow path runs all tests in three browsers + npm run test + ``` -### API guidelines +- Test runner tests. + ```bash + npm run ttest + ``` -When authoring new API methods, consider the following: +Since Playwright tests are using Playwright under the hood, everything from our documentation applies, for example [this guide on running and debugging tests](https://playwright.dev/docs/running-tests#running-tests). -- Expose as little information as needed. When in doubt, don’t expose new information. -- Methods are used in favor of getters/setters. - - The only exception is namespaces, e.g. `page.keyboard` and `page.coverage` -- All string literals must be lowercase. This includes event names and option values. -- Avoid adding "sugar" API (API that is trivially implementable in user-space) unless they're **very** common. +Note that tests should be *hermetic*, and not depend on external services. Tests should work on all three platforms: macOS, Linux and Windows. -### Commit Messages +## Write a commit message -Commit messages should follow the Semantic Commit Messages format: +Commit messages should follow the [Semantic Commit Messages](https://www.conventionalcommits.org/en/v1.0.0/) format: ``` label(namespace): title @@ -97,131 +82,57 @@ footer ``` 1. *label* is one of the following: - - `fix` - playwright bug fixes. - - `feat` - playwright features. - - `docs` - changes to docs, e.g. `docs(api): ..` to change documentation. - - `test` - changes to playwright tests infrastructure. - - `devops` - build-related work, e.g. CI related patches and general changes to the browser build infrastructure + - `fix` - bug fixes + - `feat` - new features + - `docs` - documentation-only changes + - `test` - test-only changes + - `devops` - changes to the CI or build - `chore` - everything that doesn't fall under previous categories -2. *namespace* is put in parenthesis after label and is optional. Must be lowercase. -3. *title* is a brief summary of changes. -4. *description* is **optional**, new-line separated from title and is in present tense. -5. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to github issues. +1. *namespace* is put in parenthesis after label and is optional. Must be lowercase. +1. *title* is a brief summary of changes. +1. *description* is **optional**, new-line separated from title and is in present tense. +1. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to github issues. Example: ``` -fix(firefox): make sure session cookies work +feat(trace viewer): network panel filtering -This patch fixes session cookies in the firefox browser. +This patch adds a filtering toolbar to the network panel. + -Fixes #123, fixes #234 +Fixes #123, references #234. ``` -### Writing Documentation - -All API classes, methods, and events should have a description in [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src). There's a [documentation linter](https://github.com/microsoft/playwright/tree/main/utils/doclint) which makes sure documentation is aligned with the codebase. - -To run the documentation linter, use: - -```bash -npm run doc -``` - -To build the documentation site locally and test how your changes will look in practice: - -1. Clone the [microsoft/playwright.dev](https://github.com/microsoft/playwright.dev) repo -1. Follow [the playwright.dev README instructions to "roll docs"](https://github.com/microsoft/playwright.dev/#roll-docs) against your local `playwright` repo with your changes in progress -1. Follow [the playwright.dev README instructions to "run dev server"](https://github.com/microsoft/playwright.dev/#run-dev-server) to view your changes - -### Adding New Dependencies +## Send a pull request -For all dependencies (both installation and development): -- **Do not add** a dependency if the desired functionality is easily implementable. -- If adding a dependency, it should be well-maintained and trustworthy. +All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. -A barrier for introducing new installation dependencies is especially high: -- **Do not add** installation dependency unless it's critical to project success. +After a successful code review, one of the maintainers will merge your pull request. Congratulations! -### Running & Writing Tests +## More details -- Every feature should be accompanied by a test. -- Every public api event/method should be accompanied by a test. -- Tests should be *hermetic*. Tests should not depend on external services. -- Tests should work on all three platforms: Mac, Linux and Win. This is especially important for screenshot tests. +**No new dependencies** -Playwright tests are located in [`tests`](https://github.com/microsoft/playwright/blob/main/tests) and use `@playwright/test` test runner. -These are integration tests, making sure public API methods and events work as expected. +There is a very high bar for new dependencies, including updating to a new version of an existing dependency. We recommend to explicitly discuss this in an issue and get a green light from a maintainer, before creating a pull request that updates dependencies. -- To run all tests: +**Custom browser build** - ```bash - npx playwright install - npm run test - ``` - - Be sure to run `npm run build` or let `npm run watch` run before you re-run the - tests after making your changes to check them. - -- To run tests in Chromium - - ```bash - npm run ctest # also `ftest` for firefox and `wtest` for WebKit - npm run ctest -- page-fill:23 # runs line 23 of page-fill.spec.ts - ``` - -- To run tests in WebKit / Firefox, use `wtest` or `ftest`. - -- To run the Playwright test runner tests - - ```bash - npm run ttest - npm run ttest -- --grep "specific test" - ``` - -- To run a specific test, substitute `it` with `it.only`, or use the `--grep 'My test'` CLI parameter: - - ```js - ... - // Using "it.only" to run a specific test - it.only('should work', async ({server, page}) => { - const response = await page.goto(server.EMPTY_PAGE); - expect(response.ok).toBe(true); - }); - // or - playwright test --config=xxx --grep 'should work' - ``` - -- To disable a specific test, substitute `it` with `it.skip`: - - ```js - ... - // Using "it.skip" to skip a specific test - it.skip('should work', async ({server, page}) => { - const response = await page.goto(server.EMPTY_PAGE); - expect(response.ok).toBe(true); - }); - ``` - -- To run tests in non-headless (headed) mode: - - ```bash - npm run ctest -- --headed - ``` - -- To run tests with custom browser executable, specify `CRPATH`, `WKPATH` or `FFPATH` env variable that points to browser executable: +To run tests with custom browser executable, specify `CRPATH`, `WKPATH` or `FFPATH` env variable that points to browser executable: +```bash +CRPATH= npm run ctest +``` - ```bash - CRPATH= npm run ctest - ``` +You will also find `DEBUG=pw:browser` useful for debugging custom builds. -- When should a test be marked with `skip` or `fixme`? +**Building documentation site** - - **`skip(condition)`**: This test *should ***never*** work* for `condition` - where `condition` is usually something like: `test.skip(browserName === 'chromium', 'This does not work because of ...')`. +The [playwright.dev](https://playwright.dev/) documentation site lives in a separate repository, and documentation from [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src) is frequently rolled there. - - **`fixme(condition)`**: This test *should ***eventually*** work* for `condition` - where `condition` is usually something like: `test.fixme(browserName === 'chromium', 'We are waiting for version x')`. +Most of the time this should not concern you. However, if you are doing something unusual in the docs, you can build locally and test how your changes will look in practice: +1. Clone the [microsoft/playwright.dev](https://github.com/microsoft/playwright.dev) repo. +1. Follow [the playwright.dev README instructions to "roll docs"](https://github.com/microsoft/playwright.dev/#roll-docs) against your local `playwright` repo with your changes in progress. +1. Follow [the playwright.dev README instructions to "run dev server"](https://github.com/microsoft/playwright.dev/#run-dev-server) to view your changes. ## Contributor License Agreement From aa952c1b03d5676c29760793cdefa0bdc78222f9 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 17 Oct 2024 08:33:15 -0700 Subject: [PATCH 325/805] fix(html report): generate test snippets when test dir is non-root (#33162) --- packages/html-reporter/src/testErrorView.tsx | 5 +-- packages/html-reporter/src/testResultView.tsx | 2 +- packages/playwright/src/reporters/html.ts | 4 +-- tests/playwright-test/reporter-html.spec.ts | 32 +++++++++++++++++-- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/packages/html-reporter/src/testErrorView.tsx b/packages/html-reporter/src/testErrorView.tsx index 520da1fc19c0e..8d2bb13bd3065 100644 --- a/packages/html-reporter/src/testErrorView.tsx +++ b/packages/html-reporter/src/testErrorView.tsx @@ -22,9 +22,10 @@ import { ImageDiffView } from '@web/shared/imageDiffView'; export const TestErrorView: React.FC<{ error: string; -}> = ({ error }) => { + testId?: string; +}> = ({ error, testId }) => { const html = React.useMemo(() => ansiErrorToHtml(error), [error]); - return
          ; + return
          ; }; export const TestScreenshotErrorView: React.FC<{ diff --git a/packages/html-reporter/src/testResultView.tsx b/packages/html-reporter/src/testResultView.tsx index 48a24a2391f27..bb18422dd084f 100644 --- a/packages/html-reporter/src/testResultView.tsx +++ b/packages/html-reporter/src/testResultView.tsx @@ -186,7 +186,7 @@ const StepTreeItem: React.FC<{ } loadChildren={step.steps.length + (step.snippet ? 1 : 0) ? () => { const children = step.steps.map((s, i) => ); if (step.snippet) - children.unshift(); + children.unshift(); return children; } : undefined} depth={depth}>; }; diff --git a/packages/playwright/src/reporters/html.ts b/packages/playwright/src/reporters/html.ts index 5aada7e495b3c..584c11bae81ff 100644 --- a/packages/playwright/src/reporters/html.ts +++ b/packages/playwright/src/reporters/html.ts @@ -505,8 +505,8 @@ class HtmlBuilder { error: step.error?.message, count }; - if (result.location) - this._stepsInFile.set(result.location.file, result); + if (step.location) + this._stepsInFile.set(step.location.file, result); return result; } diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index 6a75602bf1048..d9e604f99449e 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -43,7 +43,7 @@ const expect = baseExpect.configure({ timeout: process.env.CI ? 75000 : 25000 }) test.describe.configure({ mode: 'parallel' }); -for (const useIntermediateMergeReport of [false] as const) { +for (const useIntermediateMergeReport of [true, false] as const) { test.describe(`${useIntermediateMergeReport ? 'merged' : 'created'}`, () => { test.use({ useIntermediateMergeReport }); @@ -612,7 +612,7 @@ for (const useIntermediateMergeReport of [false] as const) { ]); }); `, - }, { reporter: 'html' }, { PLAYWRIGHT_HTML_OPEN: 'never' }); + }, { reporter: 'html,dot' }, { PLAYWRIGHT_HTML_OPEN: 'never' }); expect(result.exitCode).toBe(0); expect(result.passed).toBe(1); @@ -727,6 +727,34 @@ for (const useIntermediateMergeReport of [false] as const) { ]); }); + test('should show step snippets from non-root', async ({ runInlineTest, page, showReport }) => { + const result = await runInlineTest({ + 'playwright.config.js': ` + export default { testDir: './tests' }; + `, + 'tests/a.test.ts': ` + import { test, expect } from '@playwright/test'; + + test('example', async ({}) => { + await test.step('step title', async () => { + expect(1).toBe(1); + }); + }); + `, + }, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + await showReport(); + await page.click('text=example'); + await page.click('text=step title'); + await page.click('text=expect.toBe'); + await expect(page.getByTestId('test-snippet')).toContainText([ + `await test.step('step title', async () => {`, + 'expect(1).toBe(1);', + ]); + }); + test('should render annotations', async ({ runInlineTest, page, showReport }) => { const result = await runInlineTest({ 'playwright.config.js': ` From 623a8916f9acf76f3a49287f3d63af9f9dac591a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 17 Oct 2024 16:57:45 -0700 Subject: [PATCH 326/805] chore: implement tree w/o list (#33167) --- .../src/ui/uiModeTestListView.css | 12 +- .../src/ui/uiModeTestListView.tsx | 6 +- packages/web/src/components/gridView.tsx | 3 - packages/web/src/components/listView.tsx | 31 +-- packages/web/src/components/treeView.css | 91 +++++++ packages/web/src/components/treeView.tsx | 240 ++++++++++++++---- packages/web/src/uiUtils.ts | 9 + tests/config/traceViewerFixtures.ts | 4 +- tests/playwright-test/ui-mode-fixtures.ts | 16 +- .../ui-mode-test-annotations.spec.ts | 2 +- .../ui-mode-test-filters.spec.ts | 2 +- .../ui-mode-test-progress.spec.ts | 22 +- .../playwright-test/ui-mode-test-run.spec.ts | 4 +- .../ui-mode-test-setup.spec.ts | 2 +- .../ui-mode-test-update.spec.ts | 4 +- .../ui-mode-test-watch.spec.ts | 16 +- tests/playwright-test/ui-mode-trace.spec.ts | 14 +- 17 files changed, 339 insertions(+), 139 deletions(-) create mode 100644 packages/web/src/components/treeView.css diff --git a/packages/trace-viewer/src/ui/uiModeTestListView.css b/packages/trace-viewer/src/ui/uiModeTestListView.css index ae6fd624ee520..335daecfb1ad1 100644 --- a/packages/trace-viewer/src/ui/uiModeTestListView.css +++ b/packages/trace-viewer/src/ui/uiModeTestListView.css @@ -14,28 +14,28 @@ limitations under the License. */ -.ui-mode-list-item { +.ui-mode-tree-item { flex: auto; } -.ui-mode-list-item-title { +.ui-mode-tree-item-title { flex: auto; text-overflow: ellipsis; overflow: hidden; } -.ui-mode-list-item-time { +.ui-mode-tree-item-time { flex: none; color: var(--vscode-editorCodeLens-foreground); margin: 0 4px; user-select: none; } -.tests-list-view .list-view-entry.selected .ui-mode-list-item-time, -.tests-list-view .list-view-entry.highlighted .ui-mode-list-item-time { +.tests-tree-view .tree-view-entry.selected .ui-mode-tree-item-time, +.tests-tree-view .tree-view-entry.highlighted .ui-mode-tree-item-time { display: none; } -.tests-list-view .list-view-entry:not(.highlighted):not(.selected) .toolbar-button:not(.toggled) { +.tests-tree-view .tree-view-entry:not(.highlighted):not(.selected) .toolbar-button:not(.toggled) { display: none; } diff --git a/packages/trace-viewer/src/ui/uiModeTestListView.tsx b/packages/trace-viewer/src/ui/uiModeTestListView.tsx index ce1c0fef373d9..96fbaadbf78ad 100644 --- a/packages/trace-viewer/src/ui/uiModeTestListView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTestListView.tsx @@ -159,12 +159,12 @@ export const TestListView: React.FC<{ rootItem={testTree.rootItem} dataTestId='test-tree' render={treeItem => { - return
          -
          + return
          +
          {treeItem.title} {treeItem.kind === 'case' ? treeItem.tags.map(tag => handleTagClick(e, tag)} />) : null}
          - {!!treeItem.duration && treeItem.status !== 'skipped' &&
          {msToString(treeItem.duration)}
          } + {!!treeItem.duration && treeItem.status !== 'skipped' &&
          {msToString(treeItem.duration)}
          } runTreeItem(treeItem)} disabled={!!runningState && !runningState.completed}> diff --git a/packages/web/src/components/gridView.tsx b/packages/web/src/components/gridView.tsx index 5d9b0a4c6cc9e..10fc48c247037 100644 --- a/packages/web/src/components/gridView.tsx +++ b/packages/web/src/components/gridView.tsx @@ -110,15 +110,12 @@ export function GridView(model: GridViewProps) { ; }} icon={model.icon} - indent={model.indent} isError={model.isError} isWarning={model.isWarning} isInfo={model.isInfo} selectedItem={model.selectedItem} onAccepted={model.onAccepted} onSelected={model.onSelected} - onLeftArrow={model.onLeftArrow} - onRightArrow={model.onRightArrow} onHighlighted={model.onHighlighted} onIconClicked={model.onIconClicked} noItemsMessage={model.noItemsMessage} diff --git a/packages/web/src/components/listView.tsx b/packages/web/src/components/listView.tsx index 4f2de5ae5447c..73f9b65b8f3d1 100644 --- a/packages/web/src/components/listView.tsx +++ b/packages/web/src/components/listView.tsx @@ -16,7 +16,7 @@ import * as React from 'react'; import './listView.css'; -import { clsx } from '@web/uiUtils'; +import { clsx, scrollIntoViewIfNeeded } from '@web/uiUtils'; export type ListViewProps = { name: string, @@ -24,15 +24,12 @@ export type ListViewProps = { id?: (item: T, index: number) => string, render: (item: T, index: number) => React.ReactNode, icon?: (item: T, index: number) => string | undefined, - indent?: (item: T, index: number) => number | undefined, isError?: (item: T, index: number) => boolean, isWarning?: (item: T, index: number) => boolean, isInfo?: (item: T, index: number) => boolean, selectedItem?: T, onAccepted?: (item: T, index: number) => void, onSelected?: (item: T, index: number) => void, - onLeftArrow?: (item: T, index: number) => void, - onRightArrow?: (item: T, index: number) => void, onHighlighted?: (item: T | undefined) => void, onIconClicked?: (item: T, index: number) => void, noItemsMessage?: string, @@ -51,12 +48,9 @@ export function ListView({ isError, isWarning, isInfo, - indent, selectedItem, onAccepted, onSelected, - onLeftArrow, - onRightArrow, onHighlighted, onIconClicked, noItemsMessage, @@ -95,21 +89,12 @@ export function ListView({ onAccepted?.(selectedItem, items.indexOf(selectedItem)); return; } - if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp' && event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return; event.stopPropagation(); event.preventDefault(); - if (selectedItem && event.key === 'ArrowLeft') { - onLeftArrow?.(selectedItem, items.indexOf(selectedItem)); - return; - } - if (selectedItem && event.key === 'ArrowRight') { - onRightArrow?.(selectedItem, items.indexOf(selectedItem)); - return; - } - const index = selectedItem ? items.indexOf(selectedItem) : -1; let newIndex = index; if (event.key === 'ArrowDown') { @@ -135,7 +120,6 @@ export function ListView({ > {noItemsMessage && items.length === 0 &&
          {noItemsMessage}
          } {items.map((item, index) => { - const indentation = indent?.(item, index) || 0; const rendered = render(item, index); return
          ({ onMouseEnter={() => setHighlightedItem(item)} onMouseLeave={() => setHighlightedItem(undefined)} > - {/* eslint-disable-next-line react/jsx-key */} - {indentation ? new Array(indentation).fill(0).map(() =>
          ) : undefined} {icon &&
          ({
          ; } - -function scrollIntoViewIfNeeded(element: Element | undefined) { - if (!element) - return; - if ((element as any)?.scrollIntoViewIfNeeded) - (element as any).scrollIntoViewIfNeeded(false); - else - element?.scrollIntoView(); -} diff --git a/packages/web/src/components/treeView.css b/packages/web/src/components/treeView.css new file mode 100644 index 0000000000000..860d560fc9f92 --- /dev/null +++ b/packages/web/src/components/treeView.css @@ -0,0 +1,91 @@ +/* + Copyright (c) Microsoft Corporation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +.tree-view-content { + display: flex; + flex-direction: column; + flex: auto; + position: relative; + user-select: none; + overflow: hidden auto; + outline: 1px solid transparent; +} + +.tree-view-entry { + display: flex; + flex: none; + cursor: pointer; + align-items: center; + white-space: nowrap; + line-height: 28px; + padding-left: 5px; +} + +.tree-view-content.not-selectable > .tree-view-entry { + cursor: inherit; +} + +.tree-view-entry.highlighted:not(.selected) { + background-color: var(--vscode-list-inactiveSelectionBackground) !important; +} + +.tree-view-entry.selected { + z-index: 10; +} + +.tree-view-indent { + min-width: 16px; +} + +.tree-view-content:focus .tree-view-entry.selected { + background-color: var(--vscode-list-activeSelectionBackground); + color: var(--vscode-list-activeSelectionForeground); + outline: 1px solid var(--vscode-focusBorder); +} + +.tree-view-content .tree-view-entry.selected { + background-color: var(--vscode-list-inactiveSelectionBackground); +} + +.tree-view-content:focus .tree-view-entry.selected * { + color: var(--vscode-list-activeSelectionForeground) !important; + background-color: transparent !important; +} + +.tree-view-content:focus .tree-view-entry.selected .codicon { + color: var(--vscode-list-activeSelectionForeground) !important; +} + +.tree-view-empty { + flex: auto; + display: flex; + align-items: center; + justify-content: center; +} + +.tree-view-entry.error { + color: var(--vscode-list-errorForeground); + background-color: var(--vscode-inputValidation-errorBackground); +} + +.tree-view-entry.warning { + color: var(--vscode-list-warningForeground); + background-color: var(--vscode-inputValidation-warningBackground); +} + +.tree-view-entry.info { + background-color: var(--vscode-inputValidation-infoBackground); +} diff --git a/packages/web/src/components/treeView.tsx b/packages/web/src/components/treeView.tsx index 8341056779bdb..6ad722145531f 100644 --- a/packages/web/src/components/treeView.tsx +++ b/packages/web/src/components/treeView.tsx @@ -15,7 +15,8 @@ */ import * as React from 'react'; -import { ListView } from './listView'; +import { clsx, scrollIntoViewIfNeeded } from '@web/uiUtils'; +import './treeView.css'; export type TreeItem = { id: string, @@ -45,7 +46,7 @@ export type TreeViewProps = { autoExpandDepth?: number, }; -const TreeListView = ListView; +const scrollPositions = new Map(); export function TreeView({ name, @@ -97,61 +98,185 @@ export function TreeView({ return result; }, [treeItems, isVisible]); - return item.id} - dataTestId={dataTestId || (name + '-tree')} - render={item => { - const rendered = render(item as T); - return <> - {icon &&
          } - {typeof rendered === 'string' ?
          {rendered}
          : rendered} - ; - }} - icon={item => { - const expanded = treeItems.get(item as T)!.expanded; - if (typeof expanded === 'boolean') - return expanded ? 'codicon-chevron-down' : 'codicon-chevron-right'; - }} - isError={item => isError?.(item as T) || false} - indent={item => treeItems.get(item as T)!.depth} - selectedItem={selectedItem} - onAccepted={item => onAccepted?.(item as T)} - onSelected={item => onSelected?.(item as T)} - onHighlighted={item => onHighlighted?.(item as T)} - onLeftArrow={item => { - const { expanded, parent } = treeItems.get(item as T)!; - if (expanded) { - treeState.expandedItems.set(item.id, false); - setTreeState({ ...treeState }); - } else if (parent) { - onSelected?.(parent as T); - } - }} - onRightArrow={item => { - if (item.children.length) { - treeState.expandedItems.set(item.id, true); - setTreeState({ ...treeState }); + const itemListRef = React.useRef(null); + const [highlightedItem, setHighlightedItem] = React.useState(); + + React.useEffect(() => { + onHighlighted?.(highlightedItem); + }, [onHighlighted, highlightedItem]); + + React.useEffect(() => { + const treeElem = itemListRef.current; + if (!treeElem) + return; + const saveScrollPosition = () => { + scrollPositions.set(name, treeElem.scrollTop); + }; + treeElem.addEventListener('scroll', saveScrollPosition, { passive: true }); + return () => treeElem.removeEventListener('scroll', saveScrollPosition); + }, [name]); + + React.useEffect(() => { + if (itemListRef.current) + itemListRef.current.scrollTop = scrollPositions.get(name) || 0; + }, [name]); + + const toggleExpanded = React.useCallback((item: T) => { + const { expanded } = treeItems.get(item)!; + if (expanded) { + // Move nested selection up. + for (let i: TreeItem | undefined = selectedItem; i; i = i.parent) { + if (i === item) { + onSelected?.(item as T); + break; + } } - }} - onIconClicked={item => { - const { expanded } = treeItems.get(item as T)!; - if (expanded) { - // Move nested selection up. - for (let i: TreeItem | undefined = selectedItem; i; i = i.parent) { - if (i === item) { - onSelected?.(item as T); - break; + treeState.expandedItems.set(item.id, false); + } else { + treeState.expandedItems.set(item.id, true); + } + setTreeState({ ...treeState }); + }, [treeItems, selectedItem, onSelected, treeState, setTreeState]); + + return
          +
          { + if (selectedItem && event.key === 'Enter') { + onAccepted?.(selectedItem); + return; + } + if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp' && event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') + return; + + event.stopPropagation(); + event.preventDefault(); + + if (selectedItem && event.key === 'ArrowLeft') { + const { expanded, parent } = treeItems.get(selectedItem)!; + if (expanded) { + treeState.expandedItems.set(selectedItem.id, false); + setTreeState({ ...treeState }); + } else if (parent) { + onSelected?.(parent as T); } + return; } - treeState.expandedItems.set(item.id, false); - } else { - treeState.expandedItems.set(item.id, true); - } - setTreeState({ ...treeState }); - }} - noItemsMessage={noItemsMessage} />; + if (selectedItem && event.key === 'ArrowRight') { + if (selectedItem.children.length) { + treeState.expandedItems.set(selectedItem.id, true); + setTreeState({ ...treeState }); + } + return; + } + + const index = selectedItem ? visibleItems.indexOf(selectedItem) : -1; + let newIndex = index; + if (event.key === 'ArrowDown') { + if (index === -1) + newIndex = 0; + else + newIndex = Math.min(index + 1, visibleItems.length - 1); + } + if (event.key === 'ArrowUp') { + if (index === -1) + newIndex = visibleItems.length - 1; + else + newIndex = Math.max(index - 1, 0); + } + + const element = itemListRef.current?.children.item(newIndex); + scrollIntoViewIfNeeded(element || undefined); + onHighlighted?.(undefined); + onSelected?.(visibleItems[newIndex]); + setHighlightedItem(undefined); + }} + ref={itemListRef} + > + {noItemsMessage && visibleItems.length === 0 &&
          {noItemsMessage}
          } + {visibleItems.map(item => { + return
          + +
          ; + })} +
          +
          ; +} + +type TreeItemHeaderProps = { + item: T, + itemData: TreeItemData, + selectedItem: T | undefined, + onSelected?: (item: T) => void, + toggleExpanded: (item: T) => void, + highlightedItem: T | undefined, + isError?: (item: T) => boolean, + onAccepted?: (item: T) => void, + setHighlightedItem: (item: T | undefined) => void, + render: (item: T) => React.ReactNode, + icon?: (item: T) => string | undefined, +}; + +export function TreeItemHeader({ + item, + itemData, + selectedItem, + onSelected, + highlightedItem, + setHighlightedItem, + isError, + onAccepted, + toggleExpanded, + render, + icon }: TreeItemHeaderProps) { + + const indentation = itemData.depth; + const expanded = itemData.expanded; + let expandIcon = 'codicon-blank'; + if (typeof expanded === 'boolean') + expandIcon = expanded ? 'codicon-chevron-down' : 'codicon-chevron-right'; + const rendered = render(item); + + return
          onAccepted?.(item)} + className={clsx( + 'tree-view-entry', + selectedItem === item && 'selected', + highlightedItem === item && 'highlighted', + isError?.(item) && 'error')} + onClick={() => onSelected?.(item)} + onMouseEnter={() => setHighlightedItem(item)} + onMouseLeave={() => setHighlightedItem(undefined)} + > + {indentation ? new Array(indentation).fill(0).map((_, i) =>
          ) : undefined} +
          { + e.preventDefault(); + e.stopPropagation(); + }} + onClick={e => { + e.stopPropagation(); + e.preventDefault(); + toggleExpanded(item); + }} + /> + {icon &&
          } + {typeof rendered === 'string' ?
          {rendered}
          : rendered} +
          ; } type TreeItemData = { @@ -160,7 +285,12 @@ type TreeItemData = { parent: TreeItem | null, }; -function flattenTree(rootItem: T, selectedItem: T | undefined, expandedItems: Map, autoExpandDepth: number): Map { +function flattenTree( + rootItem: T, + selectedItem: T | undefined, + expandedItems: Map, + autoExpandDepth: number): Map { + const result = new Map(); const temporaryExpanded = new Set(); for (let item: TreeItem | undefined = selectedItem?.parent; item; item = item.parent) diff --git a/packages/web/src/uiUtils.ts b/packages/web/src/uiUtils.ts index 2697177c6f624..ea714860146fb 100644 --- a/packages/web/src/uiUtils.ts +++ b/packages/web/src/uiUtils.ts @@ -208,5 +208,14 @@ export async function sha1(str: string): Promise { return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-1', buffer))).map(b => b.toString(16).padStart(2, '0')).join(''); } +export function scrollIntoViewIfNeeded(element: Element | undefined) { + if (!element) + return; + if ((element as any)?.scrollIntoViewIfNeeded) + (element as any).scrollIntoViewIfNeeded(false); + else + element?.scrollIntoView(); +} + const kControlCodesRe = '\\u0000-\\u0020\\u007f-\\u009f'; export const kWebLinkRe = new RegExp('(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\\/\\/|www\\.)[^\\s' + kControlCodesRe + '"]{2,}[^\\s' + kControlCodesRe + '"\')}\\],:;.!?]', 'ug'); diff --git a/tests/config/traceViewerFixtures.ts b/tests/config/traceViewerFixtures.ts index 0fe4a9a5c9931..3eb3b11a153c7 100644 --- a/tests/config/traceViewerFixtures.ts +++ b/tests/config/traceViewerFixtures.ts @@ -62,13 +62,13 @@ class TraceViewerPage { } async actionIconsText(action: string) { - const entry = await this.page.waitForSelector(`.list-view-entry:has-text("${action}")`); + const entry = await this.page.waitForSelector(`.tree-view-entry:has-text("${action}")`); await entry.waitForSelector('.action-icon-value:visible'); return await entry.$$eval('.action-icon-value:visible', ee => ee.map(e => e.textContent)); } async actionIcons(action: string) { - return await this.page.waitForSelector(`.list-view-entry:has-text("${action}") .action-icons`); + return await this.page.waitForSelector(`.tree-view-entry:has-text("${action}") .action-icons`); } @step diff --git a/tests/playwright-test/ui-mode-fixtures.ts b/tests/playwright-test/ui-mode-fixtures.ts index 2952761d607d7..1e3b11a03ab09 100644 --- a/tests/playwright-test/ui-mode-fixtures.ts +++ b/tests/playwright-test/ui-mode-fixtures.ts @@ -66,16 +66,16 @@ export function dumpTestTree(page: Page, options: { time?: boolean } = {}): () = } const result: string[] = []; - const listItems = treeElement.querySelectorAll('[role=listitem]'); - for (const listItem of listItems) { - const iconElements = listItem.querySelectorAll('.codicon'); + const treeItems = treeElement.querySelectorAll('[role=treeitem]'); + for (const treeItem of treeItems) { + const iconElements = treeItem.querySelectorAll('.codicon'); const treeIcon = iconName(iconElements[0]); const statusIcon = iconName(iconElements[1]); - const indent = listItem.querySelectorAll('.list-view-indent').length; - const watch = listItem.querySelector('.toolbar-button.eye.toggled') ? ' 👁' : ''; - const selected = listItem.classList.contains('selected') ? ' <=' : ''; - const title = listItem.querySelector('.ui-mode-list-item-title').childNodes[0].textContent; - const timeElement = options.time ? listItem.querySelector('.ui-mode-list-item-time') : undefined; + const indent = treeItem.querySelectorAll('.tree-view-indent').length; + const watch = treeItem.querySelector('.toolbar-button.eye.toggled') ? ' 👁' : ''; + const selected = treeItem.getAttribute('aria-selected') === 'true' ? ' <=' : ''; + const title = treeItem.querySelector('.ui-mode-tree-item-title').childNodes[0].textContent; + const timeElement = options.time ? treeItem.querySelector('.ui-mode-tree-item-time') : undefined; const time = timeElement ? ' ' + timeElement.textContent.replace(/[.\d]+m?s/, 'XXms') : ''; result.push(' ' + ' '.repeat(indent) + treeIcon + ' ' + statusIcon + ' ' + title + time + watch + selected); } diff --git a/tests/playwright-test/ui-mode-test-annotations.spec.ts b/tests/playwright-test/ui-mode-test-annotations.spec.ts index 7a0dea8af10c5..f32d43aecfbab 100644 --- a/tests/playwright-test/ui-mode-test-annotations.spec.ts +++ b/tests/playwright-test/ui-mode-test-annotations.spec.ts @@ -33,7 +33,7 @@ test('should display annotations', async ({ runUITest }) => { }); await page.getByTitle('Run all').click(); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); - await page.getByRole('listitem').filter({ hasText: 'suite' }).locator('.codicon-chevron-right').click(); + await page.getByRole('treeitem').filter({ hasText: 'suite' }).locator('.codicon-chevron-right').click(); await page.getByText('annotation test').click(); await page.getByText('Annotations', { exact: true }).click(); diff --git a/tests/playwright-test/ui-mode-test-filters.spec.ts b/tests/playwright-test/ui-mode-test-filters.spec.ts index 5d70048473e5f..dd59c334b22c6 100644 --- a/tests/playwright-test/ui-mode-test-filters.spec.ts +++ b/tests/playwright-test/ui-mode-test-filters.spec.ts @@ -64,7 +64,7 @@ test('should display native tags and filter by them on click', async ({ runUITes test('pwt', { tag: '@smoke' }, () => {}); `, }); - await page.locator('.ui-mode-list-item-title').getByText('smoke').click(); + await page.locator('.ui-mode-tree-item-title').getByText('smoke').click(); await expect(page.getByPlaceholder('Filter')).toHaveValue('@smoke'); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts diff --git a/tests/playwright-test/ui-mode-test-progress.spec.ts b/tests/playwright-test/ui-mode-test-progress.spec.ts index f87eaa8fbcd68..f2f01a79ce31f 100644 --- a/tests/playwright-test/ui-mode-test-progress.spec.ts +++ b/tests/playwright-test/ui-mode-test-progress.spec.ts @@ -47,7 +47,7 @@ test('should update trace live', async ({ runUITest, server }) => { await page.getByText('live test').dblclick(); // It should halt on loading one.html. - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -57,11 +57,11 @@ test('should update trace live', async ({ runUITest, server }) => { ]); await expect( - listItem.locator(':scope.selected'), + listItem.locator(':scope[aria-selected="true"]'), 'last action to be selected' ).toHaveText(/page.goto/); await expect( - listItem.locator(':scope.selected .codicon.codicon-loading'), + listItem.locator(':scope[aria-selected="true"] .codicon.codicon-loading'), 'spinner' ).toBeVisible(); @@ -83,11 +83,11 @@ test('should update trace live', async ({ runUITest, server }) => { /page.gotohttp:\/\/localhost:\d+\/two.html/ ]); await expect( - listItem.locator(':scope.selected'), + listItem.locator(':scope[aria-selected="true"]'), 'last action to be selected' ).toHaveText(/page.goto/); await expect( - listItem.locator(':scope.selected .codicon.codicon-loading'), + listItem.locator(':scope[aria-selected="true"] .codicon.codicon-loading'), 'spinner' ).toBeVisible(); @@ -132,7 +132,7 @@ test('should preserve action list selection upon live trace update', async ({ ru await page.getByText('live test').dblclick(); // It should wait on the latch. - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -157,7 +157,7 @@ test('should preserve action list selection upon live trace update', async ({ ru /page.setContent[\d.]+m?s/, ]); await expect( - listItem.locator(':scope.selected'), + listItem.locator(':scope[aria-selected="true"]'), 'selected action stays the same' ).toHaveText(/page.goto/); }); @@ -193,7 +193,7 @@ test('should update tracing network live', async ({ runUITest, server }) => { await page.getByText('live test').dblclick(); // It should wait on the latch. - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -233,7 +233,7 @@ test('should show trace w/ multiple contexts', async ({ runUITest, server, creat await page.getByText('live test').dblclick(); // It should wait on the latch. - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -278,7 +278,7 @@ test('should show live trace for serial', async ({ runUITest, server, createLatc await page.getByText('two', { exact: true }).click(); await page.getByTitle('Run all').click(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -318,7 +318,7 @@ test('should show live trace from hooks', async ({ runUITest, createLatch }) => `); await page.getByText('test one').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index 5ead1889f0fbd..24731bcbb2173 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -93,7 +93,7 @@ test('should run on hover', async ({ runUITest }) => { }); await page.getByText('passes').hover(); - await page.getByRole('listitem').filter({ hasText: 'passes' }).getByTitle('Run').click(); + await page.getByRole('treeitem').filter({ hasText: 'passes' }).getByTitle('Run').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts @@ -275,7 +275,7 @@ test('should run folder', async ({ runUITest }) => { }); await page.getByText('folder-b').hover(); - await page.getByRole('listitem').filter({ hasText: 'folder-b' }).getByTitle('Run').click(); + await page.getByRole('treeitem').filter({ hasText: 'folder-b' }).getByTitle('Run').click(); await expect.poll(dumpTestTree(page)).toContain(` ▼ ✅ folder-b <= diff --git a/tests/playwright-test/ui-mode-test-setup.spec.ts b/tests/playwright-test/ui-mode-test-setup.spec.ts index cd5503427d1f4..f8de9e262a817 100644 --- a/tests/playwright-test/ui-mode-test-setup.spec.ts +++ b/tests/playwright-test/ui-mode-test-setup.spec.ts @@ -211,7 +211,7 @@ test('should run part of the setup only', async ({ runUITest }) => { await page.getByLabel('test').setChecked(true); await page.getByText('setup.ts').hover(); - await page.getByRole('listitem').filter({ hasText: 'setup.ts' }).getByTitle('Run').click(); + await page.getByRole('treeitem').filter({ hasText: 'setup.ts' }).getByTitle('Run').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ✅ setup.ts <= diff --git a/tests/playwright-test/ui-mode-test-update.spec.ts b/tests/playwright-test/ui-mode-test-update.spec.ts index 61e2c89dc7e47..ae5752c3f0650 100644 --- a/tests/playwright-test/ui-mode-test-update.spec.ts +++ b/tests/playwright-test/ui-mode-test-update.spec.ts @@ -149,7 +149,7 @@ test('should not loose run information after execution if test wrote into testDi await page.getByTitle('Run all').click(); await page.waitForTimeout(5_000); await expect(page.getByText('Did not run')).toBeHidden(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -215,7 +215,7 @@ test('should update test locations', async ({ runUITest, writeFiles }) => { const messages: any[] = []; await page.exposeBinding('__logForTest', (source, arg) => messages.push(arg)); - const passesItemLocator = page.getByRole('listitem').filter({ hasText: 'passes' }); + const passesItemLocator = page.getByRole('treeitem').filter({ hasText: 'passes' }); await passesItemLocator.hover(); await passesItemLocator.getByTitle('Show source').click(); await page.getByTitle('Open in VS Code').click(); diff --git a/tests/playwright-test/ui-mode-test-watch.spec.ts b/tests/playwright-test/ui-mode-test-watch.spec.ts index bd04750a1f2fe..893a0ef7acccb 100644 --- a/tests/playwright-test/ui-mode-test-watch.spec.ts +++ b/tests/playwright-test/ui-mode-test-watch.spec.ts @@ -28,14 +28,14 @@ test('should watch files', async ({ runUITest, writeFiles }) => { }); await page.getByText('fails').click(); - await page.getByRole('listitem').filter({ hasText: 'fails' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'fails' }).getByTitle('Watch').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts ◯ passes ◯ fails 👁 <= `); - await page.getByRole('listitem').filter({ hasText: 'fails' }).getByTitle('Run').click(); + await page.getByRole('treeitem').filter({ hasText: 'fails' }).getByTitle('Run').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ❌ a.test.ts @@ -75,7 +75,7 @@ test('should watch e2e deps', async ({ runUITest, writeFiles }) => { }); await page.getByText('answer').click(); - await page.getByRole('listitem').filter({ hasText: 'answer' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'answer' }).getByTitle('Watch').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts ◯ answer 👁 <= @@ -102,13 +102,13 @@ test('should batch watch updates', async ({ runUITest, writeFiles }) => { }); await page.getByText('a.test.ts').click(); - await page.getByRole('listitem').filter({ hasText: 'a.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'a.test.ts' }).getByTitle('Watch').click(); await page.getByText('b.test.ts').click(); - await page.getByRole('listitem').filter({ hasText: 'b.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'b.test.ts' }).getByTitle('Watch').click(); await page.getByText('c.test.ts').click(); - await page.getByRole('listitem').filter({ hasText: 'c.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'c.test.ts' }).getByTitle('Watch').click(); await page.getByText('d.test.ts').click(); - await page.getByRole('listitem').filter({ hasText: 'd.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'd.test.ts' }).getByTitle('Watch').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts 👁 @@ -229,7 +229,7 @@ test('should run added test in watched file', async ({ runUITest, writeFiles }) }); await page.getByText('a.test.ts').click(); - await page.getByRole('listitem').filter({ hasText: 'a.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem').filter({ hasText: 'a.test.ts' }).getByTitle('Watch').click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts 👁 <= diff --git a/tests/playwright-test/ui-mode-trace.spec.ts b/tests/playwright-test/ui-mode-trace.spec.ts index 9f0749893e573..def44e9aeb451 100644 --- a/tests/playwright-test/ui-mode-trace.spec.ts +++ b/tests/playwright-test/ui-mode-trace.spec.ts @@ -34,7 +34,7 @@ test('should merge trace events', async ({ runUITest }) => { await page.getByText('trace test').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -61,7 +61,7 @@ test('should merge web assertion events', async ({ runUITest }, testInfo) => { await page.getByText('trace test').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -86,7 +86,7 @@ test('should merge screenshot assertions', async ({ runUITest }, testInfo) => { await page.getByText('trace test').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -134,7 +134,7 @@ test('should show snapshots for sync assertions', async ({ runUITest }) => { await page.getByText('trace test').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, 'action list' @@ -214,7 +214,7 @@ test('should not fail on internal page logs', async ({ runUITest, server }) => { }); await page.getByText('pass').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, @@ -241,7 +241,7 @@ test('should not show caught errors in the errors tab', async ({ runUITest }, te }); await page.getByText('pass').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, @@ -272,7 +272,7 @@ test('should reveal errors in the sourcetab', async ({ runUITest }) => { }); await page.getByText('pass').dblclick(); - const listItem = page.getByTestId('actions-tree').getByRole('listitem'); + const listItem = page.getByTestId('actions-tree').getByRole('treeitem'); await expect( listItem, From 29c84a33c386e10dd294a5bcf9f24b9988d1777c Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 17 Oct 2024 17:06:18 -0700 Subject: [PATCH 327/805] chore: compute aria text consistently with the role accumulated text (#33157) --- .../src/server/ariaSnapshot.ts | 6 +- .../src/server/injected/ariaSnapshot.ts | 62 +- .../src/server/injected/roleUtils.ts | 107 ++-- .../src/matchers/toMatchAriaSnapshot.ts | 16 +- tests/assets/codicon.css | 596 ++++++++++++++++++ tests/assets/codicon.ttf | Bin 0 -> 80340 bytes tests/page/page-aria-snapshot.spec.ts | 375 ++++++++++- tests/page/to-match-aria-snapshot.spec.ts | 4 +- .../stable-test-runner/package-lock.json | 50 +- .../stable-test-runner/package.json | 2 +- 10 files changed, 1094 insertions(+), 124 deletions(-) create mode 100644 tests/assets/codicon.css create mode 100644 tests/assets/codicon.ttf diff --git a/packages/playwright-core/src/server/ariaSnapshot.ts b/packages/playwright-core/src/server/ariaSnapshot.ts index 6f89dd21cfc80..e450e5b15df67 100644 --- a/packages/playwright-core/src/server/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/ariaSnapshot.ts @@ -40,8 +40,12 @@ export function parseAriaSnapshot(text: string): AriaTemplateNode { return { role }; }; + const normalizeWhitespace = (text: string) => { + return text.replace(/[\r\n\s\t]+/g, ' ').trim(); + }; + const valueOrRegex = (value: string): string | RegExp => { - return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : value; + return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value); }; const convert = (object: YamlNode | string): AriaTemplateNode | RegExp | string => { diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 22ec9b5c42273..907006ce0a1f8 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -15,13 +15,13 @@ */ import { escapeWithQuotes } from '@isomorphic/stringUtils'; -import { beginAriaCaches, endAriaCaches, getAriaRole, getElementAccessibleName, isElementIgnoredForAria } from './roleUtils'; -import { isElementVisible, isElementStyleVisibilityVisible } from './domUtils'; +import { accumulatedElementText, beginAriaCaches, endAriaCaches, getAriaRole, getElementAccessibleName, getPseudoContent, isElementIgnoredForAria } from './roleUtils'; +import { isElementVisible, isElementStyleVisibilityVisible, getElementComputedStyle } from './domUtils'; type AriaNode = { role: string; name?: string; - children?: (AriaNode | string)[]; + children: (AriaNode | string)[]; }; export type AriaTemplateNode = { @@ -38,16 +38,20 @@ export function generateAriaTree(rootElement: Element): AriaNode { const name = role ? getElementAccessibleName(element, false) || undefined : undefined; const isLeaf = leafRoles.has(role); - const result: AriaNode = { role, name }; - if (isLeaf && !name && element.textContent) - result.children = [element.textContent]; + const result: AriaNode = { role, name, children: [] }; + if (isLeaf && !name) { + const text = accumulatedElementText(element); + if (text) + result.children = [text]; + } return { isLeaf, ariaNode: result }; }; const visit = (ariaNode: AriaNode, node: Node) => { if (node.nodeType === Node.TEXT_NODE && node.nodeValue) { - ariaNode.children = ariaNode.children || []; - ariaNode.children.push(node.nodeValue); + const text = node.nodeValue; + if (text) + ariaNode.children.push(node.nodeValue || ''); return; } @@ -67,10 +71,8 @@ export function generateAriaTree(rootElement: Element): AriaNode { if (visible) { const childAriaNode = toAriaNode(element); const isHiddenContainer = childAriaNode && hiddenContainerRoles.has(childAriaNode.ariaNode.role); - if (childAriaNode && !isHiddenContainer) { - ariaNode.children = ariaNode.children || []; + if (childAriaNode && !isHiddenContainer) ariaNode.children.push(childAriaNode.ariaNode); - } if (isHiddenContainer || !childAriaNode?.isLeaf) processChildNodes(childAriaNode?.ariaNode || ariaNode, element); } else { @@ -79,18 +81,36 @@ export function generateAriaTree(rootElement: Element): AriaNode { }; function processChildNodes(ariaNode: AriaNode, element: Element) { - // Process light DOM children - for (let child = element.firstChild; child; child = child.nextSibling) - visit(ariaNode, child); - // Process shadow DOM children, if any - if (element.shadowRoot) { - for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling) + // Surround every element with spaces for the sake of concatenated text nodes. + const display = getElementComputedStyle(element)?.display || 'inline'; + const treatAsBlock = (display !== 'inline' || element.nodeName === 'BR') ? ' ' : ''; + if (treatAsBlock) + ariaNode.children.push(treatAsBlock); + + ariaNode.children.push(getPseudoContent(element, '::before')); + const assignedNodes = element.nodeName === 'SLOT' ? (element as HTMLSlotElement).assignedNodes() : []; + if (assignedNodes.length) { + for (const child of assignedNodes) visit(ariaNode, child); + } else { + for (let child = element.firstChild; child; child = child.nextSibling) { + if (!(child as Element | Text).assignedSlot) + visit(ariaNode, child); + } + if (element.shadowRoot) { + for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling) + visit(ariaNode, child); + } } + + ariaNode.children.push(getPseudoContent(element, '::after')); + + if (treatAsBlock) + ariaNode.children.push(treatAsBlock); } beginAriaCaches(); - const ariaRoot: AriaNode = { role: '' }; + const ariaRoot: AriaNode = { role: '', children: [] }; try { visit(ariaRoot, rootElement); } finally { @@ -128,7 +148,7 @@ function normalizeStringChildren(rootA11yNode: AriaNode) { } } flushChildren(buffer, normalizedChildren); - ariaNode.children = normalizedChildren.length ? normalizedChildren : undefined; + ariaNode.children = normalizedChildren.length ? normalizedChildren : []; }; visit(rootA11yNode); } @@ -144,7 +164,7 @@ const leafRoles = new Set([ 'textbox', 'time', 'tooltip' ]); -const normalizeWhitespaceWithin = (text: string) => text.replace(/[\s\n]+/g, ' '); +const normalizeWhitespaceWithin = (text: string) => text.replace(/[\s\t\r\n]+/g, ' '); function matchesText(text: string | undefined, template: RegExp | string | undefined) { if (!template) @@ -233,7 +253,7 @@ export function renderAriaTree(ariaNode: AriaNode): string { lines.push(line); return; } - lines.push(line + (ariaNode.children ? ':' : '')); + lines.push(line + (ariaNode.children.length ? ':' : '')); for (const child of ariaNode.children || []) visit(child, indent + ' '); }; diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index 6e05c399013a0..d085a8e36d4de 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -363,7 +363,7 @@ function queryInAriaOwned(element: Element, selector: string): Element[] { return result; } -function getPseudoContent(element: Element, pseudo: '::before' | '::after') { +export function getPseudoContent(element: Element, pseudo: '::before' | '::after') { const cache = pseudo === '::before' ? cachePseudoContentBefore : cachePseudoContentAfter; if (cache?.has(element)) return cache?.get(element) || ''; @@ -430,10 +430,6 @@ export function getElementAccessibleName(element: Element, includeHidden: boolea accessibleName = asFlatString(getTextAlternativeInternal(element, { includeHidden, visitedElements: new Set(), - embeddedInDescribedBy: undefined, - embeddedInLabelledBy: undefined, - embeddedInLabel: undefined, - embeddedInNativeTextAlternative: undefined, embeddedInTargetElement: 'self', })); } @@ -458,10 +454,6 @@ export function getElementAccessibleDescription(element: Element, includeHidden: accessibleDescription = asFlatString(describedBy.map(ref => getTextAlternativeInternal(ref, { includeHidden, visitedElements: new Set(), - embeddedInLabelledBy: undefined, - embeddedInLabel: undefined, - embeddedInNativeTextAlternative: undefined, - embeddedInTargetElement: 'none', embeddedInDescribedBy: { element: ref, hidden: isElementHiddenForAria(ref) }, })).join(' ')); } else if (element.hasAttribute('aria-description')) { @@ -480,13 +472,13 @@ export function getElementAccessibleDescription(element: Element, includeHidden: } type AccessibleNameOptions = { - includeHidden: boolean, visitedElements: Set, - embeddedInDescribedBy: { element: Element, hidden: boolean } | undefined, - embeddedInLabelledBy: { element: Element, hidden: boolean } | undefined, - embeddedInLabel: { element: Element, hidden: boolean } | undefined, - embeddedInNativeTextAlternative: { element: Element, hidden: boolean } | undefined, - embeddedInTargetElement: 'none' | 'self' | 'descendant', + includeHidden?: boolean, + embeddedInDescribedBy?: { element: Element, hidden: boolean }, + embeddedInLabelledBy?: { element: Element, hidden: boolean }, + embeddedInLabel?: { element: Element, hidden: boolean }, + embeddedInNativeTextAlternative?: { element: Element, hidden: boolean }, + embeddedInTargetElement?: 'self' | 'descendant', }; function getTextAlternativeInternal(element: Element, options: AccessibleNameOptions): string { @@ -525,7 +517,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt ...options, embeddedInLabelledBy: { element: ref, hidden: isElementHiddenForAria(ref) }, embeddedInDescribedBy: undefined, - embeddedInTargetElement: 'none', + embeddedInTargetElement: undefined, embeddedInLabel: undefined, embeddedInNativeTextAlternative: undefined, })).join(' '); @@ -778,42 +770,7 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt !!options.embeddedInLabelledBy || !!options.embeddedInDescribedBy || !!options.embeddedInLabel || !!options.embeddedInNativeTextAlternative) { options.visitedElements.add(element); - const tokens: string[] = []; - const visit = (node: Node, skipSlotted: boolean) => { - if (skipSlotted && (node as Element | Text).assignedSlot) - return; - if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { - const display = getElementComputedStyle(node as Element)?.display || 'inline'; - let token = getTextAlternativeInternal(node as Element, childOptions); - // SPEC DIFFERENCE. - // Spec says "append the result to the accumulated text", assuming "with space". - // However, multiple tests insist that inline elements do not add a space. - // Additionally,
          insists on a space anyway, see "name_file-label-inline-block-elements-manual.html" - if (display !== 'inline' || node.nodeName === 'BR') - token = ' ' + token + ' '; - tokens.push(token); - } else if (node.nodeType === 3 /* Node.TEXT_NODE */) { - // step 2g. - tokens.push(node.textContent || ''); - } - }; - tokens.push(getPseudoContent(element, '::before')); - const assignedNodes = element.nodeName === 'SLOT' ? (element as HTMLSlotElement).assignedNodes() : []; - if (assignedNodes.length) { - for (const child of assignedNodes) - visit(child, false); - } else { - for (let child = element.firstChild; child; child = child.nextSibling) - visit(child, true); - if (element.shadowRoot) { - for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling) - visit(child, true); - } - for (const owned of getIdRefs(element, element.getAttribute('aria-owns'))) - visit(owned, true); - } - tokens.push(getPseudoContent(element, '::after')); - const accessibleName = tokens.join(''); + const accessibleName = innerAccumulatedElementText(element, childOptions); // Spec says "Return the accumulated text if it is not the empty string". However, that is not really // compatible with the real browser behavior and wpt tests, where an element with empty contents will fallback to the title. // So we follow the spec everywhere except for the target element itself. This can probably be improved. @@ -834,6 +791,50 @@ function getTextAlternativeInternal(element: Element, options: AccessibleNameOpt return ''; } +function innerAccumulatedElementText(element: Element, options: AccessibleNameOptions): string { + const tokens: string[] = []; + const visit = (node: Node, skipSlotted: boolean) => { + if (skipSlotted && (node as Element | Text).assignedSlot) + return; + if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { + const display = getElementComputedStyle(node as Element)?.display || 'inline'; + let token = getTextAlternativeInternal(node as Element, options); + // SPEC DIFFERENCE. + // Spec says "append the result to the accumulated text", assuming "with space". + // However, multiple tests insist that inline elements do not add a space. + // Additionally,
          insists on a space anyway, see "name_file-label-inline-block-elements-manual.html" + if (display !== 'inline' || node.nodeName === 'BR') + token = ' ' + token + ' '; + tokens.push(token); + } else if (node.nodeType === 3 /* Node.TEXT_NODE */) { + // step 2g. + tokens.push(node.textContent || ''); + } + }; + tokens.push(getPseudoContent(element, '::before')); + const assignedNodes = element.nodeName === 'SLOT' ? (element as HTMLSlotElement).assignedNodes() : []; + if (assignedNodes.length) { + for (const child of assignedNodes) + visit(child, false); + } else { + for (let child = element.firstChild; child; child = child.nextSibling) + visit(child, true); + if (element.shadowRoot) { + for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling) + visit(child, true); + } + for (const owned of getIdRefs(element, element.getAttribute('aria-owns'))) + visit(owned, true); + } + tokens.push(getPseudoContent(element, '::after')); + return tokens.join(''); +} + +export function accumulatedElementText(element: Element): string { + const visitedElements = new Set(); + return asFlatString(innerAccumulatedElementText(element, { visitedElements })).trim(); +} + export const kAriaSelectedRoles = ['gridcell', 'option', 'row', 'tab', 'rowheader', 'columnheader', 'treeitem']; export function getAriaSelected(element: Element): boolean { // https://www.w3.org/TR/wai-aria-1.2/#aria-selected @@ -958,7 +959,7 @@ function getAccessibleNameFromAssociatedLabels(labels: Iterable !!accessibleName).join(' '); } diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index cd79ccab61718..cf043c2ca880e 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -49,17 +49,19 @@ export async function toMatchAriaSnapshot( const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined); const notFound = received === kNoElementsFoundError; + const escapedExpected = escapePrivateUsePoints(expected); + const escapedReceived = escapePrivateUsePoints(received); const message = () => { if (pass) { if (notFound) - return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); - const printedReceived = printReceivedStringContainExpectedSubstring(received, received.indexOf(expected), expected.length); - return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived string: ${printedReceived}` + callLogText(log); + return messagePrefix + `Expected: not ${this.utils.printExpected(escapedExpected)}\nReceived: ${escapedReceived}` + callLogText(log); + const printedReceived = printReceivedStringContainExpectedSubstring(escapedReceived, escapedReceived.indexOf(escapedExpected), escapedExpected.length); + return messagePrefix + `Expected: not ${this.utils.printExpected(escapedExpected)}\nReceived string: ${printedReceived}` + callLogText(log); } else { const labelExpected = `Expected`; if (notFound) - return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); - return messagePrefix + this.utils.printDiffOrStringify(expected, received, labelExpected, 'Received string', false) + callLogText(log); + return messagePrefix + `${labelExpected}: ${this.utils.printExpected(escapedExpected)}\nReceived: ${escapedReceived}` + callLogText(log); + return messagePrefix + this.utils.printDiffOrStringify(escapedExpected, escapedReceived, labelExpected, 'Received string', false) + callLogText(log); } }; @@ -73,3 +75,7 @@ export async function toMatchAriaSnapshot( timeout: timedOut ? timeout : undefined, }; } + +function escapePrivateUsePoints(str: string) { + return str.replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`); +} diff --git a/tests/assets/codicon.css b/tests/assets/codicon.css new file mode 100644 index 0000000000000..41360ce21d643 --- /dev/null +++ b/tests/assets/codicon.css @@ -0,0 +1,596 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +@font-face { + font-family: "codicon"; + src: url("codicon.ttf") format("truetype"); +} + +.codicon { + font: normal normal normal 16px/1 codicon; + flex: none; + display: inline-block; + text-decoration: none; + text-rendering: auto; + text-align: center; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.codicon-add:before { content: '\ea60'; } +.codicon-plus:before { content: '\ea60'; } +.codicon-gist-new:before { content: '\ea60'; } +.codicon-repo-create:before { content: '\ea60'; } +.codicon-lightbulb:before { content: '\ea61'; } +.codicon-light-bulb:before { content: '\ea61'; } +.codicon-repo:before { content: '\ea62'; } +.codicon-repo-delete:before { content: '\ea62'; } +.codicon-gist-fork:before { content: '\ea63'; } +.codicon-repo-forked:before { content: '\ea63'; } +.codicon-git-pull-request:before { content: '\ea64'; } +.codicon-git-pull-request-abandoned:before { content: '\ea64'; } +.codicon-record-keys:before { content: '\ea65'; } +.codicon-keyboard:before { content: '\ea65'; } +.codicon-tag:before { content: '\ea66'; } +.codicon-git-pull-request-label:before { content: '\ea66'; } +.codicon-tag-add:before { content: '\ea66'; } +.codicon-tag-remove:before { content: '\ea66'; } +.codicon-person:before { content: '\ea67'; } +.codicon-person-follow:before { content: '\ea67'; } +.codicon-person-outline:before { content: '\ea67'; } +.codicon-person-filled:before { content: '\ea67'; } +.codicon-git-branch:before { content: '\ea68'; } +.codicon-git-branch-create:before { content: '\ea68'; } +.codicon-git-branch-delete:before { content: '\ea68'; } +.codicon-source-control:before { content: '\ea68'; } +.codicon-mirror:before { content: '\ea69'; } +.codicon-mirror-public:before { content: '\ea69'; } +.codicon-star:before { content: '\ea6a'; } +.codicon-star-add:before { content: '\ea6a'; } +.codicon-star-delete:before { content: '\ea6a'; } +.codicon-star-empty:before { content: '\ea6a'; } +.codicon-comment:before { content: '\ea6b'; } +.codicon-comment-add:before { content: '\ea6b'; } +.codicon-alert:before { content: '\ea6c'; } +.codicon-warning:before { content: '\ea6c'; } +.codicon-search:before { content: '\ea6d'; } +.codicon-search-save:before { content: '\ea6d'; } +.codicon-log-out:before { content: '\ea6e'; } +.codicon-sign-out:before { content: '\ea6e'; } +.codicon-log-in:before { content: '\ea6f'; } +.codicon-sign-in:before { content: '\ea6f'; } +.codicon-eye:before { content: '\ea70'; } +.codicon-eye-unwatch:before { content: '\ea70'; } +.codicon-eye-watch:before { content: '\ea70'; } +.codicon-circle-filled:before { content: '\ea71'; } +.codicon-primitive-dot:before { content: '\ea71'; } +.codicon-close-dirty:before { content: '\ea71'; } +.codicon-debug-breakpoint:before { content: '\ea71'; } +.codicon-debug-breakpoint-disabled:before { content: '\ea71'; } +.codicon-debug-hint:before { content: '\ea71'; } +.codicon-terminal-decoration-success:before { content: '\ea71'; } +.codicon-primitive-square:before { content: '\ea72'; } +.codicon-edit:before { content: '\ea73'; } +.codicon-pencil:before { content: '\ea73'; } +.codicon-info:before { content: '\ea74'; } +.codicon-issue-opened:before { content: '\ea74'; } +.codicon-gist-private:before { content: '\ea75'; } +.codicon-git-fork-private:before { content: '\ea75'; } +.codicon-lock:before { content: '\ea75'; } +.codicon-mirror-private:before { content: '\ea75'; } +.codicon-close:before { content: '\ea76'; } +.codicon-remove-close:before { content: '\ea76'; } +.codicon-x:before { content: '\ea76'; } +.codicon-repo-sync:before { content: '\ea77'; } +.codicon-sync:before { content: '\ea77'; } +.codicon-clone:before { content: '\ea78'; } +.codicon-desktop-download:before { content: '\ea78'; } +.codicon-beaker:before { content: '\ea79'; } +.codicon-microscope:before { content: '\ea79'; } +.codicon-vm:before { content: '\ea7a'; } +.codicon-device-desktop:before { content: '\ea7a'; } +.codicon-file:before { content: '\ea7b'; } +.codicon-file-text:before { content: '\ea7b'; } +.codicon-more:before { content: '\ea7c'; } +.codicon-ellipsis:before { content: '\ea7c'; } +.codicon-kebab-horizontal:before { content: '\ea7c'; } +.codicon-mail-reply:before { content: '\ea7d'; } +.codicon-reply:before { content: '\ea7d'; } +.codicon-organization:before { content: '\ea7e'; } +.codicon-organization-filled:before { content: '\ea7e'; } +.codicon-organization-outline:before { content: '\ea7e'; } +.codicon-new-file:before { content: '\ea7f'; } +.codicon-file-add:before { content: '\ea7f'; } +.codicon-new-folder:before { content: '\ea80'; } +.codicon-file-directory-create:before { content: '\ea80'; } +.codicon-trash:before { content: '\ea81'; } +.codicon-trashcan:before { content: '\ea81'; } +.codicon-history:before { content: '\ea82'; } +.codicon-clock:before { content: '\ea82'; } +.codicon-folder:before { content: '\ea83'; } +.codicon-file-directory:before { content: '\ea83'; } +.codicon-symbol-folder:before { content: '\ea83'; } +.codicon-logo-github:before { content: '\ea84'; } +.codicon-mark-github:before { content: '\ea84'; } +.codicon-github:before { content: '\ea84'; } +.codicon-terminal:before { content: '\ea85'; } +.codicon-console:before { content: '\ea85'; } +.codicon-repl:before { content: '\ea85'; } +.codicon-zap:before { content: '\ea86'; } +.codicon-symbol-event:before { content: '\ea86'; } +.codicon-error:before { content: '\ea87'; } +.codicon-stop:before { content: '\ea87'; } +.codicon-variable:before { content: '\ea88'; } +.codicon-symbol-variable:before { content: '\ea88'; } +.codicon-array:before { content: '\ea8a'; } +.codicon-symbol-array:before { content: '\ea8a'; } +.codicon-symbol-module:before { content: '\ea8b'; } +.codicon-symbol-package:before { content: '\ea8b'; } +.codicon-symbol-namespace:before { content: '\ea8b'; } +.codicon-symbol-object:before { content: '\ea8b'; } +.codicon-symbol-method:before { content: '\ea8c'; } +.codicon-symbol-function:before { content: '\ea8c'; } +.codicon-symbol-constructor:before { content: '\ea8c'; } +.codicon-symbol-boolean:before { content: '\ea8f'; } +.codicon-symbol-null:before { content: '\ea8f'; } +.codicon-symbol-numeric:before { content: '\ea90'; } +.codicon-symbol-number:before { content: '\ea90'; } +.codicon-symbol-structure:before { content: '\ea91'; } +.codicon-symbol-struct:before { content: '\ea91'; } +.codicon-symbol-parameter:before { content: '\ea92'; } +.codicon-symbol-type-parameter:before { content: '\ea92'; } +.codicon-symbol-key:before { content: '\ea93'; } +.codicon-symbol-text:before { content: '\ea93'; } +.codicon-symbol-reference:before { content: '\ea94'; } +.codicon-go-to-file:before { content: '\ea94'; } +.codicon-symbol-enum:before { content: '\ea95'; } +.codicon-symbol-value:before { content: '\ea95'; } +.codicon-symbol-ruler:before { content: '\ea96'; } +.codicon-symbol-unit:before { content: '\ea96'; } +.codicon-activate-breakpoints:before { content: '\ea97'; } +.codicon-archive:before { content: '\ea98'; } +.codicon-arrow-both:before { content: '\ea99'; } +.codicon-arrow-down:before { content: '\ea9a'; } +.codicon-arrow-left:before { content: '\ea9b'; } +.codicon-arrow-right:before { content: '\ea9c'; } +.codicon-arrow-small-down:before { content: '\ea9d'; } +.codicon-arrow-small-left:before { content: '\ea9e'; } +.codicon-arrow-small-right:before { content: '\ea9f'; } +.codicon-arrow-small-up:before { content: '\eaa0'; } +.codicon-arrow-up:before { content: '\eaa1'; } +.codicon-bell:before { content: '\eaa2'; } +.codicon-bold:before { content: '\eaa3'; } +.codicon-book:before { content: '\eaa4'; } +.codicon-bookmark:before { content: '\eaa5'; } +.codicon-debug-breakpoint-conditional-unverified:before { content: '\eaa6'; } +.codicon-debug-breakpoint-conditional:before { content: '\eaa7'; } +.codicon-debug-breakpoint-conditional-disabled:before { content: '\eaa7'; } +.codicon-debug-breakpoint-data-unverified:before { content: '\eaa8'; } +.codicon-debug-breakpoint-data:before { content: '\eaa9'; } +.codicon-debug-breakpoint-data-disabled:before { content: '\eaa9'; } +.codicon-debug-breakpoint-log-unverified:before { content: '\eaaa'; } +.codicon-debug-breakpoint-log:before { content: '\eaab'; } +.codicon-debug-breakpoint-log-disabled:before { content: '\eaab'; } +.codicon-briefcase:before { content: '\eaac'; } +.codicon-broadcast:before { content: '\eaad'; } +.codicon-browser:before { content: '\eaae'; } +.codicon-bug:before { content: '\eaaf'; } +.codicon-calendar:before { content: '\eab0'; } +.codicon-case-sensitive:before { content: '\eab1'; } +.codicon-check:before { content: '\eab2'; } +.codicon-checklist:before { content: '\eab3'; } +.codicon-chevron-down:before { content: '\eab4'; } +.codicon-chevron-left:before { content: '\eab5'; } +.codicon-chevron-right:before { content: '\eab6'; } +.codicon-chevron-up:before { content: '\eab7'; } +.codicon-chrome-close:before { content: '\eab8'; } +.codicon-chrome-maximize:before { content: '\eab9'; } +.codicon-chrome-minimize:before { content: '\eaba'; } +.codicon-chrome-restore:before { content: '\eabb'; } +.codicon-circle-outline:before { content: '\eabc'; } +.codicon-circle:before { content: '\eabc'; } +.codicon-debug-breakpoint-unverified:before { content: '\eabc'; } +.codicon-terminal-decoration-incomplete:before { content: '\eabc'; } +.codicon-circle-slash:before { content: '\eabd'; } +.codicon-circuit-board:before { content: '\eabe'; } +.codicon-clear-all:before { content: '\eabf'; } +.codicon-clippy:before { content: '\eac0'; } +.codicon-close-all:before { content: '\eac1'; } +.codicon-cloud-download:before { content: '\eac2'; } +.codicon-cloud-upload:before { content: '\eac3'; } +.codicon-code:before { content: '\eac4'; } +.codicon-collapse-all:before { content: '\eac5'; } +.codicon-color-mode:before { content: '\eac6'; } +.codicon-comment-discussion:before { content: '\eac7'; } +.codicon-credit-card:before { content: '\eac9'; } +.codicon-dash:before { content: '\eacc'; } +.codicon-dashboard:before { content: '\eacd'; } +.codicon-database:before { content: '\eace'; } +.codicon-debug-continue:before { content: '\eacf'; } +.codicon-debug-disconnect:before { content: '\ead0'; } +.codicon-debug-pause:before { content: '\ead1'; } +.codicon-debug-restart:before { content: '\ead2'; } +.codicon-debug-start:before { content: '\ead3'; } +.codicon-debug-step-into:before { content: '\ead4'; } +.codicon-debug-step-out:before { content: '\ead5'; } +.codicon-debug-step-over:before { content: '\ead6'; } +.codicon-debug-stop:before { content: '\ead7'; } +.codicon-debug:before { content: '\ead8'; } +.codicon-device-camera-video:before { content: '\ead9'; } +.codicon-device-camera:before { content: '\eada'; } +.codicon-device-mobile:before { content: '\eadb'; } +.codicon-diff-added:before { content: '\eadc'; } +.codicon-diff-ignored:before { content: '\eadd'; } +.codicon-diff-modified:before { content: '\eade'; } +.codicon-diff-removed:before { content: '\eadf'; } +.codicon-diff-renamed:before { content: '\eae0'; } +.codicon-diff:before { content: '\eae1'; } +.codicon-diff-sidebyside:before { content: '\eae1'; } +.codicon-discard:before { content: '\eae2'; } +.codicon-editor-layout:before { content: '\eae3'; } +.codicon-empty-window:before { content: '\eae4'; } +.codicon-exclude:before { content: '\eae5'; } +.codicon-extensions:before { content: '\eae6'; } +.codicon-eye-closed:before { content: '\eae7'; } +.codicon-file-binary:before { content: '\eae8'; } +.codicon-file-code:before { content: '\eae9'; } +.codicon-file-media:before { content: '\eaea'; } +.codicon-file-pdf:before { content: '\eaeb'; } +.codicon-file-submodule:before { content: '\eaec'; } +.codicon-file-symlink-directory:before { content: '\eaed'; } +.codicon-file-symlink-file:before { content: '\eaee'; } +.codicon-file-zip:before { content: '\eaef'; } +.codicon-files:before { content: '\eaf0'; } +.codicon-filter:before { content: '\eaf1'; } +.codicon-flame:before { content: '\eaf2'; } +.codicon-fold-down:before { content: '\eaf3'; } +.codicon-fold-up:before { content: '\eaf4'; } +.codicon-fold:before { content: '\eaf5'; } +.codicon-folder-active:before { content: '\eaf6'; } +.codicon-folder-opened:before { content: '\eaf7'; } +.codicon-gear:before { content: '\eaf8'; } +.codicon-gift:before { content: '\eaf9'; } +.codicon-gist-secret:before { content: '\eafa'; } +.codicon-gist:before { content: '\eafb'; } +.codicon-git-commit:before { content: '\eafc'; } +.codicon-git-compare:before { content: '\eafd'; } +.codicon-compare-changes:before { content: '\eafd'; } +.codicon-git-merge:before { content: '\eafe'; } +.codicon-github-action:before { content: '\eaff'; } +.codicon-github-alt:before { content: '\eb00'; } +.codicon-globe:before { content: '\eb01'; } +.codicon-grabber:before { content: '\eb02'; } +.codicon-graph:before { content: '\eb03'; } +.codicon-gripper:before { content: '\eb04'; } +.codicon-heart:before { content: '\eb05'; } +.codicon-home:before { content: '\eb06'; } +.codicon-horizontal-rule:before { content: '\eb07'; } +.codicon-hubot:before { content: '\eb08'; } +.codicon-inbox:before { content: '\eb09'; } +.codicon-issue-reopened:before { content: '\eb0b'; } +.codicon-issues:before { content: '\eb0c'; } +.codicon-italic:before { content: '\eb0d'; } +.codicon-jersey:before { content: '\eb0e'; } +.codicon-json:before { content: '\eb0f'; } +.codicon-kebab-vertical:before { content: '\eb10'; } +.codicon-key:before { content: '\eb11'; } +.codicon-law:before { content: '\eb12'; } +.codicon-lightbulb-autofix:before { content: '\eb13'; } +.codicon-link-external:before { content: '\eb14'; } +.codicon-link:before { content: '\eb15'; } +.codicon-list-ordered:before { content: '\eb16'; } +.codicon-list-unordered:before { content: '\eb17'; } +.codicon-live-share:before { content: '\eb18'; } +.codicon-loading:before { content: '\eb19'; } +.codicon-location:before { content: '\eb1a'; } +.codicon-mail-read:before { content: '\eb1b'; } +.codicon-mail:before { content: '\eb1c'; } +.codicon-markdown:before { content: '\eb1d'; } +.codicon-megaphone:before { content: '\eb1e'; } +.codicon-mention:before { content: '\eb1f'; } +.codicon-milestone:before { content: '\eb20'; } +.codicon-git-pull-request-milestone:before { content: '\eb20'; } +.codicon-mortar-board:before { content: '\eb21'; } +.codicon-move:before { content: '\eb22'; } +.codicon-multiple-windows:before { content: '\eb23'; } +.codicon-mute:before { content: '\eb24'; } +.codicon-no-newline:before { content: '\eb25'; } +.codicon-note:before { content: '\eb26'; } +.codicon-octoface:before { content: '\eb27'; } +.codicon-open-preview:before { content: '\eb28'; } +.codicon-package:before { content: '\eb29'; } +.codicon-paintcan:before { content: '\eb2a'; } +.codicon-pin:before { content: '\eb2b'; } +.codicon-play:before { content: '\eb2c'; } +.codicon-run:before { content: '\eb2c'; } +.codicon-plug:before { content: '\eb2d'; } +.codicon-preserve-case:before { content: '\eb2e'; } +.codicon-preview:before { content: '\eb2f'; } +.codicon-project:before { content: '\eb30'; } +.codicon-pulse:before { content: '\eb31'; } +.codicon-question:before { content: '\eb32'; } +.codicon-quote:before { content: '\eb33'; } +.codicon-radio-tower:before { content: '\eb34'; } +.codicon-reactions:before { content: '\eb35'; } +.codicon-references:before { content: '\eb36'; } +.codicon-refresh:before { content: '\eb37'; } +.codicon-regex:before { content: '\eb38'; } +.codicon-remote-explorer:before { content: '\eb39'; } +.codicon-remote:before { content: '\eb3a'; } +.codicon-remove:before { content: '\eb3b'; } +.codicon-replace-all:before { content: '\eb3c'; } +.codicon-replace:before { content: '\eb3d'; } +.codicon-repo-clone:before { content: '\eb3e'; } +.codicon-repo-force-push:before { content: '\eb3f'; } +.codicon-repo-pull:before { content: '\eb40'; } +.codicon-repo-push:before { content: '\eb41'; } +.codicon-report:before { content: '\eb42'; } +.codicon-request-changes:before { content: '\eb43'; } +.codicon-rocket:before { content: '\eb44'; } +.codicon-root-folder-opened:before { content: '\eb45'; } +.codicon-root-folder:before { content: '\eb46'; } +.codicon-rss:before { content: '\eb47'; } +.codicon-ruby:before { content: '\eb48'; } +.codicon-save-all:before { content: '\eb49'; } +.codicon-save-as:before { content: '\eb4a'; } +.codicon-save:before { content: '\eb4b'; } +.codicon-screen-full:before { content: '\eb4c'; } +.codicon-screen-normal:before { content: '\eb4d'; } +.codicon-search-stop:before { content: '\eb4e'; } +.codicon-server:before { content: '\eb50'; } +.codicon-settings-gear:before { content: '\eb51'; } +.codicon-settings:before { content: '\eb52'; } +.codicon-shield:before { content: '\eb53'; } +.codicon-smiley:before { content: '\eb54'; } +.codicon-sort-precedence:before { content: '\eb55'; } +.codicon-split-horizontal:before { content: '\eb56'; } +.codicon-split-vertical:before { content: '\eb57'; } +.codicon-squirrel:before { content: '\eb58'; } +.codicon-star-full:before { content: '\eb59'; } +.codicon-star-half:before { content: '\eb5a'; } +.codicon-symbol-class:before { content: '\eb5b'; } +.codicon-symbol-color:before { content: '\eb5c'; } +.codicon-symbol-constant:before { content: '\eb5d'; } +.codicon-symbol-enum-member:before { content: '\eb5e'; } +.codicon-symbol-field:before { content: '\eb5f'; } +.codicon-symbol-file:before { content: '\eb60'; } +.codicon-symbol-interface:before { content: '\eb61'; } +.codicon-symbol-keyword:before { content: '\eb62'; } +.codicon-symbol-misc:before { content: '\eb63'; } +.codicon-symbol-operator:before { content: '\eb64'; } +.codicon-symbol-property:before { content: '\eb65'; } +.codicon-wrench:before { content: '\eb65'; } +.codicon-wrench-subaction:before { content: '\eb65'; } +.codicon-symbol-snippet:before { content: '\eb66'; } +.codicon-tasklist:before { content: '\eb67'; } +.codicon-telescope:before { content: '\eb68'; } +.codicon-text-size:before { content: '\eb69'; } +.codicon-three-bars:before { content: '\eb6a'; } +.codicon-thumbsdown:before { content: '\eb6b'; } +.codicon-thumbsup:before { content: '\eb6c'; } +.codicon-tools:before { content: '\eb6d'; } +.codicon-triangle-down:before { content: '\eb6e'; } +.codicon-triangle-left:before { content: '\eb6f'; } +.codicon-triangle-right:before { content: '\eb70'; } +.codicon-triangle-up:before { content: '\eb71'; } +.codicon-twitter:before { content: '\eb72'; } +.codicon-unfold:before { content: '\eb73'; } +.codicon-unlock:before { content: '\eb74'; } +.codicon-unmute:before { content: '\eb75'; } +.codicon-unverified:before { content: '\eb76'; } +.codicon-verified:before { content: '\eb77'; } +.codicon-versions:before { content: '\eb78'; } +.codicon-vm-active:before { content: '\eb79'; } +.codicon-vm-outline:before { content: '\eb7a'; } +.codicon-vm-running:before { content: '\eb7b'; } +.codicon-watch:before { content: '\eb7c'; } +.codicon-whitespace:before { content: '\eb7d'; } +.codicon-whole-word:before { content: '\eb7e'; } +.codicon-window:before { content: '\eb7f'; } +.codicon-word-wrap:before { content: '\eb80'; } +.codicon-zoom-in:before { content: '\eb81'; } +.codicon-zoom-out:before { content: '\eb82'; } +.codicon-list-filter:before { content: '\eb83'; } +.codicon-list-flat:before { content: '\eb84'; } +.codicon-list-selection:before { content: '\eb85'; } +.codicon-selection:before { content: '\eb85'; } +.codicon-list-tree:before { content: '\eb86'; } +.codicon-debug-breakpoint-function-unverified:before { content: '\eb87'; } +.codicon-debug-breakpoint-function:before { content: '\eb88'; } +.codicon-debug-breakpoint-function-disabled:before { content: '\eb88'; } +.codicon-debug-stackframe-active:before { content: '\eb89'; } +.codicon-circle-small-filled:before { content: '\eb8a'; } +.codicon-debug-stackframe-dot:before { content: '\eb8a'; } +.codicon-terminal-decoration-mark:before { content: '\eb8a'; } +.codicon-debug-stackframe:before { content: '\eb8b'; } +.codicon-debug-stackframe-focused:before { content: '\eb8b'; } +.codicon-debug-breakpoint-unsupported:before { content: '\eb8c'; } +.codicon-symbol-string:before { content: '\eb8d'; } +.codicon-debug-reverse-continue:before { content: '\eb8e'; } +.codicon-debug-step-back:before { content: '\eb8f'; } +.codicon-debug-restart-frame:before { content: '\eb90'; } +.codicon-debug-alt:before { content: '\eb91'; } +.codicon-call-incoming:before { content: '\eb92'; } +.codicon-call-outgoing:before { content: '\eb93'; } +.codicon-menu:before { content: '\eb94'; } +.codicon-expand-all:before { content: '\eb95'; } +.codicon-feedback:before { content: '\eb96'; } +.codicon-git-pull-request-reviewer:before { content: '\eb96'; } +.codicon-group-by-ref-type:before { content: '\eb97'; } +.codicon-ungroup-by-ref-type:before { content: '\eb98'; } +.codicon-account:before { content: '\eb99'; } +.codicon-git-pull-request-assignee:before { content: '\eb99'; } +.codicon-bell-dot:before { content: '\eb9a'; } +.codicon-debug-console:before { content: '\eb9b'; } +.codicon-library:before { content: '\eb9c'; } +.codicon-output:before { content: '\eb9d'; } +.codicon-run-all:before { content: '\eb9e'; } +.codicon-sync-ignored:before { content: '\eb9f'; } +.codicon-pinned:before { content: '\eba0'; } +.codicon-github-inverted:before { content: '\eba1'; } +.codicon-server-process:before { content: '\eba2'; } +.codicon-server-environment:before { content: '\eba3'; } +.codicon-pass:before { content: '\eba4'; } +.codicon-issue-closed:before { content: '\eba4'; } +.codicon-stop-circle:before { content: '\eba5'; } +.codicon-play-circle:before { content: '\eba6'; } +.codicon-record:before { content: '\eba7'; } +.codicon-debug-alt-small:before { content: '\eba8'; } +.codicon-vm-connect:before { content: '\eba9'; } +.codicon-cloud:before { content: '\ebaa'; } +.codicon-merge:before { content: '\ebab'; } +.codicon-export:before { content: '\ebac'; } +.codicon-graph-left:before { content: '\ebad'; } +.codicon-magnet:before { content: '\ebae'; } +.codicon-notebook:before { content: '\ebaf'; } +.codicon-redo:before { content: '\ebb0'; } +.codicon-check-all:before { content: '\ebb1'; } +.codicon-pinned-dirty:before { content: '\ebb2'; } +.codicon-pass-filled:before { content: '\ebb3'; } +.codicon-circle-large-filled:before { content: '\ebb4'; } +.codicon-circle-large:before { content: '\ebb5'; } +.codicon-circle-large-outline:before { content: '\ebb5'; } +.codicon-combine:before { content: '\ebb6'; } +.codicon-gather:before { content: '\ebb6'; } +.codicon-table:before { content: '\ebb7'; } +.codicon-variable-group:before { content: '\ebb8'; } +.codicon-type-hierarchy:before { content: '\ebb9'; } +.codicon-type-hierarchy-sub:before { content: '\ebba'; } +.codicon-type-hierarchy-super:before { content: '\ebbb'; } +.codicon-git-pull-request-create:before { content: '\ebbc'; } +.codicon-run-above:before { content: '\ebbd'; } +.codicon-run-below:before { content: '\ebbe'; } +.codicon-notebook-template:before { content: '\ebbf'; } +.codicon-debug-rerun:before { content: '\ebc0'; } +.codicon-workspace-trusted:before { content: '\ebc1'; } +.codicon-workspace-untrusted:before { content: '\ebc2'; } +.codicon-workspace-unknown:before { content: '\ebc3'; } +.codicon-terminal-cmd:before { content: '\ebc4'; } +.codicon-terminal-debian:before { content: '\ebc5'; } +.codicon-terminal-linux:before { content: '\ebc6'; } +.codicon-terminal-powershell:before { content: '\ebc7'; } +.codicon-terminal-tmux:before { content: '\ebc8'; } +.codicon-terminal-ubuntu:before { content: '\ebc9'; } +.codicon-terminal-bash:before { content: '\ebca'; } +.codicon-arrow-swap:before { content: '\ebcb'; } +.codicon-copy:before { content: '\ebcc'; } +.codicon-person-add:before { content: '\ebcd'; } +.codicon-filter-filled:before { content: '\ebce'; } +.codicon-wand:before { content: '\ebcf'; } +.codicon-debug-line-by-line:before { content: '\ebd0'; } +.codicon-inspect:before { content: '\ebd1'; } +.codicon-layers:before { content: '\ebd2'; } +.codicon-layers-dot:before { content: '\ebd3'; } +.codicon-layers-active:before { content: '\ebd4'; } +.codicon-compass:before { content: '\ebd5'; } +.codicon-compass-dot:before { content: '\ebd6'; } +.codicon-compass-active:before { content: '\ebd7'; } +.codicon-azure:before { content: '\ebd8'; } +.codicon-issue-draft:before { content: '\ebd9'; } +.codicon-git-pull-request-closed:before { content: '\ebda'; } +.codicon-git-pull-request-draft:before { content: '\ebdb'; } +.codicon-debug-all:before { content: '\ebdc'; } +.codicon-debug-coverage:before { content: '\ebdd'; } +.codicon-run-errors:before { content: '\ebde'; } +.codicon-folder-library:before { content: '\ebdf'; } +.codicon-debug-continue-small:before { content: '\ebe0'; } +.codicon-beaker-stop:before { content: '\ebe1'; } +.codicon-graph-line:before { content: '\ebe2'; } +.codicon-graph-scatter:before { content: '\ebe3'; } +.codicon-pie-chart:before { content: '\ebe4'; } +.codicon-bracket:before { content: '\eb0f'; } +.codicon-bracket-dot:before { content: '\ebe5'; } +.codicon-bracket-error:before { content: '\ebe6'; } +.codicon-lock-small:before { content: '\ebe7'; } +.codicon-azure-devops:before { content: '\ebe8'; } +.codicon-verified-filled:before { content: '\ebe9'; } +.codicon-newline:before { content: '\ebea'; } +.codicon-layout:before { content: '\ebeb'; } +.codicon-layout-activitybar-left:before { content: '\ebec'; } +.codicon-layout-activitybar-right:before { content: '\ebed'; } +.codicon-layout-panel-left:before { content: '\ebee'; } +.codicon-layout-panel-center:before { content: '\ebef'; } +.codicon-layout-panel-justify:before { content: '\ebf0'; } +.codicon-layout-panel-right:before { content: '\ebf1'; } +.codicon-layout-panel:before { content: '\ebf2'; } +.codicon-layout-sidebar-left:before { content: '\ebf3'; } +.codicon-layout-sidebar-right:before { content: '\ebf4'; } +.codicon-layout-statusbar:before { content: '\ebf5'; } +.codicon-layout-menubar:before { content: '\ebf6'; } +.codicon-layout-centered:before { content: '\ebf7'; } +.codicon-target:before { content: '\ebf8'; } +.codicon-indent:before { content: '\ebf9'; } +.codicon-record-small:before { content: '\ebfa'; } +.codicon-error-small:before { content: '\ebfb'; } +.codicon-terminal-decoration-error:before { content: '\ebfb'; } +.codicon-arrow-circle-down:before { content: '\ebfc'; } +.codicon-arrow-circle-left:before { content: '\ebfd'; } +.codicon-arrow-circle-right:before { content: '\ebfe'; } +.codicon-arrow-circle-up:before { content: '\ebff'; } +.codicon-layout-sidebar-right-off:before { content: '\ec00'; } +.codicon-layout-panel-off:before { content: '\ec01'; } +.codicon-layout-sidebar-left-off:before { content: '\ec02'; } +.codicon-blank:before { content: '\ec03'; } +.codicon-heart-filled:before { content: '\ec04'; } +.codicon-map:before { content: '\ec05'; } +.codicon-map-horizontal:before { content: '\ec05'; } +.codicon-fold-horizontal:before { content: '\ec05'; } +.codicon-map-filled:before { content: '\ec06'; } +.codicon-map-horizontal-filled:before { content: '\ec06'; } +.codicon-fold-horizontal-filled:before { content: '\ec06'; } +.codicon-circle-small:before { content: '\ec07'; } +.codicon-bell-slash:before { content: '\ec08'; } +.codicon-bell-slash-dot:before { content: '\ec09'; } +.codicon-comment-unresolved:before { content: '\ec0a'; } +.codicon-git-pull-request-go-to-changes:before { content: '\ec0b'; } +.codicon-git-pull-request-new-changes:before { content: '\ec0c'; } +.codicon-search-fuzzy:before { content: '\ec0d'; } +.codicon-comment-draft:before { content: '\ec0e'; } +.codicon-send:before { content: '\ec0f'; } +.codicon-sparkle:before { content: '\ec10'; } +.codicon-insert:before { content: '\ec11'; } +.codicon-mic:before { content: '\ec12'; } +.codicon-thumbsdown-filled:before { content: '\ec13'; } +.codicon-thumbsup-filled:before { content: '\ec14'; } +.codicon-coffee:before { content: '\ec15'; } +.codicon-snake:before { content: '\ec16'; } +.codicon-game:before { content: '\ec17'; } +.codicon-vr:before { content: '\ec18'; } +.codicon-chip:before { content: '\ec19'; } +.codicon-piano:before { content: '\ec1a'; } +.codicon-music:before { content: '\ec1b'; } +.codicon-mic-filled:before { content: '\ec1c'; } +.codicon-repo-fetch:before { content: '\ec1d'; } +.codicon-copilot:before { content: '\ec1e'; } +.codicon-lightbulb-sparkle:before { content: '\ec1f'; } +.codicon-robot:before { content: '\ec20'; } +.codicon-sparkle-filled:before { content: '\ec21'; } +.codicon-diff-single:before { content: '\ec22'; } +.codicon-diff-multiple:before { content: '\ec23'; } +.codicon-surround-with:before { content: '\ec24'; } +.codicon-share:before { content: '\ec25'; } +.codicon-git-stash:before { content: '\ec26'; } +.codicon-git-stash-apply:before { content: '\ec27'; } +.codicon-git-stash-pop:before { content: '\ec28'; } +.codicon-vscode:before { content: '\ec29'; } +.codicon-vscode-insiders:before { content: '\ec2a'; } +.codicon-code-oss:before { content: '\ec2b'; } +.codicon-run-coverage:before { content: '\ec2c'; } +.codicon-run-all-coverage:before { content: '\ec2d'; } +.codicon-coverage:before { content: '\ec2e'; } +.codicon-github-project:before { content: '\ec2f'; } +.codicon-map-vertical:before { content: '\ec30'; } +.codicon-fold-vertical:before { content: '\ec30'; } +.codicon-map-vertical-filled:before { content: '\ec31'; } +.codicon-fold-vertical-filled:before { content: '\ec31'; } +.codicon-go-to-search:before { content: '\ec32'; } +.codicon-percentage:before { content: '\ec33'; } +.codicon-sort-percentage:before { content: '\ec33'; } +.codicon-attach:before { content: '\ec34'; } +.codicon-git-fetch:before { content: '\f101'; } diff --git a/tests/assets/codicon.ttf b/tests/assets/codicon.ttf new file mode 100644 index 0000000000000000000000000000000000000000..27ee4c68caef1cd22342f481420d6dbda1648012 GIT binary patch literal 80340 zcmeFa37lJ3c{hB{)zw{fudeQubR~_JnbAm^@oe^N(s&ui6FZB?ah$|)oW&E{S?mNS znSrcMfDjuRk`Tf+gg^-d8f=yVfu zfU*5JAYCl|3ZLhJuKm|se{*)j^UvXa#~D*=2d=wpPx$Vy?7&YlW1)9nv*+d+>0kM4 z@Ouj9w_m&Gnk(M&i%(54o_`F-emQg9E3UsRb=v0{Z~qu$=`M!4^FEx3_vfE~{&#$U zjx2xiW5E#|-Tv!e&0ZQ^`)|w?SKL%Q6ft30_o_<)8V1tM=`|{l%3WztOK8M>tcO zM`hm2?_*(n`*ZeJcwf;h?_)MQi=k@a5RSgYYulBZE@z*u@BRr7TGz%;M}LYZEu9^- zjDG(g{GZa``RD(8)A0Z6_W!=;|GwY{+0UI8hT^v@sXeK=b=5+ zch~Q#zp?(c`cn(=47vVEUgdA&C4Mcp z`Solo{{r95ujW^=H?c9klD&>S&3?x=@VBsAn9o1M-pTIdr}7++^8`P_zQ!JA^ZY&h zc6K*^6TgMu$zR70^4IhG_}%<4`wV|Ie*=^Z8Lc&-6GoT?y(5a2xU7xkSe_NwC2SX) zW|yLNm$6P(WL>Pp%B+X=f&%?)fDJ+;8e+q2gpIPbY@DrwezcyQ!Y0|N>@;=;JCjYZ z^Vtq|0o%#;v8&k2*tP8C?0R+syOG_*Ze|DBt?V}TO7<%DYW5m-2RqDO%l?49p54RV z$nIlrVQ*z`V{`27?0)tR_5gbqdpCQKy@$P*J;dI}{)io6N7)B)&WG5C*&nmV*r(X1 z*=N}o*_YT?*^|(vo??H&{+fM*{S7Glx9nT&@7TB5zp|gQpRu2_U$N)dui0-nAL7G&gpcwuzJ{;m>-Yp;&rjhS_$1%R zPvd9sGx-$X!ng9X(TnHsbNPk*B7QNygzw^)^2_-Z{7Sx`zl>kQXZg$dEBFokMt&>5 zjlYt=iob^6!4L7*@;~5r@q75a{O$aH{$BnNe?Nbie}Et5ALJk6ALbw7ALpOopX7hS zALF0mkMnu{Y5qn2CH`gp75-KJ6#ol$g8du&1^Xr2&GxVvwwled%lRAGb?g=F8g?|XXc_B_w< z)ocat;T^2XYHTxqD}R)KjQ=tJDEk;ckMH1Vc7T74|2cn>KfvF~-^KrszneeE-@#(+ zJl@6rkbjY`{d^~TKSqC&eV%=RS6DmiV83N? z{--?2{ulc$`$zVD_6++c_5=1W>_@D@j12v0Gy50FBf2+M0te(ucEwCfWHmpJ^@}rxnF=^i}ES~Zlkj6&JT_*sJ%IY%$;H|7aE5OE3zFYwOmepS&0M5(m z^gIAOnAL9(05@j!8wJ<~ls5^0L$mtL0^rrG-UQj3by(m8@NZU!wM_sgXZ70z*qta} zDZo!f`6>aPL-}d}9!Gh*08gNNjR2$otKT62dBEz21Rxn${jdO8>-E(z;GG1t9BK{apf(daVA3 z0+4^K{%!$CLRNoJ05Xx)i7o)7Bdfnx0CJMm9}Hqa0Hi#t|A_$PJ*z(|0Ljnle<}bS zfYreV2+#&t{Zj(a3t0Ve0cZ%U{)7N@1y-jq2S96J^-l{xe_(a$ZvdJEtN)n*bP87g ztN^qNR{xv;I|b$E1)y=T`WFPCd$9T!1)znn`j-TtkFffe1)!O*`d0*?qp~I0cbj`{#OFfd073g1)%+~`Zoli z2eJC!2tXrZ^=}G5H)8d_6@Zq+>faK8zQpQ(CjiZf)xRwO9g5ZeUI5w@tA9rTdKIhx zg8(!vR{yR5bS+l@M*(PEto}U#=wGb9AOKB_)t?c7PR8p0BmnJ<)xR$QJ&o1>SpXUv ztN%a%x*MziivYAZR{x;@^f^}lkpQ$dR<8>{$7A(|0JJ?;KP~{hkJbN|05m{W|FHmc zL011)0ceG+{;UA>LstKZ05nBb|EU0UMppls0DBM069Uj9S^eJxpi#2=&jp}cvidIs zpk=c9F9o1)vih$Cpn0*Ot0CZp0Pz9g`vxX)BeV8?L0cggo zVG2M;W{rpdv}M+?1fVywhAjXMnl+*V(4|?!5r9_B8ZiOr*R0_RK+|RoPXIbMYs3Yh zeX~YF0D3rUBn6<6vxYAK-JCU20?^V~BP{@Zoi#E74D@ZZ34mm*krm)XznlPRX^p%9 zCwdeFIMJhBfKyvL1UR*?Q-D+ZiUOS4*CoKIO(g+N^(_mK2fI-b;8d?}0Z#Sm5#aRv z6#|@|-z&iB+&%%avm5;a~5I#4-hw-@yK7!9p@KJnj zf{)>I6MPLmR|WW5lr;gq4&}H2pFp`-QE|kf0sd)}M0bFH5hc+b;9o*XbO-pCQNCJ$e+A|30{p8esXqYz6iVt30QNg; zP=5fhC5fGVLWy0Dlx~ z&@%vdrdZ=C0Y-KH3juhmSmT%gqkBFr01p;xd|d#(EY|o-0eH1o_E_V%0DOF`LEiy*`&i@0 z0`U8>#=i={1IQZB3cwf08b1+$SCBP+Dggf=Yy3=r(eqCTkb>R#HvxDLS>xvd@FTLu zF9aCT=9dESEwaY11Q?Bl=L9HAqVa11cph2fHv$yTZ&3RIcq3WkcLEgsZ#*vm4<$W1 z0DP6~I2VA|k{y=>;J;+YLjv$*vg5J<`wGgi0H+eqBf!tej^lX*cs$v0JdXh1Cp%8h z1KDL8Hlz%$B@M+Dd>P+9`;ma^lv0Na8xD!})kbOhi_WyfOz?CU690Z#Yx z1o-<1y6kvCfMM($Zx`T12aH_;yuR#srvUuF?08Xt-Hx(LfZvR=BmnO) zJ5Kcg;3sCsD+2Hsv*X`|0G0{n9*R|xRWqU;r5RL?#EegVpU0eG9)@c{w&o!Rk0 z0rmvSl>(f`1(VB* z59(R{8^)c+G2`c^W^Ob0n%A4JGw(OQXFeB+L{gEl$ll0(krUPmYr?wHy4U)RJz(Ev zKWcwHT8`cx{i-85W#SoH}^|ltz1{J6ycWMV{#g8riLu08i4)1~ z$w!mNeaG+iYyKJjc7MNrqyIoEl^RNINj;D@(qri}(s!hvO8+L4%uHl1%FJXQ%6u{N z!?tYONZTjdzMnO+JF_=t-<6%uelM5FjpcUc?#w-&`$1mIugqVPKb)U0#0ztUuNIzZ z&$Qp%{&+{e<6y@lopR@a&QEqeS6p3uPx14`XS<}XeAh!=pY8fi*Dp(_l@6C4EB&Cn zv;1UbvT|?bvF=*;bocjrZtgj;;+`QIaTV8wG+MCyYXYF(Awye8(-NWmSPq-696PqV4pSW*ge&U(+ z?)sOnzi0h3r=(7~{FHl7d2)laVRFNb8@{~Zmy_km-IK4H{QPA7)R|L1xUp;FwVTe} zbl0Z&(>hN(?X)~5a@NpU_n-CEvwpnww5@x$&YZpC?EB9CtrtFb(M1=1{bKFn$&250iF3)0OFqAA^RzQPFumo{)t4T)^o~o9 zT>8`9wcR^+-?jVLp6NZe?|FRBb9?i9H}5^L_o2&bmmRq5{>#35`P}87z2cNBZoA?K zSK3#eaph;Od~V;wzT5ZB@0a#(-T(0ZC$EZM_2H}K1M)SGU-N@&jcaeb_TAS$dF?aT zIoIvI?!N1unYn%D@tG%QzCBZ)d2aTi*#~C7{qnAtU;XlLze0Y+xv%)v_19nj{_B5! zL-!4r-|+Yizq#>@8~5M%?VIv9?Y`;po4$Q>>gJ6%zx(F-TW-JQ*@JJs)wp%*t&l6^ z!=~std;u}|cSlG+FO3ZFPMas<$pTLftw-ol?W|NM|Mb3L6r zWY|u^h~^SXNb1}vYnGdg*_vkSUR<;PK#oOpGc2oNgL5;U$z?oK(KI=1=#g01jThIR zv9{>V^=#_y-qh2vHeqBkMq=&WlxoCmBWxyYO;6pe$6ZU;Y&Q|JWn61t%(&?t~N9k>5 zhWfKvPYW@FB*|x9R1^L%{;H$+Q*l{B1uDhFFn3Pqx}hI4bUpjG3s29NXJ&X>uNe>O z`h!Mouv|VmH#ZBG-g>?ZzaFG?)mJN{cpI)%{e)Vn*1D})&FY>P#UT{dxZT}tkK+S~ z1-XG6sPK#Fs1c+^)yMO3eX&v%V@=Skf)Uj@z{OCxqT4ImHLLcq!tlg!K99G8m+l+t zO9yXn?LKgI*{W8fh2cW;ghIOcTN<+N1<&*;LQ$;@j~1&HkfMr#7`GvVCb*wi-eE7g zDaYNH?)t(S;Wt!?yGwO?!84of1dUa{I$BW`dR*{eUJ=7XJo)~mhUCR9U+~PYG^y~> z)^DK2@<+b-nd^CCc+{^}imKmiB%Z1+C-Y0SV;O0GPmLDGf*kZG`f?al9W5p*Yo@Jf zYpb{Q(5_wf)-Qf>YirEH_X_Q>N|X=!p!NGtalU<)w{+f5=)CnD)bfdLN2jOltzY=U z*6v;QE^DjXJP(n@1#v%&o?sk(ZO|ID3SQx^!9gp(e}6$d7uM3#!Fgh&CW`(+{9d@~ zs={UB{QODh1tS@gqwY+OKH%J@IlgwCq=lvHta6)mn_Vtv4a43a(!zM=5-(JV8vNQ@J+D>nd|y=iZEaro_YA%UwU3O_=Ew{q4FNkNIx&Y$LVR>`1wuW{m6l z8C%Z|$r7LP+^KuRx-P%oiX_^iemSPM_pP|l;pSG`O`Udj)b%@P7ziF~fUZ%&^-D`N zByx^bf{GW_>M#b=8Sad?SvHM%!@N@}cU@b_-H{u3L+~sk7Q0X0diLp4kzffg%?VGPodVge|nld=+FITcIic5ZZ?&bX7aNupqkWgz<;29j&seTp2A_M@Pg5y!Ubt8T#-l@P#totE(n(vJWoVxp>Yx zK8C9*s|KWAXer>C!7cq_lJw?06eKXrSxGTeS%SJB4hln&B;B#Vqlt^lp>SA17Nwy| z5)OnymZM8=l_Vt$RetGEa7J(w9`$2cOG$MWyp9vHW+-VTVnWH+%m_Xjn(Qi;rXeR& zbLbur03kPwXDg0IFAMV=hd4bJN4QFdyrug{F|W{>QmkwYY`7&i1pQt`e!KtoC7^0Dvn}!Cjwgs3OA+}6uRJ0Wz;8i4ew+ERTJEq)Ti}HT|c28nVOoLGHUwNq4KUN z*gaDVP;;{SoMFsmJoK8PeO!6(^mD^sXMYLlKRet4>+{fzY5F#_a~fa#=G? ztt?9yM=i)aJ)KSKwqaztik5`i7jXBqgHv$dMc$EtSK1`4&>IH*i$wcj^u}m03rq8a z?k(U2uCt))3zKtm9=SG~*QP+vRmjUallV2M3^`t;aZF`m4Trd*a1PTTm~GQl!vXi1046WQThy+yGe$ z*ZA#zPPdY6xok3`ealR?wM>1O;ZW&A3TzZJVrdc04(lN!mddtwb~r}NQfw_0Qe`G6g&T(VgzDbr%#hI08X^>Q0m{y0fDLvyQq`Gc6fC z1$z!-06h^gE9e#UO*niJ4pFyaFvwa!Qgp1oNj4)oD2%ho_@i!>O-r>4`K*j}9$=32jhEhRueL|-zVBRXn``u#QTq0ykDOA{xUNu$q7`MUm$QOQ{6i6nEm$2czqwwYUFxo?mF5{RqVoo3fRjX$L;U9O!^p z66k;n3LK-3^w_{hgR(;YA9C5yuP{i0Z>L$FWo7KPxy9FJtJBU{R=fCNP<;DV+_Kv2 zFnCbeEqnVrtc+!Ep<~uX^cge=>I@Ik=cvwL{M6#Pb0Ryv{gW$X>01aI zS4dM$BVyU-om|5%QFAWAK+&RUD_5|yNh3j-RO zM5;aEj28ZO6#^m<;ECapas_5GdLf8@Ahc3kyT!5|Oi!-qdd3zdPX{rV;O$Vn6>yz=O=ZtK^ zv4>^D)FfHA&4`+GOi!0%$;3TjS<)cQH+qaCh8M}V4$lV?Uh{vZlOZ5Rw`*G z$}*6I<`P~Rju}U1jhJc1j2iUqm|@%k%LE14@6hz>;(}zfw$LZL5THp1C?pZqG0I1q zSJ3&bzs0s;9+S52A>R$z4aC5~8v}M;=@{)u06x^y;RN31E$A)n?a_SR%729`zk7~A z?EMt{(E9C=H|0(0?l?F_OMWH6E0eI4`p834B{IPv0Ba-_pXf&993^unFkby2l%Rsb z6>#6c&t5rHoAZpUi}4e0GmH%|Tnq#QO)dPoxEHreR@ZG-$;L;ke55p}2fj5=pV$96 z41LNlj4<2`a^0hCj%*9`H5Dt-~%v*OXg6GC))@!E!SOTwK6R*e81xXb?1#v`Azr;m zY1NBtvLb;{v4VJ9I{ndfpMicN{*{a5qdWC5vV2bZ$i5Zd^2Qt zf+vmn6F8y<0TL3L-{bH~`q2b*0ZH-;ZHnTA!*R<{%#^L`c1Dk=W?Rg*^>T0F(v+97 zx)IOg?Sma&GN0s5G#Pem8`_y|WHXLunpUyX4~67-QYqY+y7CI&>h5mwO4N0T*4l`= z27aLz)|NQqvf5VRMW)KOx*MbywJnuiy1s*hsBcs@RX-clH&jTw|89l3)vU48>mptp z)Hr!Y`pPR(h)^!_chosSYmQoVhGDXtj7>-3N%S5T)x770)O+Mqk3lywNBbknAfZ!EEmzWK(FshZEt5zYz`zCv6 z$gVvWn~r^9)ld-R4T{~`6Qnwm)`YtEq3#LjiyM&ZxQlXUJ!BI2!;qFR#B(Ps)LQ3FT|qzG?toOnD?K^tlOR8)8)YKAcY<}At@6*b)}A9aciYUOFTE!;?_)d?E`8ftUSxbVnh zt{?`E@e8G!YDZf5a6v*0097Gr6UZQZs7!fD2US}zyklAY#v*;5)Agyz!#O><(`!qp zgYD;IWB9Q{f@o__eSkh=+&RUqeRf&zXHkxaNC z5hbTk04U>EaR7Y}_`~aPdKDGL{3iE}JA$er(Z!&Q;@fUD-cpbaaPwV+`~;dT^Qld+AvwjmK8r3AI!e z%^npQCxgz|t9ADvS~jqNdmhyX)iM3(gVYMLJ>cKPu37!yBYiFkR|h%bdxKJekNHE3K5?Pdd`MB;wt=kVx>Byct@)9| zgV5AyyKGCgs^u+hisg2>r$?K|^`C3cAmn++VEccn5$8j1 zz*RJs1Rrb3rXsDyt@?wU{)XW!da3RqXVYTm94&7tZwFa#k%(+3cf)jxgvGT-x0JVR z2LYE(Sx)bROV$Tu4()panL~Suq_7fyA0k(`qF#Y#9ST4B*?r+n4norv7&>Dx+%PVn zWCoE)Xd_5IfK3N86hep`VI+!RHx5_fi8#O5SuG>s3w?o; zl)yKQ#@>MJw1}qdptp!NB=JzJTy!i1m+WXrQdLt?BUaD3Jyt|jOjVUa@GOVImQyUB z$+;2fI;|^$Ot(n9!&PKiaXaFxwUyDx3Qr1E)R5$@h(uS;>Pi+*!J8hXxJ2;f5iW(i zue9V)>cSzf~5{^a@Q`;sf9^KO0 ztA)L8J04GJS~4EDyS*UXB6uwMJyhX|qCA*@^Anq=v??(CDesDna6TWcP0!7{?k(Pe zck0~`TD2#B=FWRiG#1AY`41HM#k&KW04glBVd#J~kKs@&7lUXD;GUsKk$Trv%?Ed@d=@UV5pQy6XPoR+ZQNi zvY?vgDdqAp*DX!Ync5*bhPN57X#+eh{3@i+P0!5C!B`Tyla5@T2rRK~%&pb5hTMZ< zEK#l+#w_{IK_Pt2!*i!112ITpQ%U`SH=?QrV|oG+Xjq;YmcEK8l7D8~hBaMsZfwKq zlAJAP+Ovb%WNGC;zQnj*x7IxvKWsrsYO$Zy@f6LEfmH8t;v? zaK939_PjG?qc0aMj}Z|dRUG5eoTEhAC_&yf{$3X3|kI=F%*u_ zmq<8tPn^?!7R~r#H)MMWTzVAIn$u8M6*5K%EW`u}_ay1Y6pbQ7ZVcMRC<2hx3It9O z90yef7r~Su?c7%rB>WMx@)NI*$?5jA9J7)k&*L&O4Af*QsV1zH%pu2{e-q- zU_R#}7?)Cmt?f8&3>zv__U%GLT zZ}jlKW}lq$U+s~qs6CXR>VMn-De;27cHNW9>L)18!$uz!z1F`NdUvfLTyOJR{7s;lh zl4ZI*DQz?5f_x()#X4IjOlwla&!#m~E3Q}r8&BxOO<$Np+E{hDbwFA%DV)nZVJ-~D zg(WZ8v@4uAflh~&PYak86)c&>7_T1kZpAad<=pKPe{Q5gFSleH_XO{w`5>e^@tO zS465yw%-`JAZ8_q6}*^%SOJ4cC^1K`Ne1?H11rG}W4Oh~r6{r{KYX!t3Ex*F_xgY_ zyvDIGl3i{rv6QriB*kDPgXJJtrr3I9yAjQ1iMt3IVs|UDWp#{WWEUYmO;*(?44Wy> zn}|jaC9i@k{2O&%-Q{Ro?r&ZbU3Lu!v3Sj3HhW1jdAMU2uK7E29sw(J@^JGS;#WHS zGO(!7<4wK;<_ghkBZmlKeh6QR^-st{d6_c2T5f^SX~A$32sk3%=KvD4EyNlPtQ9ge zMOL#(37fD<&$qbD?y#i>=LHw2mg&GdW+F<6i%e579EA6gV${-uW6*_Su#&437eG&9 zG-CRy6d)v(kv<^j4f2b^94daLGb#{f@NhIm$9fWMRDBxG%JZRc+RUhWJZ@^ab8@<@ z`60z!?IPkyOEdpIn=pq@kwB>_JK(|I#1{Mua z&w+8ko*gZTOu- z{-L6p8C(_h^uCl)EcxB`(F;$#*PDtLG}l%Av|1YK^Q^c(WO!H@l7BC{eND2TgiFw9 z%;poYaP%PN*&no4L82wnEqr)d6D9b*njP3WxTP zTl_0-Mu~N_>+zE2SSuuVM&W zNSe;?6c4;bgX>8k`OD{dU75BMNOFiOi7jAy!!lrM6?nhK-r5E0WJIgPB_~h$o zKSlH$1Z%(<;DM@cOU}(Dv)7(5FZVBxeB>=~8npZ$5gtK(+k;+3zfrChk}^lJQc3it zFCs&6r6cRCY|D+bOFSo~Dg!;{=vMazhvHVr&rS_`Nm!(CA$P`;Ue>*jj4uayEVPaX`29 zUv!T)aSxtu-DIJ8lat!p0h*#7WK)reOHr1gB>7CL$jyf8jkJ(qZoXuTsbLA{rJ9`J z$##U+gs+Eun&dBJ9!3uN+vx5mFtAW4+MdIDE_-kmYqD^@fjW zOrjBtk$i~why*U0V5^9a2JEsEB9wS%xk8}?O6$TkC?PNr-~f%tx`#hlMb3R*!n%Rc zk=~2TR(HiJ2k+NAT~=p=_YL5Vy;cvmyUJZQ?}@D7(J&wAGmCK5IJwST>}3~bN|}T2 zD2yVmk1=}s8d2gggin^{Nb>lYaylb~-IqnmQ<&f(g zi$uIkW{C4lHr?M5i*@v;b4_}Yzc4N`lF4U4o;Pw)LJJ^Q>EgKYr(%d7oG)^?UZxLp z)B2XYJ?MFe0EdzMYkb6e6TD_Pe9J8b3ppxHd6|J;MIL+%%92Qa#7!}X;D5uk#KX9` zPKRIdsJ_nLH8+PG|GzGF>-u3`FBkQfT{E+*V058KmBvZ83=@HPZVXo!hi z`4h$w1Ak5^^r^X!N<5yeKfQ}U*c3H#9^4>S;3oVhBPSBu^CtJ6eZ7wMg z;a+`V;b@B>LUz%8h=*n{wo15H0S@qBY$4C25(F+q!!S!o=+e)F{Lz|1B6@cAXl)iQ zW8|TDrRnLrd&4fT@p#Qf4&Z|Ovm@hE!7qorW4+cB-Z7|ROTM5G+759=8Uez!!81ud z&reUbD2NBlG>O+5qfMH@9kkeH(RXB2wpzSUs!dN5;e+`0!r|J~6rSADy{Hdc?freN z{aP*TQY~hVj?Yjt>2KGrmuev0zp48`7ZBr1WN$*oh~`yMQyL+y*+8wO?`32ZNKhieHKBtV1z$dF2M+b;KJ({*p~%)FkYb11a=^?JbVa(x}%f&^+GFj7ec#d7=fJOk@H*DA>gi%Jve()Z>+9=4Mu3H=$1?hoW)8F8D@G-My)>$l zkD}`TvhAIrzRX$S2af03oQ}B;o_-*FR;DlX&bB|VwHY|@f_o4jf!2pLXd-M9tRN-5 z2l;PcD#PfTH&Ckw5o-V0)ZEdme)th%yRN@o1LN8^JG*O2gX+>8E7-$M!~L)tbukTN zQLZh1n1aS_IOeoSRBje?(7lmhjAXxMMN9tBxHp5$1q^EpLh6fQic2-S1xycvaw?d_ zUd>yWot-@hp0p55>)-C%bqJYf#xV+B3cm6T_@{|hgAzhv7t)FJFOeuiB1cTkp|KAq zld;xc*OKMziK%&A>nEI(TuL~Ji<#V{OA_m667cqops&bGfK!^BT}X+A<~afTuR2yi zpdbGzW=^S?=*FhBtW@8d>~YHZXgRsE63;s!HClFiJId*_6pQA{UOC$CcXT>sx!>w< z{n3hKr>ELmaeY}&nw={K5(DW-1f&3lg+QDMkjPdJQ>UPOxxfZj8w~#6L!ij zcKBf{+u5E}BHA=h2X_)T)y$J_)BFm1utHB=X`3O10>rk-H9hRNxqJjxRkqlX3`g2J zJMzeA5xiE!aaHu2@ZgZ>hW!2yqPb;E{}-i-9CFLk)8I=l4C%J?1b8VlvaV^`Lir)~ znkfETpLOb~R^O))@jKdYZ9LWL_iBgGH-cx;8h+wgt$cIxNCYgI^vH0aXEeW~wvcvf zq|xG059tB)_q%`brd^~C9P?)3E5S!lPy7PIZU$-K^y5tMLu)L=d7QOl^^?ehRIs3n zhHjqIz^(eE0#p$(K{hd8RVjBOA_q;l+Nt`K`h-IK?K zNGZmJ*Z1jO`kb&68Ys%Lq{?l*slGuE4t&9nV#vWEeuM-NM2duh9Vjv+cq^FXSY}FT z?Bwx!mfav~UUw|4=_< z(2LYEFka(mN2<&*!8<#3{eIhV^Tk5Uv8*JB#yzA?Tii;y2HfIdB{}4^wN={Mz{GR7 zWIB~H^sHJ$X#L|lwkkjbrI^zdzuKrOPUyB>j&@cwt??ki{uj zsue`P*RWI2q9qLkqpzaIDKQ$!(uzMa6z>eACfbY!6UT-p532tQPxOxvf+{-|bZRxk7-jr2MD;Ss8ILKTe-JHBO2?$V3qe`_^Be_;PJU^*#?zDP(tS)-% zT&%&=_`;k%d2i9`!M}|*y+faduLE?V{*FQWr`6g$$P+*|9CCV~vJQ_9N+Juc2>Zzo zK0;$hsz9({56l&Y4+K$5DJ;+ElU`^-d6TYB)(+Kb`;eqCr@I9!*=<>8M|1gI-e5^+ z*`zIaJ?ex6HOgBUuLao?##BDp9jR=KX4|}h4T!Yh584#fk!WJ0mTBmb-SE3r5&Jl^ zWtmf&QBYkhrJ{f+lmL(i9SElz-iP43AUEpJh!3HKW5Ywx7RE5Uz`y7O(yzHp^@jgr z(wnM%Nyp9;hCV+(r&#d>77&DuNuB58aSM(-)6mXxt&X_+cc}foX=;Z&-fV$B?e401 zcg1p~bee6Y~e<%IPWe1qlyYbN1S z{UNxZCgTI%Y0Zpro~FHwYKrs_`e=CjG;QOowsDQ7&F=R$%)d-Sz7AGs+ps&J4IMSY zHga9Ub}bqmM{avJ@_nh6_flTd5* zH(@s94(a+KgZ3YBhpbf{H8C4JOoXZJ`qcQeLBHQJldW~EvWB4bLq_2hj5S(eaPrD1 zj5o3iFv7@$A%_CZ5ROWrQ_xX?v5b1+DC`B)6K~7PH8>LnZ!rN5gzG>IER@yZjhsR( zQ`bF1_sX6NiM)hYIJIcV11p?XVgZ@UPu%FJ+XoGF{@?;7%muF!T|q0SlFm8jMAd`0 zP&1nPZNLMg=-EXtmaw_uQ^V#Byk^Y??$D#t&_%xkg9I6QM~*B^xxpfPF*ZENZ!1_; z47Hio>^5mn(+o_3CJ?3^6~li&i{-xV+ub!zEuSyXjl=AigR#^H6&DVdarf={{K6A3 zI-aNrTO$~E;6flNC{@7@4ZEhMx!Qi={{0uWFX__c%Yil5I*Tk(B4lv(OnDlqI^qhb z2p1ylzUj02HQL@!`x+t)N~$Wji4PC=05YzizS8=wpddG?iZ9RxlaQ$uAL)NMLaD0d zijAN(3S1gwVkB1K$1*Pd5VplJUD?JOp^#z53o)!Cl6AwuvMB=#eXK&8uE;TR)9a-* z4&rf^Ax9A0$C@ALun|2j#dMfJx{M4~BdlaS+sx|GBpkq&X4`VA6jyPL6}2_Pj7H$N zNuFL(HG~DcQd>OpYSqGO_-s^$bGGQ{I#!^sNhUK^REql%!z~!_sUnlUsk51&1LaRL zPHuj5l_dP#arO5$Pesl#&w1ZjTO#L~=RUuAvw6-r$F^)S&pns;5cYc- zX!@a=e9=!(Ac`0e(ljx_0v@@@iI#M9(Il`U&Aic3&fhJ`*TL#l%|&LkJYZStk5*EV z_7lc-s9)elSZ;yII2Q1v$>p)jbJs*hJR7E=;7jCpA`VG8*`%L=7hu*0l}o&+ZkYVU z04RQfYPmOI+D>B~{jxeCH2_?^)tj;-FLp?oUVJHe!Q?rajq#Vha&@U zXc@=8e?(*c7q8co= zC5IDI$jNty^jy+5D3)1nn&+6Sq$g9DGBG9M#_?tWlh&W3w}Wz++4k;-lB$Q>tvL=694{aG6Fof_x7yI|XGFE&z1Xq8!ZxkvD21 z_zviW83&0GtPuv?FdnKE?79=I4X$8LA@~}Y%}AGqDH;S^tBZbzMR(hWjHF?eVyRGn ze>fE_MK!FlDMeG^zJ3K?VJVi|`up3;6=TGxlwhc)%N6YuKc7tIeOf9FH^sO6gHtWs zD7dos1vff1xMJDG_=sB`!m^LN?{^APwfd2CG1^^X9P#CCXk~G16zmnrJ+Mg>6(5l) z6)?>BqRNOtGg=%ij}qIhjt%)>weTrm*BbF1Ul5T{AxFuD^V>X@T*4KrA^S0ASut8j z2}@e$Ql4^R5AWJl!=@`pSd*eMxGa}EY`+jTLQyRo?58sZJ8?mann)_c1_@F)9*1u_ z1b!XDj%(y&e$N~-%&-Lt){^5&S}2Pb)@fp~Etcwrjj$vIOU)MNeFoz;i59OUe+Z^^ zlNCt;cLIa*D+$P?z@`O@3RZm6>TrCbm>8s0ZA#h!n?acfX(rT@`Pv5PWnerW0w%-Z z5|X(~(`A=qI!P1iN-UVtC$YQ6lxs{O?bmSOl9m(%3l;1lRISyTJaz$cIZB=|XzM{{ z5@u=O=3d+&<_&HZ`y&N!x>!8K`?iEutX>h?B8pqZDx>E3#s4OoMc)>nb)8B72MF2t zfvTq<>yT2qhJ&7?Xf`I}a3wi`*e5wn0)ZLq@PH1*%PAgmf*FjVoqE(_?0lRzuiy5hxi^u?RO7 z38_vkSXN=Dc-Gq=ieu$RNJ9iOmI>{P#NHW}?08hg4jj&{AtTaZM@$8$z;NFmaf0it zR9pNJ4nb=xp-9XzmgX<*Zxw1qDky^hvyu#8a&~~tlF|p)h(p_non=phh2w>2(lKl- z*4DPw-gN{^Zd$xRyaaT0cZ)yM$-e9@euqFNW};y3avNs6T!L@(06oq;Hbj22a}PMU~=Rp8M#gl*eY zPkXahp-@5NqV?gy>Tp^bgs^820>zG1pc6uaSi~q*k`&xVG7OQWl{8JmY}luuH{~3T zfyY+Kkz9eYag}CaQM=`+ma9htdNfCyYpF>b58969^?j;iY0cq;QD;+2G3HdmHB}5o zs=pJ@6|6$LRVY~P1?%e(MVbaXN!i%HQ5A#Dhxs=KIw5zbNhRTar9sdl(pXX@8j;`P zBqGsDmgVygN-e1=V8GDN6GbAAXJBD^Dz}U{UXFt{niUIi%$k#k<1WoYr0yacFz{Lj zGGo(Ibx^8q2}a}FgaQQ=|#C&5%IoGWwiBS`%8}u2jf1h z(0Cv&WMfAij1#a1oom+Dg=1+j62r2Y7&1}LD=>wjXOi*T)RD0IpSEuS)2ew#-Ehq=mBx=AYQ>gzdEmb_T2G|wwA6^W z=qxPIBQ`9*aqKx01ly*(ci=Qs&O=3UMvI>bKM}2%99Xg@%TPs8D|ph$GeHSv!7!sC zw`}PK3{4x(+RJt2{F!k>yS9RLH9@>m4gj9w-bO zW9u`efmx6A(~CM*9^G)Dy)9=>XJ%^GoIwsn81Ga8{GY5H^glMP>dct@|m;$ftgL*yQ)}M-D8-)Qf%LX)TpMr2#)XgQa zlZz{3KPOYdE+o2^Fmkadavq~bbdXHB3=|bj#;#Gc>zaZMDQUMI3rk95+frhw-fTRR zz|oL}Fg4WtFe2J4_`is;eycBt5<;*9n?aLRxkwY3G1xV86{TSjO@cinL6TKvn5#q+ zyn`xO2^!_14+0xDIZT3SfYWBrnSp#bY@66pCKSSEGa;SK3KJ!EsN!1QNjj=7Bf5u` zAu(+J4C;kBq8A11_Y=+!rh7KgM$|p+t5+DZoW?D}*dPWQHgW}voN1RJEH8*?vgK9$ zm=}lBDIAW3B<{trsI%f)a>zD%WZCFlT|iyX=GOe62pp}R#CU}+&=eudb0cP5thyZ^ zpM>Z8nC{Nc*XWx&P1gLeFU>c7NkqE{{ofxiSksBUlxSU2xq|g?w2czBpT-+xQdBCd zG}35+EV4_3!HCsy2pS=ZH3;1n$x(>UVRYuPupPTaVks?@K-$C`=MXi6J-NF#(GGiZ z*zz6hq=XK~uBkBBbhW)5wA8WX5%%0uKyd8106S5Qn%Hy8?;ET@?98LfRO;wWDA+bqZ*`8fOCiK| zu@@P71h<#4=NQ&SCDFxwt0#uC*`bNmeL79oz_18(-v~TMdFXYk5V_cZ^)qLY2gHK| zWHEq`fMW%8AX~afBWoBt5{`{vUmwh0e5NEbBoU8QgEe6|L=zSE2vnnT1w*o!tSaQQ ze6XX|(NUYEw^!sCd z8ddB+=lUg+r|B;3?R2XtB#ruQwXhtu3=Qi%4Hy=1njv*$Lq3zqx204>744kuVT0Js z$!s{CTa|2U%jVPJY_d82XkB5FRmh*;+;dncEZBr`fJ0${0+02m$Wsqo>yT7P<{h3b zle$8RijGClJQjhza_Nw_(;5$Z$N@Ss<<&l2!F~WKEO7RqucWLgQhD&xJVg0!+!Q|fpr{MLKVMRdy6ANK^qjS7HFCkBzD8nduyCutWRAU9 zle%`3wW%{*$PU(4wn?#I$yPkJ=Ok6CIgc{fTO`=yri8sL=pRpueJi*!54Rx3PAfJS zgV5e`n)V?r_KtVtUaM)Z)nhl@@XFnqwp)W+uUY4I%zXtsgw~o-x(zL& z0MUja=zNu@e~Y}dJyv0(J!KbmTV<=}>c2hl*q*{hYpSrP4EJ*@A0QLlr?rO@+^eno zLG>V?De1Igc^!#G?$M*42v&T1SiuqGIbe4tv2Rgp zZv^rb1^N`}RLeh4L;J-G+BUsTP&3N&!8_Wr6oYzUzmLLpUI*Sm-k#vD6oP`21-(wI zI+lN?IrI|8dnKAziQ#NHn=R`HX*}o%9o^Gf%f8`7M_k$fil=FT_lbSMz%krXunOKN z&57^cc(4{;FJt@YWig#BdKC?qlO*Bh!{PEXzo@Ww4L2 z3~qkibtwM|ya{`wAoziuWDM0opwm&Wy_P<-<_>%`IokXBm0Rk#TfAVC1#O*Su(1lV`C)RJ1%WvO-9YTA-oYFXCNEya&eD&V{{g2=O_a6=skyyC`mteNz(Fput0N%GG`3H|MYrjPvsUPe++~*8Ob_Q2m zIc?0XT;^vp{UZk^Jpva;OUuipYArri+l}-dA1NHTdY?ZwZjZFh;VF0N@)d+hc-}m< zJ9ES^z(vDhBON8Ad0-ripHg}a(aRru)D3v7Z63AnJ$k8pwpNsXpO*uqb_9ab$8+9& zx4e&qBk#ME+tG1CdjD7Hy<)|Sq?N8FV-Ibk)a}snJwbMh>M0bv0QH#aiOp*zO5AF1 z&t&GZ*|~dha>t<R!ul~ zajm<>_6T)!v7aZfQ$t2et|s!&a?2sFfF2^;FCJ6vuf+#flD6&&`#=X8EmLQA0EU*( zyNuqaSENHa_MVyS4E#mFT2|2Oh#uHS)@ST-YmuZ~(jMv1u#sLB5b_K*?6%`WB(Y%a zPA}O$%moEl39(>O%4_4jY^6gh+#WNU0ORe6@D6BTtVg{V1b#kpDqNweZ%?DoZ(j6lMR0??Wf?ip6eDW z)mXinYx{Ky8kJQg#+-iOP_EMa=fl3} z!8%uu{-OhcBIP@Y4$~rnS@YU#oH!Av{JXl1{Vh@t&Ya;~jd%T0*SzTf$I%L+#u^Bk zy@0Q0f*ET*WQOmRQ2nf8UJ~)FBJToEo44qfr6p?t5F2sqHksDK29K8*TK{o&;iEIa z;{2Ttp+q8;^_%wSRKoB0W@hZ5-Sl&r-KGzO-8V;b@*Ceeej=-X%Vw_%{ZQ|I!43sE zl$q9>U!9i&WfT4|$AZhthr?=cnmwUsY_pA;^pgUzV3~e~6+k9o4BE~nC}Insx7G1t z(=n#5{Adib0Rgn>th;l+Tfx>Fp4hRoRm&vry(sAY`+hW3eOqhw85 z``;agr@mB4?6W37yr%X_MIpyn-Jap^9=Yva4ijfJv1wSP|&2L4Xi0;;m}(qju= zZGWpW)$})-d-hMc<%Nb2%AeYF^l5v3=+Eg#NMlr~9vluDlc2c<@Ex>6O@CCKHEuIJ zW+T&VW00h&Pv*Euvu(!h-7vutx5|GoYXj#4rf8-M9}H|$`e-QcC7wHs)j^aFQ9lF! zDg#nxKu#5_lY0X`RKz~6a~ZGb!IIQc>X!cO`|M#mZC;mF2_s=*QcEWKbs!gpzwbTv zNb+C|v6U|bV&opOYtESSPHR3jjFZ41l4e2(Xq&^SdF!3_JMCrxCRyPuN2V8=((l7- z6TIqWQVSKG6rSZAmssWtXxvRT z;BimD!jVeA2XEuTI46Ygki)*>eikDoY(5!x zY+|DcGm|uOVe~ixx$lgT`vUSM9&eUIagcuh+WE&JPYj`mzRQDFXnoxoM=oIN7`{eM$tRlp0rN5p5H9lAM#4M zM%j)fCQ5KqzHxMf+I>MReuSGwEXFM;FGGD^+wC(%VnpvgBsCjbqG*d+Ls*di;xZLA zN8F~k`?@_QWO4Ov{z49IyVEtP&q7WgBd=KsS3m#)ef4TE%3vvDB^$~5o>sDDowa!1 zQ%|zCP6Xi#W+pAxc{_MpX|43Opxp>poTVI!Pa3O-(H*R;$7eEl#MYzlBb1OaE4x2j zt9@v94YZLqO(X^+*yKAUY{5f-4B2(-eIj)sT!O_=;XiQ}n~mgAY0n z|M4nX?)_u0J3gMVDxGAIExc~*ekUKFd_&O5?;i7FSlm@|1 zp+c6z=K84f@Wal7kF2iV{s;FvXU31e?ke3XXQHz#A3k`ncP01zcK%;Ekb9!r$w=Jf zE<-iy0^frP@7y_UZAp65#-^Nn$@Y>*5^lfo%+~hou%$c7@j=XOXGfFBOtcpXK->1) zkW;-#e+v2GUx3sfnB+Y=c&Og+exco7ZnaL3(PoD0HX>MJ)Q*E|m*c(QYKY$!M5~Uj zs1=+hnQPlct)P|Z>k6O8D;`JgYTKRZ;|vb-S&qT$<=RCI0v;(&CcXdQe%AeEQ3{2Y zkkjk)ziOLGn?!dY3_GMI@DMiwiqrXMJumY-Ug5m`V101j4bCjjV=#ZesIP2$_MA>% zsn31B+_^xAV>)zXk8Lfq;y*FC%!_i(uX3)fe)$CZgy+)z@>Sbp+qocJeXZx(c3-ed z56;Eay{2{un|Me@WhZk9l3Zs$v3^Iu>RZ*-xn1 zB&KLH4+NzEdGO4O&D%Q=6X&PIkv78AFQZbni}2XiN_Bt4f{3FUON=`is#$vJL^dd- z;jyyfYhf1I3E!_}>-FsQv9iAtWhtpL&M4+@s-7b&Ba0&Rn~~3beipsjs%E3+658P(=iuxyjc=<^gr|iaqoyC%Re+d z4NQ`dSV)z&@L7O<=xO41;mXT}fGbjp3E!b4LSj@1{}uXMEC$xB6(cYk@0yT9;qO7! zNjkv8;JUXh{`gk6O~7WRjm8%(Jchr4q^yLS!J6gJW-3GbK!xL!Tsb(NBME^K{{UjP z6I{V{WnjJpDH0}tkic_HplaxtKx81g(8s0xfK3E}kEqWN{R3?#83MvTErC7@P2%Mq z;5KfN|3Dy)z{DuoXZopSf+A0?=yrF?oyI-{naZf;5-xhVr!_jwgN(`Z+8T4h$sKtd z5hIKlxR(cL``V2w8$OUVEWmfW@4EAG8MZ5u8~*s6?{eQQKJ4f?cpD}(9#T3ScOr;S zTt9@}B=jy2Pr5)s*i!`py12Ow#+P2D>4P_cp}>UH4a>eHv=fCOp`GyPuqtFx2uD68 zZ@E3&f866&;hwsf8>PB3`A@@sTy}|PaWBLs%5m0THCPC@$@yE`a1UYs9q`ICYs<_f zDqoL=IJ0tQef``9QbY7PaX&@#-q!Y#h0N9k{uZ1 z*ga^>NV{wJ@Io6nyJo$`9g8KD$BuSgtNTp&`U7G{ioruCr>kV8tIGeNl}iy(4S&&A z5iB+QAg?&7T(TEED@N%Olu!b0L)P*x)4&tf53Z;0;|3*gM|PYxu-FwNvXFB3Fb)_n z{34Y_^l@b|&EdkM^KMd&gO&J)rH#X9Qr+~ohtGs4iae9x>{($tIe&iZsYE`(&F!@| zGH6nHD)Ky~m#v&VyS7H?^Za?dcY~)R8N$36jW6`?OZ6P=YI(941iZ_`k)z7z;5*vE z;MF?6^|}~UmN*xE4*E?~HFTV;3vQ5SkCKAf9zN$z8N7fP@(#Vb2zDJygNWfSG;TmdE@znG~VNsm;shMNv1DcEEI zb~2Jyx|%UzjJYm%mEDZR-OQ-zd6lU~P91J8^~Y2$R~!-em~kaZ2j!7rD{W6q?Ztx0 zB#p)(bLGVj>=qb6({3D%=x_^m8eRgTKo(K}H{-J&=ake^HE>Bh)-I0-QgC^Dw zcj&7si)U?gs3SHCxXI?+xCduyx2IE%_lmHfrVL00gau9#$=H;L^Pmy_tpg#{cwVLV zI(yS9byyi>7umD3wrY%1Dh<=sj7)zeyZlEVrAdZ8HCD>Hx8Lr< z|F9#Ww{+mniAG2mqXcSn6 zzzl$L&=Pogt0k1&cvc5}TKrIwdNIn85BKspdt%G)ZBMlzke2pa$|Z-^+y->E!0((lGMn+RjD8;pKQN@niK@(2Fx;2 z+l#+JosO!?peu#!(1W`Z%ns+~Ngq@{>b#4YW$oVTr^{C0R`o*W3{M-4|wr3ymPcbtJWF1?OfaR%eTaw<$&WGh3VW0jd z+Ftf4h&?HGHc&oX0)i8gGlwHF$)Eh(A?MT1 zXewhSvY?KgiT&tGX(O4OTK>@ffu8iYL;rx+{0Qx8c1(_pgGsPDsF2O^Me#sU7G8Ci zxb&`N;$aemiZ~n#QX#j9+nH6pB|IO$S*_>BDrx0WOLd}HsRPUg%b9aauAPa+a~b&7 zyh5u^rE~>+63VKpa;a?Gu6X{XpmNfchM(_@pl&utJEED4k3e6S%}@7dHl+Wgs8f?WX8$`ZZ1dCcGmKMNvB5gH^hP3Q#{wR zGSq0`w;(4-dU-uh-xqI0ldBDdjeyn|XXsJPS`;ObnhQ8@S>kc6BF*@lAyIv@66D7V zK2j~HOjf@lnLH~ZHlLEPG{0*0ihN~~F%^w7kmj6AabVuYslUSF^MC!4D~og$E!TC`d$J0& z#1o@jX98(?jzg)?Tn|VQI~5$acI>c@U-!i?)_+>)4q9Y^tgRVsuN7PAYxeZ5V>(C_ zrVpJX+d)?lD^q8mk{LD^jy9xVl#KD|N8;XF-|EF5DV#bLoI2I?rl;M}Govma^@mht z#rj-wWhMDJYvpH;tTTRjdp!lr*@jJ|l6m+%wH_2Oi;Rm$lv@E-%9N+YHfasSkvZKG zrf07xK_69lkNKWpGLu+I9y2osj~qUt+&OF3J$&lasV~jXKf0PLRFl^DcrsZjR4!Me zqpB!5u(=%+!H8rWXAEPZg0{4fKVcRl-9ALL!asmW(l<%%0+BGi<`>8OF?ZIReZUPD z7RL@B9&_jB?$Yn>*x@@HhYmFebbg;3E?n0L8s3~cyPK8noY#<^8|sbXdy-h6)JI@- z#9pz8rY%N57je7gXc4vVjF9usv?;Ih#MelGcbq5Jcq#HUNk(45S_#6;V+Y;PU)eg3 z#6zS$kVIDLy)9wt6nkDetQC?$FmgFtyBTtOOMPWX3cvwHKQAods6by49)#(Xz|~cD zZrzU7P$O||M%HGtXJ>4%-D)_vu`ihRQjV$hDMty=J%1+YA9q@I`zhHltP>ITw~8uh zERyIZxE5$;%t5-F`1kp4@dPA_M`84ZW7+Jn1^bGMeW!^!{-^8b^2Dy!LIHpRAW@IYn3*8tUX!9h4 zJjYY3I?FK#26>Knf#m354P&Hj24{?H>v$~&MY3@*Jgbrii)Qg`6lW)*MUbsP*jZb? z8{6aT&%%mOcW0ehx4tdTULE>hKpd;yDSz@(_XA!KsuL zWp>_oRKg8EK4HeM4&(Y)r?bzxdJA|?63X%Owi|x5UKH-%?Ej&zJMamIPAy$ObztSl z=YSyV-1<6fMrUv_TS5r;jD7a3@XS#DS@a3oUie_b`7S)-%U2V8yFWNV~-8=aLt5P43!>(&{0*Qh@E_`kIk;U}X_rTpiqDIq)^0Z2w z#nzBys9ukhLG{7mCf))IhXP&&3BnQ-4PoOtC=HfM>I#G<2hglo*~RY``WQL`mt%LZ zK*2bTRHlY#+VhY272i%+81sc(re3{axSq+ajb+Pe7d^r$5{fTSF)rt(%h@ZFaD}JS z(Z`pP&>Y|-Ae5YtGVm0*aFV6Q&T_#?CY?fgXX7zw-P4tTFs1k&utCv0Qt{aJxpHpv zFS=)`*&#Aq=dK8ggXEQKf0hK4OXC(I6$#c81De1jY6)R~!&7}kiF2ZGo7il>LG=T$ z?^EuSjbd%Z-2y3JI?W3g7!`W_lW}A9cMJZ73m48kL7FT&Ey z%fJ&ism5Ou@5UFX?N1!Oy~wvlrY2F=VhK;`ej=7AKjIHY9LYW;<+2wBo>uR5el^$#7fEl)<5c-!p3Z>Qwh}HmjWN@y7Qsfq>G+wzb;i@loo=4s zaAMb@VLa~Sy}ilw6ajo?q?1$Wo4{I=rLoU)#Ae=pSu1&(f ze!-RD^V>y{J@R_~uP?R{E+Mz$VEkUB2MP8_kR!~J5>`O-6G}69Zn0nS5oxvH)AyyV zhaWamZ;7ushn91{w7Pm`wH;g>vEOAk8oZ4_r=80r9erc6+fjO2>98S#{vNM|Xj zbScHaokaYEOIL+S%~(e;P#D(_aE+@=W3lV;kOSzCUvcdobz6yAxp5<#-rrA_*i)S8 z@e{j1X~yGL@|STI;#7>6f}atu;-%zTylyd`BC>Bgu|;j)Yg;M8-y?K;=>DNgg^L3a z)5AjER)#9)PP!A<*S&Q^D~h?a z)*6R@FpbWLN|?gJK^r`9E`9Djp&}?{#84Vf$gd@x8_0^yIfb?nS=JQfM^8f}r1Jxg z*b-pde01RM#gU~&%|KphFMqqYh^>a*hJ#cx1dnfGQE=LAiX0Ha$PXW3A=1RiWNZ(9 zKoy)}c5Ma!avMq|Zz_=!gk&nCM*~UtrjiUApAon=!+ze=bFm&*Ll@}t!o9Xru*JcE zeT|Ts06hq)X~~KMf%F6QDaScA_OA_Z8Ds-{LxJ?Dt5)+5-*!zNDpY7z5 z+2oQHAV(mLh+hpRJf1O4m?q-J)x-<|iJxBs{_8o36~|tI84Lv>4}{B1K*>sAHUAUmozB zP76jdcx~c5axoNMBh6{YJAT~r_q=w7)1OWDv;E{7ujzz+XXwAumYPpq&^%1+i>1pm znX{kyD3v5PlBct$ehmX@(C%MlY!t5?# z9lndg+}0o+s*j!r&9S}?gEP|xLQY^&Au~Md`+>j4`aY&p^c=p1*Hz=TM0^ZP$s^+I zf#mQBc(_@5>WL?K7GYa$$1Kr=FXEIYIuS+-2X^xY**0gWEh#W49kqCFBOv494A>s+ zOW?^~#DAeZzS8OirZI#*4vWSAG!`_AesOW1;}(PFuzktenRlLeoo~&*@rheZb_x5s z#FoDn>cveL;A`8;Dcq1Wxmrzj{A2>BvOq5c2Aj0w zxYQGAij45jNxA9OVkAQyB{80HS^(euJRMCO{1~P98eg*F1IbCBV1KNuK`oT z6qq-AfLRdlC0S#UB8*E6uppZXh@44KYZB8+!bK&1>1Q)uE`anclg(2qj{FjvkB^Zk z>_GSHx*p`BSSD1|mvxCphwJW)$>~9p>Y&$hKm2&HW&@pRsE?aDBKXUm@nSM@?o@acG>v0O_}AKKdhxlx{3=(xdT zE(F}qu#@CsS;?7jMPDm|=qSAOxOp{C6P{MlLATY+6PY2hA{wDuj&SudV#Qs=KP^Yl zxAZz063V)ebe!Y`N$$CD0oWJ@T<8y4J8^>SMIxf&J>rE&i4w9Gw~FtruSxCWzF^IK zEIqOOd~xT5coOZqB(rJ*sVCY!R!r2+FHim*sh&5yg!g+bR5FPhQ(j)zm>*DnM>e0# zg-OmJ*#hA?cz&;KN?ezs2^2&aeoZFMnXo>|XJ5086Z%rWrXpT?2~vl4g`|2t0y&At*ZedveTrR{gI-lug{*F8fAuzN436(o=#Jz7i?J=`U{5NKy~m~|QY z6vfV=XG=Gct{|V{l+@h@>`n8-lU{Y7#Kcmme65z>SM?^3KIS-&Iggz@c^M1yJ5E9& z9KB>ApWn5s_;vQmRs6hyqf4>N^WSzpG@H6<+||3Nt5C`!109H5Sr~WN$E*R&r&=Haz2e#tIkSeOBV8Uu;xK?EKC9 zqK(<(yEAMY?t!6e`$5hR*nacghyET(5^`D+Z{Y&U;p+i zS5nudue&Max7?h!&&mjs*lw8REoC*amU(I4ghr}VXDNwd*}o7K5!XC zE<4iOQRKoAiCNGqG39Av8KH#>gQ=NLY895|!E~`nnBtMgZzmTIKo$hGc>ox*nuyS7?W^}XiG*|ftRifagil)kD ziK+8PpgbF>VlHi3xfDhw^MQmB*4F-Na+e#7a_!mlXnqElz-TVjxoy~j12E^<>xq08 zsc$R zxhw9zY_@*6X?B*|!5)qQL^tY(J9Osm0;qzODDtA?F0_dUtve})nA3d0j$WWm2=VG( zh^%9%MxsyVcpZ2V6I^-{(t$RUCe-`lN|Br_$)mY=cI7(Lg#b6@n36LkJQ`%P{rt*t zM_NX|5{Z7Ibc6`sOyHvor{qKo1b?iG!URU#tcX52Dq9bUOi12;Y1+7{6XwR_!H~cF$aKb9Xd4)XS{7dAS}c{M{X^Ebp%%_rDJD|T@V@=D zm&U)z3UQ9eWX4p$96^ql{Ms1|Ole+SZeY{rDX!^KJnJPE77|`IUZ@rLlC-+AJW_~d z-FZr2XPyb`x||9%qe$P}$S~e&l~~@4RjV;GA1l|ux|d`5q!$}5$4j*!sFmX7DsnL& z%j3?Iy+4ie$Hzy)BS~9_F=yer5ROiskH{VzGMoKMSAoxdzh8=>Ze-?RmMKf)zz-l;GJlb97U zK>SrQaUn9~p0z5i1qOkAJ3w(?m#TyDToBaIpUq+%Pt`r&OB`!CYya; z@8WNl0X|9j=+zl2U4&ckwq?!HdGBpDwk2fwwDW})E2yqN^C@=j#v`XCA@!79-y#M3Ba${N^1GR^?Yt%r{3eq>y| z;M+8Ystx6VgSF}6MV%=(0)MQ0nvbASo`Dm+oINfm*VFR0E(HOhiwj2$!O?Bsj>b}u zbwSrDI(GcI>p(x5t9g*XK%s zb+0vCI&>&oXim(|#70XKr7K#&7fgz^yZl#`QZQ!sEz*atnP^SV94`;ELr|J494fQv zXl!P7qFKO|)c=^RcW@JtEEZmGsc5l?%>iC5ssYg@9}}u4G7Z~+{ppM|h-5v9Xen0^ zoZO~1ylHm_QYPR&rvUr+WmclQ`#uwz&l^usjlsE5qkOV$U3n!}r;f^zFx>Nn%cKm! zbovPh$@ zWN4>d`9+g+OQ(8;tCso^qL8ac;m$Wh!gl=Yt5)`vu32hHB%LR40-JaOxLk{y__0^H zg00{k-a8Ih@30Q6J-GPD;)C)^= zaB*>b{07=GoFf|aTk-F5oPmcIryi~&ZCZ_a-r1l0$gJS+g1W0J$qh^Ud?Dqi-+gyo z^D2e*RB7lNNagHM1A7W32W(*nY%$7+5JhpY5G*gL*MxKDxND)YE71gVMR5zWKGa=$ zPe1x2AGq^g@99gXKfp+Cd%2y{*-Vfu>;}~7lFU?WjsnQNvI#YJdSvE0?^NN|BcHSG z^>!EPw;uASZZ%a(2KnMJ_=vKj4A+EYeI)5O{9Mok=rI!AH^hSazR439+&586ebEct z^k+VL(@*~7M?SLU<$mk^*#}B*6leFVw3{ejdOjT&ANfc2zogwh61JOm4Gm%dQs=dX z%z$fEVa!toVbEUM`otLzXGaeHzum(AP7SugKn(Wvr7gIxb>TOK?< z_06iz(2`Zs<#e&)fEXApsAQ@ljg`!&a`j{|76jn<*`C{tWQDX>c%A6&|J>^YGKsB> zq0{TUmW!PtZ>*FqmgN1lUojh(^)97ydh5DHE{hH%@*=82f>74+N}?HJ-4d-UNdhRQ z11z_EQN^11DN5Eb-Oku6pY@URCn!%DtC_3cTl!`###&goX6#R$|LpQ|F$0&@s#%M* zB~UT&S61{a-$2VH9AB5pnD>`GEj0)eF<{Mau=u=Upc=~8edy!tI~-16-ia_H-4u?3MvD5YhDv1wS}aS%5F`O zw~J9cgS!w6s`jelf04#)vIgy{uQ4Tk2&4L6_m^>j!6?5$X&eXxpv%DtWFICuMO+S?L@tgDX`(<0|HYa87V0G(oOMUXrzX<>F;5- zi-c1MKrwZ|!seG<1r&(KOq7rOxh7 z>3B{T5|g+0?Wnm0u*UUjYk)T%R(0B0YRfXtdPF}!!{P2jl8OnZQ)aP2m^MuO{5aMC zj4gqOA(H^NO0Tp;wVCGleF5O1jG=4@1WSpD!$)>fy>Db@zLVWKQH=THJ0^-o&WBhv zbFEXp2IADQvj4ZiBJ@bM9W!APtQ_4_37{IF^np>`m3L02V*c2UiIS0H-#1WiCUuSH zmoK}P(Ab#tmC!#orFJvcKb4XZ4mnhXO??5~q513eZpF@@^iB?6(l6$FWB9U4 zo#}R|)Gn#1vHrf|!|8_#M*Gm=9nWYULwRFxh3AkwBJBqY^V2Y0dL715;CRb=lvh|Uco)Gz;^A98i-(H9y%qm#`@%&c82!z@9r87a zUU=isD(!>LqGf@M7E%7i1;!(83xJuJd$&M{2ZklYW(Spdll&8jzcPY7|V@k z6r5}OPw5p;hF@g$lRBjxM~&XXZ=ctsf(}r5dExI_)2xFwI2FFgD_Rl7SXj|w421K! z;EPM#kHqfK%wAew1rZ{O2H6Q6ODkJyzOk?{ zIysfvmzvr&vam3+OD|5&&Cgpk$ef*ulbs}Yp06YRWR|b2ti37a`j!0Xa4K0bO*?Hv z3ZMA(!6BlfO^(We?{g}t?FT?3*!FeBs`#0*>5Yu+hMGPFO+A`Zbk7#}uL@6bpY~@0 zebM1jLA44hMsQy}@Sok%0HX`t)JwJ@oXIv@o194(V)wvG9J@DGs1#x&_}=2NdaRH} zRS`=tc@-P5HX$q7;2wyIWm|EH$j^^wadsw@(9Hwc6x(wvkXM}SmhXi z<$NM%Ip*U*BN)r1GI6y7hUQ~e08WYh_}1KC1JiqS=yhECbONJ}ss%kRjCllgGREl2 z!+HS4!6*z|Fj&Qb;o=~XOzpPi#Uy$h`Ms>}k7jCBn6MRQbS`62^fI8BNkX!1v5|76 zN-c9=GE*qK%!F>a0F5AEq#V|fm$8W&JNMX5Jevo+2{6Uzrrq+SP3({%$sPKYqnbB57L z1^X&miDXWSwM|GEYe;fOXGo@y6cOY*Vsx=r0!@9^HdoW=9n0pWYgetT>^X7Us5d?1 z{-p|bInM9c4Lh)R1>Pr;dlmiZ*;Y zFFoUTt)9>+Pk%WQj1zGGSNfFW!Blk0Lvl)QdYfG}qDC}sVw}7jiBoM&`XO2zfcB;z zX44Z1P`U#cfN=+E;Oddf5AKLJ_8#SZbZ2GX(s+EhyO;OszR+P9v1lF1R+Cw$wX11o zt(uDE6ZO599qPnK_Z>a>g=}JYe*e-~e0YA};u|CPN%(OC1pxelDh5d}H)to(<&s2l zZ=szAJ|ZGKfciyYLpt{u{sp2P1%Ws2`&DVGVL7r<-?W=sK42_xzB-5OzM>lIDf~*qaEQP zF#|gil9c8Cz3B zhhXP;_dlmiP%Gq?0eE6@O4IS^C6D7(T6C+O^wuvr!au9+0NW=DUbX5K;4TFJ$x{Ap zuem*8IJ8~R_AysDYQm*|P8)wvP7D+^Jh5CtBLCa3((VvQs;zbx3j1v*)|U{?2l6Z; zuCoD4f*8T530)95zJI}AlcWc-XjzoZoC_B==aN_0cX4Z9y~AKv7+%Tl>EJwftf)e2yoVreqRlfj3Blq9NB5tSg!tB~z2F)7=f zQc=E45--IY55l*@0q|m@zlpFos7#R?y>Nf#RoR5^OY|(!DnbncM64cO7N-+^Ps{du zh@y~gH5yOkl8(v({EES<*kSnOO3;J6Gg~X#}aOfCrppS@|Ad=Y15X0AOrUO^@vIniC%@z#u{qRI2EaxD^k)AnWD~IF%4T7HS6- zOdVw^YmF$TMIiK>%1&48W(n3xbPON_(hyF}b_^(Z5-L?1$rf{z%(KBMqpTqntX$ED zGbtwU0xOovs$T{B59}K77X>iji!o4C60x#jI|XLYgp?{ntvAyFZn@-en)@SH1X1Hy zsZuhQ9(CRHY33lvX>c43d`IHDaj~OwXc|~Va6DK&9J@q!GY0A?LEbLl6RYm)orLY$d~EY7);RN&cklI^hq#<`?(SZ@ z)o%sk6+>T>$S;#)kA5S0e01JdOJKqHo_$Tou5&A|9n{4|MeU7WUgFVGe|%c5Yf)?b ziyB)eo&l7}5dD(hrf7w0MpfHKm#F#ANm$l?CenyPU7@AFDQ6>aKI`D2TIVy0^@bHZ zQ^Q;F+QD2WK34EK;*sV;aDZvc7M-bC;6yX6*0a2W(Y17y6ezwiEY9&@qW!rS3x5{R zNe4xEM6`00_dC!@B@!GFlUzJ=Rmbi3-5pmS>$tt1+c|dTIZaaX^kKexJ$Hw{Lw|M- z(_W!{o2Ng7HE8uy)LJlA!L%}rn!|O6+77A@`VOWpUB#L)dZj;d=PT~`YP0RGw7i0S zOWEUlbM@MOx~2bpth~SSwt2TQULN;aD{i}ZzwK1!y-IV%-j!;n`{{Q2vC4kJCj;H9 zN>7r=)#YS1+)4(cc%6WXh}tX3lVV|NKOR>?WRVO;!PJmWD8b+Zl65G)s7?J;>&~n$ zcIFAiiR98h$r}BW1d-OOvn@F6tNB`9p3{IYO0cJTw3S2^)gBb06zJf>ak;*JJ|r&;Hl*+e z#63b61fgT-pOHA5WOYg1d#SlP=vVYhIu6BG-7|7}&53CR84rF$Yc^??vQOaGu^!}p<4jh8YZsbtodx}>K+joA?>JuXC!f_&P zw^@q=rV8!i!Mg)qkwM+*F)9{&Dzlnfa~yg5)bZo?&F{R~di?RP%pA!b&&k`zcU{)b zb`DP6y#E*;`OpRp&me0gJo zWPwOd41?$mtCa!WV{mAk<5I6nnyus?4^sDy zgN;Vn&Bj2qfNseRd+}hjS<9W)^$G>>Gmx)eqcvOj_pThei=K!=(8EcM4vK0)H^LaC z)ED!BE`M&4e#c0~YNfq!Tg(>=Ob-#Pu)DY6pVo zetgg&JJ*F3$IOzn8w6RH7){Ez!f=>^EGHSi&dymz5*@@YdH9Y~wwVLQ1(zboe<%0^ zE)2?%+NCVo2h8D4F|hEPz0t(8oGVh@)k-aV)VvCn)TWS@i)%{dQmM2PF9MV&RNyFT zWGTPun+f}1wzN#LIhn&M2A#4ZfN5I!nrzAcq?Oy1MWAivl)RXm0DL%IT*fZ{^%$06 zAm8cx@|`;LCrI9aJPwMt)zhcfL42>BK5=401HM;jnIPx{r%wz^x94&kOn{ zo(tU0i@k512nd#}1}B`yZ@lrkTW`H}_4sipwX$cj^7a$+w@)8lT%5aP{w`+C=vj+@ zJ;~@5eB(~!vAD5$#Aq*;@CKI976%avabDnYLQJo$JNCI?2i3FR)<{k6$}}5!BRe`? z&l{PFQz>~y+R3(yxS>~6{Enx`cEMoK4^|#?jLc}W5g6H#@y2n>NENC@vd$U^sc@_E0ptTibG5u5jm)U~<;`b3b zeqMwzy;45p4eFoGZ%i61C#0UnU_8|Du1IeCPG=u`0Zx}DdNz*lgJKV2;vjv1?IS=KKTCLGNuI>VYB>V%l%y8(s*~=W zH~2GTr_S8xj*Sie_QcXz=t?XSgDjPUX%c;&J+RxK;zml6Iz-$p1<5JAt``1Wf+OL@5|H z65YrE#(^e&P7ogvAC6Y_&ikeWdYomn60u|a)4iHEKIZ*&ZP*(dKSxQqQ}IN=7N@A^ z(7LMTj(cO?@UT1Pjc+|md6JiKR^oO@VUf3tU8XD=xCn?#5=A?F^iZf+7`PiRMiyqidz1q4f}hjUX%c(5Q|^hjB%7?Z1h+n zk!cX5z#%?2J4;@0#c3b#Mm=HINGAHFrF5n-iW?e4_|ehiKcr#_ugxtVX;F8;hz+j* z(Wcyb0;rQ|O0k}>f5Mp<#+pLiI&#NJzuf*GSs5xo$WtnQZSs`2(2_#71fI>HZ-#c7 zk>I z>Lg#}LL^0T<0m3~eR>Fm@wOVTU;PCK~Bj*Dsx#(kSfwSI8&e*M5awgfn znaZS@Y%P29NR{AuIQA#OCg=1uFhetMGJA#?1nN^zPIcOl(Ix8XXiR48Q<>`ir3Mb) zPNtJ7sp{0+p-goTMouZy@pfd2M!7Tnz3!j6e@&I`TDM;GIy<~lc~@EeGSw_D@mQj+cYe(ma?cBed$plA_&Hg*q zaPE?tzT#*;lijng^YQQ`^%=KXOO1`@_RN&L9UZUO+7k>nQp4r!Y?PNGbN80^yq%$G zs~!X6Nc?Ohb}!19(o$c~F-!o_kOqiS_!gP58;-CY!v?y-e<98aKcUak|y* znD4yZ-R19Ul?;{7!T%s&`HXukX0(n!d|WD78oA+7?Oe}s$EOE-*WjTd@-f2#bO(&L% zP52QTsuDkus>YMGxJ3{wl}|b&$^VTt&DkVN{Hb9^I{^gn8@1q+F3pai%%!DkrQRKm^>wxo^^-q>_5Po5Yz zZx~5@0ndcl@1NC_WkZ>7f13;bdvHx8mXj~HTP@-XzfxVNu2(m!RduI2sUA>|&=1GS zc`7X}TB4W1Cc%>-wkDoU%k1`M#Sw4im*%WCEAY$Dfep~{P-^JLN^Jl>pnd8{QQmrH zsXMB=77i>C$W)yoKo6B_ySLC;1b#4w)r+w%S{7xd3Vh<3@Ad>9IuG5*Tv4#J`0`8h zvVaLT-=U&(sXbRHLi7R9DBq-$q5RG*%*px2sZLc8AnrIy0Rz%3!M8hCw3ZeCAaS7` zlV$Redb(S8G#L};M#n>i7Uw~!H@_(AcYzDBOzE79b8Qx9ml*<_$D}>x1?}7J6idDF z=6ta^+bNL|SQ4K21)>O2bt}()JnLSOL2GdJQjeHyuO6E$bqcfHxp~IV;*ymoS+4i~ zc+BvwfRtUS;jG&vdmN-LHOerE2<#*Q4J0!->gf_-2&C`oJS8|qh$4WN5Ffk(6+(e* z$@U;g5ZbOpJa5(JYaCKpXp->6Gh*T_!a?iO*)vd!aTuZwoCi8!x)?`*cAyHFfe3*q z2W4+LfV|88y1EvhawO;o*p88sZRZW2dJ9|&cq^*d+10YgFNL~Cm&6hv;gKsoZpKo+ zJzSRX0GU^IinS&uUE*-uS)5bKy;Tw>Xtb*8KxM_?U~Gz%P@&<)Kgjjqqa9$b_@Q9O~P3W5-DsXQSSX?VFj&Ve1pSK(0; zLx9%hT(G=zSNa+g78j)`!-!r(DRV2W9AY}D3g^uYrw~Y#*^VjdO3o>A&?sRjTk4(FqNxC??qyeaj=>S-=JR^s-!%d(Miy_;!1m>>#5_Qk{%&b2<{ z|Mf$^G;{$P70Hy)!DERbV}~N@!%AZUqA?gEdX#{_kZ_x^u(U{koe>&?KHU(jsIwp- zLuygrs%CHqUveSenP&kkFgk>|ujJ4~+z!STq)PdWhr+gl!yBPd$uRcHj^9*^D7` z7Y;SPjtkowL$oBbk0H~I{=@o1Vxa+XQwGA0U7CY^*k0sX#>f}{hm1U$l1C!_!Y0Nh z%tSoU_=qL0IYR1CvDtQoCyxST5zXUKS|n8_ZIwv*)JwC4=7%XHoqQJ$m|f_Ldi*K| zAZ8=DRYo+#9dt|SDx8a_2Rjc>S^{mX;pv9MP#(9Oo7f*K4C4NDw3q`$AjgP9%%8X< z&eibP6T1I$Fgb+uE+hdRJTHY+kRM685{8_xRMX|<3Sb0x4iR3YyE(9bv6Y1QkVEuE zu0bS$vfn`P56=QUo^H+E<7{BCMC6e|?8Hc+Z?cNQE(jg2-8L*IPwuHxhEmW>gXT{M zrL;>R+w|>x(RDt`9dW^Ow=(1qeN;M>hLE+@V`XBRK%YJWFZ!FX+Un+f&fF}s7VxC z?nLV7ay;6AjSEuD9?{7wnEUmLRb&5AcYeQ3$yWRC?U?i5{wDTk#*g_%Fw@I)I#`t9aYL+W zR5f+8s+%^6BXc1%6`nY8f{4Au?6o3r=G27?QS99mT|k9C&K!Do2hHVDq`?5;w3%zf zq}VY#65Q;z7dL+{AqLtVlR1_Do$IPT5zrVmNuVPIqbR>T|mC2+k4({AF&DA?G?{U^~F>J z`EnZCY5t87|U;c8woTy&{6e(@PryMixVQ3$Th0~Ti+`;`*4>JQmm8zKHu$zqR z2*7kpzxA@WU%elXyKisa=$&9UUA3?<|@$wh+doSMt`a+qpC0;#4?fR?nm)#@wnRtZTVr!J-$zZWl z_fzy)?0REC@GsaNd}RQey&}Fclu}6x(EcYPf*6-G3KbQiQzC=n5T!+By6rW5Xtq zklGh$IMbNAEN;bC-e0O`(v1wjn5GMVg6F#Rxvr;>e%?)F#L)^N-b zXyyH4a8@%?3s(`2LSdm;Thm=tzgg4m(j%qMY$``N!tdZv}FQ$whnPN$8OmqyuT8aC{t z$K}vVJl8VQPJxgCI)Tln&0pZCZS!0ht;ah;=vt7cI!e45GjC#RN4``XWD-FTN7}a< z2lEcK9_;*qF`(y;qxLL=dFngs{ngfaD5O?xeq6Cv!{msYZqlERFE6jPc*&#NnrAo9 zAI`JZ)>lBXjAo+N;cVx+%sQ z6zz2=LjbnNZj6H#wi}l;pe?0{f#2`rG(JbVPvdeaR3JaLoXZ=sG~Un~KO0bfhlG8u zDfH!rG5bI>mJw&KnM=Bi^t%h^+oVXGRSMkA5&BdnzqBG-Q-lNYu%%exm zYw%(2S-v)L^l0MRWfuFNr~2*~TX9yllZ8`3kAUy)-NE2fo{vt7)SN%!-xjZ`v{F~+ z-duwBim+QC7p5tdByJmCAALwC-Vj~DQMa|MMLI3`qV9$X-B5ym)s5+Vs6LX z;a)>)wxsC9Q}nIA4dD66OV;3aZM9UT;})+!UUoZwbN%&2x6^U&(5>wFEuDtrwARD# z!LsgxHXsve>S#`~z{?jvk4XI$C{Ic-#ESQ9(Bq|r7gwu0n^rzK4N;qZlvJVRARKQ6mB;ru6ICie0+aFqWp<}YZ<4;w0MlJbyrWWW0^DXnv}&mu-RYr$HWyKd zq#CCYTC>tv$aZmC>O^h4L(JH8&yTr{-44v%(+#&i-t zoxylim|a*~94n2W6X$~MB$ALjCJ~~TU-1)&{wQW7e#Il?UA-PO*xf_-@}w4)v{8J} zz+@h0q+!Eyvw#kp;~FbsiLosu1wbbt>c!Y@cf?{IZxhyFD(`ASQ9OD`c*uoGVR*3< z@-AjxabF0)1m@e=uy~*VkJtn=@nv9WA-^%yP+({Q>ULs&iFsz@SK-UULMG)>vFVdA zOyN|`UU;#?@;Ew>?45OoISm>S!PBHky>Mb~G>w@Y#~2k&2|JB^O>D7z9P~PV8j|qf zU~~#qujJSjw_0#2>EZnOZ63~0j|=+{&U(f=Bb+hLh(}6^e5404(nH4a9~(UQx*I*Z zgWhHCp{g4_&Zv8M^pn}kyu(#Dl7E9fDw^^?w}*yjer~Fg zziiqn@ zJDgB(nUI*Xm>ITT&-racj+ttPKcYs3VUj4}--EbL(nhyk+^H=>$hAy$w3->49=l{1 ze|vJ;PgaL@NIje@x32YN+vt_9^E+PKcfKBJDz4$%&qvQGWMyUy5a>h3Z#^eOC7M2j zs-pK3h}HH1D7H@F1y|ufttx&|!|^CoK}y`_Hy_pNh0T+A$u`j*4xmY{Ys=o!c+PM- zLl>t%if$v?gUSN*JJnyOvk<)J_|G^f+;oi3pWT#?;DalA#^1|)e}jxhNwLyIJmT@g z^%oZASXd$vQ=qisg$!d&k^!L2R+&LtqNj*Ia*&v{wcK4<7s?zfmjUqaWHLERzUsUz z%5`SFaW8A9En(xK&bbt;fm$^YpOLrq&83UF)S82D!*RyS1SErEW+huR$sMM)b9NQAg4)=T0$4EOGJa5rk!nz2v#MlnW z^A-t4Z>Hx69t5Y3ULzz6gD;lu2Res!32PXzr6Bi^0D>I3K18Lgqc^csmv8=+l*f27 znJp)uO#ZlmE%|mYfESA;Di-mQ)OdtqSPN)6No~nej_pgIlu*Ij;VksXw-Esl>N8@m z3m=Vm>O=xC`H=b`BT$&bKa%~fU-@7fHc(f^^`7_KnY!k*&YoMh{RK^T2L!iDn+ac`M|Pxe4D%qX8NyBPt8xIciQ&O z!2%l$h-^7&IL{4jaPFvnYJeYJi`0;Ej0?e4uX7khmD)HJR_&_+hVIvZ)8=bv#(2{- zI}*6)3#$~nAX_Ms-$VZ$Us{cOlDzUEy33gS$3SSB994qE0Dr7Svc?G_Xd(*<6Tkq) zxe9Zv7A^fQ_KM7EMnK?0pUn9HTh`C?^PD(jN$ zTg$DIp4iXAzcZ4ESHT^&@!?Wtz{z>TnIF0&KU}WX_j;~hD&&HEH0O)o?PYSKXoyf! z2}J=f8L(7utl@ zLs1+CN_wK}nIX7XZzXOW9=PEC45<5J;Ej>rawrWN_F@usMg>HfmrV%RaFu92o3#s% z5gQO ziih8%-gMHZ!a%}yJ%Jx0==eGQAEln$J38LdlGlFdYdZQCi{&Lvno8JAC5}%}&YH7Q zb#zH_$4fj8T^qp&Gihx45kd~|XlJt)S>miGBoKE1&7mDqvFJ^Bd5lB>GyrkC997_P zK;=Y*CW$d+U+u$H*>RW1_rRJD=i(M|uL+RbS1}T0($mfkWR(|}B*FwWNOVj~{N1?r z#IeYe7>$<>BuIr8SVl(Gjf3h3ljJ#BWP6sy@kLAb%8y~F(PO4liIO*zl7k2t~ zu~@MEokfS7uhEQTg8TMDGWoh%GHFau|Kbg5N^XZRrlGDZwwt5FB_b70X?T?KuvZbV zByiGKX&fZDMbc{7A8!no3%D~X!;NvjVyQQE49n`$W^bXNg|cRFe{UW-v+WK6^K9KA ziF5S1m%Bq8{F??7LQ1SnZ8OnTsW?JBt|=9hQ45NeI2!o6*$zdxm~}fq&heewA?Lga zU0(EhnG&J}Baxwh@SVQnWz12Q_B8dCyjbx@hEH(l}axRK^h~%41g zS1bp$gO|^q%+=E>4IhxEy*WyOyms)b`F8eN@4AvPdGts#z4#uNE$TVk%$hYwszhj5 z+NOLBucP^$ucL#u_NwPEpE&XACqJPbEX>Hi6?tKmM)HInS%YOOS|2h+h3n(2Ekx@R z%;&Xe*<}5WXxTx&%tXtA^}K<*0|&qw4+}nAHduZnT8^>&zGzw4^gb3XCx|kAGFmoS z|0~h5Lv6d?jFwYFZI!=v(x0(_Ife{N@KAXv|H|%|)w@ z-*Z<(wr|}1-~*5F_E6)dH$VK=+wW`K@W@+FzWKq%B@dpw>z+p*IlX6QMz*-?zWW}W zzVpHRhwdDDaOmXFoAu`d#2xM$IyLmxq5ELie&|KNy>QE$*zzG*xZlkF4-7T1*Tf2$ zd(l3}iDTTwuY=<^Xe-(N5!T7lLww%EuMcz1+c|54c723pxuOU8b_wq%Il?`xePrnL z&>o(_%;qufVvqaSVp^Z|{?PUq^nX5I^it>XZiq*Nd4&i~QrXH;DV0_(nn*@v@do+i z*5nl=5n!lL+ZaO-3Zwf9j-sK))VOM@3Dr_0$FB12VI;@VUOVp+6sJcvDuC7qWz-O(ftJKx%8g(s5t=ECox#V!Y~7-6Rj*fXP`9ZQ;J4nW-lT3VEZrdQhEK zXVgRLVfBc5t9qMyR6VBNt{zw4rQV_5sotgDt=^;FtKO&9)D!Cc>I3S7>buqVs1KFW>L=A_ z)K96OR-aX8)z7G(Ri9Hor+!}jg8D`EOX~CLm({;e|BLz+^#%1W)vv1mRXwB5ssBy= zn)-G1MfI=Lm(*{l-&D`4-%|ft{kHly>UY$?RllqL9Z%+h`aSh!_511%)E}xpQh%)e zM14j5srvWoKdAqx{*(IO)t{+9R~zc9>ic6W0rv6@iU0qcFp#D+)cl8bRKh!tX|E2y(eM>#BzHJOKqe?7GV`zXJBmvSnM#@MV zF63kxBWvUgg7HQk5CDN_qij@+sxfTTj1h`1){TZSW{ew6W5Q?|ZKGrCFm@Wdj7ek4 z*bRDR#+WtcjCrGLEEtQ%lF>8z#ZZd8*ZZU2(UT?g?xXn0WtQv1L-elZv++o~l zoHXt-?lw*t_ZV+B?ls|j~H(?-ex>%JZ8Mzc-;6d;~mC3 zjdvOEHr`{r*La_?W;|iM-}r#>Kl`|@CE0Nsy2X(?sKbPNy=zx(*?w@9pY&0b#Fltl z615E7qxk`+b*15gk17WP*5HuiS*4)!X0Cwmur zH+v6zFMA(*Kl=dtAo~#eF#8DmDEk=uIQsNQmH2VzuEc+b$Jo^IsBKs2iGW!bq zD*GDyI{OCuCi@oqHv10yF8dz)KKlXtA^Q>gG5ZPoDf=1wIr|0sCHocoHTw7( zw)O9MARz7d;-KN@Y|rPMUSf`XScDNb%(%6@Y}WkFY1l6gYA~s1Rt5GhbZ)E~W`SN5 zKyAF-ZaraIZW>~e$;+JKONWmRiSyg7nUY%CR*Sy^|H`X>`HC~ zD8(yKb`I)jguW_nU3GePTt+~viJNpj%$G< z)M683WGCBJR8Jy@%36y&$kykwiSdU#X$Rjv)b_GjnCjo*q(x|QT`dukT+{w%Wh;ka zgaCGj10iY)-c|k(TAcYhux=nG^~?grUF6D`gos(Gb~_=^8MG}Q!b%w!rSlHMbNHl? zy|}@%6Fs~vP3a6Z3Y(Kib0oyXxgLk3+JmTQF3s8EIdEfgpMzpGu?QGap&>j6*(wW@ zh7krHgyuCgwWzT35*tq{1m=={{5dQtZh1kWRSAR=?f-J3Z0^tRG-BTzM(#5|M^A%= zu?gPhuE*QtPKxT~|EKrHM}uU-+3eRmSK&>Mq&wFGix8;yFMi$sRC>dskyh1bGoLaW>#0IZig;5Fw)%T*bH$l)MO!8vP z>A4D`fjcwNT4>il335swu5G^4yc5x&D0^|zz{?PglVL9fF{YJ!KPv`PH0E9&-|W|q z5n-$t@&XgjdEmc_8}sA9oAY6cz-)S_8d6W zT&D`zimZ~mU5=_FsBT~wN?(T2#Q*CFe%Q`qQ?uXm7iq*lC4OH zo|8`~S14;X^n)yJ`G~zO0O4{l(yT={*fBrK9))S;aXL6X_4HiamaVHqCT<7bR~~3U zB61+Hgu;lMOpFmPs|%0|;73L0y8?+&F&q3^6g4~m!n44oyB0^Z+@V}~Z_Pag$fxIq zelR28(Kd3eMD^0+G^hsA({f%lsj*s81A3EMqKMZhI4DZMC!5uTP(V6KVowfSizU%J zVavu-h>u#lM6$u5)@kvILk@(ZQ$0tHCdG;uAL&;FwXc69u2pVTUN*e1g?ahWa4(M2 z;MIQ*UXlRWf~wDlp&d8({GbMJyB{Ta;|hOfs;5nRuC=rPk&<8(__B@spw%N(6n^%MHK*2*EfM;z%c zx8oqz4VJ{w`)Ei#GjHH7#8c9s&|fx6%RAs5pkE{QQW&pnD*Hm+&X5%-Sc&X+3N-o@ zJI7{s{QGFdIKZz_dTC{mkdip^2 z%o!_pGZh(c8-8tq>Hk`|+{Y)~y8Yxf4Js6lwK{#4x zur{3*plu!#_qwGnyl^do)LFHYw`UTAoZPo!dD7WCfsK?fTWzePj<34@l^LWBVaH1~R0i(WN14S--yofj~A(JBNmCS@S@0do@~XC1G5 zVV5131Pr`Nh{`%X#2|h`cyOzFT60JFi1TDWt}YJ z3Kt-k9Ra9??yQs4vadTJJ)+I`SP7M!t1i}|STao7IU~!Yb5<+}SSXn@Pk5x9gQN~1 z>s21fq*qp4(+}Mla*GOtbH(f^Sty|Wj+bIh`IHYD1ymf@O4q!XcmB*~@bdsy52!L| z3>O1O{VsXG@_l8<^@QjQm_PvzB_ff7RBmU1Ob5w(wHzd>7hGd62HCIi2b`y(W5-!w zRFbqex)nPJeqkmXxt3wYLc5*9Qiu}Ukac%V&QQfPDo#I*zQUr z76`152r>BDN0C{f-XU;uzytpGcc8-+ATS9cPh|i&gkWC^GY1J|fQv24 zG`e=7XMy*R1KudG1N129>oCvLmd2HePA91UImv@bzGBV8qSFEU5r^64u{Z|17Q++t_%t`B5a2pY$A<}Ma#PmbqFJO zcjGED{+1l*1Q*ci#(Q7qqCZGnG%35bQ3RjEFJ>0ljS&`|b8T|!7#0(kdOVn!MvAtY z8}xoCnhXC#c+U(a|}*VOJQcNij|_I7u!8 ziPkNE_hRBxi)b>b)v$hpgF;IiKf>K})R=5fW4>!xome-_EkYHh-B3H2Biqo{m(7^t zy7Bap2wvMh6wVyFzqWef`bWJbhJ3|#J(a)g{sO<9oR<4Jm&iDOm78`q@e2_C3bj0R zQ~L)hUZgXSKmuPrK?2Tt1PVKJ?4U0Xa4){wpdCeLrOhnx$q~1-`H^eVOphG*jqKP+ z8=@H`QZuI { - await page.setContent(``); - expect(await page.locator('body').ariaSnapshot()).toBe('- checkbox'); +function unshift(snapshot: string): string { + const lines = snapshot.split('\n'); + let whitespacePrefixLength = 100; + for (const line of lines) { + if (!line.trim()) + continue; + const match = line.match(/^(\s*)/); + if (match && match[1].length < whitespacePrefixLength) + whitespacePrefixLength = match[1].length; + break; + } + return lines.filter(t => t.trim()).map(line => line.substring(whitespacePrefixLength)).join('\n'); +} + +async function checkAndMatchSnapshot(locator: Locator, snapshot: string) { + expect.soft(await locator.ariaSnapshot()).toBe(unshift(snapshot)); + await expect.soft(locator).toMatchAriaSnapshot(snapshot); +} + +it('should snapshot', async ({ page }) => { + await page.setContent(`

          title

          `); + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "title" + `); +}); + +it('should snapshot list', async ({ page }) => { + await page.setContent(` +

          title

          +

          title 2

          + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "title" + - heading "title 2" + `); +}); + +it('should snapshot list with accessible name', async ({ page }) => { + await page.setContent(` +
            +
          • one
          • +
          • two
          • +
          + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - list "my list": + - listitem: one + - listitem: two + `); +}); + +it('should snapshot complex', async ({ page }) => { + await page.setContent(` + + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - list: + - listitem: + - link "link" + `); +}); + +it('should allow text nodes', async ({ page }) => { + await page.setContent(` +

          Microsoft

          +
          Open source projects and samples from Microsoft
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "Microsoft" + - text: Open source projects and samples from Microsoft + `); +}); + +it('should snapshot details visibility', async ({ page }) => { + await page.setContent(` +
          + Summary +
          Details
          +
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - group: Summary + `); +}); + +it('should snapshot integration', async ({ page }) => { + await page.setContent(` +

          Microsoft

          +
          Open source projects and samples from Microsoft
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - heading "Microsoft" + - text: Open source projects and samples from Microsoft + - list: + - listitem: + - group: Verified + - listitem: + - link "Sponsor" + `); +}); + +it('should support multiline text', async ({ page }) => { + await page.setContent(` +

          + Line 1 + Line 2 + Line 3 +

          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - paragraph: Line 1 Line 2 Line 3 + `); + await expect(page.locator('body')).toMatchAriaSnapshot(` + - paragraph: | + Line 1 + Line 2 + Line 3 + `); +}); + +it('should concatenate span text', async ({ page }) => { + await page.setContent(` + One Two Three + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - text: One Two Three + `); +}); + +it('should concatenate span text 2', async ({ page }) => { + await page.setContent(` + One Two Three + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - text: One Two Three + `); +}); + +it('should concatenate div text with spaces', async ({ page }) => { + await page.setContent(` +
          One
          Two
          Three
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - text: One Two Three + `); +}); + +it('should include pseudo in text', async ({ page }) => { + await page.setContent(` + + + hello +
          hello
          +
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "worldhello hellobye" + `); +}); + +it('should not include hidden pseudo in text', async ({ page }) => { + await page.setContent(` + + + hello +
          hello
          +
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "hello hello" + `); }); -it('should snapshot nested element', async ({ page }) => { +it('should include new line for block pseudo', async ({ page }) => { await page.setContent(` -
          - -
          `); - expect(await page.locator('body').ariaSnapshot()).toBe('- checkbox'); + + + hello +
          hello
          +
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - link "world hello hello bye" + `); }); -it('should snapshot fragment', async ({ page }) => { +it('should work with slots', async ({ page }) => { + // Text "foo" is assigned to the slot, should not be used twice. + await page.setContent(` + + + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - button "foo" + `); + + // Text "foo" is assigned to the slot, should be used instead of slot content. + await page.setContent(` +
          foo
          + + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - button "foo" + `); + + // Nothing is assigned to the slot, should use slot content. await page.setContent(` -
          - Link - Link -
          `); - expect(await page.locator('body').ariaSnapshot()).toBe(`- link "Link"\n- link "Link"`); +
          + + `); + await checkAndMatchSnapshot(page.locator('body'), ` + - button "pre" + `); +}); + +it('should snapshot inner text', async ({ page }) => { + await page.setContent(` +
          +
          +
          + a.test.ts +
          +
          + + + +
          +
          +
          +
          +
          +
          + snapshot +
          +
          30ms
          +
          + + + +
          +
          +
          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - listitem: + - text: a.test.ts + - button "Run" + - button "Show source" + - button "Watch" + - listitem: + - text: snapshot 30ms + - button "Run" + - button "Show source" + - button "Watch" + `); +}); + +it('should include pseudo codepoints', async ({ page, server }) => { + await page.goto(server.EMPTY_PAGE); + await page.setContent(` + +

          hello

          + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - paragraph: \ueab2hello + `); }); diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index 5e58ba94e0ebe..fa573f2704a88 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -94,7 +94,7 @@ test('should allow text nodes', async ({ page }) => { `); }); -test('details visibility', async ({ page, browserName }) => { +test('details visibility', async ({ page }) => { await page.setContent(`
          Summary @@ -107,7 +107,7 @@ test('details visibility', async ({ page, browserName }) => { `); }); -test('integration test', async ({ page, browserName }) => { +test('integration test', async ({ page }) => { await page.setContent(`

          Microsoft

          Open source projects and samples from Microsoft
          diff --git a/tests/playwright-test/stable-test-runner/package-lock.json b/tests/playwright-test/stable-test-runner/package-lock.json index 180f4d9b33395..df6792d59df93 100644 --- a/tests/playwright-test/stable-test-runner/package-lock.json +++ b/tests/playwright-test/stable-test-runner/package-lock.json @@ -5,16 +5,15 @@ "packages": { "": { "dependencies": { - "@playwright/test": "1.48.0-beta-1728384960000" + "@playwright/test": "1.49.0-alpha-2024-10-17" } }, "node_modules/@playwright/test": { - "version": "1.48.0-beta-1728384960000", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.0-beta-1728384960000.tgz", - "integrity": "sha512-bqQorY7LKVldgwAsUbjULdwKEoUlZ8OOHRZmM/1XyGiGqJwzTGdr0x8Ss312BvKddAh+5pz8cbaPopw10Rp3Ng==", - "license": "Apache-2.0", + "version": "1.49.0-alpha-2024-10-17", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-17.tgz", + "integrity": "sha512-HLZY3sM6xt9Wi8K09zPwjJQtcUBZNBcNSIVoMZhtJM3+TikCKx4SiJ3P8vbSlk7Tm3s2oqlS+wA181IxhbTGBA==", "dependencies": { - "playwright": "1.48.0-beta-1728384960000" + "playwright": "1.49.0-alpha-2024-10-17" }, "bin": { "playwright": "cli.js" @@ -28,7 +27,6 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -38,12 +36,11 @@ } }, "node_modules/playwright": { - "version": "1.48.0-beta-1728384960000", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0-beta-1728384960000.tgz", - "integrity": "sha512-5pIZTwoktOGYJL+YpF2RNhGzVUY6rA/ceQAT0lEQSZaL55MKUzraD2FAoZoBnz84cIIks2ZSlXt8j5mJ5xXt8g==", - "license": "Apache-2.0", + "version": "1.49.0-alpha-2024-10-17", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-17.tgz", + "integrity": "sha512-IgcLunnpocVS/AEq2lcftVOu0DGQzFm1Qt25SCJsrVvKVe83ElKXZYskPz7yA0HeuOVxQyN69EDWI09ph7lfoQ==", "dependencies": { - "playwright-core": "1.48.0-beta-1728384960000" + "playwright-core": "1.49.0-alpha-2024-10-17" }, "bin": { "playwright": "cli.js" @@ -56,10 +53,9 @@ } }, "node_modules/playwright-core": { - "version": "1.48.0-beta-1728384960000", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0-beta-1728384960000.tgz", - "integrity": "sha512-atIhpuvqvVEW5luPhwzhdcXsGdPvzOBLXAg3+MvOLY+6Q4JcTfXMTtTmltP+llUV+LAgj38foQz+6tKTzNMlWg==", - "license": "Apache-2.0", + "version": "1.49.0-alpha-2024-10-17", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-17.tgz", + "integrity": "sha512-XLTKmPBm2ZIOXBckXtiimSOIjQsYy8MqEP9CsHSgytsP0E+j/44v1BuwHOOMaG8sfjcuZLZ1QdFidnl07A9wSg==", "bin": { "playwright-core": "cli.js" }, @@ -70,11 +66,11 @@ }, "dependencies": { "@playwright/test": { - "version": "1.48.0-beta-1728384960000", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.0-beta-1728384960000.tgz", - "integrity": "sha512-bqQorY7LKVldgwAsUbjULdwKEoUlZ8OOHRZmM/1XyGiGqJwzTGdr0x8Ss312BvKddAh+5pz8cbaPopw10Rp3Ng==", + "version": "1.49.0-alpha-2024-10-17", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-17.tgz", + "integrity": "sha512-HLZY3sM6xt9Wi8K09zPwjJQtcUBZNBcNSIVoMZhtJM3+TikCKx4SiJ3P8vbSlk7Tm3s2oqlS+wA181IxhbTGBA==", "requires": { - "playwright": "1.48.0-beta-1728384960000" + "playwright": "1.49.0-alpha-2024-10-17" } }, "fsevents": { @@ -84,18 +80,18 @@ "optional": true }, "playwright": { - "version": "1.48.0-beta-1728384960000", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.0-beta-1728384960000.tgz", - "integrity": "sha512-5pIZTwoktOGYJL+YpF2RNhGzVUY6rA/ceQAT0lEQSZaL55MKUzraD2FAoZoBnz84cIIks2ZSlXt8j5mJ5xXt8g==", + "version": "1.49.0-alpha-2024-10-17", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-17.tgz", + "integrity": "sha512-IgcLunnpocVS/AEq2lcftVOu0DGQzFm1Qt25SCJsrVvKVe83ElKXZYskPz7yA0HeuOVxQyN69EDWI09ph7lfoQ==", "requires": { "fsevents": "2.3.2", - "playwright-core": "1.48.0-beta-1728384960000" + "playwright-core": "1.49.0-alpha-2024-10-17" } }, "playwright-core": { - "version": "1.48.0-beta-1728384960000", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.0-beta-1728384960000.tgz", - "integrity": "sha512-atIhpuvqvVEW5luPhwzhdcXsGdPvzOBLXAg3+MvOLY+6Q4JcTfXMTtTmltP+llUV+LAgj38foQz+6tKTzNMlWg==" + "version": "1.49.0-alpha-2024-10-17", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-17.tgz", + "integrity": "sha512-XLTKmPBm2ZIOXBckXtiimSOIjQsYy8MqEP9CsHSgytsP0E+j/44v1BuwHOOMaG8sfjcuZLZ1QdFidnl07A9wSg==" } } } diff --git a/tests/playwright-test/stable-test-runner/package.json b/tests/playwright-test/stable-test-runner/package.json index 3e32d0bbb7c07..14625ebe6d328 100644 --- a/tests/playwright-test/stable-test-runner/package.json +++ b/tests/playwright-test/stable-test-runner/package.json @@ -1,6 +1,6 @@ { "private": true, "dependencies": { - "@playwright/test": "1.48.0-beta-1728384960000" + "@playwright/test": "1.49.0-alpha-2024-10-17" } } From 0d63df4875b19930acef78ca25917f84b0629d1c Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Fri, 18 Oct 2024 11:03:00 +0200 Subject: [PATCH 328/805] feat(test runner): allow multiple global setups (#32955) Signed-off-by: Simon Knott Co-authored-by: Dmitry Gozman --- docs/src/test-api/class-testconfig.md | 8 ++-- packages/playwright/src/common/config.ts | 10 ++++- .../playwright/src/common/configLoader.ts | 16 +++++++- packages/playwright/src/runner/tasks.ts | 20 +++++++--- packages/playwright/types/test.d.ts | 10 +++-- tests/playwright-test/global-setup.spec.ts | 40 +++++++++++++++++++ 6 files changed, 86 insertions(+), 18 deletions(-) diff --git a/docs/src/test-api/class-testconfig.md b/docs/src/test-api/class-testconfig.md index 0d1f4c1538010..cd70b21b7014f 100644 --- a/docs/src/test-api/class-testconfig.md +++ b/docs/src/test-api/class-testconfig.md @@ -110,9 +110,9 @@ export default defineConfig({ ## property: TestConfig.globalSetup * since: v1.10 -- type: ?<[string]> +- type: ?<[string]|[Array]<[string]>> -Path to the global setup file. This file will be required and run before all the tests. It must export a single function that takes a [FullConfig] argument. +Path to the global setup file. This file will be required and run before all the tests. It must export a single function that takes a [FullConfig] argument. Pass an array of paths to specify multiple global setup files. Learn more about [global setup and teardown](../test-global-setup-teardown.md). @@ -128,9 +128,9 @@ export default defineConfig({ ## property: TestConfig.globalTeardown * since: v1.10 -- type: ?<[string]> +- type: ?<[string]|[Array]<[string]>> -Path to the global teardown file. This file will be required and run after all the tests. It must export a single function. See also [`property: TestConfig.globalSetup`]. +Path to the global teardown file. This file will be required and run after all the tests. It must export a single function. See also [`property: TestConfig.globalSetup`]. Pass an array of paths to specify multiple global teardown files. Learn more about [global setup and teardown](../test-global-setup-teardown.md). diff --git a/packages/playwright/src/common/config.ts b/packages/playwright/src/common/config.ts index a694839f815e1..fd78f0c8d9bf7 100644 --- a/packages/playwright/src/common/config.ts +++ b/packages/playwright/src/common/config.ts @@ -58,6 +58,9 @@ export class FullConfigInternal { testIdMatcher?: Matcher; defineConfigWasUsed = false; + globalSetups: string[] = []; + globalTeardowns: string[] = []; + constructor(location: ConfigLocation, userConfig: Config, configCLIOverrides: ConfigCLIOverrides) { if (configCLIOverrides.projects && userConfig.projects) throw new Error(`Cannot use --browser option when configuration file defines projects. Specify browserName in the projects instead.`); @@ -72,13 +75,16 @@ export class FullConfigInternal { this.plugins = (privateConfiguration?.plugins || []).map((p: any) => ({ factory: p })); this.singleTSConfigPath = pathResolve(configDir, userConfig.tsconfig); + this.globalSetups = (Array.isArray(userConfig.globalSetup) ? userConfig.globalSetup : [userConfig.globalSetup]).map(s => resolveScript(s, configDir)).filter(script => script !== undefined); + this.globalTeardowns = (Array.isArray(userConfig.globalTeardown) ? userConfig.globalTeardown : [userConfig.globalTeardown]).map(s => resolveScript(s, configDir)).filter(script => script !== undefined); + this.config = { configFile: resolvedConfigFile, rootDir: pathResolve(configDir, userConfig.testDir) || configDir, forbidOnly: takeFirst(configCLIOverrides.forbidOnly, userConfig.forbidOnly, false), fullyParallel: takeFirst(configCLIOverrides.fullyParallel, userConfig.fullyParallel, false), - globalSetup: takeFirst(resolveScript(userConfig.globalSetup, configDir), null), - globalTeardown: takeFirst(resolveScript(userConfig.globalTeardown, configDir), null), + globalSetup: this.globalSetups[0] ?? null, + globalTeardown: this.globalTeardowns[0] ?? null, globalTimeout: takeFirst(configCLIOverrides.globalTimeout, userConfig.globalTimeout, 0), grep: takeFirst(userConfig.grep, defaultGrep), grepInvert: takeFirst(userConfig.grepInvert, null), diff --git a/packages/playwright/src/common/configLoader.ts b/packages/playwright/src/common/configLoader.ts index eef56c4458b96..37a886d3e8ab1 100644 --- a/packages/playwright/src/common/configLoader.ts +++ b/packages/playwright/src/common/configLoader.ts @@ -139,13 +139,25 @@ function validateConfig(file: string, config: Config) { } if ('globalSetup' in config && config.globalSetup !== undefined) { - if (typeof config.globalSetup !== 'string') + if (Array.isArray(config.globalSetup)) { + config.globalSetup.forEach((item, index) => { + if (typeof item !== 'string') + throw errorWithFile(file, `config.globalSetup[${index}] must be a string`); + }); + } else if (typeof config.globalSetup !== 'string') { throw errorWithFile(file, `config.globalSetup must be a string`); + } } if ('globalTeardown' in config && config.globalTeardown !== undefined) { - if (typeof config.globalTeardown !== 'string') + if (Array.isArray(config.globalTeardown)) { + config.globalTeardown.forEach((item, index) => { + if (typeof item !== 'string') + throw errorWithFile(file, `config.globalTeardown[${index}] must be a string`); + }); + } else if (typeof config.globalTeardown !== 'string') { throw errorWithFile(file, `config.globalTeardown must be a string`); + } } if ('globalTimeout' in config && config.globalTimeout !== undefined) { diff --git a/packages/playwright/src/runner/tasks.ts b/packages/playwright/src/runner/tasks.ts index 77d84419f4dec..528cac47cd1d4 100644 --- a/packages/playwright/src/runner/tasks.ts +++ b/packages/playwright/src/runner/tasks.ts @@ -98,8 +98,11 @@ export function createGlobalSetupTasks(config: FullConfigInternal) { if (!config.configCLIOverrides.preserveOutputDir && !process.env.PW_TEST_NO_REMOVE_OUTPUT_DIRS) tasks.push(createRemoveOutputDirsTask()); tasks.push(...createPluginSetupTasks(config)); - if (config.config.globalSetup || config.config.globalTeardown) - tasks.push(createGlobalSetupTask()); + if (config.globalSetups.length || config.globalTeardowns.length) { + const length = Math.max(config.globalSetups.length, config.globalTeardowns.length); + for (let i = 0; i < length; i++) + tasks.push(createGlobalSetupTask(i, length)); + } return tasks; } @@ -161,15 +164,20 @@ function createPluginBeginTask(plugin: TestRunnerPluginRegistration): Task { +function createGlobalSetupTask(index: number, length: number): Task { let globalSetupResult: any; let globalSetupFinished = false; let teardownHook: any; + + let title = 'global setup'; + if (length > 1) + title += ` #${index}`; + return { - title: 'global setup', + title, setup: async ({ config }) => { - const setupHook = config.config.globalSetup ? await loadGlobalHook(config, config.config.globalSetup) : undefined; - teardownHook = config.config.globalTeardown ? await loadGlobalHook(config, config.config.globalTeardown) : undefined; + const setupHook = config.globalSetups[index] ? await loadGlobalHook(config, config.globalSetups[index]) : undefined; + teardownHook = config.globalTeardowns[index] ? await loadGlobalHook(config, config.globalTeardowns[index]) : undefined; globalSetupResult = setupHook ? await setupHook(config.config) : undefined; globalSetupFinished = true; }, diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index a989fe69b29f4..ae02d1506ee67 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -1077,7 +1077,8 @@ interface TestConfig { /** * Path to the global setup file. This file will be required and run before all the tests. It must export a single - * function that takes a [FullConfig](https://playwright.dev/docs/api/class-fullconfig) argument. + * function that takes a [FullConfig](https://playwright.dev/docs/api/class-fullconfig) argument. Pass an array of + * paths to specify multiple global setup files. * * Learn more about [global setup and teardown](https://playwright.dev/docs/test-global-setup-teardown). * @@ -1093,12 +1094,13 @@ interface TestConfig { * ``` * */ - globalSetup?: string; + globalSetup?: string|Array; /** * Path to the global teardown file. This file will be required and run after all the tests. It must export a single * function. See also - * [testConfig.globalSetup](https://playwright.dev/docs/api/class-testconfig#test-config-global-setup). + * [testConfig.globalSetup](https://playwright.dev/docs/api/class-testconfig#test-config-global-setup). Pass an array + * of paths to specify multiple global teardown files. * * Learn more about [global setup and teardown](https://playwright.dev/docs/test-global-setup-teardown). * @@ -1114,7 +1116,7 @@ interface TestConfig { * ``` * */ - globalTeardown?: string; + globalTeardown?: string|Array; /** * Maximum time in milliseconds the whole test suite can run. Zero timeout (default) disables this behavior. Useful on diff --git a/tests/playwright-test/global-setup.spec.ts b/tests/playwright-test/global-setup.spec.ts index 3d28be82cddc0..f1bd7b7458348 100644 --- a/tests/playwright-test/global-setup.spec.ts +++ b/tests/playwright-test/global-setup.spec.ts @@ -386,3 +386,43 @@ test('teardown after error', async ({ runInlineTest }) => { 'teardown 1', ]); }); + +test('globalSetup should support multiple', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'playwright.config.ts': ` + module.exports = { + globalSetup: ['./globalSetup1.ts','./globalSetup2.ts','./globalSetup3.ts','./globalSetup4.ts'], + globalTeardown: ['./globalTeardown1.ts', './globalTeardown2.ts'], + }; + `, + 'globalSetup1.ts': `module.exports = () => { console.log('%%globalSetup1'); return () => { console.log('%%globalSetup1Function'); throw new Error('kaboom'); } };`, + 'globalSetup2.ts': `module.exports = () => console.log('%%globalSetup2');`, + 'globalSetup3.ts': `module.exports = () => { console.log('%%globalSetup3'); return () => console.log('%%globalSetup3Function'); }`, + 'globalSetup4.ts': `module.exports = () => console.log('%%globalSetup4');`, + 'globalTeardown1.ts': `module.exports = () => console.log('%%globalTeardown1')`, + 'globalTeardown2.ts': `module.exports = () => { console.log('%%globalTeardown2'); throw new Error('kaboom'); }`, + + 'a.test.js': ` + import { test } from '@playwright/test'; + test('a', () => console.log('%%test a')); + test('b', () => console.log('%%test b')); + `, + }, { reporter: 'line' }); + expect(result.passed).toBe(2); + + // behaviour: setups in order, teardowns in reverse order. + // setup-returned functions inherit their position, and take precedence over `globalTeardown` scripts. + expect(result.outputLines).toEqual([ + 'globalSetup1', + 'globalSetup2', + 'globalSetup3', + 'globalSetup4', + 'test a', + 'test b', + 'globalSetup3Function', + 'globalTeardown2', + 'globalSetup1Function', + // 'globalTeardown1' is missing, because globalSetup1Function errored out. + ]); + expect(result.output).toContain('Error: kaboom'); +}); From 58ef9e2e5fc82189bfd3d81d2271b29c468480dc Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Fri, 18 Oct 2024 02:34:28 -0700 Subject: [PATCH 329/805] feat(firefox-beta): roll to r1465 (#33170) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index a579acc36557a..846ea1e3d351f 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -21,9 +21,9 @@ }, { "name": "firefox-beta", - "revision": "1464", + "revision": "1465", "installByDefault": false, - "browserVersion": "131.0b2" + "browserVersion": "132.0b8" }, { "name": "webkit", From 02f8acce028080e3b8dfb79ebe2f51876079a294 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Fri, 18 Oct 2024 02:34:39 -0700 Subject: [PATCH 330/805] feat(chromium): roll to r1143 (#33163) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 4 +- packages/playwright-core/browsers.json | 4 +- .../src/server/chromium/protocol.d.ts | 68 +++++++++++-- .../src/server/deviceDescriptorsSource.json | 96 +++++++++---------- packages/playwright-core/types/protocol.d.ts | 68 +++++++++++-- 5 files changed, 168 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index 860e11db6567d..e4f15a6d9746a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-130.0.6723.44-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-131.0.6778.3-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 130.0.6723.44 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 131.0.6778.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 131.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 846ea1e3d351f..11a2b1fad1e2f 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,9 +3,9 @@ "browsers": [ { "name": "chromium", - "revision": "1142", + "revision": "1143", "installByDefault": true, - "browserVersion": "130.0.6723.44" + "browserVersion": "131.0.6778.3" }, { "name": "chromium-tip-of-tree", diff --git a/packages/playwright-core/src/server/chromium/protocol.d.ts b/packages/playwright-core/src/server/chromium/protocol.d.ts index 14416bde1e542..35aa6f2eb9b78 100644 --- a/packages/playwright-core/src/server/chromium/protocol.d.ts +++ b/packages/playwright-core/src/server/chromium/protocol.d.ts @@ -695,7 +695,7 @@ percentage [0 - 100] for scroll driven animations frameId: Page.FrameId; } export type CookieExclusionReason = "ExcludeSameSiteUnspecifiedTreatedAsLax"|"ExcludeSameSiteNoneInsecure"|"ExcludeSameSiteLax"|"ExcludeSameSiteStrict"|"ExcludeInvalidSameParty"|"ExcludeSamePartyCrossPartyContext"|"ExcludeDomainNonASCII"|"ExcludeThirdPartyCookieBlockedInFirstPartySet"|"ExcludeThirdPartyPhaseout"; - export type CookieWarningReason = "WarnSameSiteUnspecifiedCrossSiteContext"|"WarnSameSiteNoneInsecure"|"WarnSameSiteUnspecifiedLaxAllowUnsafe"|"WarnSameSiteStrictLaxDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeLax"|"WarnSameSiteLaxCrossDowngradeStrict"|"WarnSameSiteLaxCrossDowngradeLax"|"WarnAttributeValueExceedsMaxSize"|"WarnDomainNonASCII"|"WarnThirdPartyPhaseout"|"WarnCrossSiteRedirectDowngradeChangesInclusion"; + export type CookieWarningReason = "WarnSameSiteUnspecifiedCrossSiteContext"|"WarnSameSiteNoneInsecure"|"WarnSameSiteUnspecifiedLaxAllowUnsafe"|"WarnSameSiteStrictLaxDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeLax"|"WarnSameSiteLaxCrossDowngradeStrict"|"WarnSameSiteLaxCrossDowngradeLax"|"WarnAttributeValueExceedsMaxSize"|"WarnDomainNonASCII"|"WarnThirdPartyPhaseout"|"WarnCrossSiteRedirectDowngradeChangesInclusion"|"WarnDeprecationTrialMetadata"|"WarnThirdPartyCookieHeuristic"; export type CookieOperation = "SetCookie"|"ReadCookie"; /** * This information is currently necessary, as the front-end has a difficult @@ -934,7 +934,7 @@ Should be updated alongside RequestIdTokenStatus in third_party/blink/public/mojom/devtools/inspector_issue.mojom to include all cases except for success. */ - export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"IdpNotPotentiallyTrustworthy"|"DisabledInSettings"|"DisabledInFlags"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByButtonMode"|"InvalidFieldsSpecified"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; + export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"IdpNotPotentiallyTrustworthy"|"DisabledInSettings"|"DisabledInFlags"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByActiveMode"|"InvalidFieldsSpecified"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; export interface FederatedAuthUserInfoRequestIssueDetails { federatedAuthUserInfoRequestIssueReason: FederatedAuthUserInfoRequestIssueReason; } @@ -5989,7 +5989,7 @@ Missing optional values will be filled in by the target with what it would norma * Used to specify sensor types to emulate. See https://w3c.github.io/sensors/#automation for more information. */ - export type SensorType = "absolute-orientation"|"accelerometer"|"ambient-light"|"gravity"|"gyroscope"|"linear-acceleration"|"magnetometer"|"proximity"|"relative-orientation"; + export type SensorType = "absolute-orientation"|"accelerometer"|"ambient-light"|"gravity"|"gyroscope"|"linear-acceleration"|"magnetometer"|"relative-orientation"; export interface SensorMetadata { available?: boolean; minimumFrequency?: number; @@ -11397,7 +11397,7 @@ Backend then generates 'inspectNodeRequested' event upon element selection. export type setShowHitTestBordersReturnValue = { } /** - * Request that backend shows an overlay with web vital metrics. + * Deprecated, no longer has any effect. */ export type setShowWebVitalsParameters = { show: boolean; @@ -11498,7 +11498,7 @@ as an ad. * All Permissions Policy features. This enum should match the one defined in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5. */ - export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; + export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"direct-sockets-private"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; /** * Reason for a permissions policy feature to be disabled. */ @@ -12086,7 +12086,7 @@ https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-expl /** * List of not restored reasons for back-forward cache. */ - export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ParserAborted"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"ContentDiscarded"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame"|"RequestedByWebViewClient"; + export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ParserAborted"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"ContentDiscarded"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame"|"RequestedByWebViewClient"|"PostMessageByWebViewClient"; /** * Types of not restored reasons for back-forward cache. */ @@ -16634,6 +16634,17 @@ flag set to this value. Defaults to the authenticator's defaultBackupState value. */ backupState?: boolean; + /** + * The credential's user.name property. Equivalent to empty if not set. +https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name + */ + userName?: string; + /** + * The credential's user.displayName property. Equivalent to empty if +not set. +https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname + */ + userDisplayName?: string; } /** @@ -16643,6 +16654,22 @@ defaultBackupState value. authenticatorId: AuthenticatorId; credential: Credential; } + /** + * Triggered when a credential is deleted, e.g. through +PublicKeyCredential.signalUnknownCredential(). + */ + export type credentialDeletedPayload = { + authenticatorId: AuthenticatorId; + credentialId: binary; + } + /** + * Triggered when a credential is updated, e.g. through +PublicKeyCredential.signalCurrentUserDetails(). + */ + export type credentialUpdatedPayload = { + authenticatorId: AuthenticatorId; + credential: Credential; + } /** * Triggered when a credential is used in a webauthn assertion. */ @@ -17076,7 +17103,7 @@ possible for multiple rule sets and links to trigger a single attempt. /** * List of FinalStatus reasons for Prerender2. */ - export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"|"WindowClosed"|"SlowNetwork"|"OtherPrerenderedPageActivated"; + export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"|"WindowClosed"|"SlowNetwork"|"OtherPrerenderedPageActivated"|"V8OptimizerDisabled"|"PrerenderFailedDuringPrefetch"; /** * Preloading status values, see also PreloadingTriggeringOutcome. This status is shared by prefetchStatusUpdated and prerenderStatusUpdated. @@ -17751,7 +17778,7 @@ variables as its properties. /** * Type of the debug symbols. */ - type: "None"|"SourceMap"|"EmbeddedDWARF"|"ExternalDWARF"; + type: "SourceMap"|"EmbeddedDWARF"|"ExternalDWARF"; /** * URL of the external symbol source. */ @@ -17955,9 +17982,9 @@ scripts upon enabling debugger. */ scriptLanguage?: Debugger.ScriptLanguage; /** - * If the scriptLanguage is WebASsembly, the source of debug symbols for the module. + * If the scriptLanguage is WebAssembly, the source of debug symbols for the module. */ - debugSymbols?: Debugger.DebugSymbols; + debugSymbols?: Debugger.DebugSymbols[]; /** * The name the embedder supplied for this script. */ @@ -18280,6 +18307,19 @@ call stacks (default). } export type setAsyncCallStackDepthReturnValue = { } + /** + * Replace previous blackbox execution contexts with passed ones. Forces backend to skip +stepping/pausing in scripts in these execution contexts. VM will try to leave blackboxed script by +performing 'step in' several times, finally resorting to 'step out' if unsuccessful. + */ + export type setBlackboxExecutionContextsParameters = { + /** + * Array of execution context unique ids for the debugger to ignore. + */ + uniqueIds: string[]; + } + export type setBlackboxExecutionContextsReturnValue = { + } /** * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by @@ -18290,6 +18330,10 @@ performing 'step in' several times, finally resorting to 'step out' if unsuccess * Array of regexps that will be used to check script url for blackbox state. */ patterns: string[]; + /** + * If true, also ignore scripts with no source url. + */ + skipAnonymous?: boolean; } export type setBlackboxPatternsReturnValue = { } @@ -20310,6 +20354,8 @@ Error was thrown. "WebAudio.nodeParamConnected": WebAudio.nodeParamConnectedPayload; "WebAudio.nodeParamDisconnected": WebAudio.nodeParamDisconnectedPayload; "WebAuthn.credentialAdded": WebAuthn.credentialAddedPayload; + "WebAuthn.credentialDeleted": WebAuthn.credentialDeletedPayload; + "WebAuthn.credentialUpdated": WebAuthn.credentialUpdatedPayload; "WebAuthn.credentialAsserted": WebAuthn.credentialAssertedPayload; "Media.playerPropertiesChanged": Media.playerPropertiesChangedPayload; "Media.playerEventsAdded": Media.playerEventsAddedPayload; @@ -20897,6 +20943,7 @@ Error was thrown. "Debugger.resume": Debugger.resumeParameters; "Debugger.searchInContent": Debugger.searchInContentParameters; "Debugger.setAsyncCallStackDepth": Debugger.setAsyncCallStackDepthParameters; + "Debugger.setBlackboxExecutionContexts": Debugger.setBlackboxExecutionContextsParameters; "Debugger.setBlackboxPatterns": Debugger.setBlackboxPatternsParameters; "Debugger.setBlackboxedRanges": Debugger.setBlackboxedRangesParameters; "Debugger.setBreakpoint": Debugger.setBreakpointParameters; @@ -21507,6 +21554,7 @@ Error was thrown. "Debugger.resume": Debugger.resumeReturnValue; "Debugger.searchInContent": Debugger.searchInContentReturnValue; "Debugger.setAsyncCallStackDepth": Debugger.setAsyncCallStackDepthReturnValue; + "Debugger.setBlackboxExecutionContexts": Debugger.setBlackboxExecutionContextsReturnValue; "Debugger.setBlackboxPatterns": Debugger.setBlackboxPatternsReturnValue; "Debugger.setBlackboxedRanges": Debugger.setBlackboxedRangesReturnValue; "Debugger.setBreakpoint": Debugger.setBreakpointReturnValue; diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index 6609089642a6e..aef1b4c62b862 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -110,7 +110,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S5": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -121,7 +121,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -132,7 +132,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 360, "height": 740 @@ -143,7 +143,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 740, "height": 360 @@ -154,7 +154,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 320, "height": 658 @@ -165,7 +165,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+ landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 658, "height": 320 @@ -176,7 +176,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "viewport": { "width": 712, "height": 1138 @@ -187,7 +187,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -1098,7 +1098,7 @@ "defaultBrowserType": "webkit" }, "LG Optimus L70": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,7 @@ "defaultBrowserType": "chromium" }, "LG Optimus L70 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,7 @@ "defaultBrowserType": "webkit" }, "Pixel 2": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36 Edg/130.0.6723.44", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36 Edg/131.0.6778.3", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.44 Safari/537.36 Edg/130.0.6723.44", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36 Edg/131.0.6778.3", "screen": { "width": 1920, "height": 1080 diff --git a/packages/playwright-core/types/protocol.d.ts b/packages/playwright-core/types/protocol.d.ts index 14416bde1e542..35aa6f2eb9b78 100644 --- a/packages/playwright-core/types/protocol.d.ts +++ b/packages/playwright-core/types/protocol.d.ts @@ -695,7 +695,7 @@ percentage [0 - 100] for scroll driven animations frameId: Page.FrameId; } export type CookieExclusionReason = "ExcludeSameSiteUnspecifiedTreatedAsLax"|"ExcludeSameSiteNoneInsecure"|"ExcludeSameSiteLax"|"ExcludeSameSiteStrict"|"ExcludeInvalidSameParty"|"ExcludeSamePartyCrossPartyContext"|"ExcludeDomainNonASCII"|"ExcludeThirdPartyCookieBlockedInFirstPartySet"|"ExcludeThirdPartyPhaseout"; - export type CookieWarningReason = "WarnSameSiteUnspecifiedCrossSiteContext"|"WarnSameSiteNoneInsecure"|"WarnSameSiteUnspecifiedLaxAllowUnsafe"|"WarnSameSiteStrictLaxDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeLax"|"WarnSameSiteLaxCrossDowngradeStrict"|"WarnSameSiteLaxCrossDowngradeLax"|"WarnAttributeValueExceedsMaxSize"|"WarnDomainNonASCII"|"WarnThirdPartyPhaseout"|"WarnCrossSiteRedirectDowngradeChangesInclusion"; + export type CookieWarningReason = "WarnSameSiteUnspecifiedCrossSiteContext"|"WarnSameSiteNoneInsecure"|"WarnSameSiteUnspecifiedLaxAllowUnsafe"|"WarnSameSiteStrictLaxDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeStrict"|"WarnSameSiteStrictCrossDowngradeLax"|"WarnSameSiteLaxCrossDowngradeStrict"|"WarnSameSiteLaxCrossDowngradeLax"|"WarnAttributeValueExceedsMaxSize"|"WarnDomainNonASCII"|"WarnThirdPartyPhaseout"|"WarnCrossSiteRedirectDowngradeChangesInclusion"|"WarnDeprecationTrialMetadata"|"WarnThirdPartyCookieHeuristic"; export type CookieOperation = "SetCookie"|"ReadCookie"; /** * This information is currently necessary, as the front-end has a difficult @@ -934,7 +934,7 @@ Should be updated alongside RequestIdTokenStatus in third_party/blink/public/mojom/devtools/inspector_issue.mojom to include all cases except for success. */ - export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"IdpNotPotentiallyTrustworthy"|"DisabledInSettings"|"DisabledInFlags"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByButtonMode"|"InvalidFieldsSpecified"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; + export type FederatedAuthRequestIssueReason = "ShouldEmbargo"|"TooManyRequests"|"WellKnownHttpNotFound"|"WellKnownNoResponse"|"WellKnownInvalidResponse"|"WellKnownListEmpty"|"WellKnownInvalidContentType"|"ConfigNotInWellKnown"|"WellKnownTooBig"|"ConfigHttpNotFound"|"ConfigNoResponse"|"ConfigInvalidResponse"|"ConfigInvalidContentType"|"ClientMetadataHttpNotFound"|"ClientMetadataNoResponse"|"ClientMetadataInvalidResponse"|"ClientMetadataInvalidContentType"|"IdpNotPotentiallyTrustworthy"|"DisabledInSettings"|"DisabledInFlags"|"ErrorFetchingSignin"|"InvalidSigninResponse"|"AccountsHttpNotFound"|"AccountsNoResponse"|"AccountsInvalidResponse"|"AccountsListEmpty"|"AccountsInvalidContentType"|"IdTokenHttpNotFound"|"IdTokenNoResponse"|"IdTokenInvalidResponse"|"IdTokenIdpErrorResponse"|"IdTokenCrossSiteIdpErrorResponse"|"IdTokenInvalidRequest"|"IdTokenInvalidContentType"|"ErrorIdToken"|"Canceled"|"RpPageNotVisible"|"SilentMediationFailure"|"ThirdPartyCookiesBlocked"|"NotSignedInWithIdp"|"MissingTransientUserActivation"|"ReplacedByActiveMode"|"InvalidFieldsSpecified"|"RelyingPartyOriginIsOpaque"|"TypeNotMatching"; export interface FederatedAuthUserInfoRequestIssueDetails { federatedAuthUserInfoRequestIssueReason: FederatedAuthUserInfoRequestIssueReason; } @@ -5989,7 +5989,7 @@ Missing optional values will be filled in by the target with what it would norma * Used to specify sensor types to emulate. See https://w3c.github.io/sensors/#automation for more information. */ - export type SensorType = "absolute-orientation"|"accelerometer"|"ambient-light"|"gravity"|"gyroscope"|"linear-acceleration"|"magnetometer"|"proximity"|"relative-orientation"; + export type SensorType = "absolute-orientation"|"accelerometer"|"ambient-light"|"gravity"|"gyroscope"|"linear-acceleration"|"magnetometer"|"relative-orientation"; export interface SensorMetadata { available?: boolean; minimumFrequency?: number; @@ -11397,7 +11397,7 @@ Backend then generates 'inspectNodeRequested' event upon element selection. export type setShowHitTestBordersReturnValue = { } /** - * Request that backend shows an overlay with web vital metrics. + * Deprecated, no longer has any effect. */ export type setShowWebVitalsParameters = { show: boolean; @@ -11498,7 +11498,7 @@ as an ad. * All Permissions Policy features. This enum should match the one defined in third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5. */ - export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; + export type PermissionsPolicyFeature = "accelerometer"|"all-screens-capture"|"ambient-light-sensor"|"attribution-reporting"|"autoplay"|"bluetooth"|"browsing-topics"|"camera"|"captured-surface-control"|"ch-dpr"|"ch-device-memory"|"ch-downlink"|"ch-ect"|"ch-prefers-color-scheme"|"ch-prefers-reduced-motion"|"ch-prefers-reduced-transparency"|"ch-rtt"|"ch-save-data"|"ch-ua"|"ch-ua-arch"|"ch-ua-bitness"|"ch-ua-platform"|"ch-ua-model"|"ch-ua-mobile"|"ch-ua-form-factors"|"ch-ua-full-version"|"ch-ua-full-version-list"|"ch-ua-platform-version"|"ch-ua-wow64"|"ch-viewport-height"|"ch-viewport-width"|"ch-width"|"clipboard-read"|"clipboard-write"|"compute-pressure"|"controlled-frame"|"cross-origin-isolated"|"deferred-fetch"|"digital-credentials-get"|"direct-sockets"|"direct-sockets-private"|"display-capture"|"document-domain"|"encrypted-media"|"execution-while-out-of-viewport"|"execution-while-not-rendered"|"focus-without-user-activation"|"fullscreen"|"frobulate"|"gamepad"|"geolocation"|"gyroscope"|"hid"|"identity-credentials-get"|"idle-detection"|"interest-cohort"|"join-ad-interest-group"|"keyboard-map"|"local-fonts"|"magnetometer"|"media-playback-while-not-visible"|"microphone"|"midi"|"otp-credentials"|"payment"|"picture-in-picture"|"popins"|"private-aggregation"|"private-state-token-issuance"|"private-state-token-redemption"|"publickey-credentials-create"|"publickey-credentials-get"|"run-ad-auction"|"screen-wake-lock"|"serial"|"shared-autofill"|"shared-storage"|"shared-storage-select-url"|"smart-card"|"speaker-selection"|"storage-access"|"sub-apps"|"sync-xhr"|"unload"|"usb"|"usb-unrestricted"|"vertical-scroll"|"web-app-installation"|"web-printing"|"web-share"|"window-management"|"xr-spatial-tracking"; /** * Reason for a permissions policy feature to be disabled. */ @@ -12086,7 +12086,7 @@ https://github.com/WICG/manifest-incubations/blob/gh-pages/scope_extensions-expl /** * List of not restored reasons for back-forward cache. */ - export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ParserAborted"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"ContentDiscarded"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame"|"RequestedByWebViewClient"; + export type BackForwardCacheNotRestoredReason = "NotPrimaryMainFrame"|"BackForwardCacheDisabled"|"RelatedActiveContentsExist"|"HTTPStatusNotOK"|"SchemeNotHTTPOrHTTPS"|"Loading"|"WasGrantedMediaAccess"|"DisableForRenderFrameHostCalled"|"DomainNotAllowed"|"HTTPMethodNotGET"|"SubframeIsNavigating"|"Timeout"|"CacheLimit"|"JavaScriptExecution"|"RendererProcessKilled"|"RendererProcessCrashed"|"SchedulerTrackedFeatureUsed"|"ConflictingBrowsingInstance"|"CacheFlushed"|"ServiceWorkerVersionActivation"|"SessionRestored"|"ServiceWorkerPostMessage"|"EnteredBackForwardCacheBeforeServiceWorkerHostAdded"|"RenderFrameHostReused_SameSite"|"RenderFrameHostReused_CrossSite"|"ServiceWorkerClaim"|"IgnoreEventAndEvict"|"HaveInnerContents"|"TimeoutPuttingInCache"|"BackForwardCacheDisabledByLowMemory"|"BackForwardCacheDisabledByCommandLine"|"NetworkRequestDatapipeDrainedAsBytesConsumer"|"NetworkRequestRedirected"|"NetworkRequestTimeout"|"NetworkExceedsBufferLimit"|"NavigationCancelledWhileRestoring"|"NotMostRecentNavigationEntry"|"BackForwardCacheDisabledForPrerender"|"UserAgentOverrideDiffers"|"ForegroundCacheLimit"|"BrowsingInstanceNotSwapped"|"BackForwardCacheDisabledForDelegate"|"UnloadHandlerExistsInMainFrame"|"UnloadHandlerExistsInSubFrame"|"ServiceWorkerUnregistration"|"CacheControlNoStore"|"CacheControlNoStoreCookieModified"|"CacheControlNoStoreHTTPOnlyCookieModified"|"NoResponseHead"|"Unknown"|"ActivationNavigationsDisallowedForBug1234857"|"ErrorDocument"|"FencedFramesEmbedder"|"CookieDisabled"|"HTTPAuthRequired"|"CookieFlushed"|"BroadcastChannelOnMessage"|"WebViewSettingsChanged"|"WebViewJavaScriptObjectChanged"|"WebViewMessageListenerInjected"|"WebViewSafeBrowsingAllowlistChanged"|"WebViewDocumentStartJavascriptChanged"|"WebSocket"|"WebTransport"|"WebRTC"|"MainResourceHasCacheControlNoStore"|"MainResourceHasCacheControlNoCache"|"SubresourceHasCacheControlNoStore"|"SubresourceHasCacheControlNoCache"|"ContainsPlugins"|"DocumentLoaded"|"OutstandingNetworkRequestOthers"|"RequestedMIDIPermission"|"RequestedAudioCapturePermission"|"RequestedVideoCapturePermission"|"RequestedBackForwardCacheBlockedSensors"|"RequestedBackgroundWorkPermission"|"BroadcastChannel"|"WebXR"|"SharedWorker"|"WebLocks"|"WebHID"|"WebShare"|"RequestedStorageAccessGrant"|"WebNfc"|"OutstandingNetworkRequestFetch"|"OutstandingNetworkRequestXHR"|"AppBanner"|"Printing"|"WebDatabase"|"PictureInPicture"|"SpeechRecognizer"|"IdleManager"|"PaymentManager"|"SpeechSynthesis"|"KeyboardLock"|"WebOTPService"|"OutstandingNetworkRequestDirectSocket"|"InjectedJavascript"|"InjectedStyleSheet"|"KeepaliveRequest"|"IndexedDBEvent"|"Dummy"|"JsNetworkRequestReceivedCacheControlNoStoreResource"|"WebRTCSticky"|"WebTransportSticky"|"WebSocketSticky"|"SmartCard"|"LiveMediaStreamTrack"|"UnloadHandler"|"ParserAborted"|"ContentSecurityHandler"|"ContentWebAuthenticationAPI"|"ContentFileChooser"|"ContentSerial"|"ContentFileSystemAccess"|"ContentMediaDevicesDispatcherHost"|"ContentWebBluetooth"|"ContentWebUSB"|"ContentMediaSessionService"|"ContentScreenReader"|"ContentDiscarded"|"EmbedderPopupBlockerTabHelper"|"EmbedderSafeBrowsingTriggeredPopupBlocker"|"EmbedderSafeBrowsingThreatDetails"|"EmbedderAppBannerManager"|"EmbedderDomDistillerViewerSource"|"EmbedderDomDistillerSelfDeletingRequestDelegate"|"EmbedderOomInterventionTabHelper"|"EmbedderOfflinePage"|"EmbedderChromePasswordManagerClientBindCredentialManager"|"EmbedderPermissionRequestManager"|"EmbedderModalDialog"|"EmbedderExtensions"|"EmbedderExtensionMessaging"|"EmbedderExtensionMessagingForOpenPort"|"EmbedderExtensionSentMessageToCachedFrame"|"RequestedByWebViewClient"|"PostMessageByWebViewClient"; /** * Types of not restored reasons for back-forward cache. */ @@ -16634,6 +16634,17 @@ flag set to this value. Defaults to the authenticator's defaultBackupState value. */ backupState?: boolean; + /** + * The credential's user.name property. Equivalent to empty if not set. +https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name + */ + userName?: string; + /** + * The credential's user.displayName property. Equivalent to empty if +not set. +https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname + */ + userDisplayName?: string; } /** @@ -16643,6 +16654,22 @@ defaultBackupState value. authenticatorId: AuthenticatorId; credential: Credential; } + /** + * Triggered when a credential is deleted, e.g. through +PublicKeyCredential.signalUnknownCredential(). + */ + export type credentialDeletedPayload = { + authenticatorId: AuthenticatorId; + credentialId: binary; + } + /** + * Triggered when a credential is updated, e.g. through +PublicKeyCredential.signalCurrentUserDetails(). + */ + export type credentialUpdatedPayload = { + authenticatorId: AuthenticatorId; + credential: Credential; + } /** * Triggered when a credential is used in a webauthn assertion. */ @@ -17076,7 +17103,7 @@ possible for multiple rule sets and links to trigger a single attempt. /** * List of FinalStatus reasons for Prerender2. */ - export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"|"WindowClosed"|"SlowNetwork"|"OtherPrerenderedPageActivated"; + export type PrerenderFinalStatus = "Activated"|"Destroyed"|"LowEndDevice"|"InvalidSchemeRedirect"|"InvalidSchemeNavigation"|"NavigationRequestBlockedByCsp"|"MainFrameNavigation"|"MojoBinderPolicy"|"RendererProcessCrashed"|"RendererProcessKilled"|"Download"|"TriggerDestroyed"|"NavigationNotCommitted"|"NavigationBadHttpStatus"|"ClientCertRequested"|"NavigationRequestNetworkError"|"CancelAllHostsForTesting"|"DidFailLoad"|"Stop"|"SslCertificateError"|"LoginAuthRequested"|"UaChangeRequiresReload"|"BlockedByClient"|"AudioOutputDeviceRequested"|"MixedContent"|"TriggerBackgrounded"|"MemoryLimitExceeded"|"DataSaverEnabled"|"TriggerUrlHasEffectiveUrl"|"ActivatedBeforeStarted"|"InactivePageRestriction"|"StartFailed"|"TimeoutBackgrounded"|"CrossSiteRedirectInInitialNavigation"|"CrossSiteNavigationInInitialNavigation"|"SameSiteCrossOriginRedirectNotOptInInInitialNavigation"|"SameSiteCrossOriginNavigationNotOptInInInitialNavigation"|"ActivationNavigationParameterMismatch"|"ActivatedInBackground"|"EmbedderHostDisallowed"|"ActivationNavigationDestroyedBeforeSuccess"|"TabClosedByUserGesture"|"TabClosedWithoutUserGesture"|"PrimaryMainFrameRendererProcessCrashed"|"PrimaryMainFrameRendererProcessKilled"|"ActivationFramePolicyNotCompatible"|"PreloadingDisabled"|"BatterySaverEnabled"|"ActivatedDuringMainFrameNavigation"|"PreloadingUnsupportedByWebContents"|"CrossSiteRedirectInMainFrameNavigation"|"CrossSiteNavigationInMainFrameNavigation"|"SameSiteCrossOriginRedirectNotOptInInMainFrameNavigation"|"SameSiteCrossOriginNavigationNotOptInInMainFrameNavigation"|"MemoryPressureOnTrigger"|"MemoryPressureAfterTriggered"|"PrerenderingDisabledByDevTools"|"SpeculationRuleRemoved"|"ActivatedWithAuxiliaryBrowsingContexts"|"MaxNumOfRunningEagerPrerendersExceeded"|"MaxNumOfRunningNonEagerPrerendersExceeded"|"MaxNumOfRunningEmbedderPrerendersExceeded"|"PrerenderingUrlHasEffectiveUrl"|"RedirectedPrerenderingUrlHasEffectiveUrl"|"ActivationUrlHasEffectiveUrl"|"JavaScriptInterfaceAdded"|"JavaScriptInterfaceRemoved"|"AllPrerenderingCanceled"|"WindowClosed"|"SlowNetwork"|"OtherPrerenderedPageActivated"|"V8OptimizerDisabled"|"PrerenderFailedDuringPrefetch"; /** * Preloading status values, see also PreloadingTriggeringOutcome. This status is shared by prefetchStatusUpdated and prerenderStatusUpdated. @@ -17751,7 +17778,7 @@ variables as its properties. /** * Type of the debug symbols. */ - type: "None"|"SourceMap"|"EmbeddedDWARF"|"ExternalDWARF"; + type: "SourceMap"|"EmbeddedDWARF"|"ExternalDWARF"; /** * URL of the external symbol source. */ @@ -17955,9 +17982,9 @@ scripts upon enabling debugger. */ scriptLanguage?: Debugger.ScriptLanguage; /** - * If the scriptLanguage is WebASsembly, the source of debug symbols for the module. + * If the scriptLanguage is WebAssembly, the source of debug symbols for the module. */ - debugSymbols?: Debugger.DebugSymbols; + debugSymbols?: Debugger.DebugSymbols[]; /** * The name the embedder supplied for this script. */ @@ -18280,6 +18307,19 @@ call stacks (default). } export type setAsyncCallStackDepthReturnValue = { } + /** + * Replace previous blackbox execution contexts with passed ones. Forces backend to skip +stepping/pausing in scripts in these execution contexts. VM will try to leave blackboxed script by +performing 'step in' several times, finally resorting to 'step out' if unsuccessful. + */ + export type setBlackboxExecutionContextsParameters = { + /** + * Array of execution context unique ids for the debugger to ignore. + */ + uniqueIds: string[]; + } + export type setBlackboxExecutionContextsReturnValue = { + } /** * Replace previous blackbox patterns with passed ones. Forces backend to skip stepping/pausing in scripts with url matching one of the patterns. VM will try to leave blackboxed script by @@ -18290,6 +18330,10 @@ performing 'step in' several times, finally resorting to 'step out' if unsuccess * Array of regexps that will be used to check script url for blackbox state. */ patterns: string[]; + /** + * If true, also ignore scripts with no source url. + */ + skipAnonymous?: boolean; } export type setBlackboxPatternsReturnValue = { } @@ -20310,6 +20354,8 @@ Error was thrown. "WebAudio.nodeParamConnected": WebAudio.nodeParamConnectedPayload; "WebAudio.nodeParamDisconnected": WebAudio.nodeParamDisconnectedPayload; "WebAuthn.credentialAdded": WebAuthn.credentialAddedPayload; + "WebAuthn.credentialDeleted": WebAuthn.credentialDeletedPayload; + "WebAuthn.credentialUpdated": WebAuthn.credentialUpdatedPayload; "WebAuthn.credentialAsserted": WebAuthn.credentialAssertedPayload; "Media.playerPropertiesChanged": Media.playerPropertiesChangedPayload; "Media.playerEventsAdded": Media.playerEventsAddedPayload; @@ -20897,6 +20943,7 @@ Error was thrown. "Debugger.resume": Debugger.resumeParameters; "Debugger.searchInContent": Debugger.searchInContentParameters; "Debugger.setAsyncCallStackDepth": Debugger.setAsyncCallStackDepthParameters; + "Debugger.setBlackboxExecutionContexts": Debugger.setBlackboxExecutionContextsParameters; "Debugger.setBlackboxPatterns": Debugger.setBlackboxPatternsParameters; "Debugger.setBlackboxedRanges": Debugger.setBlackboxedRangesParameters; "Debugger.setBreakpoint": Debugger.setBreakpointParameters; @@ -21507,6 +21554,7 @@ Error was thrown. "Debugger.resume": Debugger.resumeReturnValue; "Debugger.searchInContent": Debugger.searchInContentReturnValue; "Debugger.setAsyncCallStackDepth": Debugger.setAsyncCallStackDepthReturnValue; + "Debugger.setBlackboxExecutionContexts": Debugger.setBlackboxExecutionContextsReturnValue; "Debugger.setBlackboxPatterns": Debugger.setBlackboxPatternsReturnValue; "Debugger.setBlackboxedRanges": Debugger.setBlackboxedRangesReturnValue; "Debugger.setBreakpoint": Debugger.setBreakpointReturnValue; From 6ea17a5d82e8a9f783a86f76f7a0c1219d4a495a Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 18 Oct 2024 16:38:55 +0200 Subject: [PATCH 331/805] chore: move non-test utility workflows to ubuntu-24.04 (#33176) --- .github/workflows/infra.yml | 2 +- .github/workflows/pr_check_client_side_changes.yml | 2 +- .github/workflows/publish_canary.yml | 2 +- .github/workflows/publish_release_npm.yml | 2 +- .github/workflows/publish_release_traceviewer.yml | 2 +- .github/workflows/roll_browser_into_playwright.yml | 2 +- .github/workflows/trigger_tests.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/infra.yml b/.github/workflows/infra.yml index 905597c8bddd0..1d52ddb96d41d 100644 --- a/.github/workflows/infra.yml +++ b/.github/workflows/infra.yml @@ -16,7 +16,7 @@ env: jobs: doc-and-lint: name: "docs & lint" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/pr_check_client_side_changes.yml b/.github/workflows/pr_check_client_side_changes.yml index 7748b5d514af3..17a8da9ca3d4d 100644 --- a/.github/workflows/pr_check_client_side_changes.yml +++ b/.github/workflows/pr_check_client_side_changes.yml @@ -12,7 +12,7 @@ on: jobs: check: name: Check - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/publish_canary.yml b/.github/workflows/publish_canary.yml index 64d25dbd6dd85..78fb0ba5a95da 100644 --- a/.github/workflows/publish_canary.yml +++ b/.github/workflows/publish_canary.yml @@ -65,7 +65,7 @@ jobs: publish-trace-viewer: name: "publish Trace Viewer to trace.playwright.dev" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/publish_release_npm.yml b/.github/workflows/publish_release_npm.yml index 46b58168345dc..bbef0c5c62a28 100644 --- a/.github/workflows/publish_release_npm.yml +++ b/.github/workflows/publish_release_npm.yml @@ -10,7 +10,7 @@ env: jobs: publish-npm-release: name: "publish to NPM" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' permissions: contents: read diff --git a/.github/workflows/publish_release_traceviewer.yml b/.github/workflows/publish_release_traceviewer.yml index 60af5442e95b2..e61ac76ccdbd6 100644 --- a/.github/workflows/publish_release_traceviewer.yml +++ b/.github/workflows/publish_release_traceviewer.yml @@ -7,7 +7,7 @@ on: jobs: publish-trace-viewer: name: "publish Trace Viewer to trace.playwright.dev" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 if: github.repository == 'microsoft/playwright' steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/roll_browser_into_playwright.yml b/.github/workflows/roll_browser_into_playwright.yml index da905131603e6..e24d015cf8a2c 100644 --- a/.github/workflows/roll_browser_into_playwright.yml +++ b/.github/workflows/roll_browser_into_playwright.yml @@ -12,7 +12,7 @@ permissions: jobs: roll: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 diff --git a/.github/workflows/trigger_tests.yml b/.github/workflows/trigger_tests.yml index dcd68dca37440..1ea2ec424d2ef 100644 --- a/.github/workflows/trigger_tests.yml +++ b/.github/workflows/trigger_tests.yml @@ -9,7 +9,7 @@ on: jobs: trigger: name: "trigger" - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - run: | curl -X POST \ From 2e8e7a66cd9d6dae8f4a9d2a60331bcc4c7d24f0 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 18 Oct 2024 13:50:43 -0700 Subject: [PATCH 332/805] chore: implement tree w/o list (#33169) --- .../src/matchers/toMatchAriaSnapshot.ts | 18 +- packages/trace-viewer/src/ui/actionList.tsx | 36 ++- .../src/ui/uiModeTestListView.tsx | 3 +- packages/web/src/components/toolbarButton.tsx | 2 +- packages/web/src/components/treeView.tsx | 231 +++++++++++------- tests/page/to-match-aria-snapshot.spec.ts | 8 +- tests/playwright-test/ui-mode-fixtures.ts | 11 +- .../ui-mode-test-annotations.spec.ts | 2 +- .../playwright-test/ui-mode-test-run.spec.ts | 8 +- .../ui-mode-test-setup.spec.ts | 26 +- .../ui-mode-test-update.spec.ts | 2 +- .../ui-mode-test-watch.spec.ts | 16 +- 12 files changed, 221 insertions(+), 142 deletions(-) diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index cf043c2ca880e..5b2c2044106db 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -49,8 +49,8 @@ export async function toMatchAriaSnapshot( const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined); const notFound = received === kNoElementsFoundError; - const escapedExpected = escapePrivateUsePoints(expected); - const escapedReceived = escapePrivateUsePoints(received); + const escapedExpected = unshift(escapePrivateUsePoints(expected)); + const escapedReceived = unshift(escapePrivateUsePoints(received)); const message = () => { if (pass) { if (notFound) @@ -79,3 +79,17 @@ export async function toMatchAriaSnapshot( function escapePrivateUsePoints(str: string) { return str.replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`); } + +function unshift(snapshot: string): string { + const lines = snapshot.split('\n'); + let whitespacePrefixLength = 100; + for (const line of lines) { + if (!line.trim()) + continue; + const match = line.match(/^(\s*)/); + if (match && match[1].length < whitespacePrefixLength) + whitespacePrefixLength = match[1].length; + break; + } + return lines.filter(t => t.trim()).map(line => line.substring(whitespacePrefixLength)).join('\n'); +} diff --git a/packages/trace-viewer/src/ui/actionList.tsx b/packages/trace-viewer/src/ui/actionList.tsx index f375ab0baa62f..d369aeede3ef8 100644 --- a/packages/trace-viewer/src/ui/actionList.tsx +++ b/packages/trace-viewer/src/ui/actionList.tsx @@ -59,6 +59,30 @@ export const ActionList: React.FC = ({ return { selectedItem }; }, [itemMap, selectedAction]); + const isError = React.useCallback((item: ActionTreeItem) => { + return !!item.action?.error?.message; + }, []); + + const onAccepted = React.useCallback((item: ActionTreeItem) => { + return setSelectedTime({ minimum: item.action!.startTime, maximum: item.action!.endTime }); + }, [setSelectedTime]); + + const render = React.useCallback((item: ActionTreeItem) => { + return renderAction(item.action!, { sdkLanguage, revealConsole, isLive, showDuration: true, showBadges: true }); + }, [isLive, revealConsole, sdkLanguage]); + + const isVisible = React.useCallback((item: ActionTreeItem) => { + return !selectedTime || !item.action || (item.action!.startTime <= selectedTime.maximum && item.action!.endTime >= selectedTime.minimum); + }, [selectedTime]); + + const onSelectedAction = React.useCallback((item: ActionTreeItem) => { + onSelected?.(item.action!); + }, [onSelected]); + + const onHighlightedAction = React.useCallback((item: ActionTreeItem | undefined) => { + onHighlighted?.(item?.action); + }, [onHighlighted]); + return
          {selectedTime &&
          setSelectedTime(undefined)}>Show all
          } = ({ treeState={treeState} setTreeState={setTreeState} selectedItem={selectedItem} - onSelected={item => onSelected?.(item.action!)} - onHighlighted={item => onHighlighted?.(item?.action)} - onAccepted={item => setSelectedTime({ minimum: item.action!.startTime, maximum: item.action!.endTime })} - isError={item => !!item.action?.error?.message} - isVisible={item => !selectedTime || (item.action!.startTime <= selectedTime.maximum && item.action!.endTime >= selectedTime.minimum)} - render={item => renderAction(item.action!, { sdkLanguage, revealConsole, isLive, showDuration: true, showBadges: true })} + onSelected={onSelectedAction} + onHighlighted={onHighlightedAction} + onAccepted={onAccepted} + isError={isError} + isVisible={isVisible} + render={render} />
          ; }; diff --git a/packages/trace-viewer/src/ui/uiModeTestListView.tsx b/packages/trace-viewer/src/ui/uiModeTestListView.tsx index 96fbaadbf78ad..e0ef2a8bcac66 100644 --- a/packages/trace-viewer/src/ui/uiModeTestListView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTestListView.tsx @@ -161,7 +161,7 @@ export const TestListView: React.FC<{ render={treeItem => { return
          - {treeItem.title} + {treeItem.title} {treeItem.kind === 'case' ? treeItem.tags.map(tag => handleTagClick(e, tag)} />) : null}
          {!!treeItem.duration && treeItem.status !== 'skipped' &&
          {msToString(treeItem.duration)}
          } @@ -179,6 +179,7 @@ export const TestListView: React.FC<{
          ; }} icon={treeItem => testStatusIcon(treeItem.status)} + title={treeItem => treeItem.title} selectedItem={selectedTreeItem} onAccepted={runTreeItem} onSelected={treeItem => { diff --git a/packages/web/src/components/toolbarButton.tsx b/packages/web/src/components/toolbarButton.tsx index 184642b395e7f..2cdd85b9b7bff 100644 --- a/packages/web/src/components/toolbarButton.tsx +++ b/packages/web/src/components/toolbarButton.tsx @@ -52,7 +52,7 @@ export const ToolbarButton: React.FC disabled={!!disabled} style={style} data-testid={testId} - aria-label={ariaLabel} + aria-label={ariaLabel || title} > {icon && } {children} diff --git a/packages/web/src/components/treeView.tsx b/packages/web/src/components/treeView.tsx index 6ad722145531f..9af8609f3b86b 100644 --- a/packages/web/src/components/treeView.tsx +++ b/packages/web/src/components/treeView.tsx @@ -32,6 +32,7 @@ export type TreeViewProps = { name: string, rootItem: T, render: (item: T) => React.ReactNode, + title?: (item: T) => string, icon?: (item: T) => string | undefined, isError?: (item: T) => boolean, isVisible?: (item: T) => boolean, @@ -52,6 +53,7 @@ export function TreeView({ name, rootItem, render, + title, icon, isError, isVisible, @@ -66,40 +68,12 @@ export function TreeView({ autoExpandDepth, }: TreeViewProps) { const treeItems = React.useMemo(() => { - return flattenTree(rootItem, selectedItem, treeState.expandedItems, autoExpandDepth || 0); - }, [rootItem, selectedItem, treeState, autoExpandDepth]); - - // Filter visible items. - const visibleItems = React.useMemo(() => { - if (!isVisible) - return [...treeItems.keys()]; - const cachedVisible = new Map(); - const visit = (item: TreeItem): boolean => { - const cachedResult = cachedVisible.get(item); - if (cachedResult !== undefined) - return cachedResult; - - let hasVisibleChildren = item.children.some(child => visit(child)); - for (const child of item.children) { - const result = visit(child); - hasVisibleChildren = hasVisibleChildren || result; - } - const result = isVisible(item as T) || hasVisibleChildren; - cachedVisible.set(item, result); - return result; - }; - for (const item of treeItems.keys()) - visit(item); - const result: T[] = []; - for (const item of treeItems.keys()) { - if (isVisible(item)) - result.push(item); - } - return result; - }, [treeItems, isVisible]); + return indexTree(rootItem, selectedItem, treeState.expandedItems, autoExpandDepth || 0, isVisible); + }, [rootItem, selectedItem, treeState, autoExpandDepth, isVisible]); const itemListRef = React.useRef(null); const [highlightedItem, setHighlightedItem] = React.useState(); + const [isKeyboardNavigation, setIsKeyboardNavigation] = React.useState(false); React.useEffect(() => { onHighlighted?.(highlightedItem); @@ -171,45 +145,55 @@ export function TreeView({ return; } - const index = selectedItem ? visibleItems.indexOf(selectedItem) : -1; - let newIndex = index; + let newSelectedItem: T | undefined = selectedItem; if (event.key === 'ArrowDown') { - if (index === -1) - newIndex = 0; - else - newIndex = Math.min(index + 1, visibleItems.length - 1); + if (selectedItem) { + const itemData = treeItems.get(selectedItem)!; + newSelectedItem = itemData.next as T; + } else if (treeItems.size) { + const itemList = [...treeItems.keys()]; + newSelectedItem = itemList[0]; + } } if (event.key === 'ArrowUp') { - if (index === -1) - newIndex = visibleItems.length - 1; - else - newIndex = Math.max(index - 1, 0); + if (selectedItem) { + const itemData = treeItems.get(selectedItem)!; + newSelectedItem = itemData.prev as T; + } else if (treeItems.size) { + const itemList = [...treeItems.keys()]; + newSelectedItem = itemList[itemList.length - 1]; + } } - const element = itemListRef.current?.children.item(newIndex); - scrollIntoViewIfNeeded(element || undefined); + // scrollIntoViewIfNeeded(element || undefined); onHighlighted?.(undefined); - onSelected?.(visibleItems[newIndex]); + if (newSelectedItem) { + setIsKeyboardNavigation(true); + onSelected?.(newSelectedItem); + } setHighlightedItem(undefined); }} ref={itemListRef} > - {noItemsMessage && visibleItems.length === 0 &&
          {noItemsMessage}
          } - {visibleItems.map(item => { - return
          - -
          ; + {noItemsMessage && treeItems.size === 0 &&
          {noItemsMessage}
          } + {rootItem.children.map(child => { + const itemData = treeItems.get(child as T); + return itemData && ; })}
          ; @@ -217,7 +201,7 @@ export function TreeView({ type TreeItemHeaderProps = { item: T, - itemData: TreeItemData, + treeItems: Map, selectedItem: T | undefined, onSelected?: (item: T) => void, toggleExpanded: (item: T) => void, @@ -226,12 +210,15 @@ type TreeItemHeaderProps = { onAccepted?: (item: T) => void, setHighlightedItem: (item: T | undefined) => void, render: (item: T) => React.ReactNode, + title?: (item: T) => string, icon?: (item: T) => string | undefined, + isKeyboardNavigation: boolean, + setIsKeyboardNavigation: (value: boolean) => void, }; export function TreeItemHeader({ item, - itemData, + treeItems, selectedItem, onSelected, highlightedItem, @@ -240,68 +227,122 @@ export function TreeItemHeader({ onAccepted, toggleExpanded, render, - icon }: TreeItemHeaderProps) { + title, + icon, + isKeyboardNavigation, + setIsKeyboardNavigation }: TreeItemHeaderProps) { + const itemRef = React.useRef(null); + React.useEffect(() => { + if (selectedItem === item && isKeyboardNavigation && itemRef.current) { + scrollIntoViewIfNeeded(itemRef.current); + setIsKeyboardNavigation(false); + } + }, [item, selectedItem, isKeyboardNavigation, setIsKeyboardNavigation]); + + const itemData = treeItems.get(item)!; const indentation = itemData.depth; const expanded = itemData.expanded; let expandIcon = 'codicon-blank'; if (typeof expanded === 'boolean') expandIcon = expanded ? 'codicon-chevron-down' : 'codicon-chevron-right'; const rendered = render(item); + const children = expanded && item.children.length ? item.children as T[] : []; + const titled = title?.(item); - return
          onAccepted?.(item)} - className={clsx( - 'tree-view-entry', - selectedItem === item && 'selected', - highlightedItem === item && 'highlighted', - isError?.(item) && 'error')} - onClick={() => onSelected?.(item)} - onMouseEnter={() => setHighlightedItem(item)} - onMouseLeave={() => setHighlightedItem(undefined)} - > - {indentation ? new Array(indentation).fill(0).map((_, i) =>
          ) : undefined} + return
          { - e.preventDefault(); - e.stopPropagation(); - }} - onClick={e => { - e.stopPropagation(); - e.preventDefault(); - toggleExpanded(item); - }} - /> - {icon &&
          } - {typeof rendered === 'string' ?
          {rendered}
          : rendered} + onDoubleClick={() => onAccepted?.(item)} + className={clsx( + 'tree-view-entry', + selectedItem === item && 'selected', + highlightedItem === item && 'highlighted', + isError?.(item) && 'error')} + onClick={() => onSelected?.(item)} + onMouseEnter={() => setHighlightedItem(item)} + onMouseLeave={() => setHighlightedItem(undefined)} + > + {indentation ? new Array(indentation).fill(0).map((_, i) =>
          ) : undefined} + + {!!children.length &&
          + {children.map(child => { + const itemData = treeItems.get(child); + return itemData && ; + })} +
          }
          ; } type TreeItemData = { - depth: number, - expanded: boolean | undefined, - parent: TreeItem | null, + depth: number; + expanded: boolean | undefined; + parent: TreeItem | null; + next: TreeItem | null; + prev: TreeItem | null; }; -function flattenTree( +function indexTree( rootItem: T, selectedItem: T | undefined, expandedItems: Map, - autoExpandDepth: number): Map { + autoExpandDepth: number, + isVisible?: (item: T) => boolean): Map { const result = new Map(); const temporaryExpanded = new Set(); for (let item: TreeItem | undefined = selectedItem?.parent; item; item = item.parent) temporaryExpanded.add(item.id); + let lastItem: T | null = null; const appendChildren = (parent: T, depth: number) => { + if (isVisible && !isVisible(parent)) + return; for (const item of parent.children as T[]) { const expandState = temporaryExpanded.has(item.id) || expandedItems.get(item.id); const autoExpandMatches = autoExpandDepth > depth && result.size < 25 && expandState !== false; const expanded = item.children.length ? expandState ?? autoExpandMatches : undefined; - result.set(item, { depth, expanded, parent: rootItem === parent ? null : parent }); + const itemData: TreeItemData = { + depth, + expanded, + parent: rootItem === parent ? null : parent, + next: null, + prev: lastItem, + }; + if (lastItem) + result.get(lastItem)!.next = item; + lastItem = item; + result.set(item, itemData); if (expanded) appendChildren(item, depth + 1); } diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index fa573f2704a88..3de7b6a9d4457 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -181,14 +181,12 @@ test('expected formatter', async ({ page }) => { expect(stripAnsi(error.message)).toContain(` Locator: locator('body') -- Expected - 4 +- Expected - 2 + Received string + 3 -- +- - heading "todos" + - banner: -- - heading "todos" + - heading "todos" -- - textbox "Wrong text" -- +- - textbox "Wrong text" + - textbox "What needs to be done?"`); }); diff --git a/tests/playwright-test/ui-mode-fixtures.ts b/tests/playwright-test/ui-mode-fixtures.ts index 1e3b11a03ab09..7ae98bb6624ec 100644 --- a/tests/playwright-test/ui-mode-fixtures.ts +++ b/tests/playwright-test/ui-mode-fixtures.ts @@ -68,14 +68,15 @@ export function dumpTestTree(page: Page, options: { time?: boolean } = {}): () = const result: string[] = []; const treeItems = treeElement.querySelectorAll('[role=treeitem]'); for (const treeItem of treeItems) { - const iconElements = treeItem.querySelectorAll('.codicon'); + const treeItemHeader = treeItem.querySelector('.tree-view-entry'); + const iconElements = treeItemHeader.querySelectorAll('.codicon'); const treeIcon = iconName(iconElements[0]); const statusIcon = iconName(iconElements[1]); - const indent = treeItem.querySelectorAll('.tree-view-indent').length; - const watch = treeItem.querySelector('.toolbar-button.eye.toggled') ? ' 👁' : ''; + const indent = treeItemHeader.querySelectorAll('.tree-view-indent').length; + const watch = treeItemHeader.querySelector('.toolbar-button.eye.toggled') ? ' 👁' : ''; const selected = treeItem.getAttribute('aria-selected') === 'true' ? ' <=' : ''; - const title = treeItem.querySelector('.ui-mode-tree-item-title').childNodes[0].textContent; - const timeElement = options.time ? treeItem.querySelector('.ui-mode-tree-item-time') : undefined; + const title = treeItemHeader.querySelector('.ui-mode-tree-item-title').childNodes[0].textContent; + const timeElement = options.time ? treeItemHeader.querySelector('.ui-mode-tree-item-time') : undefined; const time = timeElement ? ' ' + timeElement.textContent.replace(/[.\d]+m?s/, 'XXms') : ''; result.push(' ' + ' '.repeat(indent) + treeIcon + ' ' + statusIcon + ' ' + title + time + watch + selected); } diff --git a/tests/playwright-test/ui-mode-test-annotations.spec.ts b/tests/playwright-test/ui-mode-test-annotations.spec.ts index f32d43aecfbab..eeff6a5aca9bb 100644 --- a/tests/playwright-test/ui-mode-test-annotations.spec.ts +++ b/tests/playwright-test/ui-mode-test-annotations.spec.ts @@ -33,7 +33,7 @@ test('should display annotations', async ({ runUITest }) => { }); await page.getByTitle('Run all').click(); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); - await page.getByRole('treeitem').filter({ hasText: 'suite' }).locator('.codicon-chevron-right').click(); + await page.getByRole('treeitem', { name: 'suite' }).locator('.codicon-chevron-right').click(); await page.getByText('annotation test').click(); await page.getByText('Annotations', { exact: true }).click(); diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index 24731bcbb2173..1120cede6b8f7 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -93,7 +93,7 @@ test('should run on hover', async ({ runUITest }) => { }); await page.getByText('passes').hover(); - await page.getByRole('treeitem').filter({ hasText: 'passes' }).getByTitle('Run').click(); + await page.getByRole('treeitem', { name: 'passes' }).getByRole('button', { name: 'Run' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts @@ -275,7 +275,7 @@ test('should run folder', async ({ runUITest }) => { }); await page.getByText('folder-b').hover(); - await page.getByRole('treeitem').filter({ hasText: 'folder-b' }).getByTitle('Run').click(); + await page.getByRole('treeitem', { name: 'folder-b' }).getByRole('button', { name: 'Run' }).click(); await expect.poll(dumpTestTree(page)).toContain(` ▼ ✅ folder-b <= @@ -421,8 +421,8 @@ test('should show proper total when using deps', async ({ runUITest }) => { await page.getByText('Status:').click(); - await page.getByLabel('setup').setChecked(true); - await page.getByLabel('chromium').setChecked(true); + await page.getByRole('checkbox', { name: 'setup' }).setChecked(true); + await page.getByRole('checkbox', { name: 'chromium' }).setChecked(true); await expect.poll(dumpTestTree(page)).toContain(` ▼ ◯ a.test.ts diff --git a/tests/playwright-test/ui-mode-test-setup.spec.ts b/tests/playwright-test/ui-mode-test-setup.spec.ts index f8de9e262a817..65c6aa25330a6 100644 --- a/tests/playwright-test/ui-mode-test-setup.spec.ts +++ b/tests/playwright-test/ui-mode-test-setup.spec.ts @@ -140,9 +140,9 @@ const testsWithSetup = { test('should run setup and teardown projects (1)', async ({ runUITest }) => { const { page } = await runUITest(testsWithSetup); await page.getByText('Status:').click(); - await page.getByLabel('setup').setChecked(false); - await page.getByLabel('teardown').setChecked(false); - await page.getByLabel('test').setChecked(false); + await page.getByRole('checkbox', { name: 'setup' }).setChecked(false); + await page.getByRole('checkbox', { name: 'teardown' }).setChecked(false); + await page.getByRole('checkbox', { name: 'test' }).setChecked(false); await page.getByTitle('Run all').click(); @@ -164,9 +164,9 @@ test('should run setup and teardown projects (1)', async ({ runUITest }) => { test('should run setup and teardown projects (2)', async ({ runUITest }) => { const { page } = await runUITest(testsWithSetup); await page.getByText('Status:').click(); - await page.getByLabel('setup').setChecked(false); - await page.getByLabel('teardown').setChecked(true); - await page.getByLabel('test').setChecked(true); + await page.getByRole('checkbox', { name: 'setup' }).setChecked(false); + await page.getByRole('checkbox', { name: 'teardown' }).setChecked(true); + await page.getByRole('checkbox', { name: 'test' }).setChecked(true); await page.getByTitle('Run all').click(); @@ -186,9 +186,9 @@ test('should run setup and teardown projects (2)', async ({ runUITest }) => { test('should run setup and teardown projects (3)', async ({ runUITest }) => { const { page } = await runUITest(testsWithSetup); await page.getByText('Status:').click(); - await page.getByLabel('setup').setChecked(false); - await page.getByLabel('teardown').setChecked(false); - await page.getByLabel('test').setChecked(true); + await page.getByRole('checkbox', { name: 'setup' }).setChecked(false); + await page.getByRole('checkbox', { name: 'teardown' }).setChecked(false); + await page.getByRole('checkbox', { name: 'test' }).setChecked(true); await page.getByTitle('Run all').click(); @@ -206,12 +206,12 @@ test('should run setup and teardown projects (3)', async ({ runUITest }) => { test('should run part of the setup only', async ({ runUITest }) => { const { page } = await runUITest(testsWithSetup); await page.getByText('Status:').click(); - await page.getByLabel('setup').setChecked(true); - await page.getByLabel('teardown').setChecked(true); - await page.getByLabel('test').setChecked(true); + await page.getByRole('checkbox', { name: 'setup' }).setChecked(true); + await page.getByRole('checkbox', { name: 'teardown' }).setChecked(true); + await page.getByRole('checkbox', { name: 'test' }).setChecked(true); await page.getByText('setup.ts').hover(); - await page.getByRole('treeitem').filter({ hasText: 'setup.ts' }).getByTitle('Run').click(); + await page.getByRole('treeitem', { name: 'setup.ts' }).getByRole('button', { name: 'Run' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ✅ setup.ts <= diff --git a/tests/playwright-test/ui-mode-test-update.spec.ts b/tests/playwright-test/ui-mode-test-update.spec.ts index ae5752c3f0650..67d0626a5f773 100644 --- a/tests/playwright-test/ui-mode-test-update.spec.ts +++ b/tests/playwright-test/ui-mode-test-update.spec.ts @@ -215,7 +215,7 @@ test('should update test locations', async ({ runUITest, writeFiles }) => { const messages: any[] = []; await page.exposeBinding('__logForTest', (source, arg) => messages.push(arg)); - const passesItemLocator = page.getByRole('treeitem').filter({ hasText: 'passes' }); + const passesItemLocator = page.getByRole('treeitem', { name: 'passes' }); await passesItemLocator.hover(); await passesItemLocator.getByTitle('Show source').click(); await page.getByTitle('Open in VS Code').click(); diff --git a/tests/playwright-test/ui-mode-test-watch.spec.ts b/tests/playwright-test/ui-mode-test-watch.spec.ts index 893a0ef7acccb..9bbbdc0ec066c 100644 --- a/tests/playwright-test/ui-mode-test-watch.spec.ts +++ b/tests/playwright-test/ui-mode-test-watch.spec.ts @@ -28,14 +28,14 @@ test('should watch files', async ({ runUITest, writeFiles }) => { }); await page.getByText('fails').click(); - await page.getByRole('treeitem').filter({ hasText: 'fails' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'fails' }).getByRole('button', { name: 'Watch' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts ◯ passes ◯ fails 👁 <= `); - await page.getByRole('treeitem').filter({ hasText: 'fails' }).getByTitle('Run').click(); + await page.getByRole('treeitem', { name: 'fails' }).getByRole('button', { name: 'Run' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ❌ a.test.ts @@ -75,7 +75,7 @@ test('should watch e2e deps', async ({ runUITest, writeFiles }) => { }); await page.getByText('answer').click(); - await page.getByRole('treeitem').filter({ hasText: 'answer' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'answer' }).getByRole('button', { name: 'Watch' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts ◯ answer 👁 <= @@ -102,13 +102,13 @@ test('should batch watch updates', async ({ runUITest, writeFiles }) => { }); await page.getByText('a.test.ts').click(); - await page.getByRole('treeitem').filter({ hasText: 'a.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'a.test.ts' }).getByRole('button', { name: 'Watch' }).click(); await page.getByText('b.test.ts').click(); - await page.getByRole('treeitem').filter({ hasText: 'b.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'b.test.ts' }).getByRole('button', { name: 'Watch' }).click(); await page.getByText('c.test.ts').click(); - await page.getByRole('treeitem').filter({ hasText: 'c.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'c.test.ts' }).getByRole('button', { name: 'Watch' }).click(); await page.getByText('d.test.ts').click(); - await page.getByRole('treeitem').filter({ hasText: 'd.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'd.test.ts' }).getByRole('button', { name: 'Watch' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts 👁 @@ -229,7 +229,7 @@ test('should run added test in watched file', async ({ runUITest, writeFiles }) }); await page.getByText('a.test.ts').click(); - await page.getByRole('treeitem').filter({ hasText: 'a.test.ts' }).getByTitle('Watch').click(); + await page.getByRole('treeitem', { name: 'a.test.ts' }).getByRole('button', { name: 'Watch' }).click(); await expect.poll(dumpTestTree(page)).toBe(` ▼ ◯ a.test.ts 👁 <= From b1fb4f16a75994330e38ea14fa38423d66197f40 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 18 Oct 2024 23:00:05 +0200 Subject: [PATCH 333/805] chore: hide 'markdown' reporter (#33140) --- .github/workflows/merge.config.ts | 2 +- packages/playwright/src/common/config.ts | 2 +- packages/playwright/src/runner/reporters.ts | 2 -- tests/playwright-test/reporter-markdown.spec.ts | 10 ++++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/merge.config.ts b/.github/workflows/merge.config.ts index b39944bc809c1..e8582ed5213e4 100644 --- a/.github/workflows/merge.config.ts +++ b/.github/workflows/merge.config.ts @@ -1,4 +1,4 @@ export default { testDir: '../../tests', - reporter: [['markdown'], ['html']] + reporter: [[require.resolve('../../packages/playwright/lib/reporters/markdown')], ['html']] }; \ No newline at end of file diff --git a/packages/playwright/src/common/config.ts b/packages/playwright/src/common/config.ts index fd78f0c8d9bf7..031a5215f2ec8 100644 --- a/packages/playwright/src/common/config.ts +++ b/packages/playwright/src/common/config.ts @@ -276,7 +276,7 @@ export function toReporters(reporters: BuiltInReporter | ReporterDescription[] | return reporters; } -export const builtInReporters = ['list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html', 'blob', 'markdown'] as const; +export const builtInReporters = ['list', 'line', 'dot', 'json', 'junit', 'null', 'github', 'html', 'blob'] as const; export type BuiltInReporter = typeof builtInReporters[number]; export type ContextReuseMode = 'none' | 'when-possible'; diff --git a/packages/playwright/src/runner/reporters.ts b/packages/playwright/src/runner/reporters.ts index 2f7b16f2a6748..2bab152f08376 100644 --- a/packages/playwright/src/runner/reporters.ts +++ b/packages/playwright/src/runner/reporters.ts @@ -25,7 +25,6 @@ import JSONReporter from '../reporters/json'; import JUnitReporter from '../reporters/junit'; import LineReporter from '../reporters/line'; import ListReporter from '../reporters/list'; -import MarkdownReporter from '../reporters/markdown'; import type { Suite } from '../common/test'; import type { BuiltInReporter, FullConfigInternal } from '../common/config'; import { loadReporter } from './loadUtils'; @@ -45,7 +44,6 @@ export async function createReporters(config: FullConfigInternal, mode: 'list' | junit: JUnitReporter, null: EmptyReporter, html: HtmlReporter, - markdown: MarkdownReporter, }; const reporters: ReporterV2[] = []; descriptions ??= config.config.reporter; diff --git a/tests/playwright-test/reporter-markdown.spec.ts b/tests/playwright-test/reporter-markdown.spec.ts index d24f2561c12c1..076e28d66e2e6 100644 --- a/tests/playwright-test/reporter-markdown.spec.ts +++ b/tests/playwright-test/reporter-markdown.spec.ts @@ -18,12 +18,14 @@ import fs from 'fs'; import path from 'path'; import { expect, test } from './playwright-test-fixtures'; +const markdownReporter = require.resolve('../../packages/playwright/lib/reporters/markdown'); + test('simple report', async ({ runInlineTest }) => { const files = { 'playwright.config.ts': ` module.exports = { retries: 1, - reporter: 'markdown', + reporter: ${JSON.stringify(markdownReporter)}, }; `, 'dir1/a.test.js': ` @@ -83,7 +85,7 @@ test('custom report file', async ({ runInlineTest }) => { const files = { 'playwright.config.ts': ` module.exports = { - reporter: [['markdown', { outputFile: 'my-report.md' }]], + reporter: [[${JSON.stringify(markdownReporter)}, { outputFile: 'my-report.md' }]], }; `, 'a.test.js': ` @@ -107,7 +109,7 @@ test('report error without snippet', async ({ runInlineTest }) => { 'playwright.config.ts': ` module.exports = { retries: 1, - reporter: 'markdown', + reporter: ${JSON.stringify(markdownReporter)}, }; `, 'a.test.js': ` @@ -135,7 +137,7 @@ test('report with worker error', async ({ runInlineTest }) => { 'playwright.config.ts': ` module.exports = { retries: 1, - reporter: 'markdown', + reporter: ${JSON.stringify(markdownReporter)}, }; `, 'a.test.js': ` From 64bf1bc1072a48e0def6785c4885a58497452fc5 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 18 Oct 2024 20:18:18 -0700 Subject: [PATCH 334/805] chore: support basic aria attributes (#33182) --- .../src/server/ariaSnapshot.ts | 120 +++++++++------- .../src/server/injected/ariaSnapshot.ts | 134 +++++++++++++----- .../src/server/injected/roleUtils.ts | 62 ++++---- tests/page/page-aria-snapshot.spec.ts | 15 +- tests/page/to-match-aria-snapshot.spec.ts | 18 ++- 5 files changed, 228 insertions(+), 121 deletions(-) diff --git a/packages/playwright-core/src/server/ariaSnapshot.ts b/packages/playwright-core/src/server/ariaSnapshot.ts index e450e5b15df67..47ed4066b76b3 100644 --- a/packages/playwright-core/src/server/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/ariaSnapshot.ts @@ -16,63 +16,87 @@ import type { AriaTemplateNode } from './injected/ariaSnapshot'; import { yaml } from '../utilsBundle'; +import type { AriaRole } from '@injected/roleUtils'; export function parseAriaSnapshot(text: string): AriaTemplateNode { - type YamlNode = Record | string>; + const fragment = yaml.parse(text) as any[]; + const result: AriaTemplateNode = { role: 'fragment' }; + populateNode(result, fragment); + return result; +} - const parseKey = (key: string): AriaTemplateNode => { - if (!key) - return { role: '' }; +function populateNode(node: AriaTemplateNode, container: any[]) { + for (const object of container) { + if (typeof object === 'string') { + const { role, name } = parseKey(object); + node.children = node.children || []; + node.children.push({ role, name }); + continue; + } + for (const key of Object.keys(object)) { + if (key === 'checked') { + node.checked = object[key]; + continue; + } + if (key === 'disabled') { + node.disabled = object[key]; + continue; + } + if (key === 'expanded') { + node.expanded = object[key]; + continue; + } + if (key === 'level') { + node.level = object[key]; + continue; + } + if (key === 'pressed') { + node.pressed = object[key]; + continue; + } + if (key === 'selected') { + node.selected = object[key]; + continue; + } - const match = key.match(/^([a-z]+)(?:\s+(?:"([^"]*)"|\/([^\/]*)\/))?$/); + const { role, name } = parseKey(key); + const value = object[key]; + node.children = node.children || []; - if (!match) - throw new Error(`Invalid key ${key}`); + if (role === 'text') { + node.children.push(valueOrRegex(value)); + continue; + } - const role = match[1]; - if (role && role !== 'text' && !allRoles.includes(role)) - throw new Error(`Invalid role ${role}`); + if (typeof value === 'string') { + node.children.push({ role, name, children: [valueOrRegex(value)] }); + continue; + } - if (match[2]) - return { role, name: match[2] }; - if (match[3]) - return { role, name: new RegExp(match[3]) }; - return { role }; - }; + const childNode = { role, name }; + node.children.push(childNode); + populateNode(childNode, value); + } + } +} - const normalizeWhitespace = (text: string) => { - return text.replace(/[\r\n\s\t]+/g, ' ').trim(); - }; +function parseKey(key: string) { + const match = key.match(/^([a-z]+)(?:\s+(?:"([^"]*)"|\/([^\/]*)\/))?$/); + if (!match) + throw new Error(`Invalid key ${key}`); - const valueOrRegex = (value: string): string | RegExp => { - return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value); - }; + const role = match[1] as AriaRole | 'text'; + if (match[2]) + return { role, name: match[2] }; + if (match[3]) + return { role, name: new RegExp(match[3]) }; + return { role }; +} - const convert = (object: YamlNode | string): AriaTemplateNode | RegExp | string => { - const key = typeof object === 'string' ? object : Object.keys(object)[0]; - const value = typeof object === 'string' ? undefined : object[key]; - const parsed = parseKey(key); - if (parsed.role === 'text') { - if (typeof value !== 'string') - throw new Error(`Generic role must have a text value`); - return valueOrRegex(value as string); - } - if (Array.isArray(value)) - parsed.children = value.map(convert); - else if (value) - parsed.children = [valueOrRegex(value)]; - return parsed; - }; - const fragment = yaml.parse(text) as YamlNode[]; - return convert({ '': fragment }) as AriaTemplateNode; +function normalizeWhitespace(text: string) { + return text.replace(/[\r\n\s\t]+/g, ' ').trim(); } -const allRoles = [ - 'alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'command', - 'complementary', 'composite', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', - 'gridcell', 'group', 'heading', 'img', 'input', 'insertion', 'landmark', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'marquee', 'math', 'meter', 'menu', - 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none', 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', - 'range', 'region', 'roletype', 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'section', 'sectionhead', 'select', 'separator', 'slider', - 'spinbutton', 'status', 'strong', 'structure', 'subscript', 'superscript', 'switch', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', - 'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem', 'widget', 'window' -]; +function valueOrRegex(value: string): string | RegExp { + return value.startsWith('/') && value.endsWith('/') ? new RegExp(value.slice(1, -1)) : normalizeWhitespace(value); +} diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 907006ce0a1f8..16d8dc60709bc 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -15,38 +15,32 @@ */ import { escapeWithQuotes } from '@isomorphic/stringUtils'; -import { accumulatedElementText, beginAriaCaches, endAriaCaches, getAriaRole, getElementAccessibleName, getPseudoContent, isElementIgnoredForAria } from './roleUtils'; +import * as roleUtils from './roleUtils'; import { isElementVisible, isElementStyleVisibilityVisible, getElementComputedStyle } from './domUtils'; +import type { AriaRole } from './roleUtils'; + +type AriaProps = { + checked?: boolean | 'mixed'; + disabled?: boolean; + expanded?: boolean | 'none', + level?: number, + pressed?: boolean | 'mixed'; + selected?: boolean; +}; -type AriaNode = { - role: string; - name?: string; +type AriaNode = AriaProps & { + role: AriaRole | 'fragment' | 'text'; + name: string; children: (AriaNode | string)[]; }; -export type AriaTemplateNode = { - role: string; +export type AriaTemplateNode = AriaProps & { + role: AriaRole | 'fragment' | 'text'; name?: RegExp | string; children?: (AriaTemplateNode | string | RegExp)[]; }; export function generateAriaTree(rootElement: Element): AriaNode { - const toAriaNode = (element: Element): { ariaNode: AriaNode, isLeaf: boolean } | null => { - const role = getAriaRole(element); - if (!role) - return null; - - const name = role ? getElementAccessibleName(element, false) || undefined : undefined; - const isLeaf = leafRoles.has(role); - const result: AriaNode = { role, name, children: [] }; - if (isLeaf && !name) { - const text = accumulatedElementText(element); - if (text) - result.children = [text]; - } - return { isLeaf, ariaNode: result }; - }; - const visit = (ariaNode: AriaNode, node: Node) => { if (node.nodeType === Node.TEXT_NODE && node.nodeValue) { const text = node.nodeValue; @@ -59,7 +53,7 @@ export function generateAriaTree(rootElement: Element): AriaNode { return; const element = node as Element; - if (isElementIgnoredForAria(element)) + if (roleUtils.isElementIgnoredForAria(element)) return; const visible = isElementVisible(element); @@ -87,7 +81,7 @@ export function generateAriaTree(rootElement: Element): AriaNode { if (treatAsBlock) ariaNode.children.push(treatAsBlock); - ariaNode.children.push(getPseudoContent(element, '::before')); + ariaNode.children.push(roleUtils.getPseudoContent(element, '::before')); const assignedNodes = element.nodeName === 'SLOT' ? (element as HTMLSlotElement).assignedNodes() : []; if (assignedNodes.length) { for (const child of assignedNodes) @@ -103,24 +97,59 @@ export function generateAriaTree(rootElement: Element): AriaNode { } } - ariaNode.children.push(getPseudoContent(element, '::after')); + ariaNode.children.push(roleUtils.getPseudoContent(element, '::after')); if (treatAsBlock) ariaNode.children.push(treatAsBlock); } - beginAriaCaches(); - const ariaRoot: AriaNode = { role: '', children: [] }; + roleUtils.beginAriaCaches(); + const ariaRoot: AriaNode = { role: 'fragment', name: '', children: [] }; try { visit(ariaRoot, rootElement); } finally { - endAriaCaches(); + roleUtils.endAriaCaches(); } normalizeStringChildren(ariaRoot); return ariaRoot; } +function toAriaNode(element: Element): { ariaNode: AriaNode, isLeaf: boolean } | null { + const role = roleUtils.getAriaRole(element); + if (!role) + return null; + + const name = roleUtils.getElementAccessibleName(element, false) || ''; + const isLeaf = leafRoles.has(role); + const result: AriaNode = { role, name, children: [] }; + if (isLeaf && !name) { + const text = roleUtils.accumulatedElementText(element); + if (text) + result.children = [text]; + } + + if (roleUtils.kAriaCheckedRoles.includes(role)) + result.checked = roleUtils.getAriaChecked(element); + + if (roleUtils.kAriaDisabledRoles.includes(role)) + result.disabled = roleUtils.getAriaDisabled(element); + + if (roleUtils.kAriaExpandedRoles.includes(role)) + result.expanded = roleUtils.getAriaExpanded(element); + + if (roleUtils.kAriaLevelRoles.includes(role)) + result.level = roleUtils.getAriaLevel(element); + + if (roleUtils.kAriaPressedRoles.includes(role)) + result.pressed = roleUtils.getAriaPressed(element); + + if (roleUtils.kAriaSelectedRoles.includes(role)) + result.selected = roleUtils.getAriaSelected(element); + + return { isLeaf, ariaNode: result }; +} + export function renderedAriaTree(rootElement: Element): string { return renderAriaTree(generateAriaTree(rootElement)); } @@ -155,7 +184,7 @@ function normalizeStringChildren(rootA11yNode: AriaNode) { const hiddenContainerRoles = new Set(['none', 'presentation']); -const leafRoles = new Set([ +const leafRoles = new Set([ 'alert', 'blockquote', 'button', 'caption', 'checkbox', 'code', 'columnheader', 'definition', 'deletion', 'emphasis', 'generic', 'heading', 'img', 'insertion', 'link', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'meter', 'option', @@ -178,7 +207,7 @@ function matchesText(text: string | undefined, template: RegExp | string | undef export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode): { matches: boolean, received: string } { const root = generateAriaTree(rootElement); - const matches = nodeMatches(root, template); + const matches = matchesNodeDeep(root, template); return { matches, received: renderAriaTree(root) }; } @@ -187,7 +216,19 @@ function matchesNode(node: AriaNode | string, template: AriaTemplateNode | RegEx return matchesText(node, template); if (typeof node === 'object' && typeof template === 'object' && !(template instanceof RegExp)) { - if (template.role && template.role !== node.role) + if (template.role !== 'fragment' && template.role !== node.role) + return false; + if (template.checked !== undefined && template.checked !== node.checked) + return false; + if (template.disabled !== undefined && template.disabled !== node.disabled) + return false; + if (template.expanded !== undefined && template.expanded !== node.expanded) + return false; + if (template.level !== undefined && template.level !== node.level) + return false; + if (template.pressed !== undefined && template.pressed !== node.pressed) + return false; + if (template.selected !== undefined && template.selected !== node.selected) return false; if (!matchesText(node.name, template.name)) return false; @@ -216,7 +257,7 @@ function containsList(children: (AriaNode | string)[], template: (AriaTemplateNo return true; } -function nodeMatches(root: AriaNode, template: AriaTemplateNode): boolean { +function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): boolean { const results: (AriaNode | string)[] = []; const visit = (node: AriaNode | string): boolean => { if (matchesNode(node, template, 0)) { @@ -245,19 +286,36 @@ export function renderAriaTree(ariaNode: AriaNode): string { let line = `${indent}- ${ariaNode.role}`; if (ariaNode.name) line += ` ${escapeWithQuotes(ariaNode.name, '"')}`; - const noChild = !ariaNode.name && !ariaNode.children?.length; - const oneChild = !ariaNode.name && ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string'; - if (noChild || oneChild) { - if (oneChild) + const stringValue = !ariaNode.checked + && !ariaNode.disabled + && (!ariaNode.expanded || ariaNode.expanded === 'none') + && !ariaNode.level + && !ariaNode.pressed + && !ariaNode.selected + && (!ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string')); + if (stringValue) { + if (ariaNode.children.length) line += ': ' + escapeYamlString(ariaNode.children?.[0] as string); lines.push(line); return; } - lines.push(line + (ariaNode.children.length ? ':' : '')); + + lines.push(line + ':'); + if (ariaNode.checked) + lines.push(`${indent} - checked: ${ariaNode.checked}`); + if (ariaNode.disabled) + lines.push(`${indent} - disabled: ${ariaNode.disabled}`); + if (ariaNode.expanded && ariaNode.expanded !== 'none') + lines.push(`${indent} - expanded: ${ariaNode.expanded}`); + if (ariaNode.level) + lines.push(`${indent} - level: ${ariaNode.level}`); + if (ariaNode.pressed) + lines.push(`${indent} - pressed: ${ariaNode.pressed}`); for (const child of ariaNode.children || []) visit(child, indent + ' '); }; - if (ariaNode.role === '') { + + if (ariaNode.role === 'fragment') { // Render fragment. for (const child of ariaNode.children || []) visit(child, ''); diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index d085a8e36d4de..9c5712311ef41 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -82,7 +82,7 @@ function isNativelyFocusable(element: Element) { // https://w3c.github.io/html-aam/#html-element-role-mappings // https://www.w3.org/TR/html-aria/#docconformance -const kImplicitRoleByTagName: { [tagName: string]: (e: Element) => string | null } = { +const kImplicitRoleByTagName: { [tagName: string]: (e: Element) => AriaRole | null } = { 'A': (e: Element) => { return e.hasAttribute('href') ? 'link' : null; }, @@ -127,17 +127,8 @@ const kImplicitRoleByTagName: { [tagName: string]: (e: Element) => string | null return (list && elementSafeTagName(list) === 'DATALIST') ? 'combobox' : 'textbox'; } if (type === 'hidden') - return ''; - return { - 'button': 'button', - 'checkbox': 'checkbox', - 'image': 'button', - 'number': 'spinbutton', - 'radio': 'radio', - 'range': 'slider', - 'reset': 'button', - 'submit': 'button', - }[type] || 'textbox'; + return null; + return inputTypeToRole[type] || 'textbox'; }, 'INS': () => 'insertion', 'LI': () => 'listitem', @@ -200,7 +191,7 @@ const kPresentationInheritanceParents: { [tagName: string]: string[] } = { 'TR': ['THEAD', 'TBODY', 'TFOOT', 'TABLE'], }; -function getImplicitAriaRole(element: Element): string | null { +function getImplicitAriaRole(element: Element): AriaRole | null { const implicitRole = kImplicitRoleByTagName[elementSafeTagName(element)]?.(element) || ''; if (!implicitRole) return null; @@ -221,23 +212,29 @@ function getImplicitAriaRole(element: Element): string | null { } // https://www.w3.org/TR/wai-aria-1.2/#role_definitions -const allRoles = [ - 'alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'command', - 'complementary', 'composite', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', - 'gridcell', 'group', 'heading', 'img', 'input', 'insertion', 'landmark', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'marquee', 'math', 'meter', 'menu', - 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none', 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', - 'range', 'region', 'roletype', 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'section', 'sectionhead', 'select', 'separator', 'slider', - 'spinbutton', 'status', 'strong', 'structure', 'subscript', 'superscript', 'switch', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', - 'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem', 'widget', 'window' -]; // https://www.w3.org/TR/wai-aria-1.2/#abstract_roles -const abstractRoles = ['command', 'composite', 'input', 'landmark', 'range', 'roletype', 'section', 'sectionhead', 'select', 'structure', 'widget', 'window']; -const validRoles = allRoles.filter(role => !abstractRoles.includes(role)); +// type AbstractRoles = 'command' | 'composite' | 'input' | 'landmark' | 'range' | 'roletype' | 'section' | 'sectionhead' | 'select' | 'structure' | 'widget' | 'window'; + +export type AriaRole = 'alert' | 'alertdialog' | 'application' | 'article' | 'banner' | 'blockquote' | 'button' | 'caption' | 'cell' | 'checkbox' | 'code' | 'columnheader' | 'combobox' | + 'complementary' | 'contentinfo' | 'definition' | 'deletion' | 'dialog' | 'directory' | 'document' | 'emphasis' | 'feed' | 'figure' | 'form' | 'generic' | 'grid' | + 'gridcell' | 'group' | 'heading' | 'img' | 'insertion' | 'link' | 'list' | 'listbox' | 'listitem' | 'log' | 'main' | 'mark' | 'marquee' | 'math' | 'meter' | 'menu' | + 'menubar' | 'menuitem' | 'menuitemcheckbox' | 'menuitemradio' | 'navigation' | 'none' | 'note' | 'option' | 'paragraph' | 'presentation' | 'progressbar' | 'radio' | 'radiogroup' | + 'region' | 'row' | 'rowgroup' | 'rowheader' | 'scrollbar' | 'search' | 'searchbox' | 'separator' | 'slider' | + 'spinbutton' | 'status' | 'strong' | 'subscript' | 'superscript' | 'switch' | 'tab' | 'table' | 'tablist' | 'tabpanel' | 'term' | 'textbox' | 'time' | 'timer' | + 'toolbar' | 'tooltip' | 'tree' | 'treegrid' | 'treeitem'; + +const validRoles: AriaRole[] = ['alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption', 'cell', 'checkbox', 'code', 'columnheader', 'combobox', + 'complementary', 'contentinfo', 'definition', 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form', 'generic', 'grid', + 'gridcell', 'group', 'heading', 'img', 'insertion', 'link', 'list', 'listbox', 'listitem', 'log', 'main', 'mark', 'marquee', 'math', 'meter', 'menu', + 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none', 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', + 'region', 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'separator', 'slider', + 'spinbutton', 'status', 'strong', 'subscript', 'superscript', 'switch', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', + 'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem']; -function getExplicitAriaRole(element: Element): string | null { +function getExplicitAriaRole(element: Element): AriaRole | null { // https://www.w3.org/TR/wai-aria-1.2/#document-handling_author-errors_roles const roles = (element.getAttribute('role') || '').split(' ').map(role => role.trim()); - return roles.find(role => validRoles.includes(role)) || null; + return roles.find(role => validRoles.includes(role as any)) as AriaRole || null; } function hasPresentationConflictResolution(element: Element, role: string | null) { @@ -245,7 +242,7 @@ function hasPresentationConflictResolution(element: Element, role: string | null return hasGlobalAriaAttribute(element, role) || isFocusable(element); } -export function getAriaRole(element: Element): string | null { +export function getAriaRole(element: Element): AriaRole | null { const explicitRole = getExplicitAriaRole(element); if (!explicitRole) return getImplicitAriaRole(element); @@ -994,3 +991,14 @@ export function endAriaCaches() { cachePseudoContentAfter = undefined; } } + +const inputTypeToRole: Record = { + 'button': 'button', + 'checkbox': 'checkbox', + 'image': 'button', + 'number': 'spinbutton', + 'radio': 'radio', + 'range': 'slider', + 'reset': 'button', + 'submit': 'button', +}; diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index 878f48439edaf..cf71611320c17 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -40,7 +40,8 @@ async function checkAndMatchSnapshot(locator: Locator, snapshot: string) { it('should snapshot', async ({ page }) => { await page.setContent(`

          title

          `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "title" + - heading "title": + - level: 1 `); }); @@ -50,8 +51,10 @@ it('should snapshot list', async ({ page }) => {

          title 2

          `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "title" - - heading "title 2" + - heading "title": + - level: 1 + - heading "title 2": + - level: 1 `); }); @@ -91,7 +94,8 @@ it('should allow text nodes', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "Microsoft" + - heading "Microsoft": + - level: 1 - text: Open source projects and samples from Microsoft `); }); @@ -144,7 +148,8 @@ it('should snapshot integration', async ({ page }) => {
        `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "Microsoft" + - heading "Microsoft": + - level: 1 - text: Open source projects and samples from Microsoft - list: - listitem: diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index 3de7b6a9d4457..d4be35fb8a366 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -107,6 +107,17 @@ test('details visibility', async ({ page }) => { `); }); +test('checked state', async ({ page }) => { + await page.setContent(` + + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - checkbox: + - checked: true + `); +}); + test('integration test', async ({ page }) => { await page.setContent(`

        Microsoft

        @@ -182,11 +193,12 @@ test('expected formatter', async ({ page }) => { expect(stripAnsi(error.message)).toContain(` Locator: locator('body') - Expected - 2 -+ Received string + 3 ++ Received string + 4 - - heading "todos" -+ - banner: -+ - heading "todos" - - textbox "Wrong text" ++ - banner: ++ - heading "todos": ++ - level: 1 + - textbox "What needs to be done?"`); }); From 97d26e8166b0519756344afbfc33277dbfd530af Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Sat, 19 Oct 2024 14:23:08 -0700 Subject: [PATCH 335/805] chore: add aria attribute tests (#33184) --- .../src/server/ariaSnapshot.ts | 118 ++++++---- .../src/server/injected/ariaSnapshot.ts | 38 ++-- .../src/server/injected/roleUtils.ts | 6 +- tests/page/page-aria-snapshot.spec.ts | 15 +- tests/page/to-match-aria-snapshot.spec.ts | 215 +++++++++++++++++- .../playwright-test/ui-mode-test-run.spec.ts | 17 ++ 6 files changed, 331 insertions(+), 78 deletions(-) diff --git a/packages/playwright-core/src/server/ariaSnapshot.ts b/packages/playwright-core/src/server/ariaSnapshot.ts index 47ed4066b76b3..03b5a05e92a45 100644 --- a/packages/playwright-core/src/server/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/ariaSnapshot.ts @@ -17,6 +17,7 @@ import type { AriaTemplateNode } from './injected/ariaSnapshot'; import { yaml } from '../utilsBundle'; import type { AriaRole } from '@injected/roleUtils'; +import { assert } from '../utils'; export function parseAriaSnapshot(text: string): AriaTemplateNode { const fragment = yaml.parse(text) as any[]; @@ -28,69 +29,106 @@ export function parseAriaSnapshot(text: string): AriaTemplateNode { function populateNode(node: AriaTemplateNode, container: any[]) { for (const object of container) { if (typeof object === 'string') { - const { role, name } = parseKey(object); + const childNode = parseKey(object); node.children = node.children || []; - node.children.push({ role, name }); + node.children.push(childNode); continue; } - for (const key of Object.keys(object)) { - if (key === 'checked') { - node.checked = object[key]; - continue; - } - if (key === 'disabled') { - node.disabled = object[key]; - continue; - } - if (key === 'expanded') { - node.expanded = object[key]; - continue; - } - if (key === 'level') { - node.level = object[key]; - continue; - } - if (key === 'pressed') { - node.pressed = object[key]; - continue; - } - if (key === 'selected') { - node.selected = object[key]; - continue; - } - const { role, name } = parseKey(key); + for (const key of Object.keys(object)) { + const childNode = parseKey(key); const value = object[key]; node.children = node.children || []; - if (role === 'text') { + if (childNode.role === 'text') { node.children.push(valueOrRegex(value)); continue; } if (typeof value === 'string') { - node.children.push({ role, name, children: [valueOrRegex(value)] }); + node.children.push({ ...childNode, children: [valueOrRegex(value)] }); continue; } - const childNode = { role, name }; node.children.push(childNode); populateNode(childNode, value); } } } -function parseKey(key: string) { - const match = key.match(/^([a-z]+)(?:\s+(?:"([^"]*)"|\/([^\/]*)\/))?$/); - if (!match) +function applyAttribute(node: AriaTemplateNode, key: string, value: string) { + if (key === 'checked') { + assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "disabled" attribute must be a boolean or "mixed"'); + node.checked = value === 'true' ? true : value === 'false' ? false : 'mixed'; + return; + } + if (key === 'disabled') { + assert(value === 'true' || value === 'false', 'Value of "disabled" attribute must be a boolean'); + node.disabled = value === 'true'; + return; + } + if (key === 'expanded') { + assert(value === 'true' || value === 'false', 'Value of "expanded" attribute must be a boolean'); + node.expanded = value === 'true'; + return; + } + if (key === 'level') { + assert(!isNaN(Number(value)), 'Value of "level" attribute must be a number'); + node.level = Number(value); + return; + } + if (key === 'pressed') { + assert(value === 'true' || value === 'false' || value === 'mixed', 'Value of "pressed" attribute must be a boolean or "mixed"'); + node.pressed = value === 'true' ? true : value === 'false' ? false : 'mixed'; + return; + } + if (key === 'selected') { + assert(value === 'true' || value === 'false', 'Value of "selected" attribute must be a boolean'); + node.selected = value === 'true'; + return; + } + throw new Error(`Unsupported attribute [${key}] `); +} + +function parseKey(key: string): AriaTemplateNode { + const tokenRegex = /\s*([a-z]+|"(?:[^"]*)"|\/(?:[^\/]*)\/|\[.*?\])/g; + let match; + const tokens = []; + while ((match = tokenRegex.exec(key)) !== null) + tokens.push(match[1]); + + if (tokens.length === 0) throw new Error(`Invalid key ${key}`); - const role = match[1] as AriaRole | 'text'; - if (match[2]) - return { role, name: match[2] }; - if (match[3]) - return { role, name: new RegExp(match[3]) }; - return { role }; + const role = tokens[0] as AriaRole | 'text'; + + let name: string | RegExp = ''; + let index = 1; + if (tokens.length > 1 && (tokens[1].startsWith('"') || tokens[1].startsWith('/'))) { + const nameToken = tokens[1]; + if (nameToken.startsWith('"')) { + name = nameToken.slice(1, -1); + } else { + const pattern = nameToken.slice(1, -1); + name = new RegExp(pattern); + } + index = 2; + } + + const result: AriaTemplateNode = { role, name }; + for (; index < tokens.length; index++) { + const attrToken = tokens[index]; + if (attrToken.startsWith('[') && attrToken.endsWith(']')) { + const attrContent = attrToken.slice(1, -1).trim(); + const [attrName, attrValue] = attrContent.split('=', 2); + const value = attrValue !== undefined ? attrValue.trim() : 'true'; + applyAttribute(result, attrName, value); + } else { + throw new Error(`Invalid attribute token ${attrToken} in key ${key}`); + } + } + + return result; } function normalizeWhitespace(text: string) { diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 16d8dc60709bc..56044a2027c3d 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -22,8 +22,8 @@ import type { AriaRole } from './roleUtils'; type AriaProps = { checked?: boolean | 'mixed'; disabled?: boolean; - expanded?: boolean | 'none', - level?: number, + expanded?: boolean; + level?: number; pressed?: boolean | 'mixed'; selected?: boolean; }; @@ -286,13 +286,23 @@ export function renderAriaTree(ariaNode: AriaNode): string { let line = `${indent}- ${ariaNode.role}`; if (ariaNode.name) line += ` ${escapeWithQuotes(ariaNode.name, '"')}`; - const stringValue = !ariaNode.checked - && !ariaNode.disabled - && (!ariaNode.expanded || ariaNode.expanded === 'none') - && !ariaNode.level - && !ariaNode.pressed - && !ariaNode.selected - && (!ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string')); + + if (ariaNode.checked === 'mixed') + line += ` [checked=mixed]`; + if (ariaNode.checked === true) + line += ` [checked]`; + if (ariaNode.disabled) + line += ` [disabled]`; + if (ariaNode.expanded) + line += ` [expanded]`; + if (ariaNode.level) + line += ` [level=${ariaNode.level}]`; + if (ariaNode.pressed === 'mixed') + line += ` [pressed=mixed]`; + if (ariaNode.pressed === true) + line += ` [pressed]`; + + const stringValue = !ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string'); if (stringValue) { if (ariaNode.children.length) line += ': ' + escapeYamlString(ariaNode.children?.[0] as string); @@ -301,16 +311,6 @@ export function renderAriaTree(ariaNode: AriaNode): string { } lines.push(line + ':'); - if (ariaNode.checked) - lines.push(`${indent} - checked: ${ariaNode.checked}`); - if (ariaNode.disabled) - lines.push(`${indent} - disabled: ${ariaNode.disabled}`); - if (ariaNode.expanded && ariaNode.expanded !== 'none') - lines.push(`${indent} - expanded: ${ariaNode.expanded}`); - if (ariaNode.level) - lines.push(`${indent} - level: ${ariaNode.level}`); - if (ariaNode.pressed) - lines.push(`${indent} - pressed: ${ariaNode.pressed}`); for (const child of ariaNode.children || []) visit(child, indent + ' '); }; diff --git a/packages/playwright-core/src/server/injected/roleUtils.ts b/packages/playwright-core/src/server/injected/roleUtils.ts index 9c5712311ef41..df52329b1ead4 100644 --- a/packages/playwright-core/src/server/injected/roleUtils.ts +++ b/packages/playwright-core/src/server/injected/roleUtils.ts @@ -881,7 +881,7 @@ export function getAriaPressed(element: Element): boolean | 'mixed' { } export const kAriaExpandedRoles = ['application', 'button', 'checkbox', 'combobox', 'gridcell', 'link', 'listbox', 'menuitem', 'row', 'rowheader', 'tab', 'treeitem', 'columnheader', 'menuitemcheckbox', 'menuitemradio', 'rowheader', 'switch']; -export function getAriaExpanded(element: Element): boolean | 'none' { +export function getAriaExpanded(element: Element): boolean | undefined { // https://www.w3.org/TR/wai-aria-1.2/#aria-expanded // https://www.w3.org/TR/html-aam-1.0/#html-attribute-state-and-property-mappings if (elementSafeTagName(element) === 'DETAILS') @@ -889,12 +889,12 @@ export function getAriaExpanded(element: Element): boolean | 'none' { if (kAriaExpandedRoles.includes(getAriaRole(element) || '')) { const expanded = element.getAttribute('aria-expanded'); if (expanded === null) - return 'none'; + return undefined; if (expanded === 'true') return true; return false; } - return 'none'; + return undefined; } export const kAriaLevelRoles = ['heading', 'listitem', 'row', 'treeitem']; diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index cf71611320c17..88306a1e43495 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -40,8 +40,7 @@ async function checkAndMatchSnapshot(locator: Locator, snapshot: string) { it('should snapshot', async ({ page }) => { await page.setContent(`

        title

        `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "title": - - level: 1 + - heading "title" [level=1] `); }); @@ -51,10 +50,8 @@ it('should snapshot list', async ({ page }) => {

        title 2

        `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "title": - - level: 1 - - heading "title 2": - - level: 1 + - heading "title" [level=1] + - heading "title 2" [level=1] `); }); @@ -94,8 +91,7 @@ it('should allow text nodes', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "Microsoft": - - level: 1 + - heading "Microsoft" [level=1] - text: Open source projects and samples from Microsoft `); }); @@ -148,8 +144,7 @@ it('should snapshot integration', async ({ page }) => {
      `); await checkAndMatchSnapshot(page.locator('body'), ` - - heading "Microsoft": - - level: 1 + - heading "Microsoft" [level=1] - text: Open source projects and samples from Microsoft - list: - listitem: diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index d4be35fb8a366..1335be5a59c9a 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -107,15 +107,219 @@ test('details visibility', async ({ page }) => { `); }); -test('checked state', async ({ page }) => { +test('checked attribute', async ({ page }) => { await page.setContent(` `); await expect(page.locator('body')).toMatchAriaSnapshot(` - - checkbox: - - checked: true + - checkbox `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - checkbox [checked] + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - checkbox [checked=true] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - checkbox [checked=false] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - checkbox [checked=mixed] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - checkbox [checked=5] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain(' attribute must be a boolean or "mixed"'); + } +}); + +test('disabled attribute', async ({ page }) => { + await page.setContent(` + + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [disabled] + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [disabled=true] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [disabled=false] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [disabled=invalid] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain(' attribute must be a boolean'); + } +}); + +test('expanded attribute', async ({ page }) => { + await page.setContent(` + + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [expanded] + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [expanded=true] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [expanded=false] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [expanded=invalid] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain(' attribute must be a boolean'); + } +}); + +test('level attribute', async ({ page }) => { + await page.setContent(` +

      Section Title

      + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading [level=2] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading [level=3] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - heading [level=two] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain(' attribute must be a number'); + } +}); + +test('pressed attribute', async ({ page }) => { + await page.setContent(` + + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [pressed] + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [pressed=true] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [pressed=false] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + // Test for 'mixed' state + await page.setContent(` + + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [pressed=mixed] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [pressed=true] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - button [pressed=5] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain(' attribute must be a boolean or "mixed"'); + } +}); + +test('selected attribute', async ({ page }) => { + await page.setContent(` + + + + +
      Row
      + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - row + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - row [selected] + `); + + await expect(page.locator('body')).toMatchAriaSnapshot(` + - row [selected=true] + `); + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - row [selected=false] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain('Timed out 1000ms waiting for expect'); + } + + { + const e = await expect(page.locator('body')).toMatchAriaSnapshot(` + - row [selected=invalid] + `, { timeout: 1000 }).catch(e => e); + expect(stripAnsi(e.message)).toContain(' attribute must be a boolean'); + } }); test('integration test', async ({ page }) => { @@ -193,12 +397,11 @@ test('expected formatter', async ({ page }) => { expect(stripAnsi(error.message)).toContain(` Locator: locator('body') - Expected - 2 -+ Received string + 4 ++ Received string + 3 - - heading "todos" - - textbox "Wrong text" + - banner: -+ - heading "todos": -+ - level: 1 ++ - heading "todos" [level=1] + - textbox "What needs to be done?"`); }); diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index 1120cede6b8f7..f60a6dde86aa7 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -61,6 +61,23 @@ test('should run visible', async ({ runUITest }) => { ⊘ skipped `); + // await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + // - tree: + // - treeitem "a.test.ts" [expanded]: + // - treeitem "passes" + // - treeitem "fails" [selected]: + // - button "Run" + // - button "Show source" + // - button "Watch" + // - treeitem "suite" + // - treeitem "b.test.ts" [expanded]: + // - treeitem "passes" + // - treeitem "fails" + // - treeitem "c.test.ts" [expanded]: + // - treeitem "passes" + // - treeitem "skipped" + // `); + await expect(page.getByTestId('status-line')).toHaveText('4/8 passed (50%)'); }); From 4b187107ee341fb1576f790f8377d356acc4fa87 Mon Sep 17 00:00:00 2001 From: Meir Blachman Date: Sun, 20 Oct 2024 19:44:48 +0300 Subject: [PATCH 336/805] devops: fix 'client side changes bot' PR links in PRs (#33189) --- .github/workflows/pr_check_client_side_changes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_check_client_side_changes.yml b/.github/workflows/pr_check_client_side_changes.yml index 17a8da9ca3d4d..6612845f47202 100644 --- a/.github/workflows/pr_check_client_side_changes.yml +++ b/.github/workflows/pr_check_client_side_changes.yml @@ -27,7 +27,7 @@ jobs: repo: context.repo.repo, commit_sha: context.sha, }); - const commitHeader = data.message.split('\n')[0]; + const commitHeader = data.message.split('\n')[0].replace(/#(\d+)/g, 'https://github.com/microsoft/playwright/pull/$1'); const title = '[Ports]: Backport client side changes for ' + currentPlaywrightVersion; for (const repo of ['playwright-python', 'playwright-java', 'playwright-dotnet']) { From 40d5a1cb4af61fe6b670540abc9f0889ab0d98f9 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 21 Oct 2024 11:14:48 +0200 Subject: [PATCH 337/805] fix(ff): resource type for image sets should be `image` (#33195) --- .../src/server/firefox/ffNetworkManager.ts | 2 +- tests/page/page-event-request.spec.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/server/firefox/ffNetworkManager.ts b/packages/playwright-core/src/server/firefox/ffNetworkManager.ts index 978eb30bd4a72..73b8e3589fc0f 100644 --- a/packages/playwright-core/src/server/firefox/ffNetworkManager.ts +++ b/packages/playwright-core/src/server/firefox/ffNetworkManager.ts @@ -183,7 +183,7 @@ const causeToResourceType: {[key: string]: string} = { TYPE_XSLT: 'other', TYPE_BEACON: 'other', TYPE_FETCH: 'fetch', - TYPE_IMAGESET: 'images', + TYPE_IMAGESET: 'image', TYPE_WEB_MANIFEST: 'manifest', }; diff --git a/tests/page/page-event-request.spec.ts b/tests/page/page-event-request.spec.ts index f32f224374b33..2c1d7a7ebaf75 100644 --- a/tests/page/page-event-request.spec.ts +++ b/tests/page/page-event-request.spec.ts @@ -258,3 +258,18 @@ it('should finish 204 request', { page.evaluate(async url => { await fetch(url); }, server.PREFIX + '/204').catch(() => {}); expect(await reqPromise).toBe('requestfinished'); }); + +it(' resource should have type image', async ({ page }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33148' }); + const [request] = await Promise.all([ + page.waitForEvent('request'), + page.setContent(` + + + + + + `) + ]); + expect(request.resourceType()).toBe('image'); +}); \ No newline at end of file From 014577d345a7985bb716a9c856bac783660c7c5e Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Mon, 21 Oct 2024 02:33:16 -0700 Subject: [PATCH 338/805] feat(webkit): roll to r2094 (#33188) --- packages/playwright-core/browsers.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 11a2b1fad1e2f..b808a2fe5e8ce 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -27,7 +27,7 @@ }, { "name": "webkit", - "revision": "2092", + "revision": "2094", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", @@ -35,7 +35,9 @@ "mac11": "1816", "mac11-arm64": "1816", "mac12": "2009", - "mac12-arm64": "2009" + "mac12-arm64": "2009", + "ubuntu20.04-x64": "2092", + "ubuntu20.04-arm64": "2092" }, "browserVersion": "18.0" }, From e866e3306ee7e07918733cefca33ce6451bbb3e1 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 21 Oct 2024 17:00:10 +0200 Subject: [PATCH 339/805] devops: stop publishing Ubuntu 20.04 (#33203) --- docs/src/docker.md | 4 +-- utils/docker/Dockerfile.focal | 51 ---------------------------------- utils/docker/build.sh | 6 ++-- utils/docker/publish_docker.sh | 22 +++------------ 4 files changed, 8 insertions(+), 75 deletions(-) delete mode 100644 utils/docker/Dockerfile.focal diff --git a/docs/src/docker.md b/docs/src/docker.md index 665904a1440c6..bfcf5e73b5e7a 100644 --- a/docs/src/docker.md +++ b/docs/src/docker.md @@ -5,7 +5,7 @@ title: "Docker" ## Introduction -[Dockerfile.jammy] can be used to run Playwright scripts in Docker environment. This image includes the [Playwright browsers](./browsers.md#install-browsers) and [browser system dependencies](./browsers.md#install-system-dependencies). The Playwright package/dependency is not included in the image and should be installed separately. +[Dockerfile.noble] can be used to run Playwright scripts in Docker environment. This image includes the [Playwright browsers](./browsers.md#install-browsers) and [browser system dependencies](./browsers.md#install-system-dependencies). The Playwright package/dependency is not included in the image and should be installed separately. ## Usage @@ -111,7 +111,6 @@ We currently publish images with the following tags: - `:v%%VERSION%%` - Playwright v%%VERSION%% release docker image based on Ubuntu 24.04 LTS (Noble Numbat). - `:v%%VERSION%%-noble` - Playwright v%%VERSION%% release docker image based on Ubuntu 24.04 LTS (Noble Numbat). - `:v%%VERSION%%-jammy` - Playwright v%%VERSION%% release docker image based on Ubuntu 22.04 LTS (Jammy Jellyfish). -- `:v%%VERSION%%-focal` - Playwright v%%VERSION%% release docker image based on Ubuntu 20.04 LTS (Focal Fossa). :::note It is recommended to always pin your Docker image to a specific version if possible. If the Playwright version in your Docker image does not match the version in your project/tests, Playwright will be unable to locate browser executables. @@ -122,7 +121,6 @@ It is recommended to always pin your Docker image to a specific version if possi We currently publish images based on the following [Ubuntu](https://hub.docker.com/_/ubuntu) versions: - **Ubuntu 24.04 LTS** (Noble Numbat), image tags include `noble` - **Ubuntu 22.04 LTS** (Jammy Jellyfish), image tags include `jammy` -- **Ubuntu 20.04 LTS** (Focal Fossa), image tags include `focal` #### Alpine diff --git a/utils/docker/Dockerfile.focal b/utils/docker/Dockerfile.focal deleted file mode 100644 index cd1d1d7c6e045..0000000000000 --- a/utils/docker/Dockerfile.focal +++ /dev/null @@ -1,51 +0,0 @@ -FROM ubuntu:focal - -ARG DEBIAN_FRONTEND=noninteractive -ARG TZ=America/Los_Angeles -ARG DOCKER_IMAGE_NAME_TEMPLATE="mcr.microsoft.com/playwright:v%version%-focal" - -ENV LANG=C.UTF-8 -ENV LC_ALL=C.UTF-8 - -# === INSTALL Node.js === - -RUN apt-get update && \ - # Install Node.js - apt-get install -y curl wget gpg ca-certificates && \ - mkdir -p /etc/apt/keyrings && \ - curl -sL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" >> /etc/apt/sources.list.d/nodesource.list && \ - apt-get update && \ - apt-get install -y nodejs && \ - # Feature-parity with node.js base images. - apt-get install -y --no-install-recommends git openssh-client && \ - npm install -g yarn && \ - # clean apt cache - rm -rf /var/lib/apt/lists/* && \ - # Create the pwuser - adduser pwuser - -# === BAKE BROWSERS INTO IMAGE === - -ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright - -# 1. Add tip-of-tree Playwright package to install its browsers. -# The package should be built beforehand from tip-of-tree Playwright. -COPY ./playwright-core.tar.gz /tmp/playwright-core.tar.gz - -# 2. Bake in Playwright Agent. -# Playwright Agent is used to bake in browsers and browser dependencies, -# and run docker server later on. -# Browsers will be downloaded in `/ms-playwright`. -# Note: make sure to set 777 to the registry so that any user can access -# registry. -RUN mkdir /ms-playwright && \ - mkdir /ms-playwright-agent && \ - cd /ms-playwright-agent && npm init -y && \ - npm i /tmp/playwright-core.tar.gz && \ - npm exec --no -- playwright-core mark-docker-image "${DOCKER_IMAGE_NAME_TEMPLATE}" && \ - npm exec --no -- playwright-core install --with-deps && rm -rf /var/lib/apt/lists/* && \ - rm /tmp/playwright-core.tar.gz && \ - rm -rf /ms-playwright-agent && \ - rm -rf ~/.npm/ && \ - chmod -R 777 /ms-playwright diff --git a/utils/docker/build.sh b/utils/docker/build.sh index 46e8d9e6b6fc1..280727eac5ce0 100755 --- a/utils/docker/build.sh +++ b/utils/docker/build.sh @@ -3,12 +3,12 @@ set -e set +x if [[ ($1 == '--help') || ($1 == '-h') || ($1 == '') || ($2 == '') ]]; then - echo "usage: $(basename $0) {--arm64,--amd64} {focal,jammy} playwright:localbuild-focal" + echo "usage: $(basename $0) {--arm64,--amd64} {jammy,noble} playwright:localbuild-noble" echo - echo "Build Playwright docker image and tag it as 'playwright:localbuild-focal'." + echo "Build Playwright docker image and tag it as 'playwright:localbuild-noble'." echo "Once image is built, you can run it with" echo "" - echo " docker run --rm -it playwright:localbuild-focal /bin/bash" + echo " docker run --rm -it playwright:localbuild-noble /bin/bash" echo "" echo "NOTE: this requires on Playwright dependencies to be installed with 'npm install'" echo " and Playwright itself being built with 'npm run build'" diff --git a/utils/docker/publish_docker.sh b/utils/docker/publish_docker.sh index a4892024a82c0..870da29a905a0 100755 --- a/utils/docker/publish_docker.sh +++ b/utils/docker/publish_docker.sh @@ -21,11 +21,6 @@ else exit 1 fi -# Ubuntu 20.04 -FOCAL_TAGS=( - "v${PW_VERSION}-focal" -) - # Ubuntu 22.04 JAMMY_TAGS=( "v${PW_VERSION}-jammy" @@ -69,14 +64,12 @@ install_oras_if_needed() { publish_docker_images_with_arch_suffix() { local FLAVOR="$1" local TAGS=() - if [[ "$FLAVOR" == "focal" ]]; then - TAGS=("${FOCAL_TAGS[@]}") - elif [[ "$FLAVOR" == "jammy" ]]; then + if [[ "$FLAVOR" == "jammy" ]]; then TAGS=("${JAMMY_TAGS[@]}") elif [[ "$FLAVOR" == "noble" ]]; then TAGS=("${NOBLE_TAGS[@]}") else - echo "ERROR: unknown flavor - $FLAVOR. Must be either 'focal', 'jammy', or 'noble'" + echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', or 'noble'" exit 1 fi local ARCH="$2" @@ -97,14 +90,12 @@ publish_docker_images_with_arch_suffix() { publish_docker_manifest () { local FLAVOR="$1" local TAGS=() - if [[ "$FLAVOR" == "focal" ]]; then - TAGS=("${FOCAL_TAGS[@]}") - elif [[ "$FLAVOR" == "jammy" ]]; then + if [[ "$FLAVOR" == "jammy" ]]; then TAGS=("${JAMMY_TAGS[@]}") elif [[ "$FLAVOR" == "noble" ]]; then TAGS=("${NOBLE_TAGS[@]}") else - echo "ERROR: unknown flavor - $FLAVOR. Must be either 'focal', 'jammy', or 'noble'" + echo "ERROR: unknown flavor - $FLAVOR. Must be either 'jammy', or 'noble'" exit 1 fi @@ -123,11 +114,6 @@ publish_docker_manifest () { done } -# Ubuntu 20.04 -publish_docker_images_with_arch_suffix focal amd64 -publish_docker_images_with_arch_suffix focal arm64 -publish_docker_manifest focal amd64 arm64 - # Ubuntu 22.04 publish_docker_images_with_arch_suffix jammy amd64 publish_docker_images_with_arch_suffix jammy arm64 From 36d3a6764ea8bcb42e29e84d00e4106b0d3f2827 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 21 Oct 2024 18:41:27 +0200 Subject: [PATCH 340/805] docs: set minimal Ubuntu version to 22 and Debian to 12 (#33207) --- docs/src/intro-csharp.md | 4 ++-- docs/src/intro-java.md | 4 ++-- docs/src/intro-js.md | 4 ++-- docs/src/intro-python.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/src/intro-csharp.md b/docs/src/intro-csharp.md index d26874d456dbc..e0491aa3cc072 100644 --- a/docs/src/intro-csharp.md +++ b/docs/src/intro-csharp.md @@ -180,8 +180,8 @@ See our doc on [Running and Debugging Tests](./running-tests.md) to learn more a - Playwright is distributed as a .NET Standard 2.0 library. We recommend .NET 8. - Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL). -- macOS 13 Ventura, or macOS 14 Sonoma. -- Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. +- macOS 13 Ventura, or later. +- Debian 12, Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. ## What's next diff --git a/docs/src/intro-java.md b/docs/src/intro-java.md index 4e1503f2a3dea..733fee7fdc165 100644 --- a/docs/src/intro-java.md +++ b/docs/src/intro-java.md @@ -130,8 +130,8 @@ By default browsers launched with Playwright run headless, meaning no browser UI - Java 8 or higher. - Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL). -- macOS 13 Ventura, or macOS 14 Sonoma. -- Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. +- macOS 13 Ventura, or later. +- Debian 12, Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. ## What's next diff --git a/docs/src/intro-js.md b/docs/src/intro-js.md index 09c070aecf4f8..8c29641bd9ebf 100644 --- a/docs/src/intro-js.md +++ b/docs/src/intro-js.md @@ -288,8 +288,8 @@ pnpm exec playwright --version - Node.js 18+ - Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL). -- macOS 13 Ventura, or macOS 14 Sonoma. -- Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. +- macOS 13 Ventura, or later. +- Debian 12, Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. ## What's next diff --git a/docs/src/intro-python.md b/docs/src/intro-python.md index 3d17c2077d4c3..e44f8a2642c66 100644 --- a/docs/src/intro-python.md +++ b/docs/src/intro-python.md @@ -101,8 +101,8 @@ pip install pytest-playwright playwright -U - Python 3.8 or higher. - Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL). -- macOS 13 Ventura, or macOS 14 Sonoma. -- Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. +- macOS 13 Ventura, or later. +- Debian 12, Ubuntu 22.04, Ubuntu 24.04, on x86-64 and arm64 architecture. ## What's next From aebceb345e7849804752842c57ce02af130e202f Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 21 Oct 2024 11:15:55 -0700 Subject: [PATCH 341/805] chore: expose expect error details on TestError (#33183) --- docs/src/test-reporter-api/class-testerror.md | 36 +++++++++++ .../playwright/src/matchers/matcherHint.ts | 4 ++ .../playwright/src/matchers/toBeTruthy.ts | 29 +++++++-- packages/playwright/src/matchers/toEqual.ts | 46 +++++++++----- .../src/matchers/toMatchSnapshot.ts | 4 ++ .../playwright/src/matchers/toMatchText.ts | 62 ++++++++++++++----- packages/playwright/src/reporters/base.ts | 14 +++++ packages/playwright/src/worker/testInfo.ts | 7 ++- packages/playwright/src/worker/util.ts | 45 ++++++++++++++ packages/playwright/src/worker/workerMain.ts | 9 +-- packages/playwright/types/testReporter.d.ts | 30 +++++++++ tests/page/expect-matcher-result.spec.ts | 30 +++++++++ 12 files changed, 274 insertions(+), 42 deletions(-) create mode 100644 packages/playwright/src/worker/util.ts diff --git a/docs/src/test-reporter-api/class-testerror.md b/docs/src/test-reporter-api/class-testerror.md index 7a872c63fcb8a..8e76d6f595c7d 100644 --- a/docs/src/test-reporter-api/class-testerror.md +++ b/docs/src/test-reporter-api/class-testerror.md @@ -4,18 +4,54 @@ Information about an error thrown during test execution. +## property: TestError.expected +* since: v1.49 +- type: ?<[string]> + +Expected value formatted as a human-readable string. + +## property: TestError.locator +* since: v1.49 +- type: ?<[string]> + +Receiver's locator. + +## property: TestError.log +* since: v1.49 +- type: ?<[Array]<[string]>> + +Call log. + +## property: TestError.matcherName +* since: v1.49 +- type: ?<[string]> + +Expect matcher name. + ## property: TestError.message * since: v1.10 - type: ?<[string]> Error message. Set when [Error] (or its subclass) has been thrown. +## property: TestError.received +* since: v1.49 +- type: ?<[string]> + +Received value formatted as a human-readable string. + ## property: TestError.stack * since: v1.10 - type: ?<[string]> Error stack. Set when [Error] (or its subclass) has been thrown. +## property: TestError.timeout +* since: v1.49 +- type: ?<[int]> + +Timeout in milliseconds, if the error was caused by a timeout. + ## property: TestError.value * since: v1.10 - type: ?<[string]> diff --git a/packages/playwright/src/matchers/matcherHint.ts b/packages/playwright/src/matchers/matcherHint.ts index 8a78932c68d8c..5ffc745263cda 100644 --- a/packages/playwright/src/matchers/matcherHint.ts +++ b/packages/playwright/src/matchers/matcherHint.ts @@ -39,6 +39,10 @@ export type MatcherResult = { actual?: A; log?: string[]; timeout?: number; + locator?: string; + printedReceived?: string; + printedExpected?: string; + printedDiff?: string; }; export class ExpectError extends Error { diff --git a/packages/playwright/src/matchers/toBeTruthy.ts b/packages/playwright/src/matchers/toBeTruthy.ts index 0941ab7a636c5..8902a14eeac97 100644 --- a/packages/playwright/src/matchers/toBeTruthy.ts +++ b/packages/playwright/src/matchers/toBeTruthy.ts @@ -39,22 +39,41 @@ export async function toBeTruthy( }; const timeout = options.timeout ?? this.timeout; - const { matches, log, timedOut, received } = await query(!!this.isNot, timeout); + const { matches: pass, log, timedOut, received } = await query(!!this.isNot, timeout); + if (pass === !this.isNot) { + return { + name: matcherName, + message: () => '', + pass, + expected + }; + } + const notFound = received === kNoElementsFoundError ? received : undefined; - const actual = matches ? expected : unexpected; + const actual = pass ? expected : unexpected; + let printedReceived: string | undefined; + let printedExpected: string | undefined; + if (pass) { + printedExpected = `Expected: not ${expected}`; + printedReceived = `Received: ${notFound ? kNoElementsFoundError : expected}`; + } else { + printedExpected = `Expected: ${expected}`; + printedReceived = `Received: ${notFound ? kNoElementsFoundError : unexpected}`; + } const message = () => { const header = matcherHint(this, receiver, matcherName, 'locator', arg, matcherOptions, timedOut ? timeout : undefined); const logText = callLogText(log); - return matches ? `${header}Expected: not ${expected}\nReceived: ${notFound ? kNoElementsFoundError : expected}${logText}` : - `${header}Expected: ${expected}\nReceived: ${notFound ? kNoElementsFoundError : unexpected}${logText}`; + return `${header}${printedExpected}\n${printedReceived}${logText}`; }; return { message, - pass: matches, + pass, actual, name: matcherName, expected, log, timeout: timedOut ? timeout : undefined, + ...(printedReceived ? { printedReceived } : {}), + ...(printedExpected ? { printedExpected } : {}), }; } diff --git a/packages/playwright/src/matchers/toEqual.ts b/packages/playwright/src/matchers/toEqual.ts index 29d3fd4866da4..f75caf87f58ef 100644 --- a/packages/playwright/src/matchers/toEqual.ts +++ b/packages/playwright/src/matchers/toEqual.ts @@ -44,22 +44,35 @@ export async function toEqual( const timeout = options.timeout ?? this.timeout; const { matches: pass, received, log, timedOut } = await query(!!this.isNot, timeout); + if (pass === !this.isNot) { + return { + name: matcherName, + message: () => '', + pass, + expected + }; + } - const message = pass - ? () => - matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined) + - `Expected: not ${this.utils.printExpected(expected)}\n` + - `Received: ${this.utils.printReceived(received)}` + callLogText(log) - : () => - matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined) + - this.utils.printDiffOrStringify( - expected, - received, - EXPECTED_LABEL, - RECEIVED_LABEL, - false, - ) + callLogText(log); - + let printedReceived: string | undefined; + let printedExpected: string | undefined; + let printedDiff: string | undefined; + if (pass) { + printedExpected = `Expected: not ${this.utils.printExpected(expected)}`; + printedReceived = `Received: ${this.utils.printReceived(received)}`; + } else { + printedDiff = this.utils.printDiffOrStringify( + expected, + received, + EXPECTED_LABEL, + RECEIVED_LABEL, + false, + ); + } + const message = () => { + const header = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined); + const details = printedDiff || `${printedExpected}\n${printedReceived}`; + return `${header}${details}${callLogText(log)}`; + }; // Passing the actual and expected objects so that a custom reporter // could access them, for example in order to display a custom visual diff, // or create a different error message @@ -70,5 +83,8 @@ export async function toEqual( pass, log, timeout: timedOut ? timeout : undefined, + ...(printedReceived ? { printedReceived } : {}), + ...(printedExpected ? { printedExpected } : {}), + ...(printedDiff ? { printedDiff } : {}), }; } diff --git a/packages/playwright/src/matchers/toMatchSnapshot.ts b/packages/playwright/src/matchers/toMatchSnapshot.ts index b3fa3f556e588..86504062d30d7 100644 --- a/packages/playwright/src/matchers/toMatchSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchSnapshot.ts @@ -194,6 +194,10 @@ class SnapshotHelper { pass, message: () => message, log, + // eslint-disable-next-line @typescript-eslint/no-base-to-string + ...(this.locator ? { locator: this.locator.toString() } : {}), + printedExpected: this.expectedPath, + printedReceived: this.actualPath, }; return Object.fromEntries(Object.entries(unfiltered).filter(([_, v]) => v !== undefined)) as ImageMatcherResult; } diff --git a/packages/playwright/src/matchers/toMatchText.ts b/packages/playwright/src/matchers/toMatchText.ts index ebac8f80283cb..76ed48af1eda2 100644 --- a/packages/playwright/src/matchers/toMatchText.ts +++ b/packages/playwright/src/matchers/toMatchText.ts @@ -58,29 +58,56 @@ export async function toMatchText( const timeout = options.timeout ?? this.timeout; const { matches: pass, received, log, timedOut } = await query(!!this.isNot, timeout); + if (pass === !this.isNot) { + return { + name: matcherName, + message: () => '', + pass, + expected + }; + } + const stringSubstring = options.matchSubstring ? 'substring' : 'string'; const receivedString = received || ''; const messagePrefix = matcherHint(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined); const notFound = received === kNoElementsFoundError; - const message = () => { - if (pass) { - if (typeof expected === 'string') { - if (notFound) - return messagePrefix + `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); - const printedReceived = printReceivedStringContainExpectedSubstring(receivedString, receivedString.indexOf(expected), expected.length); - return messagePrefix + `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}\nReceived string: ${printedReceived}` + callLogText(log); + + let printedReceived: string | undefined; + let printedExpected: string | undefined; + let printedDiff: string | undefined; + if (pass) { + if (typeof expected === 'string') { + if (notFound) { + printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`; + printedReceived = `Received: ${received}`; } else { - if (notFound) - return messagePrefix + `Expected pattern: not ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); - const printedReceived = printReceivedStringContainExpectedResult(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null); - return messagePrefix + `Expected pattern: not ${this.utils.printExpected(expected)}\nReceived string: ${printedReceived}` + callLogText(log); + printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`; + const formattedReceived = printReceivedStringContainExpectedSubstring(receivedString, receivedString.indexOf(expected), expected.length); + printedReceived = `Received string: ${formattedReceived}`; } } else { - const labelExpected = `Expected ${typeof expected === 'string' ? stringSubstring : 'pattern'}`; - if (notFound) - return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${received}` + callLogText(log); - return messagePrefix + this.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false) + callLogText(log); + if (notFound) { + printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`; + printedReceived = `Received: ${received}`; + } else { + printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`; + const formattedReceived = printReceivedStringContainExpectedResult(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null); + printedReceived = `Received string: ${formattedReceived}`; + } } + } else { + const labelExpected = `Expected ${typeof expected === 'string' ? stringSubstring : 'pattern'}`; + if (notFound) { + printedExpected = `${labelExpected}: ${this.utils.printExpected(expected)}`; + printedReceived = `Received: ${received}`; + } else { + printedDiff = this.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false); + } + } + + const message = () => { + const resultDetails = printedDiff ? printedDiff : printedExpected + '\n' + printedReceived; + return messagePrefix + resultDetails + callLogText(log); }; return { @@ -91,5 +118,10 @@ export async function toMatchText( actual: received, log, timeout: timedOut ? timeout : undefined, + // eslint-disable-next-line @typescript-eslint/no-base-to-string + locator: receiver.toString(), + ...(printedReceived ? { printedReceived } : {}), + ...(printedExpected ? { printedExpected } : {}), + ...(printedDiff ? { printedDiff } : {}), }; } diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 4249429a364c8..138820baee6f9 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -32,6 +32,13 @@ type Annotation = { type ErrorDetails = { message: string; location?: Location; + timeout?: number; + matcherName?: string; + locator?: string; + expected?: string; + received?: string; + log?: string[]; + snippet?: string; }; type TestSummary = { @@ -383,6 +390,13 @@ export function formatResultFailure(test: TestCase, result: TestResult, initialI errorDetails.push({ message: indent(formattedError.message, initialIndent), location: formattedError.location, + timeout: error.timeout, + matcherName: error.matcherName, + locator: error.locator, + expected: error.expected, + received: error.received, + log: error.log, + snippet: error.snippet, }); } return errorDetails; diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index 378b32524fe03..e41f1a9a523e9 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -24,10 +24,11 @@ import { TimeoutManager, TimeoutManagerError, kMaxDeadline } from './timeoutMana import type { RunnableDescription } from './timeoutManager'; import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config'; import type { FullConfig, Location } from '../../types/testReporter'; -import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, serializeError, trimLongString, windowsFilesystemFriendlyLength } from '../util'; +import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, trimLongString, windowsFilesystemFriendlyLength } from '../util'; import { TestTracing } from './testTracing'; import type { Attachment } from './testTracing'; import type { StackFrame } from '@protocol/channels'; +import { serializeWorkerError } from './util'; export interface TestStepInternal { complete(result: { error?: Error | unknown, attachments?: Attachment[] }): void; @@ -272,7 +273,7 @@ export class TestInfoImpl implements TestInfo { if (result.error) { if (typeof result.error === 'object' && !(result.error as any)?.[stepSymbol]) (result.error as any)[stepSymbol] = step; - const error = serializeError(result.error); + const error = serializeWorkerError(result.error); if (data.boxedStack) error.stack = `${error.message}\n${stringifyStackFrames(data.boxedStack).join('\n')}`; step.error = error; @@ -330,7 +331,7 @@ export class TestInfoImpl implements TestInfo { _failWithError(error: Error | unknown) { if (this.status === 'passed' || this.status === 'skipped') this.status = error instanceof TimeoutManagerError ? 'timedOut' : 'failed'; - const serialized = serializeError(error); + const serialized = serializeWorkerError(error); const step: TestStepInternal | undefined = typeof error === 'object' ? (error as any)?.[stepSymbol] : undefined; if (step && step.boxedStack) serialized.stack = `${(error as Error).name}: ${(error as Error).message}\n${stringifyStackFrames(step.boxedStack).join('\n')}`; diff --git a/packages/playwright/src/worker/util.ts b/packages/playwright/src/worker/util.ts new file mode 100644 index 0000000000000..d24d3371911d7 --- /dev/null +++ b/packages/playwright/src/worker/util.ts @@ -0,0 +1,45 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { TestError } from '../../types/testReporter'; +import type { TestInfoError } from '../../types/test'; +import type { MatcherResult } from '../matchers/matcherHint'; +import { serializeError } from '../util'; + + +type MatcherResultDetails = Pick; + +export function serializeWorkerError(error: Error | any): TestInfoError & MatcherResultDetails { + return { + ...serializeError(error), + ...serializeExpectDetails(error), + }; +} + +function serializeExpectDetails(e: Error): MatcherResultDetails { + const matcherResult = (e as any).matcherResult as MatcherResult; + if (!matcherResult) + return {}; + return { + timeout: matcherResult.timeout, + matcherName: matcherResult.name, + locator: matcherResult.locator, + expected: matcherResult.printedExpected, + received: matcherResult.printedReceived, + log: matcherResult.log, + }; +} + diff --git a/packages/playwright/src/worker/workerMain.ts b/packages/playwright/src/worker/workerMain.ts index f180f3d08ba05..5680c3ddb39bb 100644 --- a/packages/playwright/src/worker/workerMain.ts +++ b/packages/playwright/src/worker/workerMain.ts @@ -15,7 +15,7 @@ */ import { colors } from 'playwright-core/lib/utilsBundle'; -import { debugTest, relativeFilePath, serializeError } from '../util'; +import { debugTest, relativeFilePath } from '../util'; import { type TestBeginPayload, type TestEndPayload, type RunPayload, type DonePayload, type WorkerInitParams, type TeardownErrorsPayload, stdioChunkToParams } from '../common/ipc'; import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals'; import { deserializeConfig } from '../common/configLoader'; @@ -32,6 +32,7 @@ import type { TestInfoError } from '../../types/test'; import type { Location } from '../../types/testReporter'; import { inheritFixtureNames } from '../common/fixtures'; import { type TimeSlot } from './timeoutManager'; +import { serializeWorkerError } from './util'; export class WorkerMain extends ProcessRunner { private _params: WorkerInitParams; @@ -112,7 +113,7 @@ export class WorkerMain extends ProcessRunner { await fakeTestInfo._runAsStage({ title: 'worker cleanup', runnable }, () => gracefullyCloseAll()).catch(() => {}); this._fatalErrors.push(...fakeTestInfo.errors); } catch (e) { - this._fatalErrors.push(serializeError(e)); + this._fatalErrors.push(serializeWorkerError(e)); } if (this._fatalErrors.length) { @@ -153,7 +154,7 @@ export class WorkerMain extends ProcessRunner { // No current test - fatal error. if (!this._currentTest) { if (!this._fatalErrors.length) - this._fatalErrors.push(serializeError(error)); + this._fatalErrors.push(serializeWorkerError(error)); void this._stop(); return; } @@ -224,7 +225,7 @@ export class WorkerMain extends ProcessRunner { // In theory, we should run above code without any errors. // However, in the case we screwed up, or loadTestFile failed in the worker // but not in the runner, let's do a fatal error. - this._fatalErrors.push(serializeError(e)); + this._fatalErrors.push(serializeWorkerError(e)); void this._stop(); } finally { const donePayload: DonePayload = { diff --git a/packages/playwright/types/testReporter.d.ts b/packages/playwright/types/testReporter.d.ts index a9d1f020ae888..5663f92f9817e 100644 --- a/packages/playwright/types/testReporter.d.ts +++ b/packages/playwright/types/testReporter.d.ts @@ -554,16 +554,41 @@ export interface TestCase { * Information about an error thrown during test execution. */ export interface TestError { + /** + * Expected value formatted as a human-readable string. + */ + expected?: string; + /** * Error location in the source code. */ location?: Location; + /** + * Receiver's locator. + */ + locator?: string; + + /** + * Call log. + */ + log?: Array; + + /** + * Expect matcher name. + */ + matcherName?: string; + /** * Error message. Set when [Error] (or its subclass) has been thrown. */ message?: string; + /** + * Received value formatted as a human-readable string. + */ + received?: string; + /** * Source code snippet with highlighted error. */ @@ -574,6 +599,11 @@ export interface TestError { */ stack?: string; + /** + * Timeout in milliseconds, if the error was caused by a timeout. + */ + timeout?: number; + /** * The value that was thrown. Set when anything except the [Error] (or its subclass) has been thrown. */ diff --git a/tests/page/expect-matcher-result.spec.ts b/tests/page/expect-matcher-result.spec.ts index 8f8a83bc83055..7767ecf5f62a0 100644 --- a/tests/page/expect-matcher-result.spec.ts +++ b/tests/page/expect-matcher-result.spec.ts @@ -24,12 +24,16 @@ test('toMatchText-based assertions should have matcher result', async ({ page }) { const e = await expect(locator).toHaveText(/Text2/, { timeout: 1 }).catch(e => e); e.matcherResult.message = stripAnsi(e.matcherResult.message); + e.matcherResult.printedDiff = stripAnsi(e.matcherResult.printedDiff); expect.soft(e.matcherResult).toEqual({ actual: 'Text content', expected: /Text2/, message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).toHaveText(expected)`), name: 'toHaveText', pass: false, + locator: `locator('#node')`, + printedDiff: `Expected pattern: /Text2/ +Received string: \"Text content\"`, log: expect.any(Array), timeout: 1, }); @@ -46,12 +50,17 @@ Call log`); { const e = await expect(locator).not.toHaveText(/Text/, { timeout: 1 }).catch(e => e); e.matcherResult.message = stripAnsi(e.matcherResult.message); + e.matcherResult.printedExpected = stripAnsi(e.matcherResult.printedExpected); + e.matcherResult.printedReceived = stripAnsi(e.matcherResult.printedReceived); expect.soft(e.matcherResult).toEqual({ actual: 'Text content', expected: /Text/, message: expect.stringContaining(`Timed out 1ms waiting for expect(locator).not.toHaveText(expected)`), name: 'toHaveText', pass: true, + locator: `locator('#node')`, + printedExpected: 'Expected pattern: not /Text/', + printedReceived: `Received string: \"Text content\"`, log: expect.any(Array), timeout: 1, }); @@ -79,6 +88,8 @@ test('toBeTruthy-based assertions should have matcher result', async ({ page }) name: 'toBeVisible', pass: false, log: expect.any(Array), + printedExpected: 'Expected: visible', + printedReceived: 'Received: ', timeout: 1, }); @@ -101,6 +112,8 @@ Call log`); name: 'toBeVisible', pass: true, log: expect.any(Array), + printedExpected: 'Expected: not visible', + printedReceived: 'Received: visible', timeout: 1, }); @@ -120,6 +133,7 @@ test('toEqual-based assertions should have matcher result', async ({ page }) => { const e = await expect(page.locator('#node2')).toHaveCount(1, { timeout: 1 }).catch(e => e); e.matcherResult.message = stripAnsi(e.matcherResult.message); + e.matcherResult.printedDiff = stripAnsi(e.matcherResult.printedDiff); expect.soft(e.matcherResult).toEqual({ actual: 0, expected: 1, @@ -127,6 +141,8 @@ test('toEqual-based assertions should have matcher result', async ({ page }) => name: 'toHaveCount', pass: false, log: expect.any(Array), + printedDiff: `Expected: 1 +Received: 0`, timeout: 1, }); @@ -141,6 +157,8 @@ Call log`); { const e = await expect(page.locator('#node')).not.toHaveCount(1, { timeout: 1 }).catch(e => e); e.matcherResult.message = stripAnsi(e.matcherResult.message); + e.matcherResult.printedExpected = stripAnsi(e.matcherResult.printedExpected); + e.matcherResult.printedReceived = stripAnsi(e.matcherResult.printedReceived); expect.soft(e.matcherResult).toEqual({ actual: 1, expected: 1, @@ -148,6 +166,8 @@ Call log`); name: 'toHaveCount', pass: true, log: expect.any(Array), + printedExpected: `Expected: not 1`, + printedReceived: `Received: 1`, timeout: 1, }); @@ -177,6 +197,8 @@ test('toBeChecked({ checked: false }) should have expected: false', async ({ pag name: 'toBeChecked', pass: false, log: expect.any(Array), + printedExpected: 'Expected: checked', + printedReceived: 'Received: unchecked', timeout: 1, }); @@ -199,6 +221,8 @@ Call log`); name: 'toBeChecked', pass: true, log: expect.any(Array), + printedExpected: 'Expected: not checked', + printedReceived: 'Received: checked', timeout: 1, }); @@ -221,6 +245,8 @@ Call log`); name: 'toBeChecked', pass: false, log: expect.any(Array), + printedExpected: 'Expected: unchecked', + printedReceived: 'Received: checked', timeout: 1, }); @@ -243,6 +269,8 @@ Call log`); name: 'toBeChecked', pass: true, log: expect.any(Array), + printedExpected: 'Expected: not unchecked', + printedReceived: 'Received: unchecked', timeout: 1, }); @@ -271,6 +299,8 @@ test('toHaveScreenshot should populate matcherResult', async ({ page, server, is name: 'toHaveScreenshot', pass: false, log: expect.any(Array), + printedExpected: expect.stringContaining('screenshot-sanity-'), + printedReceived: expect.stringContaining('screenshot-sanity-actual'), }); expect.soft(stripAnsi(e.toString())).toContain(`Error: Screenshot comparison failed: From 0351fd9401a70a6cd300329e7fa1869449cf0a03 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Mon, 21 Oct 2024 21:21:30 +0200 Subject: [PATCH 342/805] docs: use WebSocketFrame abstraction for Java & .NET (#33211) --- docs/src/api/class-page.md | 8 ++--- docs/src/api/class-websocketroute.md | 52 ++++++++++++++-------------- docs/src/mock.md | 20 +++++------ docs/src/release-notes-csharp.md | 4 +-- docs/src/release-notes-java.md | 4 +-- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/src/api/class-page.md b/docs/src/api/class-page.md index 373649154d4bd..f65a904932daa 100644 --- a/docs/src/api/class-page.md +++ b/docs/src/api/class-page.md @@ -3691,8 +3691,8 @@ await page.routeWebSocket('/ws', ws => { ```java page.routeWebSocket("/ws", ws -> { - ws.onMessage(message -> { - if ("request".equals(message)) + ws.onMessage(frame -> { + if ("request".equals(frame.text())) ws.send("response"); }); }); @@ -3722,8 +3722,8 @@ page.route_web_socket("/ws", handler) ```csharp await page.RouteWebSocketAsync("/ws", ws => { - ws.OnMessage(message => { - if (message == "request") + ws.OnMessage(frame => { + if (frame.Text == "request") ws.Send("response"); }); }); diff --git a/docs/src/api/class-websocketroute.md b/docs/src/api/class-websocketroute.md index b827db25dd6e7..e23316ebcbd07 100644 --- a/docs/src/api/class-websocketroute.md +++ b/docs/src/api/class-websocketroute.md @@ -18,8 +18,8 @@ await page.routeWebSocket('wss://example.com/ws', ws => { ```java page.routeWebSocket("wss://example.com/ws", ws -> { - ws.onMessage(message -> { - if ("request".equals(message)) + ws.onMessage(frame -> { + if ("request".equals(frame.text())) ws.send("response"); }); }); @@ -47,8 +47,8 @@ page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( ```csharp await page.RouteWebSocketAsync("wss://example.com/ws", ws => { - ws.OnMessage(message => { - if (message == "request") + ws.OnMessage(frame => { + if (frame.Text == "request") ws.Send("response"); }); }); @@ -70,8 +70,8 @@ await page.routeWebSocket('wss://example.com/ws', ws => { ```java page.routeWebSocket("wss://example.com/ws", ws -> { - ws.onMessage(message -> { - JsonObject json = new JsonParser().parse(message).getAsJsonObject(); + ws.onMessage(frame -> { + JsonObject json = new JsonParser().parse(frame.text()).getAsJsonObject(); if ("question".equals(json.get("request").getAsString())) { Map result = new HashMap(); result.put("response", "answer"); @@ -105,8 +105,8 @@ page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( ```csharp await page.RouteWebSocketAsync("wss://example.com/ws", ws => { - ws.OnMessage(message => { - using var jsonDoc = JsonDocument.Parse(message); + ws.OnMessage(frame => { + using var jsonDoc = JsonDocument.Parse(frame.Text); JsonElement root = jsonDoc.RootElement; if (root.TryGetProperty("request", out JsonElement requestElement) && requestElement.GetString() == "question") { @@ -140,11 +140,11 @@ await page.routeWebSocket('/ws', ws => { ```java page.routeWebSocket("/ws", ws -> { WebSocketRoute server = ws.connectToServer(); - ws.onMessage(message -> { - if ("request".equals(message)) + ws.onMessage(frame -> { + if ("request".equals(frame.text())) server.send("request2"); else - server.send(message); + server.send(frame.text()); }); }); ``` @@ -180,11 +180,11 @@ page.route_web_socket("/ws", handler) ```csharp await page.RouteWebSocketAsync("/ws", ws => { var server = ws.ConnectToServer(); - ws.OnMessage(message => { - if (message == "request") + ws.OnMessage(frame => { + if (frame.Text == "request") server.Send("request2"); else - server.Send(message); + server.Send(frame.Text); }); }); ``` @@ -215,13 +215,13 @@ await page.routeWebSocket('/ws', ws => { ```java page.routeWebSocket("/ws", ws -> { WebSocketRoute server = ws.connectToServer(); - ws.onMessage(message -> { - if (!"blocked-from-the-page".equals(message)) - server.send(message); + ws.onMessage(frame -> { + if (!"blocked-from-the-page".equals(frame.text())) + server.send(frame.text()); }); - server.onMessage(message -> { - if (!"blocked-from-the-server".equals(message)) - ws.send(message); + server.onMessage(frame -> { + if (!"blocked-from-the-server".equals(frame.text())) + ws.send(frame.text()); }); }); ``` @@ -263,13 +263,13 @@ page.route_web_socket("/ws", handler) ```csharp await page.RouteWebSocketAsync("/ws", ws => { var server = ws.ConnectToServer(); - ws.OnMessage(message => { - if (message != "blocked-from-the-page") - server.Send(message); + ws.OnMessage(frame => { + if (frame.Text != "blocked-from-the-page") + server.Send(frame.Text); }); - server.OnMessage(message => { - if (message != "blocked-from-the-server") - ws.Send(message); + server.OnMessage(frame => { + if (frame.Text != "blocked-from-the-server") + ws.Send(frame.Text); }); }); ``` diff --git a/docs/src/mock.md b/docs/src/mock.md index 468690904abe3..50bc3915ceef8 100644 --- a/docs/src/mock.md +++ b/docs/src/mock.md @@ -451,8 +451,8 @@ await page.routeWebSocket('wss://example.com/ws', ws => { ```java page.routeWebSocket("wss://example.com/ws", ws -> { - ws.onMessage(message -> { - if ("request".equals(message)) + ws.onMessage(frame -> { + if ("request".equals(frame.text())) ws.send("response"); }); }); @@ -480,8 +480,8 @@ page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message( ```csharp await page.RouteWebSocketAsync("wss://example.com/ws", ws => { - ws.OnMessage(message => { - if (message == "request") + ws.OnMessage(frame => { + if (frame.Text == "request") ws.Send("response"); }); }); @@ -504,11 +504,11 @@ await page.routeWebSocket('wss://example.com/ws', ws => { ```java page.routeWebSocket("wss://example.com/ws", ws -> { WebSocketRoute server = ws.connectToServer(); - ws.onMessage(message -> { - if ("request".equals(message)) + ws.onMessage(frame -> { + if ("request".equals(frame.text())) server.send("request2"); else - server.send(message); + server.send(frame.text()); }); }); ``` @@ -544,11 +544,11 @@ page.route_web_socket("wss://example.com/ws", handler) ```csharp await page.RouteWebSocketAsync("wss://example.com/ws", ws => { var server = ws.ConnectToServer(); - ws.OnMessage(message => { - if (message == "request") + ws.OnMessage(frame => { + if (frame.Text == "request") server.Send("request2"); else - server.Send(message); + server.Send(frame.Text); }); }); ``` diff --git a/docs/src/release-notes-csharp.md b/docs/src/release-notes-csharp.md index fee7d732fec4b..130b9d4a7168c 100644 --- a/docs/src/release-notes-csharp.md +++ b/docs/src/release-notes-csharp.md @@ -13,8 +13,8 @@ New methods [`method: Page.routeWebSocket`] and [`method: BrowserContext.routeWe ```csharp await page.RouteWebSocketAsync("/ws", ws => { - ws.OnMessage(message => { - if (message == "request") + ws.OnMessage(frame => { + if (frame.Text == "request") ws.Send("response"); }); }); diff --git a/docs/src/release-notes-java.md b/docs/src/release-notes-java.md index 908a7683574c5..a5d01668def38 100644 --- a/docs/src/release-notes-java.md +++ b/docs/src/release-notes-java.md @@ -12,8 +12,8 @@ New methods [`method: Page.routeWebSocket`] and [`method: BrowserContext.routeWe ```java page.routeWebSocket("/ws", ws -> { - ws.onMessage(message -> { - if ("request".equals(message)) + ws.onMessage(frame -> { + if ("request".equals(frame.text())) ws.send("response"); }); }); From 2a3d67195dff6ece12bd36aab970a1fc95776998 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 21 Oct 2024 21:54:06 -0700 Subject: [PATCH 343/805] chore: use aria snapshots in some ui mode tests (#33212) --- .../src/server/injected/ariaSnapshot.ts | 11 +- .../playwright-core/src/utils/sequence.ts | 63 ++++ .../playwright-core/src/utils/stackTrace.ts | 20 +- .../src/ui/uiModeTestListView.tsx | 9 +- packages/web/src/components/treeView.tsx | 7 +- tests/library/sequence.spec.ts | 157 ++++++++++ .../stable-test-runner/package-lock.json | 46 +-- .../stable-test-runner/package.json | 2 +- .../playwright-test/ui-mode-test-run.spec.ts | 270 ++++++++++++++++-- 9 files changed, 534 insertions(+), 51 deletions(-) create mode 100644 packages/playwright-core/src/utils/sequence.ts create mode 100644 tests/library/sequence.spec.ts diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 56044a2027c3d..682f48365acd8 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -208,7 +208,7 @@ function matchesText(text: string | undefined, template: RegExp | string | undef export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode): { matches: boolean, received: string } { const root = generateAriaTree(rootElement); const matches = matchesNodeDeep(root, template); - return { matches, received: renderAriaTree(root) }; + return { matches, received: renderAriaTree(root, { noText: true }) }; } function matchesNode(node: AriaNode | string, template: AriaTemplateNode | RegExp | string, depth: number): boolean { @@ -276,11 +276,12 @@ function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): boolean { return !!results.length; } -export function renderAriaTree(ariaNode: AriaNode): string { +export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean }): string { const lines: string[] = []; const visit = (ariaNode: AriaNode | string, indent: string) => { if (typeof ariaNode === 'string') { - lines.push(indent + '- text: ' + escapeYamlString(ariaNode)); + if (!options?.noText) + lines.push(indent + '- text: ' + escapeYamlString(ariaNode)); return; } let line = `${indent}- ${ariaNode.role}`; @@ -301,10 +302,12 @@ export function renderAriaTree(ariaNode: AriaNode): string { line += ` [pressed=mixed]`; if (ariaNode.pressed === true) line += ` [pressed]`; + if (ariaNode.selected === true) + line += ` [selected]`; const stringValue = !ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string'); if (stringValue) { - if (ariaNode.children.length) + if (!options?.noText && ariaNode.children.length) line += ': ' + escapeYamlString(ariaNode.children?.[0] as string); lines.push(line); return; diff --git a/packages/playwright-core/src/utils/sequence.ts b/packages/playwright-core/src/utils/sequence.ts new file mode 100644 index 0000000000000..2af5429bd6539 --- /dev/null +++ b/packages/playwright-core/src/utils/sequence.ts @@ -0,0 +1,63 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function findRepeatedSubsequences(s: string[]): { sequence: string[]; count: number }[] { + const n = s.length; + const result = []; + let i = 0; + + const arraysEqual = (a1: string[], a2: string[]) => { + if (a1.length !== a2.length) return false; + for (let j = 0; j < a1.length; j++) { + if (a1[j] !== a2[j]) return false; + } + return true; + }; + + while (i < n) { + let maxRepeatCount = 1; + let maxRepeatSubstr = [s[i]]; // Initialize with the element at index i + let maxRepeatLength = 1; + + // Try substrings of length from 1 to the remaining length of the array + for (let p = 1; p <= n - i; p++) { + const substr = s.slice(i, i + p); // Extract substring as array + let k = 1; + + // Count how many times the substring repeats consecutively + while ( + i + p * k <= n && + arraysEqual(s.slice(i + p * (k - 1), i + p * k), substr) + ) { + k += 1; + } + k -= 1; // Adjust k since it increments one extra time in the loop + + // Update the maximal repeating substring if necessary + if (k > 1 && (k * p) > (maxRepeatCount * maxRepeatLength)) { + maxRepeatCount = k; + maxRepeatSubstr = substr; + maxRepeatLength = p; + } + } + + // Record the substring and its count + result.push({ sequence: maxRepeatSubstr, count: maxRepeatCount }); + i += maxRepeatLength * maxRepeatCount; // Move index forward + } + + return result; +} \ No newline at end of file diff --git a/packages/playwright-core/src/utils/stackTrace.ts b/packages/playwright-core/src/utils/stackTrace.ts index 77e1365b3f876..6f9a87578b54b 100644 --- a/packages/playwright-core/src/utils/stackTrace.ts +++ b/packages/playwright-core/src/utils/stackTrace.ts @@ -19,6 +19,7 @@ import { parseStackTraceLine } from '../utilsBundle'; import { isUnderTest } from './'; import type { StackFrame } from '@protocol/channels'; import { colors } from '../utilsBundle'; +import { findRepeatedSubsequences } from './sequence'; export function rewriteErrorMessage(e: E, newMessage: string): E { const lines: string[] = (e.stack?.split('\n') || []).filter(l => l.startsWith(' at ')); @@ -132,9 +133,26 @@ export function splitErrorMessage(message: string): { name: string, message: str export function formatCallLog(log: string[] | undefined): string { if (!log || !log.some(l => !!l)) return ''; + + const lines: string[] = []; + + for (const block of findRepeatedSubsequences(log)) { + for (let i = 0; i < block.sequence.length; i++) { + const line = block.sequence[i]; + const leadingWhitespace = line.match(/^\s*/); + const whitespacePrefix = ' ' + leadingWhitespace?.[0] || ''; + const countPrefix = `${block.count} × `; + if (block.count > 1 && i === 0) + lines.push(whitespacePrefix + countPrefix + line.trim()); + else if (block.count > 1) + lines.push(whitespacePrefix + ' '.repeat(countPrefix.length - 2) + '- ' + line.trim()); + else + lines.push(whitespacePrefix + '- ' + line.trim()); + } + } return ` Call log: - ${colors.dim('- ' + (log || []).join('\n - '))} +${colors.dim(lines.join('\n'))} `; } diff --git a/packages/trace-viewer/src/ui/uiModeTestListView.tsx b/packages/trace-viewer/src/ui/uiModeTestListView.tsx index e0ef2a8bcac66..a6cb82fb8a4f8 100644 --- a/packages/trace-viewer/src/ui/uiModeTestListView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTestListView.tsx @@ -159,12 +159,15 @@ export const TestListView: React.FC<{ rootItem={testTree.rootItem} dataTestId='test-tree' render={treeItem => { - return
      -
      + const prefixId = treeItem.id.replace(/[^\w\d-_]/g, '-'); + const labelId = prefixId + '-label'; + const timeId = prefixId + '-time'; + return
      +
      {treeItem.title} {treeItem.kind === 'case' ? treeItem.tags.map(tag => handleTagClick(e, tag)} />) : null}
      - {!!treeItem.duration && treeItem.status !== 'skipped' &&
      {msToString(treeItem.duration)}
      } + {!!treeItem.duration && treeItem.status !== 'skipped' &&
      {msToString(treeItem.duration)}
      } runTreeItem(treeItem)} disabled={!!runningState && !runningState.completed}> diff --git a/packages/web/src/components/treeView.tsx b/packages/web/src/components/treeView.tsx index 9af8609f3b86b..cb7ab7150d5f0 100644 --- a/packages/web/src/components/treeView.tsx +++ b/packages/web/src/components/treeView.tsx @@ -249,8 +249,9 @@ export function TreeItemHeader({ const rendered = render(item); const children = expanded && item.children.length ? item.children as T[] : []; const titled = title?.(item); + const iconed = icon?.(item) || 'codicon-blank'; - return
      + return
      onAccepted?.(item)} className={clsx( @@ -277,10 +278,10 @@ export function TreeItemHeader({ toggleExpanded(item); }} /> - {icon && } + {icon &&
      } {typeof rendered === 'string' ?
      {rendered}
      : rendered}
      - {!!children.length &&
      + {!!children.length &&
      {children.map(child => { const itemData = treeItems.get(child); return itemData && { + const input = []; + const expectedOutput = []; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle a single-element array', () => { + const input = ['a']; + const expectedOutput = [{ sequence: ['a'], count: 1 }]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle an array with no repeats', () => { + const input = ['a', 'b', 'c']; + const expectedOutput = [ + { sequence: ['a'], count: 1 }, + { sequence: ['b'], count: 1 }, + { sequence: ['c'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle contiguous repeats of single elements', () => { + const input = ['a', 'a', 'a', 'b', 'b', 'c']; + const expectedOutput = [ + { sequence: ['a'], count: 3 }, + { sequence: ['b'], count: 2 }, + { sequence: ['c'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should detect longer repeating substrings', () => { + const input = ['a', 'b', 'a', 'b', 'a', 'b']; + const expectedOutput = [{ sequence: ['a', 'b'], count: 3 }]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle multiple repeating substrings', () => { + const input = ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b']; + const expectedOutput = [ + { sequence: ['a', 'a', 'b', 'b'], count: 2 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle complex cases with overlapping repeats', () => { + const input = ['a', 'a', 'a', 'a']; + const expectedOutput = [{ sequence: ['a'], count: 4 }]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle complex acceptance cases with multiple possible repeats', () => { + const input = ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c']; + const expectedOutput = [ + { sequence: ['a', 'a', 'b', 'b'], count: 2 }, + { sequence: ['c'], count: 4 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle non-repeating sequences correctly', () => { + const input = ['a', 'b', 'c', 'd', 'e']; + const expectedOutput = [ + { sequence: ['a'], count: 1 }, + { sequence: ['b'], count: 1 }, + { sequence: ['c'], count: 1 }, + { sequence: ['d'], count: 1 }, + { sequence: ['e'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle a case where the entire array is a repeating sequence', () => { + const input = ['x', 'y', 'x', 'y', 'x', 'y']; + const expectedOutput = [{ sequence: ['x', 'y'], count: 3 }]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should correctly identify the maximal repeating substring', () => { + const input = ['a', 'b', 'a', 'b', 'a', 'b', 'c', 'c', 'c', 'c']; + const expectedOutput = [ + { sequence: ['a', 'b'], count: 3 }, + { sequence: ['c'], count: 4 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle repeats with varying lengths', () => { + const input = ['a', 'a', 'b', 'b', 'b', 'b', 'a', 'a']; + const expectedOutput = [ + { sequence: ['a'], count: 2 }, + { sequence: ['b'], count: 4 }, + { sequence: ['a'], count: 2 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should correctly handle a repeat count of one (k adjustment to zero)', () => { + const input = ['a', 'b', 'a', 'b', 'c']; + const expectedOutput = [ + { sequence: ['a', 'b'], count: 2 }, + { sequence: ['c'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should correctly handle repeats at the end of the array', () => { + const input = ['x', 'y', 'x', 'y', 'x', 'y', 'z']; + const expectedOutput = [ + { sequence: ['x', 'y'], count: 3 }, + { sequence: ['z'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should not overcount repeats when the last potential repeat is incomplete', () => { + const input = ['m', 'n', 'm', 'n', 'm']; + const expectedOutput = [ + { sequence: ['m', 'n'], count: 2 }, + { sequence: ['m'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); + +it('should handle single repeats correctly when the substring length is greater than one', () => { + const input = ['a', 'b', 'c', 'a', 'b', 'd']; + const expectedOutput = [ + { sequence: ['a'], count: 1 }, + { sequence: ['b'], count: 1 }, + { sequence: ['c'], count: 1 }, + { sequence: ['a'], count: 1 }, + { sequence: ['b'], count: 1 }, + { sequence: ['d'], count: 1 }, + ]; + expect(findRepeatedSubsequences(input)).toEqual(expectedOutput); +}); diff --git a/tests/playwright-test/stable-test-runner/package-lock.json b/tests/playwright-test/stable-test-runner/package-lock.json index df6792d59df93..1ebdfb52cccbf 100644 --- a/tests/playwright-test/stable-test-runner/package-lock.json +++ b/tests/playwright-test/stable-test-runner/package-lock.json @@ -5,15 +5,15 @@ "packages": { "": { "dependencies": { - "@playwright/test": "1.49.0-alpha-2024-10-17" + "@playwright/test": "1.49.0-alpha-2024-10-20" } }, "node_modules/@playwright/test": { - "version": "1.49.0-alpha-2024-10-17", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-17.tgz", - "integrity": "sha512-HLZY3sM6xt9Wi8K09zPwjJQtcUBZNBcNSIVoMZhtJM3+TikCKx4SiJ3P8vbSlk7Tm3s2oqlS+wA181IxhbTGBA==", + "version": "1.49.0-alpha-2024-10-20", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-20.tgz", + "integrity": "sha512-lSagJ8KSD636T/TNfSJRh+vuBBssCL5xJgYmsvsF37cDMATTdVf2OVozVK91V9MAL7CxP4F5sQFVq/8rqu23WA==", "dependencies": { - "playwright": "1.49.0-alpha-2024-10-17" + "playwright": "1.49.0-alpha-2024-10-20" }, "bin": { "playwright": "cli.js" @@ -36,11 +36,11 @@ } }, "node_modules/playwright": { - "version": "1.49.0-alpha-2024-10-17", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-17.tgz", - "integrity": "sha512-IgcLunnpocVS/AEq2lcftVOu0DGQzFm1Qt25SCJsrVvKVe83ElKXZYskPz7yA0HeuOVxQyN69EDWI09ph7lfoQ==", + "version": "1.49.0-alpha-2024-10-20", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-20.tgz", + "integrity": "sha512-lkZXCaLoVKaa3eVu8qJJiLym6SkjXD+ilE4XZJx3AIE0o4vqMEYVB8tjLzAcl4UZx8wVcCps/WcCvTWhOSIXRA==", "dependencies": { - "playwright-core": "1.49.0-alpha-2024-10-17" + "playwright-core": "1.49.0-alpha-2024-10-20" }, "bin": { "playwright": "cli.js" @@ -53,9 +53,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.0-alpha-2024-10-17", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-17.tgz", - "integrity": "sha512-XLTKmPBm2ZIOXBckXtiimSOIjQsYy8MqEP9CsHSgytsP0E+j/44v1BuwHOOMaG8sfjcuZLZ1QdFidnl07A9wSg==", + "version": "1.49.0-alpha-2024-10-20", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-20.tgz", + "integrity": "sha512-TeQNA7vsGVrHaArr+giPyiWPAV27+wIcuMLrAJXzUB0leVA9bkXbNQ5lA5+G4OhqlmYAbMOpJMtN+TREDv4nXA==", "bin": { "playwright-core": "cli.js" }, @@ -66,11 +66,11 @@ }, "dependencies": { "@playwright/test": { - "version": "1.49.0-alpha-2024-10-17", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-17.tgz", - "integrity": "sha512-HLZY3sM6xt9Wi8K09zPwjJQtcUBZNBcNSIVoMZhtJM3+TikCKx4SiJ3P8vbSlk7Tm3s2oqlS+wA181IxhbTGBA==", + "version": "1.49.0-alpha-2024-10-20", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.0-alpha-2024-10-20.tgz", + "integrity": "sha512-lSagJ8KSD636T/TNfSJRh+vuBBssCL5xJgYmsvsF37cDMATTdVf2OVozVK91V9MAL7CxP4F5sQFVq/8rqu23WA==", "requires": { - "playwright": "1.49.0-alpha-2024-10-17" + "playwright": "1.49.0-alpha-2024-10-20" } }, "fsevents": { @@ -80,18 +80,18 @@ "optional": true }, "playwright": { - "version": "1.49.0-alpha-2024-10-17", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-17.tgz", - "integrity": "sha512-IgcLunnpocVS/AEq2lcftVOu0DGQzFm1Qt25SCJsrVvKVe83ElKXZYskPz7yA0HeuOVxQyN69EDWI09ph7lfoQ==", + "version": "1.49.0-alpha-2024-10-20", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0-alpha-2024-10-20.tgz", + "integrity": "sha512-lkZXCaLoVKaa3eVu8qJJiLym6SkjXD+ilE4XZJx3AIE0o4vqMEYVB8tjLzAcl4UZx8wVcCps/WcCvTWhOSIXRA==", "requires": { "fsevents": "2.3.2", - "playwright-core": "1.49.0-alpha-2024-10-17" + "playwright-core": "1.49.0-alpha-2024-10-20" } }, "playwright-core": { - "version": "1.49.0-alpha-2024-10-17", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-17.tgz", - "integrity": "sha512-XLTKmPBm2ZIOXBckXtiimSOIjQsYy8MqEP9CsHSgytsP0E+j/44v1BuwHOOMaG8sfjcuZLZ1QdFidnl07A9wSg==" + "version": "1.49.0-alpha-2024-10-20", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0-alpha-2024-10-20.tgz", + "integrity": "sha512-TeQNA7vsGVrHaArr+giPyiWPAV27+wIcuMLrAJXzUB0leVA9bkXbNQ5lA5+G4OhqlmYAbMOpJMtN+TREDv4nXA==" } } } diff --git a/tests/playwright-test/stable-test-runner/package.json b/tests/playwright-test/stable-test-runner/package.json index 14625ebe6d328..dbe21acd15ee4 100644 --- a/tests/playwright-test/stable-test-runner/package.json +++ b/tests/playwright-test/stable-test-runner/package.json @@ -1,6 +1,6 @@ { "private": true, "dependencies": { - "@playwright/test": "1.49.0-alpha-2024-10-17" + "@playwright/test": "1.49.0-alpha-2024-10-20" } } diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index f60a6dde86aa7..3673faab45477 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -61,22 +61,25 @@ test('should run visible', async ({ runUITest }) => { ⊘ skipped `); - // await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` - // - tree: - // - treeitem "a.test.ts" [expanded]: - // - treeitem "passes" - // - treeitem "fails" [selected]: - // - button "Run" - // - button "Show source" - // - button "Watch" - // - treeitem "suite" - // - treeitem "b.test.ts" [expanded]: - // - treeitem "passes" - // - treeitem "fails" - // - treeitem "c.test.ts" [expanded]: - // - treeitem "passes" - // - treeitem "skipped" - // `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-error] suite" + - treeitem "[icon-error] b.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem "[icon-check] c.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem "[icon-circle-slash] skipped" + `); await expect(page.getByTestId('status-line')).toHaveText('4/8 passed (50%)'); }); @@ -117,6 +120,17 @@ test('should run on hover', async ({ runUITest }) => { ✅ passes <= ◯ fails `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-circle-outline] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/}: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-circle-outline] fails" + `); }); test('should run on double click', async ({ runUITest }) => { @@ -135,6 +149,17 @@ test('should run on double click', async ({ runUITest }) => { ✅ passes <= ◯ fails `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-circle-outline] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-circle-outline] fails" + `); }); test('should run on Enter', async ({ runUITest }) => { @@ -154,6 +179,17 @@ test('should run on Enter', async ({ runUITest }) => { ◯ passes ❌ fails <= `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem "[icon-circle-outline] passes" + - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + `); }); test('should run by project', async ({ runUITest }) => { @@ -185,6 +221,26 @@ test('should run by project', async ({ runUITest }) => { ⊘ skipped `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-error] suite" + - treeitem "[icon-error] b.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem "[icon-check] c.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem "[icon-circle-slash] skipped" + `); + await page.getByText('Status:').click(); await page.getByLabel('bar').setChecked(true); @@ -203,6 +259,29 @@ test('should run by project', async ({ runUITest }) => { ► ◯ skipped `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-circle-outline\] passes/} + - treeitem ${/\[icon-error\] fails/}: + - group: + - treeitem ${/\[icon-error\] foo/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-circle-outline] bar" + - treeitem "[icon-error] suite" + - treeitem "[icon-error] b.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-circle-outline\] passes/} + - treeitem ${/\[icon-error\] fails/} + - treeitem "[icon-circle-outline] c.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-circle-outline\] passes/} + - treeitem ${/\[icon-circle-outline\] skipped/} + `); + await page.getByText('Status:').click(); await page.getByTestId('test-tree').getByText('passes').first().click(); @@ -216,6 +295,20 @@ test('should run by project', async ({ runUITest }) => { ► ❌ fails `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-circle-outline\] passes \d+ms/} [expanded] [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - group: + - treeitem ${/\[icon-check\] foo \d+ms/} + - treeitem ${/\[icon-circle-outline\] bar/} + - treeitem ${/\[icon-error\] fails \d+ms/} + `); + await expect(page.getByText('Projects: foo bar')).toBeVisible(); await page.getByTitle('Run all').click(); @@ -235,6 +328,32 @@ test('should run by project', async ({ runUITest }) => { ► ✅ passes ► ⊘ skipped `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} [expanded]: + - group: + - treeitem ${/\[icon-check\] foo \d+ms/} + - treeitem ${/\[icon-check\] bar \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} [expanded]: + - group: + - treeitem ${/\[icon-error\] foo \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem ${/\[icon-error\] bar \d+ms/} + - treeitem ${/\[icon-error\] suite/} + - treeitem "[icon-error] b.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes/} + - treeitem ${/\[icon-error\] fails/} + - treeitem "[icon-check] c.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes/} + - treeitem ${/\[icon-circle-slash\] skipped/} + `); }); test('should stop', async ({ runUITest }) => { @@ -261,6 +380,16 @@ test('should stop', async ({ runUITest }) => { 🕦 test 3 `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-loading] a.test.ts" [expanded]: + - group: + - treeitem "[icon-circle-slash] test 0" + - treeitem ${/\[icon-check\] test 1 \d+ms/} + - treeitem ${/\[icon-loading\] test 2/} + - treeitem ${/\[icon-clock\] test 3/} + `); + await expect(page.getByTitle('Run all')).toBeDisabled(); await expect(page.getByTitle('Stop')).toBeEnabled(); @@ -273,6 +402,16 @@ test('should stop', async ({ runUITest }) => { ◯ test 2 ◯ test 3 `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-circle-outline] a.test.ts" [expanded]: + - group: + - treeitem "[icon-circle-slash] test 0" + - treeitem ${/\[icon-check\] test 1 \d+ms/} + - treeitem ${/\[icon-circle-outline\] test 2/} + - treeitem ${/\[icon-circle-outline\] test 3/} + `); }); test('should run folder', async ({ runUITest }) => { @@ -301,6 +440,17 @@ test('should run folder', async ({ runUITest }) => { ▼ ◯ in-a.test.ts ◯ passes `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] folder-b" [expanded] [selected]: + - group: + - treeitem "[icon-check] folder-c" + - treeitem "[icon-check] in-b.test.ts" + - treeitem "[icon-circle-outline] in-a.test.ts" [expanded]: + - group: + - treeitem "[icon-circle-outline] passes" + `); }); test('should show time', async ({ runUITest }) => { @@ -324,6 +474,26 @@ test('should show time', async ({ runUITest }) => { ⊘ skipped `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-error] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-error] suite" + - treeitem "[icon-error] b.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem "[icon-check] c.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem "[icon-circle-slash] skipped" + `); + await expect(page.getByTestId('status-line')).toHaveText('4/8 passed (50%)'); }); @@ -348,6 +518,13 @@ test('should show test.fail as passing', async ({ runUITest }) => { ✅ should fail XXms `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] should fail \d+ms/} + `); + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); }); @@ -377,6 +554,13 @@ test('should ignore repeatEach', async ({ runUITest }) => { ✅ should pass `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] should pass \d+ms/} + `); + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); }); @@ -404,6 +588,14 @@ test('should remove output folder before test run', async ({ runUITest }) => { ▼ ✅ a.test.ts ✅ should pass `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] should pass \d+ms/} + `); + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); await page.getByTitle('Run all').click(); @@ -411,6 +603,14 @@ test('should remove output folder before test run', async ({ runUITest }) => { ▼ ✅ a.test.ts ✅ should pass `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] should pass \d+ms/} + `); + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); }); @@ -451,6 +651,18 @@ test('should show proper total when using deps', async ({ runUITest }) => { ✅ run @setup <= ◯ run @chromium `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-circle-outline] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] run @setup setup \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + - treeitem "[icon-circle-outline] run @chromium chromium" + `); + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); await page.getByTitle('run @chromium').dblclick(); @@ -459,6 +671,18 @@ test('should show proper total when using deps', async ({ runUITest }) => { ✅ run @setup ✅ run @chromium <= `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] run @setup setup \d+ms/} + - treeitem ${/\[icon-check\] run @chromium chromium \d+ms/} [selected]: + - button "Run" + - button "Show source" + - button "Watch" + `); + await expect(page.getByTestId('status-line')).toHaveText('2/2 passed (100%)'); }); @@ -518,6 +742,13 @@ test('should respect --tsconfig option', { ✅ test `); + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] test \d+ms/} + `); + await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); }); @@ -539,4 +770,11 @@ test('should respect --ignore-snapshots option', { ▼ ✅ a.test.ts ✅ snapshot `); + + await expect(page.getByTestId('test-tree')).toMatchAriaSnapshot(` + - tree: + - treeitem "[icon-check] a.test.ts" [expanded]: + - group: + - treeitem ${/\[icon-check\] snapshot \d+ms/} + `); }); From b275c1961237c61492ac6fe20402524cb88d368b Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 22 Oct 2024 11:52:20 +0200 Subject: [PATCH 344/805] chore: update eslintignore to lint files in utils/ folders (#33218) --- .eslintignore | 9 +++------ packages/playwright-core/src/utils/crypto.ts | 11 +++++----- .../src/utils/happy-eyeballs.ts | 20 +++++++++---------- .../src/utils/isomorphic/locatorGenerators.ts | 2 +- packages/playwright-core/src/utils/network.ts | 2 +- .../playwright-core/src/utils/sequence.ts | 11 ++++++---- .../playwright-core/src/utils/stackTrace.ts | 2 -- packages/playwright-core/src/utils/zones.ts | 3 ++- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.eslintignore b/.eslintignore index 60b8fd360fcb9..9d22f618d81c1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,14 +8,11 @@ test/assets/modernizr.js /packages/playwright-ct-core/src/generated/* /index.d.ts node_modules/ -browser_patches/*/checkout/ -browser_patches/chromium/output/ **/*.d.ts output/ test-results/ -tests/components/ -tests/installation/fixture-scripts/ -examples/ +/tests/components/ +/tests/installation/fixture-scripts/ DEPS .cache/ -utils/ +/utils/ diff --git a/packages/playwright-core/src/utils/crypto.ts b/packages/playwright-core/src/utils/crypto.ts index 5da56d4e9b695..f538912d24bd9 100644 --- a/packages/playwright-core/src/utils/crypto.ts +++ b/packages/playwright-core/src/utils/crypto.ts @@ -33,11 +33,12 @@ function encodeBase128(value: number): Buffer { do { let byte = value & 0x7f; value >>>= 7; - if (bytes.length > 0) byte |= 0x80; + if (bytes.length > 0) + byte |= 0x80; bytes.push(byte); } while (value > 0); return Buffer.from(bytes.reverse()); -}; +} // ASN1/DER Speficiation: https://www.itu.int/rec/T-REC-X.680-X.693-202102-I/en class DER { @@ -49,13 +50,13 @@ class DER { return this._encode(0x02, Buffer.from([data])); } static encodeObjectIdentifier(oid: string): Buffer { - const parts = oid.split('.').map((v) => Number(v)); + const parts = oid.split('.').map(v => Number(v)); // Encode the second part, which could be large, using base-128 encoding if necessary const output = [encodeBase128(40 * parts[0] + parts[1])]; - for (let i = 2; i < parts.length; i++) { + for (let i = 2; i < parts.length; i++) output.push(encodeBase128(parts[i])); - } + return this._encode(0x06, Buffer.concat(output)); } diff --git a/packages/playwright-core/src/utils/happy-eyeballs.ts b/packages/playwright-core/src/utils/happy-eyeballs.ts index 18de1a938cad2..02b78de4f045e 100644 --- a/packages/playwright-core/src/utils/happy-eyeballs.ts +++ b/packages/playwright-core/src/utils/happy-eyeballs.ts @@ -29,8 +29,8 @@ import { monotonicTime } from './time'; // Same as in Chromium (https://source.chromium.org/chromium/chromium/src/+/5666ff4f5077a7e2f72902f3a95f5d553ea0d88d:net/socket/transport_connect_job.cc;l=102) const connectionAttemptDelayMs = 300; -const kDNSLookupAt = Symbol('kDNSLookupAt') -const kTCPConnectionAt = Symbol('kTCPConnectionAt') +const kDNSLookupAt = Symbol('kDNSLookupAt'); +const kTCPConnectionAt = Symbol('kTCPConnectionAt'); class HttpHappyEyeballsAgent extends http.Agent { createConnection(options: http.ClientRequestArgs, oncreate?: (err: Error | null, socket?: net.Socket) => void): net.Socket | undefined { @@ -75,7 +75,7 @@ export async function createTLSSocket(options: tls.ConnectionOptions): Promise { assert(options.host, 'host is required'); if (net.isIP(options.host)) { - const socket = tls.connect(options) + const socket = tls.connect(options); socket.on('secureConnect', () => resolve(socket)); socket.on('error', error => reject(error)); } else { @@ -92,20 +92,20 @@ export async function createTLSSocket(options: tls.ConnectionOptions): Promise void) | undefined, + options: http.ClientRequestArgs, + oncreate: ((err: Error | null, socket?: tls.TLSSocket) => void) | undefined, useTLS: true ): Promise; export async function createConnectionAsync( - options: http.ClientRequestArgs, - oncreate: ((err: Error | null, socket?: net.Socket) => void) | undefined, + options: http.ClientRequestArgs, + oncreate: ((err: Error | null, socket?: net.Socket) => void) | undefined, useTLS: false ): Promise; export async function createConnectionAsync( - options: http.ClientRequestArgs, - oncreate: ((err: Error | null, socket?: any) => void) | undefined, + options: http.ClientRequestArgs, + oncreate: ((err: Error | null, socket?: any) => void) | undefined, useTLS: boolean ): Promise { const lookup = (options as any).__testHookLookup || lookupAddresses; @@ -202,5 +202,5 @@ export function timingForSocket(socket: net.Socket | tls.TLSSocket) { return { dnsLookupAt: (socket as any)[kDNSLookupAt] as number | undefined, tcpConnectionAt: (socket as any)[kTCPConnectionAt] as number | undefined, - } + }; } diff --git a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts index 56252d02d3dd1..930abaaba6e00 100644 --- a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts +++ b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts @@ -163,7 +163,7 @@ function innerAsLocators(factory: LocatorFactory, parsed: ParsedSelector, isFram continue; } - let locatorType: LocatorType = 'default'; + const locatorType: LocatorType = 'default'; const nextPart = parts[index + 1]; diff --git a/packages/playwright-core/src/utils/network.ts b/packages/playwright-core/src/utils/network.ts index 632c74fe3a19d..25d3a111563af 100644 --- a/packages/playwright-core/src/utils/network.ts +++ b/packages/playwright-core/src/utils/network.ts @@ -124,7 +124,7 @@ export function createHttpsServer(...args: any[]): https.Server { return server; } -export function createHttp2Server( onRequestHandler?: (request: http2.Http2ServerRequest, response: http2.Http2ServerResponse) => void,): http2.Http2SecureServer; +export function createHttp2Server(onRequestHandler?: (request: http2.Http2ServerRequest, response: http2.Http2ServerResponse) => void,): http2.Http2SecureServer; export function createHttp2Server(options: http2.SecureServerOptions, onRequestHandler?: (request: http2.Http2ServerRequest, response: http2.Http2ServerResponse) => void,): http2.Http2SecureServer; export function createHttp2Server(...args: any[]): http2.Http2SecureServer { const server = http2.createSecureServer(...args); diff --git a/packages/playwright-core/src/utils/sequence.ts b/packages/playwright-core/src/utils/sequence.ts index 2af5429bd6539..27756fabeb06c 100644 --- a/packages/playwright-core/src/utils/sequence.ts +++ b/packages/playwright-core/src/utils/sequence.ts @@ -20,10 +20,13 @@ export function findRepeatedSubsequences(s: string[]): { sequence: string[]; cou let i = 0; const arraysEqual = (a1: string[], a2: string[]) => { - if (a1.length !== a2.length) return false; + if (a1.length !== a2.length) + return false; for (let j = 0; j < a1.length; j++) { - if (a1[j] !== a2[j]) return false; + if (a1[j] !== a2[j]) + return false; } + return true; }; @@ -41,9 +44,9 @@ export function findRepeatedSubsequences(s: string[]): { sequence: string[]; cou while ( i + p * k <= n && arraysEqual(s.slice(i + p * (k - 1), i + p * k), substr) - ) { + ) k += 1; - } + k -= 1; // Adjust k since it increments one extra time in the loop // Update the maximal repeating substring if necessary diff --git a/packages/playwright-core/src/utils/stackTrace.ts b/packages/playwright-core/src/utils/stackTrace.ts index 6f9a87578b54b..84d08b0184e26 100644 --- a/packages/playwright-core/src/utils/stackTrace.ts +++ b/packages/playwright-core/src/utils/stackTrace.ts @@ -16,7 +16,6 @@ import path from 'path'; import { parseStackTraceLine } from '../utilsBundle'; -import { isUnderTest } from './'; import type { StackFrame } from '@protocol/channels'; import { colors } from '../utilsBundle'; import { findRepeatedSubsequences } from './sequence'; @@ -51,7 +50,6 @@ export function captureRawStack(): RawStack { export function captureLibraryStackTrace(): { frames: StackFrame[], apiName: string } { const stack = captureRawStack(); - const isTesting = isUnderTest(); type ParsedFrame = { frame: StackFrame; frameText: string; diff --git a/packages/playwright-core/src/utils/zones.ts b/packages/playwright-core/src/utils/zones.ts index 68cb6fa7fa74c..e6fabac0f1555 100644 --- a/packages/playwright-core/src/utils/zones.ts +++ b/packages/playwright-core/src/utils/zones.ts @@ -46,8 +46,9 @@ class ZoneManager { if (zone.type === 'apiZone') str += `(${(zone.data as any).apiName})`; zones.push(str); - + } + // eslint-disable-next-line no-console console.log('zones: ', zones.join(' -> ')); } } From b194d6a1e9762502dd39a04c84b6e209af444394 Mon Sep 17 00:00:00 2001 From: Rui Figueira Date: Tue, 22 Oct 2024 11:44:18 +0100 Subject: [PATCH 345/805] fix(recorder): fix recorder injected icons (#33198) --- .../src/server/injected/highlight.ts | 2 +- .../src/server/injected/recorder/recorder.ts | 2 +- tests/library/inspector/cli-codegen-3.spec.ts | 13 +++++++++++++ tests/library/inspector/inspectorTest.ts | 7 ++++--- tests/library/trace-viewer.spec.ts | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/playwright-core/src/server/injected/highlight.ts b/packages/playwright-core/src/server/injected/highlight.ts index c89df54a6fec2..c06e58f5291c2 100644 --- a/packages/playwright-core/src/server/injected/highlight.ts +++ b/packages/playwright-core/src/server/injected/highlight.ts @@ -287,7 +287,7 @@ export class Highlight { return this._injectedScript.document.createElement('x-pw-highlight'); } - appendChild(element: HTMLElement) { + appendChild(element: Element) { this._glassPaneShadow.appendChild(element); } } diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index c82f55c984487..7c38c6386e88d 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -825,7 +825,6 @@ class Overlay { this._recorder = recorder; const document = this._recorder.document; this._overlayElement = document.createElement('x-pw-overlay'); - this._overlayElement.appendChild(createSvgElement(this._recorder.document, clipPaths)); const toolsListElement = document.createElement('x-pw-tools-list'); this._overlayElement.appendChild(toolsListElement); @@ -1094,6 +1093,7 @@ export class Recorder { recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500); this._listeners.push(() => clearInterval(recreationInterval)); + this.highlight.appendChild(createSvgElement(this.document, clipPaths)); this.overlay?.install(); this.document.adoptedStyleSheets.push(this._stylesheet); } diff --git a/tests/library/inspector/cli-codegen-3.spec.ts b/tests/library/inspector/cli-codegen-3.spec.ts index ddc44914b9dc1..a57e7d5405429 100644 --- a/tests/library/inspector/cli-codegen-3.spec.ts +++ b/tests/library/inspector/cli-codegen-3.spec.ts @@ -810,6 +810,19 @@ await page.GetByLabel("Coun\\"try").ClickAsync();`); await expect(recorder.page.getByText('Post-Hydration Content')).toBeVisible(); await expect(recorder.page.locator('x-pw-glass')).toBeVisible(); }); + + test('should display inline svg icons on text assertion dialog inside iframe', async ({ openRecorder, server }) => { + const { page, recorder } = await openRecorder(); + await recorder.page.click('x-pw-tool-item.text'); + + const { frameHello1 } = await createFrameHierarchy(page, recorder, server); + await recorder.trustedMove(frameHello1.locator('div')); + await recorder.trustedClick(); + + const glassPane = frameHello1.locator('x-pw-glass'); + await expect(glassPane.locator('> x-pw-dialog .accept > x-div').evaluate(elem => getComputedStyle(elem).clipPath)).resolves.toBe('url("#icon-check")'); + await expect(glassPane.locator('> svg > defs > clipPath#icon-check')).toBeAttached(); + }); }); async function createFrameHierarchy(page: Page, recorder: Recorder, server: TestServer) { diff --git a/tests/library/inspector/inspectorTest.ts b/tests/library/inspector/inspectorTest.ts index d77ad866977a8..a90f73fcdfb46 100644 --- a/tests/library/inspector/inspectorTest.ts +++ b/tests/library/inspector/inspectorTest.ts @@ -15,7 +15,7 @@ */ import { contextTest } from '../../config/browserTest'; -import type { Page } from 'playwright-core'; +import type { Locator, Page } from 'playwright-core'; import { step } from '../../config/baseTest'; import * as path from 'path'; import type { Source } from '../../../packages/recorder/src/recorderTypes'; @@ -209,8 +209,9 @@ export class Recorder { }); } - async trustedMove(selector: string) { - const box = await this.page.locator(selector).first().boundingBox(); + async trustedMove(selector: string | Locator) { + const locator = typeof selector === 'string' ? this.page.locator(selector).first() : selector; + const box = await locator.boundingBox(); await this.page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); } diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 0eda4b092a111..aa794eb7166c4 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -431,7 +431,7 @@ test('should capture data-url svg iframe', async ({ page, server, runAndTrace }) // Render snapshot, check expectations. const snapshotFrame = await traceViewer.snapshotFrame('page.evaluate', 0, true); - await expect(snapshotFrame.frameLocator('iframe').locator('svg')).toBeVisible(); + await expect(snapshotFrame.frameLocator('iframe').locator('> body > svg')).toBeVisible(); const content = await snapshotFrame.frameLocator('iframe').locator(':root').innerHTML(); expect(content).toContain(`d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"`); }); From ef84051c919577fcb4b0f4084de24e16176fb9cf Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 22 Oct 2024 14:12:25 +0200 Subject: [PATCH 346/805] feat(tracing): clip `canvas` contents from screenshots (#33119) --- .../server/trace/test/inMemorySnapshotter.ts | 2 +- packages/trace-viewer/src/sw/main.ts | 7 ++ .../trace-viewer/src/sw/snapshotRenderer.ts | 99 ++++++++++++++++++- .../trace-viewer/src/sw/snapshotServer.ts | 9 ++ .../trace-viewer/src/sw/snapshotStorage.ts | 5 +- .../trace-viewer/src/sw/traceModernizer.ts | 2 +- packages/trace-viewer/src/ui/snapshotTab.tsx | 4 + tests/assets/screenshots/canvas.html | 3 + tests/library/trace-viewer.spec.ts | 27 +++++ 9 files changed, 152 insertions(+), 6 deletions(-) diff --git a/packages/playwright-core/src/server/trace/test/inMemorySnapshotter.ts b/packages/playwright-core/src/server/trace/test/inMemorySnapshotter.ts index f28c5ef03b360..8de07c2aad19e 100644 --- a/packages/playwright-core/src/server/trace/test/inMemorySnapshotter.ts +++ b/packages/playwright-core/src/server/trace/test/inMemorySnapshotter.ts @@ -85,7 +85,7 @@ export class InMemorySnapshotter implements SnapshotterDelegate, HarTracerDelega onFrameSnapshot(snapshot: FrameSnapshot): void { ++this._snapshotCount; - const renderer = this._storage.addFrameSnapshot(snapshot); + const renderer = this._storage.addFrameSnapshot(snapshot, []); this._snapshotReadyPromises.get(snapshot.snapshotName || '')?.resolve(renderer); } diff --git a/packages/trace-viewer/src/sw/main.ts b/packages/trace-viewer/src/sw/main.ts index 7888aa6a308e6..6773b9fb76460 100644 --- a/packages/trace-viewer/src/sw/main.ts +++ b/packages/trace-viewer/src/sw/main.ts @@ -129,6 +129,13 @@ async function doFetch(event: FetchEvent): Promise { return response; } + if (relativePath.startsWith('/closest-screenshot/')) { + const { snapshotServer } = loadedTraces.get(traceUrl!) || {}; + if (!snapshotServer) + return new Response(null, { status: 404 }); + return snapshotServer.serveClosestScreenshot(relativePath, url.searchParams); + } + if (relativePath.startsWith('/sha1/')) { // Sha1 for sources is based on the file path, can't load it of a random model. const sha1 = relativePath.slice('/sha1/'.length); diff --git a/packages/trace-viewer/src/sw/snapshotRenderer.ts b/packages/trace-viewer/src/sw/snapshotRenderer.ts index 0d2f2af502655..438683ed84976 100644 --- a/packages/trace-viewer/src/sw/snapshotRenderer.ts +++ b/packages/trace-viewer/src/sw/snapshotRenderer.ts @@ -16,6 +16,16 @@ import { escapeHTMLAttribute, escapeHTML } from '@isomorphic/stringUtils'; import type { FrameSnapshot, NodeNameAttributesChildNodesSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot, SubtreeReferenceSnapshot } from '@trace/snapshot'; +import type { PageEntry } from '../types/entries'; + +function findClosest(items: T[], metric: (v: T) => number, target: number) { + return items.find((item, index) => { + if (index === items.length - 1) + return true; + const next = items[index + 1]; + return Math.abs(metric(item) - target) < Math.abs(metric(next) - target); + }); +} function isNodeNameAttributesChildNodesSnapshot(n: NodeSnapshot): n is NodeNameAttributesChildNodesSnapshot { return Array.isArray(n) && typeof n[0] === 'string'; @@ -60,13 +70,15 @@ export class SnapshotRenderer { private _resources: ResourceSnapshot[]; private _snapshot: FrameSnapshot; private _callId: string; + private _screencastFrames: PageEntry['screencastFrames']; - constructor(resources: ResourceSnapshot[], snapshots: FrameSnapshot[], index: number) { + constructor(resources: ResourceSnapshot[], snapshots: FrameSnapshot[], screencastFrames: PageEntry['screencastFrames'], index: number) { this._resources = resources; this._snapshots = snapshots; this._index = index; this._snapshot = snapshots[index]; this._callId = snapshots[index].callId; + this._screencastFrames = screencastFrames; this.snapshotName = snapshots[index].snapshotName; } @@ -78,6 +90,14 @@ export class SnapshotRenderer { return this._snapshots[this._index].viewport; } + closestScreenshot(): string | undefined { + const { wallTime, timestamp } = this.snapshot(); + const closestFrame = (wallTime && this._screencastFrames[0]?.frameSwapWallTime) + ? findClosest(this._screencastFrames, frame => frame.frameSwapWallTime!, wallTime) + : findClosest(this._screencastFrames, frame => frame.timestamp, timestamp); + return closestFrame?.sha1; + } + render(): RenderedFrameSnapshot { const result: string[] = []; const visit = (n: NodeSnapshot, snapshotIndex: number, parentTag: string | undefined, parentAttrs: [string, string][] | undefined) => { @@ -244,6 +264,8 @@ function snapshotNodes(snapshot: FrameSnapshot): NodeSnapshot[] { function snapshotScript(...targetIds: (string | undefined)[]) { function applyPlaywrightAttributes(unwrapPopoutUrl: (url: string) => string, ...targetIds: (string | undefined)[]) { + const isUnderTest = new URLSearchParams(location.search).has('isUnderTest'); + const kPointerWarningTitle = 'Recorded click position in absolute coordinates did not' + ' match the center of the clicked element. This is likely due to a difference between' + ' the test runner and the trace viewer operating systems.'; @@ -251,6 +273,7 @@ function snapshotScript(...targetIds: (string | undefined)[]) { const scrollTops: Element[] = []; const scrollLefts: Element[] = []; const targetElements: Element[] = []; + const canvasElements: HTMLCanvasElement[] = []; const visit = (root: Document | ShadowRoot) => { // Collect all scrolled elements for later use. @@ -326,6 +349,8 @@ function snapshotScript(...targetIds: (string | undefined)[]) { } (root as any).adoptedStyleSheets = adoptedSheets; } + + canvasElements.push(...root.querySelectorAll('canvas')); }; const onLoad = () => { @@ -342,12 +367,12 @@ function snapshotScript(...targetIds: (string | undefined)[]) { document.styleSheets[0].disabled = true; const search = new URL(window.location.href).searchParams; + const isTopFrame = window.location.pathname.match(/\/page@[a-z0-9]+$/); if (search.get('pointX') && search.get('pointY')) { const pointX = +search.get('pointX')!; const pointY = +search.get('pointY')!; const hasInputTarget = search.has('hasInputTarget'); - const isTopFrame = window.location.pathname.match(/\/page@[a-z0-9]+$/); const hasTargetElements = targetElements.length > 0; const roots = document.documentElement ? [document.documentElement] : []; for (const target of (hasTargetElements ? targetElements : roots)) { @@ -393,6 +418,76 @@ function snapshotScript(...targetIds: (string | undefined)[]) { } } } + + if (canvasElements.length > 0) { + function drawCheckerboard(context: CanvasRenderingContext2D, canvas: HTMLCanvasElement) { + function createCheckerboardPattern() { + const pattern = document.createElement('canvas'); + pattern.width = pattern.width / Math.floor(pattern.width / 24); + pattern.height = pattern.height / Math.floor(pattern.height / 24); + const context = pattern.getContext('2d')!; + context.fillStyle = 'lightgray'; + context.fillRect(0, 0, pattern.width, pattern.height); + context.fillStyle = 'white'; + context.fillRect(0, 0, pattern.width / 2, pattern.height / 2); + context.fillRect(pattern.width / 2, pattern.height / 2, pattern.width, pattern.height); + return context.createPattern(pattern, 'repeat')!; + } + + context.fillStyle = createCheckerboardPattern(); + context.fillRect(0, 0, canvas.width, canvas.height); + } + + + if (!isTopFrame) { + for (const canvas of canvasElements) { + const context = canvas.getContext('2d')!; + drawCheckerboard(context, canvas); + canvas.title = `Playwright displays canvas contents on a best-effort basis. It doesn't support canvas elements inside an iframe yet. If this impacts your workflow, please open an issue so we can prioritize.`; + } + return; + } + + const img = new Image(); + img.onload = () => { + for (const canvas of canvasElements) { + const context = canvas.getContext('2d')!; + + const boundingRect = canvas.getBoundingClientRect(); + const xStart = boundingRect.left / window.innerWidth; + const yStart = boundingRect.top / window.innerHeight; + const xEnd = boundingRect.right / window.innerWidth; + const yEnd = boundingRect.bottom / window.innerHeight; + + const partiallyUncaptured = xEnd > 1 || yEnd > 1; + const fullyUncaptured = xStart > 1 || yStart > 1; + if (fullyUncaptured) { + canvas.title = `Playwright couldn't capture canvas contents because it's located outside the viewport.`; + continue; + } + + drawCheckerboard(context, canvas); + + context.drawImage(img, xStart * img.width, yStart * img.height, (xEnd - xStart) * img.width, (yEnd - yStart) * img.height, 0, 0, canvas.width, canvas.height); + if (isUnderTest) + // eslint-disable-next-line no-console + console.log(`canvas drawn:`, JSON.stringify([xStart, yStart, xEnd, yEnd].map(v => Math.floor(v * 100)))); + + if (partiallyUncaptured) + canvas.title = `Playwright couldn't capture full canvas contents because it's located partially outside the viewport.`; + else + canvas.title = `Canvas contents are displayed on a best-effort basis based on viewport screenshots taken during test execution.`; + } + }; + img.onerror = () => { + for (const canvas of canvasElements) { + const context = canvas.getContext('2d')!; + drawCheckerboard(context, canvas); + canvas.title = `Playwright couldn't show canvas contents because the screenshot failed to load.`; + } + }; + img.src = location.href.replace('/snapshot', '/closest-screenshot'); + } }; const onDOMContentLoaded = () => visit(document); diff --git a/packages/trace-viewer/src/sw/snapshotServer.ts b/packages/trace-viewer/src/sw/snapshotServer.ts index 4b61104d33cd2..e1978c79b62e0 100644 --- a/packages/trace-viewer/src/sw/snapshotServer.ts +++ b/packages/trace-viewer/src/sw/snapshotServer.ts @@ -35,11 +35,20 @@ export class SnapshotServer { const snapshot = this._snapshot(pathname.substring('/snapshot'.length), searchParams); if (!snapshot) return new Response(null, { status: 404 }); + const renderedSnapshot = snapshot.render(); this._snapshotIds.set(snapshotUrl, snapshot); return new Response(renderedSnapshot.html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } }); } + async serveClosestScreenshot(pathname: string, searchParams: URLSearchParams): Promise { + const snapshot = this._snapshot(pathname.substring('/closest-screenshot'.length), searchParams); + const sha1 = snapshot?.closestScreenshot(); + if (!sha1) + return new Response(null, { status: 404 }); + return new Response(await this._resourceLoader(sha1)); + } + serveSnapshotInfo(pathname: string, searchParams: URLSearchParams): Response { const snapshot = this._snapshot(pathname.substring('/snapshotInfo'.length), searchParams); return this._respondWithJson(snapshot ? { diff --git a/packages/trace-viewer/src/sw/snapshotStorage.ts b/packages/trace-viewer/src/sw/snapshotStorage.ts index 9f4aea60c2a53..5e10fc97fbcd6 100644 --- a/packages/trace-viewer/src/sw/snapshotStorage.ts +++ b/packages/trace-viewer/src/sw/snapshotStorage.ts @@ -16,6 +16,7 @@ import type { FrameSnapshot, ResourceSnapshot } from '@trace/snapshot'; import { rewriteURLForCustomProtocol, SnapshotRenderer } from './snapshotRenderer'; +import type { PageEntry } from '../types/entries'; export class SnapshotStorage { private _resources: ResourceSnapshot[] = []; @@ -29,7 +30,7 @@ export class SnapshotStorage { this._resources.push(resource); } - addFrameSnapshot(snapshot: FrameSnapshot) { + addFrameSnapshot(snapshot: FrameSnapshot, screencastFrames: PageEntry['screencastFrames']) { for (const override of snapshot.resourceOverrides) override.url = rewriteURLForCustomProtocol(override.url); let frameSnapshots = this._frameSnapshots.get(snapshot.frameId); @@ -43,7 +44,7 @@ export class SnapshotStorage { this._frameSnapshots.set(snapshot.pageId, frameSnapshots); } frameSnapshots.raw.push(snapshot); - const renderer = new SnapshotRenderer(this._resources, frameSnapshots.raw, frameSnapshots.raw.length - 1); + const renderer = new SnapshotRenderer(this._resources, frameSnapshots.raw, screencastFrames, frameSnapshots.raw.length - 1); frameSnapshots.renderers.push(renderer); return renderer; } diff --git a/packages/trace-viewer/src/sw/traceModernizer.ts b/packages/trace-viewer/src/sw/traceModernizer.ts index 69d7f965dc3d1..80f98762dbe46 100644 --- a/packages/trace-viewer/src/sw/traceModernizer.ts +++ b/packages/trace-viewer/src/sw/traceModernizer.ts @@ -159,7 +159,7 @@ export class TraceModernizer { contextEntry.resources.push(event.snapshot); break; case 'frame-snapshot': - this._snapshotStorage.addFrameSnapshot(event.snapshot); + this._snapshotStorage.addFrameSnapshot(event.snapshot, this._pageEntry(event.snapshot.pageId).screencastFrames); break; } // Make sure there is a page entry for each page, even without screencast frames, diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 82e4282c6fdd1..f8bcc3a5a33fd 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -369,10 +369,14 @@ export function collectSnapshots(action: ActionTraceEvent | undefined): Snapshot return { action: actionSnapshot, before: beforeSnapshot, after: afterSnapshot }; } +const isUnderTest = new URLSearchParams(window.location.search).has('isUnderTest'); + export function extendSnapshot(snapshot: Snapshot): SnapshotUrls { const params = new URLSearchParams(); params.set('trace', context(snapshot.action).traceUrl); params.set('name', snapshot.snapshotName); + if (isUnderTest) + params.set('isUnderTest', 'true'); if (snapshot.point) { params.set('pointX', String(snapshot.point.x)); params.set('pointY', String(snapshot.point.y)); diff --git a/tests/assets/screenshots/canvas.html b/tests/assets/screenshots/canvas.html index 011148c5fff15..a0ebc55829002 100644 --- a/tests/assets/screenshots/canvas.html +++ b/tests/assets/screenshots/canvas.html @@ -7,4 +7,7 @@ ctx.fillRect(25, 25, 100, 100); ctx.clearRect(45, 45, 60, 60); ctx.strokeRect(50, 50, 50, 50); + + if (location.hash.includes('canvas-on-edge')) + canvas.style.marginTop = '90vh'; diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index aa794eb7166c4..0ae5716e2f4fa 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -21,6 +21,7 @@ import path from 'path'; import { pathToFileURL } from 'url'; import { expect, playwrightTest } from '../config/browserTest'; import type { FrameLocator } from '@playwright/test'; +import { rafraf } from 'tests/page/pageTest'; const test = playwrightTest.extend(traceViewerFixtures); @@ -1439,6 +1440,32 @@ test.skip('should allow showing screenshots instead of snapshots', async ({ runA await expect(screenshot).toBeVisible(); }); +test('canvas clipping', async ({ runAndTrace, page, server }) => { + const traceViewer = await runAndTrace(async () => { + await page.goto(server.PREFIX + '/screenshots/canvas.html#canvas-on-edge'); + await rafraf(page, 5); + }); + + const msg = await traceViewer.page.waitForEvent('console', { predicate: msg => msg.text().startsWith('canvas drawn:') }); + expect(msg.text()).toEqual('canvas drawn: [0,91,12,111]'); + + const snapshot = await traceViewer.snapshotFrame('page.goto'); + await expect(snapshot.locator('canvas')).toHaveAttribute('title', `Playwright couldn't capture full canvas contents because it's located partially outside the viewport.`); +}); + +test('canvas clipping in iframe', async ({ runAndTrace, page, server }) => { + const traceViewer = await runAndTrace(async () => { + await page.setContent(` + + `); + await rafraf(page, 5); + }); + + const snapshot = await traceViewer.snapshotFrame('page.evaluate'); + const canvas = snapshot.locator('iframe').contentFrame().locator('canvas'); + await expect(canvas).toHaveAttribute('title', `Playwright displays canvas contents on a best-effort basis. It doesn't support canvas elements inside an iframe yet. If this impacts your workflow, please open an issue so we can prioritize.`); +}); + test.skip('should handle case where neither snapshots nor screenshots exist', async ({ runAndTrace, page, server }) => { const traceViewer = await runAndTrace(async () => { await page.goto(server.PREFIX + '/one-style.html'); From 131f8b39c36f81cf646eba7cdb8c18757ccaab54 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 22 Oct 2024 14:25:23 +0200 Subject: [PATCH 347/805] docs(vscode): outline more that global teardown needs to be executed manually (#33221) --- docs/src/getting-started-vscode-js.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/getting-started-vscode-js.md b/docs/src/getting-started-vscode-js.md index d8a2ccfcf3fd6..03e29ff2e9660 100644 --- a/docs/src/getting-started-vscode-js.md +++ b/docs/src/getting-started-vscode-js.md @@ -202,7 +202,7 @@ To run the **setup** test only once, deselect it from the projects section in th ## Global Setup -**Global setup** tests are run when you execute your first test. This runs only once and is useful for setting up a database or starting a server. You can manually run a **global setup** test by clicking the `Run global setup` option from the **Setup** section in the Playwright sidebar. You can also run **global teardown** tests by clicking the `Run global teardown` option. +**Global setup** runs when you execute your first test. It runs only once and is useful for setting up a database or starting a server. You can manually run **global setup** by clicking the `Run global setup` option from the **Setup** section in the Playwright sidebar. **Global teardown** does not run by default; you need to manually initiate it by clicking the `Run global teardown` option. Global setup will re-run when you debug tests as this ensures an isolated environment and dedicated setup for the test. From c8431ca1228634c8ee7410c9812b364c82038268 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Tue, 22 Oct 2024 06:47:17 -0700 Subject: [PATCH 348/805] feat(chromium-tip-of-tree): roll to r1271 (#33224) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- packages/playwright-core/browsers.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index b808a2fe5e8ce..4e2285d3ebb84 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -9,9 +9,9 @@ }, { "name": "chromium-tip-of-tree", - "revision": "1269", + "revision": "1271", "installByDefault": false, - "browserVersion": "131.0.6778.0" + "browserVersion": "132.0.6791.0" }, { "name": "firefox", From 29ca54eb388ba53b7e85bdaddabd15cf33f2d6d4 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 22 Oct 2024 15:47:50 +0200 Subject: [PATCH 349/805] chore: add headless shell builds (#33222) --- .../src/server/registry/index.ts | 78 ++++++++++++++++--- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index 7778d812189e6..faadda45ee353 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -56,6 +56,11 @@ const EXECUTABLE_PATHS = { 'mac': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'], 'win': ['chrome-win', 'chrome.exe'], }, + 'chromium-headless-shell': { + 'linux': ['chrome-linux', 'headless_shell'], + 'mac': ['chrome-mac', 'headless_shell'], + 'win': ['chrome-win', 'headless_shell.exe'], + }, 'firefox': { 'linux': ['firefox', 'firefox'], 'mac': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'], @@ -104,6 +109,35 @@ const DOWNLOAD_PATHS: Record = { 'mac15-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip', 'win64': 'builds/chromium/%s/chromium-win64.zip', }, + 'chromium-headless-shell': { + '': undefined, + 'ubuntu18.04-x64': undefined, + 'ubuntu20.04-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip', + 'ubuntu22.04-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip', + 'ubuntu24.04-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip', + 'ubuntu18.04-arm64': undefined, + 'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip', + 'ubuntu22.04-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip', + 'ubuntu24.04-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip', + 'debian11-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip', + 'debian11-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip', + 'debian12-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip', + 'debian12-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip', + 'mac10.13': undefined, + 'mac10.14': undefined, + 'mac10.15': undefined, + 'mac11': 'builds/chromium/%s/chromium-headless-shell-mac.zip', + 'mac11-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip', + 'mac12': 'builds/chromium/%s/chromium-headless-shell-mac.zip', + 'mac12-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip', + 'mac13': 'builds/chromium/%s/chromium-headless-shell-mac.zip', + 'mac13-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip', + 'mac14': 'builds/chromium/%s/chromium-headless-shell-mac.zip', + 'mac14-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip', + 'mac15': 'builds/chromium/%s/chromium-headless-shell-mac.zip', + 'mac15-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip', + 'win64': 'builds/chromium/%s/chromium-headless-shell-win64.zip', + }, 'chromium-tip-of-tree': { '': undefined, 'ubuntu18.04-x64': undefined, @@ -343,7 +377,7 @@ type BrowsersJSONDescriptor = { dir: string, }; -function readDescriptors(browsersJSON: BrowsersJSON) { +function readDescriptors(browsersJSON: BrowsersJSON): BrowsersJSONDescriptor[] { return (browsersJSON['browsers']).map(obj => { const name = obj.name; const revisionOverride = (obj.revisionOverrides || {})[hostPlatform]; @@ -367,10 +401,10 @@ function readDescriptors(browsersJSON: BrowsersJSON) { } export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi'; -type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'android'; +type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'chromium-headless-shell' |'android'; type BidiChannel = 'bidi-firefox-stable' | 'bidi-firefox-beta' | 'bidi-firefox-nightly' | 'bidi-chrome-canary' | 'bidi-chrome-stable' | 'bidi-chromium'; type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; -const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree']; +const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell']; export interface Executable { type: 'browser' | 'tool' | 'channel'; @@ -445,7 +479,7 @@ export class Registry { executablePath: () => chromiumExecutable, executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage), installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']), + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromium.dir, ['chrome-linux'], [], ['chrome-win']), downloadURLs: this._downloadURLs(chromium), browserVersion: chromium.browserVersion, _install: () => this._downloadExecutable(chromium, chromiumExecutable), @@ -453,6 +487,30 @@ export class Registry { _isHermeticInstallation: true, }); + const chromiumHeadlessShellDescriptor: BrowsersJSONDescriptor = { + name: 'chromium-headless-shell', + revision: chromium.revision, + browserVersion: chromium.browserVersion, + dir: chromium.dir.replace(/(.*)(-\d+)$/, '$1-headless-shell$2'), + installByDefault: false + }; + const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShellDescriptor.dir, 'chromium-headless-shell'); + this._executables.push({ + type: 'tool', + name: 'chromium-headless-shell', + browserName: 'chromium', + directory: chromiumHeadlessShellDescriptor.dir, + executablePath: () => chromiumHeadlessShellExecutable, + executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-headless-shell', chromiumHeadlessShellExecutable, false, sdkLanguage), + installType: 'download-on-demand', + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShellDescriptor.dir, ['chrome-linux'], [], ['chrome-win']), + downloadURLs: this._downloadURLs(chromiumHeadlessShellDescriptor), + browserVersion: chromium.browserVersion, + _install: () => this._downloadExecutable(chromiumHeadlessShellDescriptor, chromiumHeadlessShellExecutable), + _dependencyGroup: 'chromium', + _isHermeticInstallation: true, + }); + const chromiumTipOfTree = descriptors.find(d => d.name === 'chromium-tip-of-tree')!; const chromiumTipOfTreeExecutable = findExecutablePath(chromiumTipOfTree.dir, 'chromium'); this._executables.push({ @@ -463,7 +521,7 @@ export class Registry { executablePath: () => chromiumTipOfTreeExecutable, executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium-tip-of-tree', chromiumTipOfTreeExecutable, chromiumTipOfTree.installByDefault, sdkLanguage), installType: chromiumTipOfTree.installByDefault ? 'download-by-default' : 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumTipOfTree.dir, ['chrome-linux'], [], ['chrome-win']), + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromiumTipOfTree.dir, ['chrome-linux'], [], ['chrome-win']), downloadURLs: this._downloadURLs(chromiumTipOfTree), browserVersion: chromiumTipOfTree.browserVersion, _install: () => this._downloadExecutable(chromiumTipOfTree, chromiumTipOfTreeExecutable), @@ -573,7 +631,7 @@ export class Registry { executablePath: () => chromiumExecutable, executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage), installType: 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']), + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, chromium.dir, ['chrome-linux'], [], ['chrome-win']), downloadURLs: this._downloadURLs(chromium), browserVersion: chromium.browserVersion, _install: () => this._downloadExecutable(chromium, chromiumExecutable), @@ -591,7 +649,7 @@ export class Registry { executablePath: () => firefoxExecutable, executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage), installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']), + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, firefox.dir, ['firefox'], [], ['firefox']), downloadURLs: this._downloadURLs(firefox), browserVersion: firefox.browserVersion, _install: () => this._downloadExecutable(firefox, firefoxExecutable), @@ -609,7 +667,7 @@ export class Registry { executablePath: () => firefoxBetaExecutable, executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage), installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']), + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, firefoxBeta.dir, ['firefox'], [], ['firefox']), downloadURLs: this._downloadURLs(firefoxBeta), browserVersion: firefoxBeta.browserVersion, _install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable), @@ -637,7 +695,7 @@ export class Registry { executablePath: () => webkitExecutable, executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage), installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand', - _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']), + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']), downloadURLs: this._downloadURLs(webkit), browserVersion: webkit.browserVersion, _install: () => this._downloadExecutable(webkit, webkitExecutable), @@ -835,7 +893,7 @@ export class Registry { return Array.from(set); } - private async _validateHostRequirements(sdkLanguage: string, browserName: BrowserName, browserDirectory: string, linuxLddDirectories: string[], dlOpenLibraries: string[], windowsExeAndDllDirectories: string[]) { + private async _validateHostRequirements(sdkLanguage: string, browserDirectory: string, linuxLddDirectories: string[], dlOpenLibraries: string[], windowsExeAndDllDirectories: string[]) { if (os.platform() === 'linux') return await validateDependenciesLinux(sdkLanguage, linuxLddDirectories.map(d => path.join(browserDirectory, d)), dlOpenLibraries); if (os.platform() === 'win32' && os.arch() === 'x64') From 8ec981c3948eb6716b3b787779f45f2267ae87c2 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Tue, 22 Oct 2024 11:45:12 -0700 Subject: [PATCH 350/805] chore: move github reporter formatting out of base (#33213) --- packages/playwright/src/reporters/base.ts | 106 +++++++------------- packages/playwright/src/reporters/github.ts | 33 +++--- packages/playwright/src/reporters/junit.ts | 2 +- packages/playwright/src/reporters/line.ts | 4 +- 4 files changed, 58 insertions(+), 87 deletions(-) diff --git a/packages/playwright/src/reporters/base.ts b/packages/playwright/src/reporters/base.ts index 138820baee6f9..66f78bfdc96d7 100644 --- a/packages/playwright/src/reporters/base.ts +++ b/packages/playwright/src/reporters/base.ts @@ -23,12 +23,6 @@ import { resolveReporterOutputPath } from '../util'; export type TestResultOutput = { chunk: string | Buffer, type: 'stdout' | 'stderr' }; export const kOutputSymbol = Symbol('output'); -type Annotation = { - title: string; - message: string; - location?: Location; -}; - type ErrorDetails = { message: string; location?: Location; @@ -260,9 +254,7 @@ export class BaseReporter implements ReporterV2 { private _printFailures(failures: TestCase[]) { console.log(''); failures.forEach((test, index) => { - console.log(formatFailure(this.config, test, { - index: index + 1, - }).message); + console.log(formatFailure(this.config, test, index + 1)); }); } @@ -285,14 +277,8 @@ export class BaseReporter implements ReporterV2 { } } -export function formatFailure(config: FullConfig, test: TestCase, options: {index?: number, includeStdio?: boolean, includeAttachments?: boolean} = {}): { - message: string, - annotations: Annotation[] -} { - const { index, includeStdio, includeAttachments = true } = options; +export function formatFailure(config: FullConfig, test: TestCase, index?: number): string { const lines: string[] = []; - const title = formatTestTitle(config, test); - const annotations: Annotation[] = []; const header = formatTestHeader(config, test, { indent: ' ', index, mode: 'error' }); lines.push(colors.red(header)); for (const result of test.results) { @@ -307,62 +293,48 @@ export function formatFailure(config: FullConfig, test: TestCase, options: {inde } resultLines.push(...retryLines); resultLines.push(...errors.map(error => '\n' + error.message)); - if (includeAttachments) { - for (let i = 0; i < result.attachments.length; ++i) { - const attachment = result.attachments[i]; - const hasPrintableContent = attachment.contentType.startsWith('text/'); - if (!attachment.path && !hasPrintableContent) - continue; - resultLines.push(''); - resultLines.push(colors.cyan(separator(` attachment #${i + 1}: ${attachment.name} (${attachment.contentType})`))); - if (attachment.path) { - const relativePath = path.relative(process.cwd(), attachment.path); - resultLines.push(colors.cyan(` ${relativePath}`)); - // Make this extensible - if (attachment.name === 'trace') { - const packageManagerCommand = getPackageManagerExecCommand(); - resultLines.push(colors.cyan(` Usage:`)); - resultLines.push(''); - resultLines.push(colors.cyan(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`)); - resultLines.push(''); - } - } else { - if (attachment.contentType.startsWith('text/') && attachment.body) { - let text = attachment.body.toString(); - if (text.length > 300) - text = text.slice(0, 300) + '...'; - for (const line of text.split('\n')) - resultLines.push(colors.cyan(` ${line}`)); - } + for (let i = 0; i < result.attachments.length; ++i) { + const attachment = result.attachments[i]; + const hasPrintableContent = attachment.contentType.startsWith('text/'); + if (!attachment.path && !hasPrintableContent) + continue; + resultLines.push(''); + resultLines.push(colors.cyan(separator(` attachment #${i + 1}: ${attachment.name} (${attachment.contentType})`))); + if (attachment.path) { + const relativePath = path.relative(process.cwd(), attachment.path); + resultLines.push(colors.cyan(` ${relativePath}`)); + // Make this extensible + if (attachment.name === 'trace') { + const packageManagerCommand = getPackageManagerExecCommand(); + resultLines.push(colors.cyan(` Usage:`)); + resultLines.push(''); + resultLines.push(colors.cyan(` ${packageManagerCommand} playwright show-trace ${quotePathIfNeeded(relativePath)}`)); + resultLines.push(''); + } + } else { + if (attachment.contentType.startsWith('text/') && attachment.body) { + let text = attachment.body.toString(); + if (text.length > 300) + text = text.slice(0, 300) + '...'; + for (const line of text.split('\n')) + resultLines.push(colors.cyan(` ${line}`)); } - resultLines.push(colors.cyan(separator(' '))); } - } - const output = ((result as any)[kOutputSymbol] || []) as TestResultOutput[]; - if (includeStdio && output.length) { - const outputText = output.map(({ chunk, type }) => { - const text = chunk.toString('utf8'); - if (type === 'stderr') - return colors.red(stripAnsiEscapes(text)); - return text; - }).join(''); - resultLines.push(''); - resultLines.push(colors.gray(separator('--- Test output')) + '\n\n' + outputText + '\n' + separator()); - } - for (const error of errors) { - annotations.push({ - location: error.location, - title, - message: [header, ...retryLines, error.message].join('\n'), - }); + resultLines.push(colors.cyan(separator(' '))); } lines.push(...resultLines); } lines.push(''); - return { - message: lines.join('\n'), - annotations - }; + return lines.join('\n'); +} + +export function formatRetry(result: TestResult) { + const retryLines = []; + if (result.retry) { + retryLines.push(''); + retryLines.push(colors.gray(separator(` Retry #${result.retry}`))); + } + return retryLines; } function quotePathIfNeeded(path: string): string { @@ -428,7 +400,7 @@ export function formatTestTitle(config: FullConfig, test: TestCase, step?: TestS return `${projectTitle}${location} › ${titles.join(' › ')}${stepSuffix(step)}${tags}`; } -function formatTestHeader(config: FullConfig, test: TestCase, options: { indent?: string, index?: number, mode?: 'default' | 'error' } = {}): string { +export function formatTestHeader(config: FullConfig, test: TestCase, options: { indent?: string, index?: number, mode?: 'default' | 'error' } = {}): string { const title = formatTestTitle(config, test); const header = `${options.indent || ''}${options.index ? options.index + ') ' : ''}${title}`; let fullHeader = header; diff --git a/packages/playwright/src/reporters/github.ts b/packages/playwright/src/reporters/github.ts index dc036777141fd..c178cce64d629 100644 --- a/packages/playwright/src/reporters/github.ts +++ b/packages/playwright/src/reporters/github.ts @@ -16,7 +16,7 @@ import { ms as milliseconds } from 'playwright-core/lib/utilsBundle'; import path from 'path'; -import { BaseReporter, formatError, formatFailure, stripAnsiEscapes } from './base'; +import { BaseReporter, colors, formatError, formatResultFailure, formatRetry, formatTestHeader, formatTestTitle, stripAnsiEscapes } from './base'; import type { TestCase, FullResult, TestError } from '../../types/testReporter'; type GitHubLogType = 'debug' | 'notice' | 'warning' | 'error'; @@ -100,22 +100,23 @@ export class GitHubReporter extends BaseReporter { private _printFailureAnnotations(failures: TestCase[]) { failures.forEach((test, index) => { - const { annotations } = formatFailure(this.config, test, { - index: index + 1, - includeStdio: true, - includeAttachments: false, - }); - annotations.forEach(({ location, title, message }) => { - const options: GitHubLogOptions = { - file: workspaceRelativePath(location?.file || test.location.file), - title, - }; - if (location) { - options.line = location.line; - options.col = location.column; + const title = formatTestTitle(this.config, test); + const header = formatTestHeader(this.config, test, { indent: ' ', index: index + 1, mode: 'error' }); + for (const result of test.results) { + const errors = formatResultFailure(test, result, ' ', colors.enabled); + for (const error of errors) { + const options: GitHubLogOptions = { + file: workspaceRelativePath(error.location?.file || test.location.file), + title, + }; + if (error.location) { + options.line = error.location.line; + options.col = error.location.column; + } + const message = [header, ...formatRetry(result), error.message].join('\n'); + this.githubLogger.error(message, options); } - this.githubLogger.error(message, options); - }); + } }); } } diff --git a/packages/playwright/src/reporters/junit.ts b/packages/playwright/src/reporters/junit.ts index befd652e4b41b..f193f4f79da45 100644 --- a/packages/playwright/src/reporters/junit.ts +++ b/packages/playwright/src/reporters/junit.ts @@ -188,7 +188,7 @@ class JUnitReporter implements ReporterV2 { message: `${path.basename(test.location.file)}:${test.location.line}:${test.location.column} ${test.title}`, type: 'FAILURE', }, - text: stripAnsiEscapes(formatFailure(this.config, test).message) + text: stripAnsiEscapes(formatFailure(this.config, test)) }); } diff --git a/packages/playwright/src/reporters/line.ts b/packages/playwright/src/reporters/line.ts index af4c786e1602b..de5fc6170363c 100644 --- a/packages/playwright/src/reporters/line.ts +++ b/packages/playwright/src/reporters/line.ts @@ -82,9 +82,7 @@ class LineReporter extends BaseReporter { if (!this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected' || result.status === 'interrupted')) { if (!process.env.PW_TEST_DEBUG_REPORTERS) process.stdout.write(`\u001B[1A\u001B[2K`); - console.log(formatFailure(this.config, test, { - index: ++this._failures - }).message); + console.log(formatFailure(this.config, test, ++this._failures)); console.log(); } } From 6800fd45a2b78b4fc537e5c1a814305414ad9c65 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Tue, 22 Oct 2024 22:30:54 +0200 Subject: [PATCH 351/805] feat(webkit): roll to r2095 (#33229) --- packages/playwright-core/browsers.json | 2 +- .../playwright-core/src/server/registry/nativeDeps.ts | 8 +++++++- tests/library/capabilities.spec.ts | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 4e2285d3ebb84..6cd5bc321d200 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -27,7 +27,7 @@ }, { "name": "webkit", - "revision": "2094", + "revision": "2095", "installByDefault": true, "revisionOverrides": { "mac10.14": "1446", diff --git a/packages/playwright-core/src/server/registry/nativeDeps.ts b/packages/playwright-core/src/server/registry/nativeDeps.ts index 0f67455d267e6..d569f132586f2 100644 --- a/packages/playwright-core/src/server/registry/nativeDeps.ts +++ b/packages/playwright-core/src/server/registry/nativeDeps.ts @@ -359,8 +359,10 @@ export const deps: any = { 'libx264-163', 'libatomic1', 'libevent-2.1-7', + 'libavif13', ], lib2package: { + 'libavif.so.13': 'libavif13', 'libsoup-3.0.so.0': 'libsoup-3.0-0', 'libasound.so.2': 'libasound2', 'libatk-1.0.so.0': 'libatk1.0-0', @@ -566,9 +568,11 @@ export const deps: any = { 'libxkbcommon0', 'libxml2', 'libxslt1.1', - 'libx264-164' + 'libx264-164', + 'libavif16', ], lib2package: { + 'libavif.so.16': 'libavif16', 'libasound.so.2': 'libasound2t64', 'libatk-1.0.so.0': 'libatk1.0-0t64', 'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0t64', @@ -994,8 +998,10 @@ export const deps: any = { 'libxslt1.1', 'libatomic1', 'libevent-2.1-7', + 'libavif15', ], lib2package: { + 'libavif.so.15': 'libavif15', 'libsoup-3.0.so.0': 'libsoup-3.0-0', 'libasound.so.2': 'libasound2', 'libatk-1.0.so.0': 'libatk1.0-0', diff --git a/tests/library/capabilities.spec.ts b/tests/library/capabilities.spec.ts index 864022a1f4900..cdc97d15237d1 100644 --- a/tests/library/capabilities.spec.ts +++ b/tests/library/capabilities.spec.ts @@ -400,7 +400,7 @@ it('should be able to render avif images', { } }, async ({ page, server, browserName, platform }) => { it.fixme(browserName === 'webkit' && platform === 'win32'); - it.fixme(browserName === 'webkit' && platform === 'linux', 'https://github.com/microsoft/playwright/issues/32673'); + it.skip(browserName === 'webkit' && hostPlatform.startsWith('ubuntu20.04'), 'Ubuntu 20.04 is frozen'); await page.goto(server.EMPTY_PAGE); await page.setContent(``); await expect.poll(() => page.locator('img').boundingBox()).toEqual(expect.objectContaining({ From 6bfdad068c1c171a551540df0b7f32a16b10b26c Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 22 Oct 2024 16:36:03 -0700 Subject: [PATCH 352/805] chore: introduce accessibility tab in recorder (#33235) --- .../src/server/debugController.ts | 8 ++-- .../src/server/injected/ariaSnapshot.ts | 44 ++++--------------- .../src/server/injected/consoleApi.ts | 6 ++- .../injected/recorder/pollingRecorder.ts | 8 ++-- .../src/server/injected/recorder/recorder.ts | 18 ++++---- .../playwright-core/src/server/recorder.ts | 12 +++-- .../src/server/recorder/recorderApp.ts | 22 ++++------ .../src/server/recorder/recorderFrontend.ts | 4 +- .../server/recorder/recorderInTraceViewer.ts | 6 +-- packages/recorder/src/recorder.tsx | 25 ++++++++--- packages/recorder/src/recorderTypes.ts | 7 ++- packages/recorder/tsconfig.json | 1 + packages/trace-viewer/src/ui/snapshotTab.tsx | 5 ++- .../web/src/components/codeMirrorModule.tsx | 1 + tests/page/page-aria-snapshot.spec.ts | 26 +++++------ utils/build/build.js | 4 +- 16 files changed, 95 insertions(+), 102 deletions(-) diff --git a/packages/playwright-core/src/server/debugController.ts b/packages/playwright-core/src/server/debugController.ts index 53c6c3d99e904..a9a79a49e2cb8 100644 --- a/packages/playwright-core/src/server/debugController.ts +++ b/packages/playwright-core/src/server/debugController.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Mode, Source } from '@recorder/recorderTypes'; +import type { ElementInfo, Mode, Source } from '@recorder/recorderTypes'; import { gracefullyProcessExitDoNotHang } from '../utils/processLauncher'; import type { Browser } from './browser'; import type { BrowserContext } from './browserContext'; @@ -221,9 +221,9 @@ class InspectingRecorderApp extends EmptyRecorderApp { this._debugController = debugController; } - override async setSelector(selector: string): Promise { - const locator: string = asLocator(this._debugController._sdkLanguage, selector); - this._debugController.emit(DebugController.Events.InspectRequested, { selector, locator }); + override async elementPicked(elementInfo: ElementInfo): Promise { + const locator: string = asLocator(this._debugController._sdkLanguage, elementInfo.selector); + this._debugController.emit(DebugController.Events.InspectRequested, { selector: elementInfo.selector, locator }); } override async setSources(sources: Source[]): Promise { diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 682f48365acd8..7156d0cce7e2f 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -53,7 +53,7 @@ export function generateAriaTree(rootElement: Element): AriaNode { return; const element = node as Element; - if (roleUtils.isElementIgnoredForAria(element)) + if (roleUtils.isElementHiddenForAria(element)) return; const visible = isElementVisible(element); @@ -281,7 +281,7 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean const visit = (ariaNode: AriaNode | string, indent: string) => { if (typeof ariaNode === 'string') { if (!options?.noText) - lines.push(indent + '- text: ' + escapeYamlString(ariaNode)); + lines.push(indent + '- text: ' + quoteYamlString(ariaNode)); return; } let line = `${indent}- ${ariaNode.role}`; @@ -308,7 +308,7 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean const stringValue = !ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string'); if (stringValue) { if (!options?.noText && ariaNode.children.length) - line += ': ' + escapeYamlString(ariaNode.children?.[0] as string); + line += ': ' + quoteYamlString(ariaNode.children?.[0] as string); lines.push(line); return; } @@ -328,36 +328,10 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean return lines.join('\n'); } -function escapeYamlString(str: string) { - if (str === '') - return '""'; - - const needQuotes = ( - // Starts or ends with whitespace - /^\s|\s$/.test(str) || - // Contains control characters - /[\x00-\x1f]/.test(str) || - // Contains special YAML characters that could cause parsing issues - /[\[\]{}&*!,|>%@`]/.test(str) || - // Contains a colon followed by a space (could be interpreted as a key-value pair) - /:\s/.test(str) || - // Is a YAML boolean or null value - /^(?:y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|null|Null|NULL|~)$/.test(str) || - // Could be interpreted as a number - /^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/.test(str) || - // Contains a newline character - /\n/.test(str) || - // Starts with a special character - /^[\-?:,>|%@"`]/.test(str) - ); - - if (needQuotes) { - return `"${str - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r')}"`; - } - - return str; +function quoteYamlString(str: string) { + return `"${str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r')}"`; } diff --git a/packages/playwright-core/src/server/injected/consoleApi.ts b/packages/playwright-core/src/server/injected/consoleApi.ts index 0287240493291..eae874834ec10 100644 --- a/packages/playwright-core/src/server/injected/consoleApi.ts +++ b/packages/playwright-core/src/server/injected/consoleApi.ts @@ -85,7 +85,11 @@ class ConsoleAPI { inspect: (selector: string) => this._inspect(selector), selector: (element: Element) => this._selector(element), generateLocator: (element: Element, language?: Language) => this._generateLocator(element, language), - ariaSnapshot: (element?: Element) => this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body), + ariaSnapshot: (element?: Element) => { + const snapshot = this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body); + // eslint-disable-next-line no-console + console.log(snapshot); + }, resume: () => this._resume(), ...new Locator(injectedScript, ''), }; diff --git a/packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts b/packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts index 9a96d8f25d952..c48645ad09cea 100644 --- a/packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/pollingRecorder.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Mode, OverlayState, UIState } from '@recorder/recorderTypes'; +import type { ElementInfo, Mode, OverlayState, UIState } from '@recorder/recorderTypes'; import type * as actions from '@recorder/actions'; import type { InjectedScript } from '../injectedScript'; import { Recorder } from './recorder'; @@ -24,7 +24,7 @@ interface Embedder { __pw_recorderPerformAction(action: actions.PerformOnRecordAction): Promise; __pw_recorderRecordAction(action: actions.Action): Promise; __pw_recorderState(): Promise; - __pw_recorderSetSelector(selector: string): Promise; + __pw_recorderElementPicked(element: { selector: string, ariaSnapshot?: string }): Promise; __pw_recorderSetMode(mode: Mode): Promise; __pw_recorderSetOverlayState(state: OverlayState): Promise; __pw_refreshOverlay(): void; @@ -75,8 +75,8 @@ export class PollingRecorder implements RecorderDelegate { await this._embedder.__pw_recorderRecordAction(action); } - async setSelector(selector: string): Promise { - await this._embedder.__pw_recorderSetSelector(selector); + async elementPicked(elementInfo: ElementInfo): Promise { + await this._embedder.__pw_recorderElementPicked(elementInfo); } async setMode(mode: Mode): Promise { diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index 7c38c6386e88d..9dfa2cd3729d5 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -17,7 +17,7 @@ import type * as actions from '@recorder/actions'; import type { InjectedScript } from '../injectedScript'; import type { Point } from '../../../common/types'; -import type { Mode, OverlayState, UIState } from '@recorder/recorderTypes'; +import type { ElementInfo, Mode, OverlayState, UIState } from '@recorder/recorderTypes'; import type { ElementText } from '../selectorUtils'; import type { Highlight, HighlightOptions } from '../highlight'; import clipPaths from './clipPaths'; @@ -25,7 +25,7 @@ import clipPaths from './clipPaths'; export interface RecorderDelegate { performAction?(action: actions.PerformOnRecordAction): Promise; recordAction?(action: actions.Action): Promise; - setSelector?(selector: string): Promise; + elementPicked?(elementInfo: ElementInfo): Promise; setMode?(mode: Mode): Promise; setOverlayState?(state: OverlayState): Promise; highlightUpdated?(): void; @@ -85,7 +85,7 @@ class InspectTool implements RecorderTool { if (event.button !== 0) return; if (this._hoveredModel?.selector) - this._commit(this._hoveredModel.selector); + this._commit(this._hoveredModel.selector, this._hoveredModel); } onContextMenu(event: MouseEvent) { @@ -93,13 +93,14 @@ class InspectTool implements RecorderTool { && this._hoveredSelectors && this._hoveredSelectors.length > 1) { consumeEvent(event); const selectors = this._hoveredSelectors; + const hoveredModel = this._hoveredModel; this._hoveredModel.tooltipFooter = undefined; this._hoveredModel.tooltipList = selectors.map(selector => this._recorder.injectedScript.utils.asLocator(this._recorder.state.language, selector)); this._hoveredModel.tooltipListItemSelected = (index: number | undefined) => { if (index === undefined) this._reset(true); else - this._commit(selectors[index]); + this._commit(selectors[index], hoveredModel); }; this._recorder.updateHighlight(this._hoveredModel, true); } @@ -181,7 +182,7 @@ class InspectTool implements RecorderTool { this._reset(false); } - private _commit(selector: string) { + private _commit(selector: string, model: HighlightModel) { if (this._assertVisibility) { this._recorder.recordAction({ name: 'assertVisible', @@ -191,7 +192,7 @@ class InspectTool implements RecorderTool { this._recorder.setMode('recording'); this._recorder.overlay?.flashToolSucceeded('assertingVisibility'); } else { - this._recorder.setSelector(selector); + this._recorder.elementPicked(selector, model); } } @@ -1314,8 +1315,9 @@ export class Recorder { void this._delegate.setOverlayState?.(state); } - setSelector(selector: string) { - void this._delegate.setSelector?.(selector); + elementPicked(selector: string, model: HighlightModel) { + const ariaSnapshot = this.injectedScript.ariaSnapshot(model.elements[0]); + void this._delegate.elementPicked?.({ selector, ariaSnapshot }); } } diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index c5e133c06908a..74ebefee86c0c 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -15,7 +15,7 @@ */ import type * as channels from '@protocol/channels'; -import type { CallLog, CallLogStatus, EventData, Mode, OverlayState, Source, UIState } from '@recorder/recorderTypes'; +import type { CallLog, CallLogStatus, ElementInfo, EventData, Mode, OverlayState, Source, UIState } from '@recorder/recorderTypes'; import * as fs from 'fs'; import type { Point } from '../common/types'; import * as consoleApiSource from '../generated/consoleApiSource'; @@ -168,9 +168,9 @@ export class Recorder implements InstrumentationListener, IRecorder { return uiState; }); - await this._context.exposeBinding('__pw_recorderSetSelector', false, async ({ frame }, selector: string) => { + await this._context.exposeBinding('__pw_recorderElementPicked', false, async ({ frame }, elementInfo: ElementInfo) => { const selectorChain = await generateFrameSelector(frame); - await this._recorderApp?.setSelector(buildFullSelector(selectorChain, selector), true); + await this._recorderApp?.elementPicked({ selector: buildFullSelector(selectorChain, elementInfo.selector), ariaSnapshot: elementInfo.ariaSnapshot }, true); }); await this._context.exposeBinding('__pw_recorderSetMode', false, async ({ frame }, mode: Mode) => { @@ -256,12 +256,10 @@ export class Recorder implements InstrumentationListener, IRecorder { this._currentCallsMetadata.set(metadata, sdkObject); this._updateUserSources(); this.updateCallLog([metadata]); - if (isScreenshotCommand(metadata)) { + if (isScreenshotCommand(metadata)) this.hideHighlightedSelector(); - } else if (metadata.params && metadata.params.selector) { + else if (metadata.params && metadata.params.selector) this._highlightedSelector = metadata.params.selector; - this._recorderApp?.setSelector(this._highlightedSelector).catch(() => {}); - } } async onAfterCall(sdkObject: SdkObject, metadata: CallMetadata) { diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index 3f9a636579efe..df27a96c6c8f0 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -20,7 +20,7 @@ import type { Page } from '../page'; import { ProgressController } from '../progress'; import { EventEmitter } from 'events'; import { serverSideCallMetadata } from '../instrumentation'; -import type { CallLog, Mode, Source } from '@recorder/recorderTypes'; +import type { CallLog, ElementInfo, Mode, Source } from '@recorder/recorderTypes'; import { isUnderTest } from '../../utils'; import { mime } from '../../utilsBundle'; import { syncLocalStorageWithSettings } from '../launchApp'; @@ -35,7 +35,7 @@ export class EmptyRecorderApp extends EventEmitter implements IRecorderApp { async setPaused(paused: boolean): Promise {} async setMode(mode: Mode): Promise {} async setRunningFile(file: string | undefined): Promise {} - async setSelector(selector: string, userGesture?: boolean): Promise {} + async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise {} async updateCallLogs(callLogs: CallLog[]): Promise {} async setSources(sources: Source[]): Promise {} async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise {} @@ -158,18 +158,12 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise { } - async setSelector(selector: string, userGesture?: boolean): Promise { - if (userGesture) { - if (this._recorder?.mode() === 'inspecting') { - this._recorder.setMode('standby'); - this._page.bringToFront(); - } else { - this._recorder?.setMode('recording'); - } - } - await this._page.mainFrame().evaluateExpression(((data: { selector: string, userGesture?: boolean }) => { - window.playwrightSetSelector(data.selector, data.userGesture); - }).toString(), { isFunction: true }, { selector, userGesture }).catch(() => {}); + async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise { + if (userGesture) + this._page.bringToFront(); + await this._page.mainFrame().evaluateExpression(((param: { elementInfo: ElementInfo, userGesture?: boolean }) => { + window.playwrightElementPicked(param.elementInfo, param.userGesture); + }).toString(), { isFunction: true }, { elementInfo, userGesture }).catch(() => {}); } async updateCallLogs(callLogs: CallLog[]): Promise { diff --git a/packages/playwright-core/src/server/recorder/recorderFrontend.ts b/packages/playwright-core/src/server/recorder/recorderFrontend.ts index 9bf48022a7087..dbba78ceeb4e9 100644 --- a/packages/playwright-core/src/server/recorder/recorderFrontend.ts +++ b/packages/playwright-core/src/server/recorder/recorderFrontend.ts @@ -15,7 +15,7 @@ */ import type * as actions from '@recorder/actions'; -import type { CallLog, Mode, Source } from '@recorder/recorderTypes'; +import type { CallLog, Mode, Source, ElementInfo } from '@recorder/recorderTypes'; import type { EventEmitter } from 'events'; export interface IRecorder { @@ -29,7 +29,7 @@ export interface IRecorderApp extends EventEmitter { setPaused(paused: boolean): Promise; setMode(mode: Mode): Promise; setRunningFile(file: string | undefined): Promise; - setSelector(selector: string, userGesture?: boolean): Promise; + elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise; updateCallLogs(callLogs: CallLog[]): Promise; setSources(sources: Source[]): Promise; setActions(actions: actions.ActionInContext[], sources: Source[]): Promise; diff --git a/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts b/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts index e11ef1283a80f..fcfd0a36c5331 100644 --- a/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts +++ b/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts @@ -15,7 +15,7 @@ */ import path from 'path'; -import type { CallLog, Mode, Source } from '@recorder/recorderTypes'; +import type { CallLog, ElementInfo, Mode, Source } from '@recorder/recorderTypes'; import { EventEmitter } from 'events'; import type { IRecorder, IRecorderApp, IRecorderAppFactory } from './recorderFrontend'; import { installRootRedirect, openTraceViewerApp, startTraceViewerServer } from '../trace/viewer/traceViewer'; @@ -70,8 +70,8 @@ export class RecorderInTraceViewer extends EventEmitter implements IRecorderApp this._transport.deliverEvent('setRunningFile', { file }); } - async setSelector(selector: string, userGesture?: boolean): Promise { - this._transport.deliverEvent('setSelector', { selector, userGesture }); + async elementPicked(elementInfo: ElementInfo, userGesture?: boolean): Promise { + this._transport.deliverEvent('elementPicked', { elementInfo, userGesture }); } async updateCallLogs(callLogs: CallLog[]): Promise { diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx index a8cd2b271987a..2e05b65f6e59d 100644 --- a/packages/recorder/src/recorder.tsx +++ b/packages/recorder/src/recorder.tsx @@ -14,7 +14,7 @@ limitations under the License. */ -import type { CallLog, Mode, Source } from './recorderTypes'; +import type { CallLog, ElementInfo, Mode, Source } from './recorderTypes'; import { CodeMirrorWrapper } from '@web/components/codeMirrorWrapper'; import { SplitView } from '@web/components/splitView'; import { TabbedPane } from '@web/components/tabbedPane'; @@ -44,6 +44,7 @@ export const Recorder: React.FC = ({ const [selectedFileId, setSelectedFileId] = React.useState(); const [runningFileId, setRunningFileId] = React.useState(); const [selectedTab, setSelectedTab] = React.useState('log'); + const [ariaSnapshot, setAriaSnapshot] = React.useState(); const fileId = selectedFileId || runningFileId || sources[0]?.id; @@ -57,11 +58,18 @@ export const Recorder: React.FC = ({ }, [sources, fileId]); const [locator, setLocator] = React.useState(''); - window.playwrightSetSelector = (selector: string, focus?: boolean) => { + window.playwrightElementPicked = (elementInfo: ElementInfo, userGesture?: boolean) => { const language = source.language; - if (focus) + setLocator(asLocator(language, elementInfo.selector)); + setAriaSnapshot(elementInfo.ariaSnapshot); + if (userGesture && selectedTab !== 'locator' && selectedTab !== 'aria') setSelectedTab('locator'); - setLocator(asLocator(language, selector)); + + if (mode === 'inspecting' && selectedTab === 'aria') { + // Keep exploring aria. + } else { + window.dispatch({ event: 'setMode', params: { mode: mode === 'inspecting' ? 'standby' : 'recording' } }).catch(() => { }); + } }; window.playwrightSetRunningFile = setRunningFileId; @@ -94,7 +102,7 @@ export const Recorder: React.FC = ({ }, [paused]); const onEditorChange = React.useCallback((selector: string) => { - if (mode === 'none') + if (mode === 'none' || mode === 'inspecting') window.dispatch({ event: 'setMode', params: { mode: 'standby' } }); setLocator(selector); window.dispatch({ event: 'selectorUpdated', params: { selector } }); @@ -157,7 +165,7 @@ export const Recorder: React.FC = ({ sidebarSize={200} main={} sidebar={ copy(locator)} />] : []} + rightToolbar={selectedTab === 'locator' || selectedTab === 'aria' ? [ copy((selectedTab === 'locator' ? locator : ariaSnapshot) || '')} />] : []} tabs={[ { id: 'locator', @@ -169,6 +177,11 @@ export const Recorder: React.FC = ({ title: 'Log', render: () => }, + { + id: 'aria', + title: 'Accessibility', + render: () => + }, ]} selectedTab={selectedTab} setSelectedTab={setSelectedTab} diff --git a/packages/recorder/src/recorderTypes.ts b/packages/recorder/src/recorderTypes.ts index a0e04a72836fd..22afde3dadd1a 100644 --- a/packages/recorder/src/recorderTypes.ts +++ b/packages/recorder/src/recorderTypes.ts @@ -29,6 +29,11 @@ export type Mode = | 'assertingValue' | 'assertingSnapshot'; +export type ElementInfo = { + selector: string; + ariaSnapshot: string; +}; + export type EventData = { event: | 'clear' @@ -98,7 +103,7 @@ declare global { playwrightSetOverlayVisible: (visible: boolean) => void; playwrightUpdateLogs: (callLogs: CallLog[]) => void; playwrightSetRunningFile: (file: string | undefined) => void; - playwrightSetSelector: (selector: string, focus?: boolean) => void; + playwrightElementPicked: (elementInfo: ElementInfo, userGesture?: boolean) => void; playwrightSourcesEchoForTest: Source[]; dispatch(data: any): Promise; } diff --git a/packages/recorder/tsconfig.json b/packages/recorder/tsconfig.json index 10f4bfcf2f27f..16546d6e0de1c 100644 --- a/packages/recorder/tsconfig.json +++ b/packages/recorder/tsconfig.json @@ -19,6 +19,7 @@ "paths": { "@isomorphic/*": ["../playwright-core/src/utils/isomorphic/*"], "@protocol/*": ["../protocol/src/*"], + "@recorder/*": ["../recorder/src/*"], "@web/*": ["../web/src/*"], } }, diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index f8bcc3a5a33fd..fb874ccef4573 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -30,6 +30,7 @@ import { locatorOrSelectorAsSelector } from '@isomorphic/locatorParser'; import { TabbedPaneTab } from '@web/components/tabbedPane'; import { BrowserFrame } from './browserFrame'; import { ClickPointer } from './clickPointer'; +import type { ElementInfo } from '@recorder/recorderTypes'; function findClosest(items: T[], metric: (v: T) => number, target: number) { return items.find((item, index) => { @@ -291,8 +292,8 @@ export const InspectModeController: React.FunctionComponent<{ testIdAttributeName, overlay: { offsetX: 0 }, }, { - async setSelector(selector: string) { - setHighlightedLocator(asLocator(sdkLanguage, frameSelector + selector)); + async elementPicked(elementInfo: ElementInfo) { + setHighlightedLocator(asLocator(sdkLanguage, frameSelector + elementInfo.selector)); }, highlightUpdated() { for (const r of recorders) { diff --git a/packages/web/src/components/codeMirrorModule.tsx b/packages/web/src/components/codeMirrorModule.tsx index 4376e0a18fb17..ea0953bf8fbf2 100644 --- a/packages/web/src/components/codeMirrorModule.tsx +++ b/packages/web/src/components/codeMirrorModule.tsx @@ -25,6 +25,7 @@ import 'codemirror-shadow-1/mode/python/python'; import 'codemirror-shadow-1/mode/clike/clike'; import 'codemirror-shadow-1/mode/markdown/markdown'; import 'codemirror-shadow-1/addon/mode/simple'; +import 'codemirror-shadow-1/mode/yaml/yaml'; export type CodeMirror = typeof codemirrorType; export default codemirror; diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index 88306a1e43495..188808a178e55 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -64,8 +64,8 @@ it('should snapshot list with accessible name', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - list "my list": - - listitem: one - - listitem: two + - listitem: "one" + - listitem: "two" `); }); @@ -92,7 +92,7 @@ it('should allow text nodes', async ({ page }) => { await checkAndMatchSnapshot(page.locator('body'), ` - heading "Microsoft" [level=1] - - text: Open source projects and samples from Microsoft + - text: "Open source projects and samples from Microsoft" `); }); @@ -105,7 +105,7 @@ it('should snapshot details visibility', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - group: Summary + - group: "Summary" `); }); @@ -145,10 +145,10 @@ it('should snapshot integration', async ({ page }) => { await checkAndMatchSnapshot(page.locator('body'), ` - heading "Microsoft" [level=1] - - text: Open source projects and samples from Microsoft + - text: "Open source projects and samples from Microsoft" - list: - listitem: - - group: Verified + - group: "Verified" - listitem: - link "Sponsor" `); @@ -164,7 +164,7 @@ it('should support multiline text', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: Line 1 Line 2 Line 3 + - paragraph: "Line 1 Line 2 Line 3" `); await expect(page.locator('body')).toMatchAriaSnapshot(` - paragraph: | @@ -180,7 +180,7 @@ it('should concatenate span text', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - text: One Two Three + - text: "One Two Three" `); }); @@ -190,7 +190,7 @@ it('should concatenate span text 2', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - text: One Two Three + - text: "One Two Three" `); }); @@ -200,7 +200,7 @@ it('should concatenate div text with spaces', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - text: One Two Three + - text: "One Two Three" `); }); @@ -362,12 +362,12 @@ it('should snapshot inner text', async ({ page }) => { await checkAndMatchSnapshot(page.locator('body'), ` - listitem: - - text: a.test.ts + - text: "a.test.ts" - button "Run" - button "Show source" - button "Watch" - listitem: - - text: snapshot 30ms + - text: "snapshot 30ms" - button "Run" - button "Show source" - button "Watch" @@ -382,6 +382,6 @@ it('should include pseudo codepoints', async ({ page, server }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: \ueab2hello + - paragraph: "\ueab2hello" `); }); diff --git a/utils/build/build.js b/utils/build/build.js index 56442c094847b..7a289bd5edaa1 100644 --- a/utils/build/build.js +++ b/utils/build/build.js @@ -283,7 +283,7 @@ for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) { 'vite', 'build', ...(watchMode ? ['--watch', '--minify=false'] : []), - ...(withSourceMaps ? ['--sourcemap'] : []), + ...(withSourceMaps ? ['--sourcemap=inline'] : []), ], shell: true, cwd: path.join(__dirname, '..', '..', 'packages', webPackage), @@ -299,7 +299,7 @@ steps.push({ 'vite.sw.config.ts', 'build', ...(watchMode ? ['--watch', '--minify=false'] : []), - ...(withSourceMaps ? ['--sourcemap'] : []), + ...(withSourceMaps ? ['--sourcemap=inline'] : []), ], shell: true, cwd: path.join(__dirname, '..', '..', 'packages', 'trace-viewer'), From 3322a7f3bb92b250b7921d0c9614a424755474a3 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Wed, 23 Oct 2024 12:17:02 +0200 Subject: [PATCH 353/805] chore(trace): remove screenshot instead of snapshot code (#33225) --- .../src/ui/embeddedWorkbenchLoader.tsx | 2 +- packages/trace-viewer/src/ui/inspectorTab.tsx | 5 +- packages/trace-viewer/src/ui/modelUtil.ts | 6 -- .../src/ui/recorder/recorderView.tsx | 1 - packages/trace-viewer/src/ui/snapshotTab.tsx | 57 ++----------------- packages/trace-viewer/src/ui/workbench.tsx | 5 +- .../trace-viewer/src/ui/workbenchLoader.tsx | 2 +- tests/library/trace-viewer.spec.ts | 30 ---------- 8 files changed, 10 insertions(+), 98 deletions(-) diff --git a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx index 3500b93b1f38d..785ce623ca02e 100644 --- a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx +++ b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx @@ -91,7 +91,7 @@ export const EmbeddedWorkbenchLoader: React.FunctionComponent = () => {
      - + {!traceURLs.length &&
      Select test to see the trace
      } diff --git a/packages/trace-viewer/src/ui/inspectorTab.tsx b/packages/trace-viewer/src/ui/inspectorTab.tsx index c608cde21b9be..7b3a90b709a32 100644 --- a/packages/trace-viewer/src/ui/inspectorTab.tsx +++ b/packages/trace-viewer/src/ui/inspectorTab.tsx @@ -22,16 +22,15 @@ import * as React from 'react'; import './sourceTab.css'; export const InspectorTab: React.FunctionComponent<{ - showScreenshot: boolean, sdkLanguage: Language, setIsInspecting: (isInspecting: boolean) => void, highlightedLocator: string, setHighlightedLocator: (locator: string) => void, -}> = ({ showScreenshot, sdkLanguage, setIsInspecting, highlightedLocator, setHighlightedLocator }) => { +}> = ({ sdkLanguage, setIsInspecting, highlightedLocator, setHighlightedLocator }) => { return
      Locator
      - { + { // Updating text needs to go first - react can squeeze a render between the state updates. setHighlightedLocator(text); setIsInspecting(false); diff --git a/packages/trace-viewer/src/ui/modelUtil.ts b/packages/trace-viewer/src/ui/modelUtil.ts index b639a4c03d105..8badcbd87e768 100644 --- a/packages/trace-viewer/src/ui/modelUtil.ts +++ b/packages/trace-viewer/src/ui/modelUtil.ts @@ -22,7 +22,6 @@ import type { ActionEntry, ContextEntry, PageEntry } from '../types/entries'; import type { StackFrame } from '@protocol/channels'; const contextSymbol = Symbol('context'); -const pageSymbol = Symbol('page'); const nextInContextSymbol = Symbol('next'); const prevInListSymbol = Symbol('prev'); const eventsSymbol = Symbol('events'); @@ -148,7 +147,6 @@ function indexModel(context: ContextEntry) { for (let i = 0; i < context.actions.length; ++i) { const action = context.actions[i] as any; action[contextSymbol] = context; - action[pageSymbol] = context.pages.find(page => page.pageId === action.pageId); } let lastNonRouteAction = undefined; for (let i = context.actions.length - 1; i >= 0; i--) { @@ -353,10 +351,6 @@ export function prevInList(action: ActionTraceEvent): ActionTraceEvent { return (action as any)[prevInListSymbol]; } -export function pageForAction(action: ActionTraceEvent): PageEntry { - return (action as any)[pageSymbol]; -} - export function stats(action: ActionTraceEvent): { errors: number, warnings: number } { let errors = 0; let warnings = 0; diff --git a/packages/trace-viewer/src/ui/recorder/recorderView.tsx b/packages/trace-viewer/src/ui/recorder/recorderView.tsx index ed36efbbb6121..6ff6b665d3bb2 100644 --- a/packages/trace-viewer/src/ui/recorder/recorderView.tsx +++ b/packages/trace-viewer/src/ui/recorder/recorderView.tsx @@ -213,7 +213,6 @@ const PropertiesView: React.FunctionComponent<{ id: 'inspector', title: 'Locator', render: () => (items: T[], metric: (v: T) => number, target: number) { - return items.find((item, index) => { - if (index === items.length - 1) - return true; - const next = items[index + 1]; - return Math.abs(metric(item) - target) < Math.abs(metric(next) - target); - }); -} - export const SnapshotTabsView: React.FunctionComponent<{ action: ActionTraceEvent | undefined, model?: MultiTraceModel, @@ -53,7 +43,6 @@ export const SnapshotTabsView: React.FunctionComponent<{ openPage?: (url: string, target?: string) => Window | any, }> = ({ action, sdkLanguage, testIdAttributeName, isInspecting, setIsInspecting, highlightedLocator, setHighlightedLocator, openPage }) => { const [snapshotTab, setSnapshotTab] = React.useState<'action'|'before'|'after'>('action'); - const showScreenshotInsteadOfSnapshot = false; const snapshots = React.useMemo(() => { return collectSnapshots(action); @@ -65,7 +54,7 @@ export const SnapshotTabsView: React.FunctionComponent<{ return
      - setIsInspecting(!isInspecting)} disabled={showScreenshotInsteadOfSnapshot} /> + setIsInspecting(!isInspecting)} /> {['action', 'before', 'after'].map(tab => { return ; })}
      - { + { if (!openPage) openPage = window.open; const win = openPage(snapshotUrls?.popoutUrl || '', '_blank'); @@ -86,7 +75,7 @@ export const SnapshotTabsView: React.FunctionComponent<{ }); }} />
      - {!showScreenshotInsteadOfSnapshot && } - {showScreenshotInsteadOfSnapshot && } + />
      ; }; @@ -194,38 +179,6 @@ export const SnapshotView: React.FunctionComponent<{
      ; }; -export const ScreenshotView: React.FunctionComponent<{ - action: ActionTraceEvent | undefined, - snapshotUrls: SnapshotUrls | undefined, - snapshot: Snapshot | undefined, -}> = ({ action, snapshotUrls, snapshot }) => { - const [snapshotInfo, setSnapshotInfo] = React.useState({ viewport: kDefaultViewport, url: '' }); - React.useEffect(() => { - fetchSnapshotInfo(snapshotUrls?.snapshotInfoUrl).then(setSnapshotInfo); - }, [snapshotUrls?.snapshotInfoUrl]); - - const page = action ? pageForAction(action) : undefined; - const screencastFrame = React.useMemo(() => { - if (snapshotInfo.wallTime && page?.screencastFrames[0]?.frameSwapWallTime) - return findClosest(page.screencastFrames, frame => frame.frameSwapWallTime!, snapshotInfo.wallTime); - - if (snapshotInfo.timestamp && page?.screencastFrames) - return findClosest(page.screencastFrames, frame => frame.timestamp, snapshotInfo.timestamp); - }, - [page?.screencastFrames, snapshotInfo.timestamp, snapshotInfo.wallTime]); - - const point = snapshot?.point; - - return - {screencastFrame && ( - <> - {point && } - {`Screenshot - - )} - ; -}; - const SnapshotWrapper: React.FunctionComponent> = ({ snapshotInfo, children }) => { diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index f5471ca81ccb9..8e2291705305f 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -55,8 +55,7 @@ export const Workbench: React.FunctionComponent<{ openPage?: (url: string, target?: string) => Window | any, onOpenExternally?: (location: modelUtil.SourceLocation) => void, revealSource?: boolean, - showSettings?: boolean, -}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, openPage, onOpenExternally, revealSource, showSettings }) => { +}> = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, openPage, onOpenExternally, revealSource }) => { const [selectedCallId, setSelectedCallId] = React.useState(undefined); const [revealedError, setRevealedError] = React.useState(undefined); const [highlightedCallId, setHighlightedCallId] = React.useState(); @@ -68,7 +67,6 @@ export const Workbench: React.FunctionComponent<{ const [highlightedLocator, setHighlightedLocator] = React.useState(''); const [selectedTime, setSelectedTime] = React.useState(); const [sidebarLocation, setSidebarLocation] = useSetting<'bottom' | 'right'>('propertiesSidebarLocation', 'bottom'); - const showScreenshot = false; const setSelectedAction = React.useCallback((action: modelUtil.ActionTraceEventInContext | undefined) => { setSelectedCallId(action?.callId); @@ -164,7 +162,6 @@ export const Workbench: React.FunctionComponent<{ id: 'inspector', title: 'Locator', render: () =>
      - + {fileForLocalModeError &&
      Trace Viewer uses Service Workers to show traces. To view trace:
      diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 0ae5716e2f4fa..37666fc1c62a8 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1422,24 +1422,6 @@ test('should serve css without content-type', async ({ page, runAndTrace, server await expect(snapshotFrame.locator('body')).toHaveCSS('background-color', 'rgb(255, 0, 0)', { timeout: 0 }); }); -test.skip('should allow showing screenshots instead of snapshots', async ({ runAndTrace, page, server }) => { - const traceViewer = await runAndTrace(async () => { - await page.goto(server.PREFIX + '/one-style.html'); - await page.waitForTimeout(1000); // ensure we could take a screenshot - }); - - const screenshot = traceViewer.page.getByAltText(`Screenshot of page.goto`); - const snapshot = (await traceViewer.snapshotFrame('page.goto')).owner(); - await expect(snapshot).toBeVisible(); - await expect(screenshot).not.toBeVisible(); - - await traceViewer.page.getByTitle('Settings').click(); - await traceViewer.page.getByText('Show screenshot instead of snapshot').setChecked(true); - - await expect(snapshot).not.toBeVisible(); - await expect(screenshot).toBeVisible(); -}); - test('canvas clipping', async ({ runAndTrace, page, server }) => { const traceViewer = await runAndTrace(async () => { await page.goto(server.PREFIX + '/screenshots/canvas.html#canvas-on-edge'); @@ -1466,18 +1448,6 @@ test('canvas clipping in iframe', async ({ runAndTrace, page, server }) => { await expect(canvas).toHaveAttribute('title', `Playwright displays canvas contents on a best-effort basis. It doesn't support canvas elements inside an iframe yet. If this impacts your workflow, please open an issue so we can prioritize.`); }); -test.skip('should handle case where neither snapshots nor screenshots exist', async ({ runAndTrace, page, server }) => { - const traceViewer = await runAndTrace(async () => { - await page.goto(server.PREFIX + '/one-style.html'); - }, { snapshots: false, screenshots: false }); - - await traceViewer.page.getByTitle('Settings').click(); - await traceViewer.page.getByText('Show screenshot instead of snapshot').setChecked(true); - - const screenshot = traceViewer.page.getByAltText(`Screenshot of page.goto > Action`); - await expect(screenshot).not.toBeVisible(); -}); - test('should show only one pointer with multilevel iframes', async ({ page, runAndTrace, server, browserName }) => { test.fixme(browserName === 'firefox', 'Elements in iframe are not marked'); From 0d12fbe0025729d372800934dc01a9283cb348b5 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 23 Oct 2024 12:19:29 +0200 Subject: [PATCH 354/805] fix: have more friendly playwright-report error when opening TV via file:// (#33239) --- packages/trace-viewer/index.html | 21 +++++++++++++++-- tests/playwright-test/reporter-html.spec.ts | 26 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/packages/trace-viewer/index.html b/packages/trace-viewer/index.html index bdd822dc0a672..046eef0afb15f 100644 --- a/packages/trace-viewer/index.html +++ b/packages/trace-viewer/index.html @@ -30,8 +30,25 @@

      For more information, please see the docs.

      diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index d9e604f99449e..11169fadffa0e 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -2510,6 +2510,32 @@ for (const useIntermediateMergeReport of [true, false] as const) { await testFilePathLink.click(); await expect(page.locator('.test-case-path')).toHaveText('Root describe'); }); + + test('should print a user-friendly warning when opening a trace via file:// protocol', async ({ runInlineTest, showReport, page }) => { + await runInlineTest({ + 'playwright.config.ts': ` + module.exports = { + projects: [{ + name: 'chromium', + use: { + browserName: 'chromium', + trace: 'on', + } + }] + }; + `, + 'a.test.js': ` + import { test } from '@playwright/test'; + test('passes', ({ page }) => {}); + `, + }, { reporter: 'dot,html' }, { PLAYWRIGHT_HTML_OPEN: 'never' }); + + const reportPath = path.join(test.info().outputPath(), 'playwright-report'); + await page.goto(url.pathToFileURL(path.join(reportPath, 'index.html')).toString()); + await page.getByRole('link', { name: 'View trace' }).click(); + await expect(page.locator('#fallback-error')).toContainText('The Playwright Trace Viewer must be loaded over the http:// or https:// protocols.'); + await expect(page.locator('#fallback-error')).toContainText(`npx playwright show-report ${reportPath.replace(/\\/g, '\\\\')}`); + }); }); } From f1f2a7b33a56495b0b7842f1fe45346c606c22ec Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 23 Oct 2024 18:14:55 +0200 Subject: [PATCH 355/805] chore: warn when browser with revision override is getting installed (#33226) --- .../playwright-core/src/server/registry/index.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index faadda45ee353..2c94b7f381881 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -372,6 +372,7 @@ type BrowsersJSON = { type BrowsersJSONDescriptor = { name: string, revision: string, + hasRevisionOverride: boolean browserVersion?: string, installByDefault: boolean, dir: string, @@ -386,6 +387,7 @@ function readDescriptors(browsersJSON: BrowsersJSON): BrowsersJSONDescriptor[] { const descriptor: BrowsersJSONDescriptor = { name, revision, + hasRevisionOverride: !!revisionOverride, // We only put browser version for the supported operating systems. browserVersion: revisionOverride ? undefined : obj.browserVersion, installByDefault: !!obj.installByDefault, @@ -492,7 +494,8 @@ export class Registry { revision: chromium.revision, browserVersion: chromium.browserVersion, dir: chromium.dir.replace(/(.*)(-\d+)$/, '$1-headless-shell$2'), - installByDefault: false + installByDefault: false, + hasRevisionOverride: false, }; const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShellDescriptor.dir, 'chromium-headless-shell'); this._executables.push({ @@ -1069,6 +1072,13 @@ export class Registry { throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${hostPlatform}`); if (!isOfficiallySupportedPlatform) logPolitely(`BEWARE: your OS is not officially supported by Playwright; downloading fallback build for ${hostPlatform}.`); + if (descriptor.hasRevisionOverride) { + const message = `You are using a frozen ${descriptor.name} browser which does not receive updates anymore on ${hostPlatform}. Please update to the latest version of your operating system to test up-to-date browsers.`; + if (process.env.GITHUB_ACTIONS) + console.log(`::warning title=Playwright::${message}`); // eslint-disable-line no-console + else + logPolitely(message); + } const displayName = descriptor.name.split('-').map(word => { return word === 'ffmpeg' ? 'FFMPEG' : word.charAt(0).toUpperCase() + word.slice(1); From 993a6b2a2a886d4504ae359ee40cfa1966feffe9 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 23 Oct 2024 10:24:53 -0700 Subject: [PATCH 356/805] fix(recorder): do not leak when instantiated in snapshots (#33240) --- .../src/server/injected/injectedScript.ts | 11 ++++++-- .../src/server/injected/recorder/recorder.ts | 2 +- packages/trace-viewer/src/ui/snapshotTab.tsx | 4 +++ tests/library/trace-viewer.spec.ts | 27 +++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 7abc5850bbcaf..6446d16966944 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -143,13 +143,19 @@ export class InjectedScript { builtinSetTimeout(callback: Function, timeout: number) { if (this.window.__pwClock?.builtin) return this.window.__pwClock.builtin.setTimeout(callback, timeout); - return setTimeout(callback, timeout); + return this.window.setTimeout(callback, timeout); + } + + builtinClearTimeout(timeout: number | undefined) { + if (this.window.__pwClock?.builtin) + return this.window.__pwClock.builtin.clearTimeout(timeout); + return this.window.clearTimeout(timeout); } builtinRequestAnimationFrame(callback: FrameRequestCallback) { if (this.window.__pwClock?.builtin) return this.window.__pwClock.builtin.requestAnimationFrame(callback); - return requestAnimationFrame(callback); + return this.window.requestAnimationFrame(callback); } eval(expression: string): any { @@ -1558,6 +1564,7 @@ declare global { __pwClock?: { builtin: { setTimeout: Window['setTimeout'], + clearTimeout: Window['clearTimeout'], requestAnimationFrame: Window['requestAnimationFrame'], } } diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index 9dfa2cd3729d5..1d50495c7709d 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -1092,7 +1092,7 @@ export class Recorder { recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500); }; recreationInterval = this.injectedScript.builtinSetTimeout(recreate, 500); - this._listeners.push(() => clearInterval(recreationInterval)); + this._listeners.push(() => this.injectedScript.builtinClearTimeout(recreationInterval)); this.highlight.appendChild(createSvgElement(this.document, clipPaths)); this.overlay?.install(); diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 56d5b0b2e5a06..bbf0e763da79e 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -269,6 +269,10 @@ function createRecorders(recorders: { recorder: Recorder, frameSelector: string const recorder = new Recorder(injectedScript); win._injectedScript = injectedScript; win._recorder = { recorder, frameSelector: parentFrameSelector }; + if (isUnderTest) { + (window as any)._weakRecordersForTest = (window as any)._weakRecordersForTest || new Set(); + (window as any)._weakRecordersForTest.add(new WeakRef(recorder)); + } } recorders.push(win._recorder); diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index 37666fc1c62a8..eb81fa8b9cd65 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1410,6 +1410,33 @@ test('should show baseURL in metadata pane', { await expect(traceViewer.metadataTab).toContainText('baseURL:https://example.com'); }); +test('should not leak recorders', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33086' }, +}, async ({ showTraceViewer }) => { + const traceViewer = await showTraceViewer([traceFile]); + + const counts = async () => { + return await traceViewer.page.evaluate(() => { + const weakSet = (window as any)._weakRecordersForTest || new Set(); + const weakList = [...weakSet]; + const aliveList = weakList.filter(r => !!r.deref()); + return { total: weakList.length, alive: aliveList.length }; + }); + }; + + await traceViewer.snapshotFrame('page.goto'); + await traceViewer.snapshotFrame('page.evaluate'); + await traceViewer.page.requestGC(); + await expect.poll(() => counts()).toEqual({ total: 4, alive: 1 }); + + await traceViewer.snapshotFrame('page.setContent'); + await traceViewer.snapshotFrame('page.goto'); + await traceViewer.snapshotFrame('page.evaluate'); + await traceViewer.snapshotFrame('page.setContent'); + await traceViewer.page.requestGC(); + await expect.poll(() => counts()).toEqual({ total: 8, alive: 1 }); +}); + test('should serve css without content-type', async ({ page, runAndTrace, server }) => { server.setRoute('/one-style.css', (req, res) => { res.writeHead(200); From ec9c11f1cd123d4a1b5ca2aed98bd6c7fcbf8eb3 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 23 Oct 2024 10:25:04 -0700 Subject: [PATCH 357/805] fix(trace viewer): limit the number of contexts loaded in sw (#33244) --- packages/trace-viewer/src/sw/main.ts | 31 ++++++++++++------- .../src/ui/embeddedWorkbenchLoader.tsx | 1 + .../src/ui/recorder/modelContext.tsx | 1 + .../trace-viewer/src/ui/uiModeTraceView.tsx | 1 + .../trace-viewer/src/ui/workbenchLoader.tsx | 1 + 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/trace-viewer/src/sw/main.ts b/packages/trace-viewer/src/sw/main.ts index 6773b9fb76460..6fcb08daa7f05 100644 --- a/packages/trace-viewer/src/sw/main.ts +++ b/packages/trace-viewer/src/sw/main.ts @@ -36,16 +36,16 @@ const scopePath = new URL(self.registration.scope).pathname; const loadedTraces = new Map(); -const clientIdToTraceUrls = new Map>(); +const clientIdToTraceUrls = new Map }>(); -async function loadTrace(traceUrl: string, traceFileName: string | null, clientId: string, progress: (done: number, total: number) => undefined): Promise { +async function loadTrace(traceUrl: string, traceFileName: string | null, clientId: string, limit: number | undefined, progress: (done: number, total: number) => undefined): Promise { await gc(); - let set = clientIdToTraceUrls.get(clientId); - if (!set) { - set = new Set(); - clientIdToTraceUrls.set(clientId, set); + let data = clientIdToTraceUrls.get(clientId); + if (!data) { + data = { limit, traceUrls: new Set() }; + clientIdToTraceUrls.set(clientId, data); } - set.add(traceUrl); + data.traceUrls.add(traceUrl); const traceModel = new TraceModel(); try { @@ -97,7 +97,8 @@ async function doFetch(event: FetchEvent): Promise { if (relativePath === '/contexts') { try { - const traceModel = await loadTrace(traceUrl!, url.searchParams.get('traceFileName'), event.clientId, (done: number, total: number) => { + const limit = url.searchParams.has('limit') ? +url.searchParams.get('limit')! : undefined; + const traceModel = await loadTrace(traceUrl!, url.searchParams.get('traceFileName'), event.clientId, limit, (done: number, total: number) => { client.postMessage({ method: 'progress', params: { done, total } }); }); return new Response(JSON.stringify(traceModel!.contextEntries), { @@ -179,12 +180,18 @@ async function gc() { const clients = await self.clients.matchAll(); const usedTraces = new Set(); - for (const [clientId, traceUrls] of clientIdToTraceUrls) { + for (const [clientId, data] of clientIdToTraceUrls) { // @ts-ignore - if (!clients.find(c => c.id === clientId)) + if (!clients.find(c => c.id === clientId)) { clientIdToTraceUrls.delete(clientId); - else - traceUrls.forEach(url => usedTraces.add(url)); + continue; + } + if (data.limit !== undefined) { + const ordered = [...data.traceUrls]; + // Leave the newest requested traces. + data.traceUrls = new Set(ordered.slice(ordered.length - data.limit)); + } + data.traceUrls.forEach(url => usedTraces.add(url)); } for (const traceUrl of loadedTraces.keys()) { diff --git a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx index 785ce623ca02e..c8b8aa216c469 100644 --- a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx +++ b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx @@ -65,6 +65,7 @@ export const EmbeddedWorkbenchLoader: React.FunctionComponent = () => { const url = traceURLs[i]; const params = new URLSearchParams(); params.set('trace', url); + params.set('limit', String(traceURLs.length)); const response = await fetch(`contexts?${params.toString()}`); if (!response.ok) { setProcessingErrorMessage((await response.json()).error); diff --git a/packages/trace-viewer/src/ui/recorder/modelContext.tsx b/packages/trace-viewer/src/ui/recorder/modelContext.tsx index 9db52e1964f53..98f450361b3db 100644 --- a/packages/trace-viewer/src/ui/recorder/modelContext.tsx +++ b/packages/trace-viewer/src/ui/recorder/modelContext.tsx @@ -58,6 +58,7 @@ export const ModelProvider: React.FunctionComponent { const params = new URLSearchParams(); params.set('trace', url); + params.set('limit', '1'); const response = await fetch(`contexts?${params.toString()}`); const contextEntries = await response.json() as ContextEntry[]; diff --git a/packages/trace-viewer/src/ui/uiModeTraceView.tsx b/packages/trace-viewer/src/ui/uiModeTraceView.tsx index ed63a2adab240..cf35d89007007 100644 --- a/packages/trace-viewer/src/ui/uiModeTraceView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTraceView.tsx @@ -111,6 +111,7 @@ const outputDirForTestCase = (testCase: reporterTypes.TestCase): string | undefi async function loadSingleTraceFile(url: string): Promise { const params = new URLSearchParams(); params.set('trace', url); + params.set('limit', '1'); const response = await fetch(`contexts?${params.toString()}`); const contextEntries = await response.json() as ContextEntry[]; return new MultiTraceModel(contextEntries); diff --git a/packages/trace-viewer/src/ui/workbenchLoader.tsx b/packages/trace-viewer/src/ui/workbenchLoader.tsx index dd6cae5bc1e00..9f3fe83fc47b2 100644 --- a/packages/trace-viewer/src/ui/workbenchLoader.tsx +++ b/packages/trace-viewer/src/ui/workbenchLoader.tsx @@ -131,6 +131,7 @@ export const WorkbenchLoader: React.FunctionComponent<{ params.set('trace', url); if (uploadedTraceNames.length) params.set('traceFileName', uploadedTraceNames[i]); + params.set('limit', String(traceURLs.length)); const response = await fetch(`contexts?${params.toString()}`); if (!response.ok) { if (!isServer) From 9a6e1b71a4da2e21c776241ed925402dbbd2e0d9 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 23 Oct 2024 10:25:16 -0700 Subject: [PATCH 358/805] fix(trace viewer): make LRUCache per-trace (#33245) --- packages/trace-viewer/src/sw/lruCache.ts | 49 +++++++++++++++++++ .../trace-viewer/src/sw/snapshotRenderer.ts | 44 ++++------------- .../trace-viewer/src/sw/snapshotStorage.ts | 4 +- 3 files changed, 61 insertions(+), 36 deletions(-) create mode 100644 packages/trace-viewer/src/sw/lruCache.ts diff --git a/packages/trace-viewer/src/sw/lruCache.ts b/packages/trace-viewer/src/sw/lruCache.ts new file mode 100644 index 0000000000000..573a15ea49a55 --- /dev/null +++ b/packages/trace-viewer/src/sw/lruCache.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class LRUCache { + private _maxSize: number; + private _map: Map; + private _size: number; + + constructor(maxSize: number) { + this._maxSize = maxSize; + this._map = new Map(); + this._size = 0; + } + + getOrCompute(key: K, compute: () => { value: V, size: number }): V { + if (this._map.has(key)) { + const result = this._map.get(key)!; + // reinserting makes this the least recently used entry + this._map.delete(key); + this._map.set(key, result); + return result.value; + } + + const result = compute(); + + while (this._map.size && this._size + result.size > this._maxSize) { + const [firstKey, firstValue] = this._map.entries().next().value; + this._size -= firstValue.size; + this._map.delete(firstKey); + } + + this._map.set(key, result); + this._size += result.size; + return result.value; + } +} diff --git a/packages/trace-viewer/src/sw/snapshotRenderer.ts b/packages/trace-viewer/src/sw/snapshotRenderer.ts index 438683ed84976..a9f89ba27338c 100644 --- a/packages/trace-viewer/src/sw/snapshotRenderer.ts +++ b/packages/trace-viewer/src/sw/snapshotRenderer.ts @@ -17,6 +17,7 @@ import { escapeHTMLAttribute, escapeHTML } from '@isomorphic/stringUtils'; import type { FrameSnapshot, NodeNameAttributesChildNodesSnapshot, NodeSnapshot, RenderedFrameSnapshot, ResourceSnapshot, SubtreeReferenceSnapshot } from '@trace/snapshot'; import type { PageEntry } from '../types/entries'; +import type { LRUCache } from './lruCache'; function findClosest(items: T[], metric: (v: T) => number, target: number) { return items.find((item, index) => { @@ -35,35 +36,8 @@ function isSubtreeReferenceSnapshot(n: NodeSnapshot): n is SubtreeReferenceSnaps return Array.isArray(n) && Array.isArray(n[0]); } -let cacheSize = 0; -const cache = new Map(); -const CACHE_SIZE = 300_000_000; // 300mb - -function lruCache(key: SnapshotRenderer, compute: () => string): string { - if (cache.has(key)) { - const value = cache.get(key)!; - // reinserting makes this the least recently used entry - cache.delete(key); - cache.set(key, value); - return value; - } - - - const result = compute(); - - while (cache.size && cacheSize + result.length > CACHE_SIZE) { - const [firstKey, firstValue] = cache.entries().next().value; - cacheSize -= firstValue.length; - cache.delete(firstKey); - } - - cache.set(key, result); - cacheSize += result.length; - - return result; -} - export class SnapshotRenderer { + private _htmlCache: LRUCache; private _snapshots: FrameSnapshot[]; private _index: number; readonly snapshotName: string | undefined; @@ -72,7 +46,8 @@ export class SnapshotRenderer { private _callId: string; private _screencastFrames: PageEntry['screencastFrames']; - constructor(resources: ResourceSnapshot[], snapshots: FrameSnapshot[], screencastFrames: PageEntry['screencastFrames'], index: number) { + constructor(htmlCache: LRUCache, resources: ResourceSnapshot[], snapshots: FrameSnapshot[], screencastFrames: PageEntry['screencastFrames'], index: number) { + this._htmlCache = htmlCache; this._resources = resources; this._snapshots = snapshots; this._index = index; @@ -171,16 +146,15 @@ export class SnapshotRenderer { }; const snapshot = this._snapshot; - const html = lruCache(this, () => { + const html = this._htmlCache.getOrCompute(this, () => { visit(snapshot.html, this._index, undefined, undefined); - - const html = result.join(''); - // Hide the document in order to prevent flickering. We will unhide once script has processed shadow. const prefix = snapshot.doctype ? `` : ''; - return prefix + [ + const html = prefix + [ + // Hide the document in order to prevent flickering. We will unhide once script has processed shadow. '', `` - ].join('') + html; + ].join('') + result.join(''); + return { value: html, size: html.length }; }); return { html, pageId: snapshot.pageId, frameId: snapshot.frameId, index: this._index }; diff --git a/packages/trace-viewer/src/sw/snapshotStorage.ts b/packages/trace-viewer/src/sw/snapshotStorage.ts index 5e10fc97fbcd6..d15bfc4f41674 100644 --- a/packages/trace-viewer/src/sw/snapshotStorage.ts +++ b/packages/trace-viewer/src/sw/snapshotStorage.ts @@ -17,6 +17,7 @@ import type { FrameSnapshot, ResourceSnapshot } from '@trace/snapshot'; import { rewriteURLForCustomProtocol, SnapshotRenderer } from './snapshotRenderer'; import type { PageEntry } from '../types/entries'; +import { LRUCache } from './lruCache'; export class SnapshotStorage { private _resources: ResourceSnapshot[] = []; @@ -24,6 +25,7 @@ export class SnapshotStorage { raw: FrameSnapshot[], renderers: SnapshotRenderer[] }>(); + private _cache = new LRUCache(100_000_000); // 100MB per each trace addResource(resource: ResourceSnapshot): void { resource.request.url = rewriteURLForCustomProtocol(resource.request.url); @@ -44,7 +46,7 @@ export class SnapshotStorage { this._frameSnapshots.set(snapshot.pageId, frameSnapshots); } frameSnapshots.raw.push(snapshot); - const renderer = new SnapshotRenderer(this._resources, frameSnapshots.raw, screencastFrames, frameSnapshots.raw.length - 1); + const renderer = new SnapshotRenderer(this._cache, this._resources, frameSnapshots.raw, screencastFrames, frameSnapshots.raw.length - 1); frameSnapshots.renderers.push(renderer); return renderer; } From 8da065a2ea0c18c2b59bcd679e89c409db447dcc Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 23 Oct 2024 12:57:15 -0700 Subject: [PATCH 359/805] Revert "chore: remove unused @babel/parser (#32654)" (#33252) --- packages/playwright/bundles/babel/package-lock.json | 1 + packages/playwright/bundles/babel/package.json | 1 + packages/playwright/bundles/babel/src/babelBundleImpl.ts | 1 + packages/playwright/src/transform/babelBundle.ts | 1 + 4 files changed, 4 insertions(+) diff --git a/packages/playwright/bundles/babel/package-lock.json b/packages/playwright/bundles/babel/package-lock.json index d3531ca0d7ffd..0902f0601e76d 100644 --- a/packages/playwright/bundles/babel/package-lock.json +++ b/packages/playwright/bundles/babel/package-lock.json @@ -11,6 +11,7 @@ "@babel/code-frame": "^7.24.2", "@babel/core": "^7.24.4", "@babel/helper-plugin-utils": "^7.24.0", + "@babel/parser": "^7.24.4", "@babel/plugin-proposal-decorators": "^7.24.1", "@babel/plugin-proposal-explicit-resource-management": "^7.24.1", "@babel/plugin-syntax-async-generators": "^7.8.4", diff --git a/packages/playwright/bundles/babel/package.json b/packages/playwright/bundles/babel/package.json index 90a0aa85debe2..27853cf80eb11 100644 --- a/packages/playwright/bundles/babel/package.json +++ b/packages/playwright/bundles/babel/package.json @@ -12,6 +12,7 @@ "@babel/code-frame": "^7.24.2", "@babel/core": "^7.24.4", "@babel/helper-plugin-utils": "^7.24.0", + "@babel/parser": "^7.24.4", "@babel/plugin-proposal-decorators": "^7.24.1", "@babel/plugin-proposal-explicit-resource-management": "^7.24.1", "@babel/plugin-syntax-async-generators": "^7.8.4", diff --git a/packages/playwright/bundles/babel/src/babelBundleImpl.ts b/packages/playwright/bundles/babel/src/babelBundleImpl.ts index 81e617ef27448..5e09be2a0c863 100644 --- a/packages/playwright/bundles/babel/src/babelBundleImpl.ts +++ b/packages/playwright/bundles/babel/src/babelBundleImpl.ts @@ -23,6 +23,7 @@ import * as babel from '@babel/core'; export { codeFrameColumns } from '@babel/code-frame'; export { declare } from '@babel/helper-plugin-utils'; export { types } from '@babel/core'; +export { parse } from '@babel/parser'; import traverseFunction from '@babel/traverse'; export const traverse = traverseFunction; diff --git a/packages/playwright/src/transform/babelBundle.ts b/packages/playwright/src/transform/babelBundle.ts index faf06b7158fe5..2806a05aec656 100644 --- a/packages/playwright/src/transform/babelBundle.ts +++ b/packages/playwright/src/transform/babelBundle.ts @@ -18,6 +18,7 @@ import type { BabelFileResult } from '../../bundles/babel/node_modules/@types/ba export const codeFrameColumns: typeof import('../../bundles/babel/node_modules/@types/babel__code-frame').codeFrameColumns = require('./babelBundleImpl').codeFrameColumns; export const declare: typeof import('../../bundles/babel/node_modules/@types/babel__helper-plugin-utils').declare = require('./babelBundleImpl').declare; export const types: typeof import('../../bundles/babel/node_modules/@types/babel__core').types = require('./babelBundleImpl').types; +export const parse: typeof import('../../bundles/babel/node_modules/@babel/parser/typings/babel-parser').parse = require('./babelBundleImpl').parse; export const traverse: typeof import('../../bundles/babel/node_modules/@types/babel__traverse').default = require('./babelBundleImpl').traverse; export type BabelPlugin = [string, any?]; export type BabelTransformFunction = (code: string, filename: string, isTypeScript: boolean, isModule: boolean, pluginsPrefix: BabelPlugin[], pluginsSuffix: BabelPlugin[]) => BabelFileResult; From 24cafbc8cb9dac71a38bfe36c9653d883b39bf7a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 23 Oct 2024 16:04:37 -0700 Subject: [PATCH 360/805] chore: use diff_match_patch with types (#33254) --- .../playwright-core/ThirdPartyNotices.txt | 209 +- .../bundles/utils/package-lock.json | 24 + .../bundles/utils/package.json | 6 +- .../bundles/utils/src/utilsBundleImpl.ts | 3 + .../src/third_party/diff_match_patch.js | 2222 ----------------- packages/playwright-core/src/utils/DEPS.list | 1 - .../playwright-core/src/utils/comparators.ts | 4 +- packages/playwright-core/src/utils/index.ts | 1 + packages/playwright-core/src/utils/patch.ts | 127 + packages/playwright-core/src/utilsBundle.ts | 1 + tests/library/{ => unit}/clock.spec.ts | 4 +- tests/library/unit/patch.spec.ts | 260 ++ tests/library/{ => unit}/sequence.spec.ts | 2 +- 13 files changed, 634 insertions(+), 2230 deletions(-) delete mode 100644 packages/playwright-core/src/third_party/diff_match_patch.js create mode 100644 packages/playwright-core/src/utils/patch.ts rename tests/library/{ => unit}/clock.spec.ts (99%) create mode 100644 tests/library/unit/patch.spec.ts rename tests/library/{ => unit}/sequence.spec.ts (98%) diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index 23e3cff257ceb..71ac7d1bed658 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -16,6 +16,7 @@ This project incorporates components from the projects listed below. The origina - concat-map@0.0.1 (https://github.com/substack/node-concat-map) - debug@4.3.4 (https://github.com/debug-js/debug) - define-lazy-prop@2.0.0 (https://github.com/sindresorhus/define-lazy-prop) +- diff-match-patch@1.0.5 (https://github.com/JackuB/diff-match-patch) - dotenv@16.4.5 (https://github.com/motdotla/dotenv) - end-of-stream@1.4.4 (https://github.com/mafintosh/end-of-stream) - escape-string-regexp@2.0.0 (https://github.com/sindresorhus/escape-string-regexp) @@ -351,6 +352,212 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI ========================================= END OF define-lazy-prop@2.0.0 AND INFORMATION +%% diff-match-patch@1.0.5 NOTICES AND INFORMATION BEGIN HERE +========================================= +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +========================================= +END OF diff-match-patch@1.0.5 AND INFORMATION + %% dotenv@16.4.5 NOTICES AND INFORMATION BEGIN HERE ========================================= Copyright (c) 2015, Scott Motte @@ -1194,6 +1401,6 @@ END OF yazl@2.5.1 AND INFORMATION SUMMARY BEGIN HERE ========================================= -Total Packages: 47 +Total Packages: 48 ========================================= END OF SUMMARY \ No newline at end of file diff --git a/packages/playwright-core/bundles/utils/package-lock.json b/packages/playwright-core/bundles/utils/package-lock.json index f786cb4db7bd5..e31dbe6209ac1 100644 --- a/packages/playwright-core/bundles/utils/package-lock.json +++ b/packages/playwright-core/bundles/utils/package-lock.json @@ -11,6 +11,7 @@ "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", + "diff-match-patch": "^1.0.5", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", "https-proxy-agent": "7.0.5", @@ -30,6 +31,7 @@ }, "devDependencies": { "@types/debug": "^4.1.7", + "@types/diff-match-patch": "^1.0.36", "@types/mime": "^2.0.3", "@types/minimatch": "^3.0.5", "@types/pngjs": "^6.0.1", @@ -49,6 +51,12 @@ "@types/ms": "*" } }, + "node_modules/@types/diff-match-patch": { + "version": "1.0.36", + "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", + "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", + "dev": true + }, "node_modules/@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", @@ -201,6 +209,11 @@ "node": ">=8" } }, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -456,6 +469,12 @@ "@types/ms": "*" } }, + "@types/diff-match-patch": { + "version": "1.0.36", + "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", + "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", + "dev": true + }, "@types/mime": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", @@ -587,6 +606,11 @@ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" }, + "diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + }, "dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", diff --git a/packages/playwright-core/bundles/utils/package.json b/packages/playwright-core/bundles/utils/package.json index 005e32fbe6a62..d8f6b7a481252 100644 --- a/packages/playwright-core/bundles/utils/package.json +++ b/packages/playwright-core/bundles/utils/package.json @@ -12,6 +12,7 @@ "colors": "1.4.0", "commander": "8.3.0", "debug": "^4.3.4", + "diff-match-patch": "^1.0.5", "dotenv": "^16.4.5", "graceful-fs": "4.2.10", "https-proxy-agent": "7.0.5", @@ -26,11 +27,12 @@ "signal-exit": "3.0.7", "socks-proxy-agent": "8.0.4", "stack-utils": "2.0.5", - "yaml": "^2.5.1", - "ws": "8.17.1" + "ws": "8.17.1", + "yaml": "^2.5.1" }, "devDependencies": { "@types/debug": "^4.1.7", + "@types/diff-match-patch": "^1.0.36", "@types/mime": "^2.0.3", "@types/minimatch": "^3.0.5", "@types/pngjs": "^6.0.1", diff --git a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts index 975e291bb5dbc..ba8bc8d90bc2b 100644 --- a/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts +++ b/packages/playwright-core/bundles/utils/src/utilsBundleImpl.ts @@ -20,6 +20,9 @@ export const colors = colorsLibrary; import debugLibrary from 'debug'; export const debug = debugLibrary; +import diffMatchPatchLibrary from 'diff-match-patch'; +export const diffMatchPatch = diffMatchPatchLibrary; + import dotenvLibrary from 'dotenv'; export const dotenv = dotenvLibrary; diff --git a/packages/playwright-core/src/third_party/diff_match_patch.js b/packages/playwright-core/src/third_party/diff_match_patch.js deleted file mode 100644 index ba0df0f6abd13..0000000000000 --- a/packages/playwright-core/src/third_party/diff_match_patch.js +++ /dev/null @@ -1,2222 +0,0 @@ -/** - * Diff Match and Patch - * Copyright 2018 The diff-match-patch Authors. - * https://github.com/google/diff-match-patch - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Computes the difference between two texts to create a patch. - * Applies the patch onto another text, allowing for errors. - * @author fraser@google.com (Neil Fraser) - */ - -/** - * Class containing the diff, match and patch methods. - * @constructor - */ -var diff_match_patch = function() { - - // Defaults. - // Redefine these in your program to override the defaults. - - // Number of seconds to map a diff before giving up (0 for infinity). - this.Diff_Timeout = 1.0; - // Cost of an empty edit operation in terms of edit characters. - this.Diff_EditCost = 4; - // At what point is no match declared (0.0 = perfection, 1.0 = very loose). - this.Match_Threshold = 0.5; - // How far to search for a match (0 = exact location, 1000+ = broad match). - // A match this many characters away from the expected location will add - // 1.0 to the score (0.0 is a perfect match). - this.Match_Distance = 1000; - // When deleting a large block of text (over ~64 characters), how close do - // the contents have to be to match the expected contents. (0.0 = perfection, - // 1.0 = very loose). Note that Match_Threshold controls how closely the - // end points of a delete need to match. - this.Patch_DeleteThreshold = 0.5; - // Chunk size for context length. - this.Patch_Margin = 4; - - // The number of bits in an int. - this.Match_MaxBits = 32; -}; - - -// DIFF FUNCTIONS - - -/** - * The data structure representing a diff is an array of tuples: - * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']] - * which means: delete 'Hello', add 'Goodbye' and keep ' world.' - */ -var DIFF_DELETE = -1; -var DIFF_INSERT = 1; -var DIFF_EQUAL = 0; - -/** - * Class representing one diff tuple. - * Attempts to look like a two-element array (which is what this used to be). - * @param {number} op Operation, one of: DIFF_DELETE, DIFF_INSERT, DIFF_EQUAL. - * @param {string} text Text to be deleted, inserted, or retained. - * @constructor - */ -diff_match_patch.Diff = function(op, text) { - this[0] = op; - this[1] = text; -}; - -diff_match_patch.Diff.prototype.length = 2; - -/** - * Emulate the output of a two-element array. - * @return {string} Diff operation as a string. - */ -diff_match_patch.Diff.prototype.toString = function() { - return this[0] + ',' + this[1]; -}; - - -/** - * Find the differences between two texts. Simplifies the problem by stripping - * any common prefix or suffix off the texts before diffing. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {boolean=} opt_checklines Optional speedup flag. If present and false, - * then don't run a line-level diff first to identify the changed areas. - * Defaults to true, which does a faster, slightly less optimal diff. - * @param {number=} opt_deadline Optional time when the diff should be complete - * by. Used internally for recursive calls. Users should set DiffTimeout - * instead. - * @return {!Array.} Array of diff tuples. - */ -diff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines, - opt_deadline) { - // Set a deadline by which time the diff must be complete. - if (typeof opt_deadline == 'undefined') { - if (this.Diff_Timeout <= 0) { - opt_deadline = Number.MAX_VALUE; - } else { - opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000; - } - } - var deadline = opt_deadline; - - // Check for null inputs. - if (text1 == null || text2 == null) { - throw new Error('Null input. (diff_main)'); - } - - // Check for equality (speedup). - if (text1 == text2) { - if (text1) { - return [new diff_match_patch.Diff(DIFF_EQUAL, text1)]; - } - return []; - } - - if (typeof opt_checklines == 'undefined') { - opt_checklines = true; - } - var checklines = opt_checklines; - - // Trim off common prefix (speedup). - var commonlength = this.diff_commonPrefix(text1, text2); - var commonprefix = text1.substring(0, commonlength); - text1 = text1.substring(commonlength); - text2 = text2.substring(commonlength); - - // Trim off common suffix (speedup). - commonlength = this.diff_commonSuffix(text1, text2); - var commonsuffix = text1.substring(text1.length - commonlength); - text1 = text1.substring(0, text1.length - commonlength); - text2 = text2.substring(0, text2.length - commonlength); - - // Compute the diff on the middle block. - var diffs = this.diff_compute_(text1, text2, checklines, deadline); - - // Restore the prefix and suffix. - if (commonprefix) { - diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL, commonprefix)); - } - if (commonsuffix) { - diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, commonsuffix)); - } - this.diff_cleanupMerge(diffs); - return diffs; -}; - - -/** - * Find the differences between two texts. Assumes that the texts do not - * have any common prefix or suffix. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {boolean} checklines Speedup flag. If false, then don't run a - * line-level diff first to identify the changed areas. - * If true, then run a faster, slightly less optimal diff. - * @param {number} deadline Time when the diff should be complete by. - * @return {!Array.} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines, - deadline) { - var diffs; - - if (!text1) { - // Just add some text (speedup). - return [new diff_match_patch.Diff(DIFF_INSERT, text2)]; - } - - if (!text2) { - // Just delete some text (speedup). - return [new diff_match_patch.Diff(DIFF_DELETE, text1)]; - } - - var longtext = text1.length > text2.length ? text1 : text2; - var shorttext = text1.length > text2.length ? text2 : text1; - var i = longtext.indexOf(shorttext); - if (i != -1) { - // Shorter text is inside the longer text (speedup). - diffs = [new diff_match_patch.Diff(DIFF_INSERT, longtext.substring(0, i)), - new diff_match_patch.Diff(DIFF_EQUAL, shorttext), - new diff_match_patch.Diff(DIFF_INSERT, - longtext.substring(i + shorttext.length))]; - // Swap insertions for deletions if diff is reversed. - if (text1.length > text2.length) { - diffs[0][0] = diffs[2][0] = DIFF_DELETE; - } - return diffs; - } - - if (shorttext.length == 1) { - // Single character string. - // After the previous speedup, the character can't be an equality. - return [new diff_match_patch.Diff(DIFF_DELETE, text1), - new diff_match_patch.Diff(DIFF_INSERT, text2)]; - } - - // Check to see if the problem can be split in two. - var hm = this.diff_halfMatch_(text1, text2); - if (hm) { - // A half-match was found, sort out the return data. - var text1_a = hm[0]; - var text1_b = hm[1]; - var text2_a = hm[2]; - var text2_b = hm[3]; - var mid_common = hm[4]; - // Send both pairs off for separate processing. - var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline); - var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline); - // Merge the results. - return diffs_a.concat([new diff_match_patch.Diff(DIFF_EQUAL, mid_common)], - diffs_b); - } - - if (checklines && text1.length > 100 && text2.length > 100) { - return this.diff_lineMode_(text1, text2, deadline); - } - - return this.diff_bisect_(text1, text2, deadline); -}; - - -/** - * Do a quick line-level diff on both strings, then rediff the parts for - * greater accuracy. - * This speedup can produce non-minimal diffs. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {number} deadline Time when the diff should be complete by. - * @return {!Array.} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) { - // Scan the text on a line-by-line basis first. - var a = this.diff_linesToChars_(text1, text2); - text1 = a.chars1; - text2 = a.chars2; - var linearray = a.lineArray; - - var diffs = this.diff_main(text1, text2, false, deadline); - - // Convert the diff back to original text. - this.diff_charsToLines_(diffs, linearray); - // Eliminate freak matches (e.g. blank lines) - this.diff_cleanupSemantic(diffs); - - // Rediff any replacement blocks, this time character-by-character. - // Add a dummy entry at the end. - diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, '')); - var pointer = 0; - var count_delete = 0; - var count_insert = 0; - var text_delete = ''; - var text_insert = ''; - while (pointer < diffs.length) { - switch (diffs[pointer][0]) { - case DIFF_INSERT: - count_insert++; - text_insert += diffs[pointer][1]; - break; - case DIFF_DELETE: - count_delete++; - text_delete += diffs[pointer][1]; - break; - case DIFF_EQUAL: - // Upon reaching an equality, check for prior redundancies. - if (count_delete >= 1 && count_insert >= 1) { - // Delete the offending records and add the merged ones. - diffs.splice(pointer - count_delete - count_insert, - count_delete + count_insert); - pointer = pointer - count_delete - count_insert; - var subDiff = - this.diff_main(text_delete, text_insert, false, deadline); - for (var j = subDiff.length - 1; j >= 0; j--) { - diffs.splice(pointer, 0, subDiff[j]); - } - pointer = pointer + subDiff.length; - } - count_insert = 0; - count_delete = 0; - text_delete = ''; - text_insert = ''; - break; - } - pointer++; - } - diffs.pop(); // Remove the dummy entry at the end. - - return diffs; -}; - - -/** - * Find the 'middle snake' of a diff, split the problem in two - * and return the recursively constructed diff. - * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {number} deadline Time at which to bail if not yet complete. - * @return {!Array.} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) { - // Cache the text lengths to prevent multiple calls. - var text1_length = text1.length; - var text2_length = text2.length; - var max_d = Math.ceil((text1_length + text2_length) / 2); - var v_offset = max_d; - var v_length = 2 * max_d; - var v1 = new Array(v_length); - var v2 = new Array(v_length); - // Setting all elements to -1 is faster in Chrome & Firefox than mixing - // integers and undefined. - for (var x = 0; x < v_length; x++) { - v1[x] = -1; - v2[x] = -1; - } - v1[v_offset + 1] = 0; - v2[v_offset + 1] = 0; - var delta = text1_length - text2_length; - // If the total number of characters is odd, then the front path will collide - // with the reverse path. - var front = (delta % 2 != 0); - // Offsets for start and end of k loop. - // Prevents mapping of space beyond the grid. - var k1start = 0; - var k1end = 0; - var k2start = 0; - var k2end = 0; - for (var d = 0; d < max_d; d++) { - // Bail out if deadline is reached. - if ((new Date()).getTime() > deadline) { - break; - } - - // Walk the front path one step. - for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) { - var k1_offset = v_offset + k1; - var x1; - if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) { - x1 = v1[k1_offset + 1]; - } else { - x1 = v1[k1_offset - 1] + 1; - } - var y1 = x1 - k1; - while (x1 < text1_length && y1 < text2_length && - text1.charAt(x1) == text2.charAt(y1)) { - x1++; - y1++; - } - v1[k1_offset] = x1; - if (x1 > text1_length) { - // Ran off the right of the graph. - k1end += 2; - } else if (y1 > text2_length) { - // Ran off the bottom of the graph. - k1start += 2; - } else if (front) { - var k2_offset = v_offset + delta - k1; - if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) { - // Mirror x2 onto top-left coordinate system. - var x2 = text1_length - v2[k2_offset]; - if (x1 >= x2) { - // Overlap detected. - return this.diff_bisectSplit_(text1, text2, x1, y1, deadline); - } - } - } - } - - // Walk the reverse path one step. - for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) { - var k2_offset = v_offset + k2; - var x2; - if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) { - x2 = v2[k2_offset + 1]; - } else { - x2 = v2[k2_offset - 1] + 1; - } - var y2 = x2 - k2; - while (x2 < text1_length && y2 < text2_length && - text1.charAt(text1_length - x2 - 1) == - text2.charAt(text2_length - y2 - 1)) { - x2++; - y2++; - } - v2[k2_offset] = x2; - if (x2 > text1_length) { - // Ran off the left of the graph. - k2end += 2; - } else if (y2 > text2_length) { - // Ran off the top of the graph. - k2start += 2; - } else if (!front) { - var k1_offset = v_offset + delta - k2; - if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) { - var x1 = v1[k1_offset]; - var y1 = v_offset + x1 - k1_offset; - // Mirror x2 onto top-left coordinate system. - x2 = text1_length - x2; - if (x1 >= x2) { - // Overlap detected. - return this.diff_bisectSplit_(text1, text2, x1, y1, deadline); - } - } - } - } - } - // Diff took too long and hit the deadline or - // number of diffs equals number of characters, no commonality at all. - return [new diff_match_patch.Diff(DIFF_DELETE, text1), - new diff_match_patch.Diff(DIFF_INSERT, text2)]; -}; - - -/** - * Given the location of the 'middle snake', split the diff in two parts - * and recurse. - * @param {string} text1 Old string to be diffed. - * @param {string} text2 New string to be diffed. - * @param {number} x Index of split point in text1. - * @param {number} y Index of split point in text2. - * @param {number} deadline Time at which to bail if not yet complete. - * @return {!Array.} Array of diff tuples. - * @private - */ -diff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y, - deadline) { - var text1a = text1.substring(0, x); - var text2a = text2.substring(0, y); - var text1b = text1.substring(x); - var text2b = text2.substring(y); - - // Compute both diffs serially. - var diffs = this.diff_main(text1a, text2a, false, deadline); - var diffsb = this.diff_main(text1b, text2b, false, deadline); - - return diffs.concat(diffsb); -}; - - -/** - * Split two texts into an array of strings. Reduce the texts to a string of - * hashes where each Unicode character represents one line. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {{chars1: string, chars2: string, lineArray: !Array.}} - * An object containing the encoded text1, the encoded text2 and - * the array of unique strings. - * The zeroth element of the array of unique strings is intentionally blank. - * @private - */ -diff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) { - var lineArray = []; // e.g. lineArray[4] == 'Hello\n' - var lineHash = {}; // e.g. lineHash['Hello\n'] == 4 - - // '\x00' is a valid character, but various debuggers don't like it. - // So we'll insert a junk entry to avoid generating a null character. - lineArray[0] = ''; - - /** - * Split a text into an array of strings. Reduce the texts to a string of - * hashes where each Unicode character represents one line. - * Modifies linearray and linehash through being a closure. - * @param {string} text String to encode. - * @return {string} Encoded string. - * @private - */ - function diff_linesToCharsMunge_(text) { - var chars = ''; - // Walk the text, pulling out a substring for each line. - // text.split('\n') would would temporarily double our memory footprint. - // Modifying text would create many large strings to garbage collect. - var lineStart = 0; - var lineEnd = -1; - // Keeping our own length variable is faster than looking it up. - var lineArrayLength = lineArray.length; - while (lineEnd < text.length - 1) { - lineEnd = text.indexOf('\n', lineStart); - if (lineEnd == -1) { - lineEnd = text.length - 1; - } - var line = text.substring(lineStart, lineEnd + 1); - - if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : - (lineHash[line] !== undefined)) { - chars += String.fromCharCode(lineHash[line]); - } else { - if (lineArrayLength == maxLines) { - // Bail out at 65535 because - // String.fromCharCode(65536) == String.fromCharCode(0) - line = text.substring(lineStart); - lineEnd = text.length; - } - chars += String.fromCharCode(lineArrayLength); - lineHash[line] = lineArrayLength; - lineArray[lineArrayLength++] = line; - } - lineStart = lineEnd + 1; - } - return chars; - } - // Allocate 2/3rds of the space for text1, the rest for text2. - var maxLines = 40000; - var chars1 = diff_linesToCharsMunge_(text1); - maxLines = 65535; - var chars2 = diff_linesToCharsMunge_(text2); - return {chars1: chars1, chars2: chars2, lineArray: lineArray}; -}; - - -/** - * Rehydrate the text in a diff from a string of line hashes to real lines of - * text. - * @param {!Array.} diffs Array of diff tuples. - * @param {!Array.} lineArray Array of unique strings. - * @private - */ -diff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) { - for (var i = 0; i < diffs.length; i++) { - var chars = diffs[i][1]; - var text = []; - for (var j = 0; j < chars.length; j++) { - text[j] = lineArray[chars.charCodeAt(j)]; - } - diffs[i][1] = text.join(''); - } -}; - - -/** - * Determine the common prefix of two strings. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the start of each - * string. - */ -diff_match_patch.prototype.diff_commonPrefix = function(text1, text2) { - // Quick check for common null cases. - if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) { - return 0; - } - // Binary search. - // Performance analysis: https://neil.fraser.name/news/2007/10/09/ - var pointermin = 0; - var pointermax = Math.min(text1.length, text2.length); - var pointermid = pointermax; - var pointerstart = 0; - while (pointermin < pointermid) { - if (text1.substring(pointerstart, pointermid) == - text2.substring(pointerstart, pointermid)) { - pointermin = pointermid; - pointerstart = pointermin; - } else { - pointermax = pointermid; - } - pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); - } - return pointermid; -}; - - -/** - * Determine the common suffix of two strings. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the end of each string. - */ -diff_match_patch.prototype.diff_commonSuffix = function(text1, text2) { - // Quick check for common null cases. - if (!text1 || !text2 || - text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) { - return 0; - } - // Binary search. - // Performance analysis: https://neil.fraser.name/news/2007/10/09/ - var pointermin = 0; - var pointermax = Math.min(text1.length, text2.length); - var pointermid = pointermax; - var pointerend = 0; - while (pointermin < pointermid) { - if (text1.substring(text1.length - pointermid, text1.length - pointerend) == - text2.substring(text2.length - pointermid, text2.length - pointerend)) { - pointermin = pointermid; - pointerend = pointermin; - } else { - pointermax = pointermid; - } - pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); - } - return pointermid; -}; - - -/** - * Determine if the suffix of one string is the prefix of another. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {number} The number of characters common to the end of the first - * string and the start of the second string. - * @private - */ -diff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) { - // Cache the text lengths to prevent multiple calls. - var text1_length = text1.length; - var text2_length = text2.length; - // Eliminate the null case. - if (text1_length == 0 || text2_length == 0) { - return 0; - } - // Truncate the longer string. - if (text1_length > text2_length) { - text1 = text1.substring(text1_length - text2_length); - } else if (text1_length < text2_length) { - text2 = text2.substring(0, text1_length); - } - var text_length = Math.min(text1_length, text2_length); - // Quick check for the worst case. - if (text1 == text2) { - return text_length; - } - - // Start by looking for a single character match - // and increase length until no match is found. - // Performance analysis: https://neil.fraser.name/news/2010/11/04/ - var best = 0; - var length = 1; - while (true) { - var pattern = text1.substring(text_length - length); - var found = text2.indexOf(pattern); - if (found == -1) { - return best; - } - length += found; - if (found == 0 || text1.substring(text_length - length) == - text2.substring(0, length)) { - best = length; - length++; - } - } -}; - - -/** - * Do the two texts share a substring which is at least half the length of the - * longer text? - * This speedup can produce non-minimal diffs. - * @param {string} text1 First string. - * @param {string} text2 Second string. - * @return {Array.} Five element Array, containing the prefix of - * text1, the suffix of text1, the prefix of text2, the suffix of - * text2 and the common middle. Or null if there was no match. - * @private - */ -diff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) { - if (this.Diff_Timeout <= 0) { - // Don't risk returning a non-optimal diff if we have unlimited time. - return null; - } - var longtext = text1.length > text2.length ? text1 : text2; - var shorttext = text1.length > text2.length ? text2 : text1; - if (longtext.length < 4 || shorttext.length * 2 < longtext.length) { - return null; // Pointless. - } - var dmp = this; // 'this' becomes 'window' in a closure. - - /** - * Does a substring of shorttext exist within longtext such that the substring - * is at least half the length of longtext? - * Closure, but does not reference any external variables. - * @param {string} longtext Longer string. - * @param {string} shorttext Shorter string. - * @param {number} i Start index of quarter length substring within longtext. - * @return {Array.} Five element Array, containing the prefix of - * longtext, the suffix of longtext, the prefix of shorttext, the suffix - * of shorttext and the common middle. Or null if there was no match. - * @private - */ - function diff_halfMatchI_(longtext, shorttext, i) { - // Start with a 1/4 length substring at position i as a seed. - var seed = longtext.substring(i, i + Math.floor(longtext.length / 4)); - var j = -1; - var best_common = ''; - var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b; - while ((j = shorttext.indexOf(seed, j + 1)) != -1) { - var prefixLength = dmp.diff_commonPrefix(longtext.substring(i), - shorttext.substring(j)); - var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i), - shorttext.substring(0, j)); - if (best_common.length < suffixLength + prefixLength) { - best_common = shorttext.substring(j - suffixLength, j) + - shorttext.substring(j, j + prefixLength); - best_longtext_a = longtext.substring(0, i - suffixLength); - best_longtext_b = longtext.substring(i + prefixLength); - best_shorttext_a = shorttext.substring(0, j - suffixLength); - best_shorttext_b = shorttext.substring(j + prefixLength); - } - } - if (best_common.length * 2 >= longtext.length) { - return [best_longtext_a, best_longtext_b, - best_shorttext_a, best_shorttext_b, best_common]; - } else { - return null; - } - } - - // First check if the second quarter is the seed for a half-match. - var hm1 = diff_halfMatchI_(longtext, shorttext, - Math.ceil(longtext.length / 4)); - // Check again based on the third quarter. - var hm2 = diff_halfMatchI_(longtext, shorttext, - Math.ceil(longtext.length / 2)); - var hm; - if (!hm1 && !hm2) { - return null; - } else if (!hm2) { - hm = hm1; - } else if (!hm1) { - hm = hm2; - } else { - // Both matched. Select the longest. - hm = hm1[4].length > hm2[4].length ? hm1 : hm2; - } - - // A half-match was found, sort out the return data. - var text1_a, text1_b, text2_a, text2_b; - if (text1.length > text2.length) { - text1_a = hm[0]; - text1_b = hm[1]; - text2_a = hm[2]; - text2_b = hm[3]; - } else { - text2_a = hm[0]; - text2_b = hm[1]; - text1_a = hm[2]; - text1_b = hm[3]; - } - var mid_common = hm[4]; - return [text1_a, text1_b, text2_a, text2_b, mid_common]; -}; - - -/** - * Reduce the number of edits by eliminating semantically trivial equalities. - * @param {!Array.} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupSemantic = function(diffs) { - var changes = false; - var equalities = []; // Stack of indices where equalities are found. - var equalitiesLength = 0; // Keeping our own length var is faster in JS. - /** @type {?string} */ - var lastEquality = null; - // Always equal to diffs[equalities[equalitiesLength - 1]][1] - var pointer = 0; // Index of current position. - // Number of characters that changed prior to the equality. - var length_insertions1 = 0; - var length_deletions1 = 0; - // Number of characters that changed after the equality. - var length_insertions2 = 0; - var length_deletions2 = 0; - while (pointer < diffs.length) { - if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found. - equalities[equalitiesLength++] = pointer; - length_insertions1 = length_insertions2; - length_deletions1 = length_deletions2; - length_insertions2 = 0; - length_deletions2 = 0; - lastEquality = diffs[pointer][1]; - } else { // An insertion or deletion. - if (diffs[pointer][0] == DIFF_INSERT) { - length_insertions2 += diffs[pointer][1].length; - } else { - length_deletions2 += diffs[pointer][1].length; - } - // Eliminate an equality that is smaller or equal to the edits on both - // sides of it. - if (lastEquality && (lastEquality.length <= - Math.max(length_insertions1, length_deletions1)) && - (lastEquality.length <= Math.max(length_insertions2, - length_deletions2))) { - // Duplicate record. - diffs.splice(equalities[equalitiesLength - 1], 0, - new diff_match_patch.Diff(DIFF_DELETE, lastEquality)); - // Change second copy to insert. - diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; - // Throw away the equality we just deleted. - equalitiesLength--; - // Throw away the previous equality (it needs to be reevaluated). - equalitiesLength--; - pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; - length_insertions1 = 0; // Reset the counters. - length_deletions1 = 0; - length_insertions2 = 0; - length_deletions2 = 0; - lastEquality = null; - changes = true; - } - } - pointer++; - } - - // Normalize the diff. - if (changes) { - this.diff_cleanupMerge(diffs); - } - this.diff_cleanupSemanticLossless(diffs); - - // Find any overlaps between deletions and insertions. - // e.g: abcxxxxxxdef - // -> abcxxxdef - // e.g: xxxabcdefxxx - // -> defxxxabc - // Only extract an overlap if it is as big as the edit ahead or behind it. - pointer = 1; - while (pointer < diffs.length) { - if (diffs[pointer - 1][0] == DIFF_DELETE && - diffs[pointer][0] == DIFF_INSERT) { - var deletion = diffs[pointer - 1][1]; - var insertion = diffs[pointer][1]; - var overlap_length1 = this.diff_commonOverlap_(deletion, insertion); - var overlap_length2 = this.diff_commonOverlap_(insertion, deletion); - if (overlap_length1 >= overlap_length2) { - if (overlap_length1 >= deletion.length / 2 || - overlap_length1 >= insertion.length / 2) { - // Overlap found. Insert an equality and trim the surrounding edits. - diffs.splice(pointer, 0, new diff_match_patch.Diff(DIFF_EQUAL, - insertion.substring(0, overlap_length1))); - diffs[pointer - 1][1] = - deletion.substring(0, deletion.length - overlap_length1); - diffs[pointer + 1][1] = insertion.substring(overlap_length1); - pointer++; - } - } else { - if (overlap_length2 >= deletion.length / 2 || - overlap_length2 >= insertion.length / 2) { - // Reverse overlap found. - // Insert an equality and swap and trim the surrounding edits. - diffs.splice(pointer, 0, new diff_match_patch.Diff(DIFF_EQUAL, - deletion.substring(0, overlap_length2))); - diffs[pointer - 1][0] = DIFF_INSERT; - diffs[pointer - 1][1] = - insertion.substring(0, insertion.length - overlap_length2); - diffs[pointer + 1][0] = DIFF_DELETE; - diffs[pointer + 1][1] = - deletion.substring(overlap_length2); - pointer++; - } - } - pointer++; - } - pointer++; - } -}; - - -/** - * Look for single edits surrounded on both sides by equalities - * which can be shifted sideways to align the edit to a word boundary. - * e.g: The cat came. -> The cat came. - * @param {!Array.} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) { - /** - * Given two strings, compute a score representing whether the internal - * boundary falls on logical boundaries. - * Scores range from 6 (best) to 0 (worst). - * Closure, but does not reference any external variables. - * @param {string} one First string. - * @param {string} two Second string. - * @return {number} The score. - * @private - */ - function diff_cleanupSemanticScore_(one, two) { - if (!one || !two) { - // Edges are the best. - return 6; - } - - // Each port of this function behaves slightly differently due to - // subtle differences in each language's definition of things like - // 'whitespace'. Since this function's purpose is largely cosmetic, - // the choice has been made to use each language's native features - // rather than force total conformity. - var char1 = one.charAt(one.length - 1); - var char2 = two.charAt(0); - var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_); - var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_); - var whitespace1 = nonAlphaNumeric1 && - char1.match(diff_match_patch.whitespaceRegex_); - var whitespace2 = nonAlphaNumeric2 && - char2.match(diff_match_patch.whitespaceRegex_); - var lineBreak1 = whitespace1 && - char1.match(diff_match_patch.linebreakRegex_); - var lineBreak2 = whitespace2 && - char2.match(diff_match_patch.linebreakRegex_); - var blankLine1 = lineBreak1 && - one.match(diff_match_patch.blanklineEndRegex_); - var blankLine2 = lineBreak2 && - two.match(diff_match_patch.blanklineStartRegex_); - - if (blankLine1 || blankLine2) { - // Five points for blank lines. - return 5; - } else if (lineBreak1 || lineBreak2) { - // Four points for line breaks. - return 4; - } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) { - // Three points for end of sentences. - return 3; - } else if (whitespace1 || whitespace2) { - // Two points for whitespace. - return 2; - } else if (nonAlphaNumeric1 || nonAlphaNumeric2) { - // One point for non-alphanumeric. - return 1; - } - return 0; - } - - var pointer = 1; - // Intentionally ignore the first and last element (don't need checking). - while (pointer < diffs.length - 1) { - if (diffs[pointer - 1][0] == DIFF_EQUAL && - diffs[pointer + 1][0] == DIFF_EQUAL) { - // This is a single edit surrounded by equalities. - var equality1 = diffs[pointer - 1][1]; - var edit = diffs[pointer][1]; - var equality2 = diffs[pointer + 1][1]; - - // First, shift the edit as far left as possible. - var commonOffset = this.diff_commonSuffix(equality1, edit); - if (commonOffset) { - var commonString = edit.substring(edit.length - commonOffset); - equality1 = equality1.substring(0, equality1.length - commonOffset); - edit = commonString + edit.substring(0, edit.length - commonOffset); - equality2 = commonString + equality2; - } - - // Second, step character by character right, looking for the best fit. - var bestEquality1 = equality1; - var bestEdit = edit; - var bestEquality2 = equality2; - var bestScore = diff_cleanupSemanticScore_(equality1, edit) + - diff_cleanupSemanticScore_(edit, equality2); - while (edit.charAt(0) === equality2.charAt(0)) { - equality1 += edit.charAt(0); - edit = edit.substring(1) + equality2.charAt(0); - equality2 = equality2.substring(1); - var score = diff_cleanupSemanticScore_(equality1, edit) + - diff_cleanupSemanticScore_(edit, equality2); - // The >= encourages trailing rather than leading whitespace on edits. - if (score >= bestScore) { - bestScore = score; - bestEquality1 = equality1; - bestEdit = edit; - bestEquality2 = equality2; - } - } - - if (diffs[pointer - 1][1] != bestEquality1) { - // We have an improvement, save it back to the diff. - if (bestEquality1) { - diffs[pointer - 1][1] = bestEquality1; - } else { - diffs.splice(pointer - 1, 1); - pointer--; - } - diffs[pointer][1] = bestEdit; - if (bestEquality2) { - diffs[pointer + 1][1] = bestEquality2; - } else { - diffs.splice(pointer + 1, 1); - pointer--; - } - } - } - pointer++; - } -}; - -// Define some regex patterns for matching boundaries. -diff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/; -diff_match_patch.whitespaceRegex_ = /\s/; -diff_match_patch.linebreakRegex_ = /[\r\n]/; -diff_match_patch.blanklineEndRegex_ = /\n\r?\n$/; -diff_match_patch.blanklineStartRegex_ = /^\r?\n\r?\n/; - -/** - * Reduce the number of edits by eliminating operationally trivial equalities. - * @param {!Array.} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) { - var changes = false; - var equalities = []; // Stack of indices where equalities are found. - var equalitiesLength = 0; // Keeping our own length var is faster in JS. - /** @type {?string} */ - var lastEquality = null; - // Always equal to diffs[equalities[equalitiesLength - 1]][1] - var pointer = 0; // Index of current position. - // Is there an insertion operation before the last equality. - var pre_ins = false; - // Is there a deletion operation before the last equality. - var pre_del = false; - // Is there an insertion operation after the last equality. - var post_ins = false; - // Is there a deletion operation after the last equality. - var post_del = false; - while (pointer < diffs.length) { - if (diffs[pointer][0] == DIFF_EQUAL) { // Equality found. - if (diffs[pointer][1].length < this.Diff_EditCost && - (post_ins || post_del)) { - // Candidate found. - equalities[equalitiesLength++] = pointer; - pre_ins = post_ins; - pre_del = post_del; - lastEquality = diffs[pointer][1]; - } else { - // Not a candidate, and can never become one. - equalitiesLength = 0; - lastEquality = null; - } - post_ins = post_del = false; - } else { // An insertion or deletion. - if (diffs[pointer][0] == DIFF_DELETE) { - post_del = true; - } else { - post_ins = true; - } - /* - * Five types to be split: - * ABXYCD - * AXCD - * ABXC - * AXCD - * ABXC - */ - if (lastEquality && ((pre_ins && pre_del && post_ins && post_del) || - ((lastEquality.length < this.Diff_EditCost / 2) && - (pre_ins + pre_del + post_ins + post_del) == 3))) { - // Duplicate record. - diffs.splice(equalities[equalitiesLength - 1], 0, - new diff_match_patch.Diff(DIFF_DELETE, lastEquality)); - // Change second copy to insert. - diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; - equalitiesLength--; // Throw away the equality we just deleted; - lastEquality = null; - if (pre_ins && pre_del) { - // No changes made which could affect previous entry, keep going. - post_ins = post_del = true; - equalitiesLength = 0; - } else { - equalitiesLength--; // Throw away the previous equality. - pointer = equalitiesLength > 0 ? - equalities[equalitiesLength - 1] : -1; - post_ins = post_del = false; - } - changes = true; - } - } - pointer++; - } - - if (changes) { - this.diff_cleanupMerge(diffs); - } -}; - - -/** - * Reorder and merge like edit sections. Merge equalities. - * Any edit section can move as long as it doesn't cross an equality. - * @param {!Array.} diffs Array of diff tuples. - */ -diff_match_patch.prototype.diff_cleanupMerge = function(diffs) { - // Add a dummy entry at the end. - diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, '')); - var pointer = 0; - var count_delete = 0; - var count_insert = 0; - var text_delete = ''; - var text_insert = ''; - var commonlength; - while (pointer < diffs.length) { - switch (diffs[pointer][0]) { - case DIFF_INSERT: - count_insert++; - text_insert += diffs[pointer][1]; - pointer++; - break; - case DIFF_DELETE: - count_delete++; - text_delete += diffs[pointer][1]; - pointer++; - break; - case DIFF_EQUAL: - // Upon reaching an equality, check for prior redundancies. - if (count_delete + count_insert > 1) { - if (count_delete !== 0 && count_insert !== 0) { - // Factor out any common prefixies. - commonlength = this.diff_commonPrefix(text_insert, text_delete); - if (commonlength !== 0) { - if ((pointer - count_delete - count_insert) > 0 && - diffs[pointer - count_delete - count_insert - 1][0] == - DIFF_EQUAL) { - diffs[pointer - count_delete - count_insert - 1][1] += - text_insert.substring(0, commonlength); - } else { - diffs.splice(0, 0, new diff_match_patch.Diff(DIFF_EQUAL, - text_insert.substring(0, commonlength))); - pointer++; - } - text_insert = text_insert.substring(commonlength); - text_delete = text_delete.substring(commonlength); - } - // Factor out any common suffixies. - commonlength = this.diff_commonSuffix(text_insert, text_delete); - if (commonlength !== 0) { - diffs[pointer][1] = text_insert.substring(text_insert.length - - commonlength) + diffs[pointer][1]; - text_insert = text_insert.substring(0, text_insert.length - - commonlength); - text_delete = text_delete.substring(0, text_delete.length - - commonlength); - } - } - // Delete the offending records and add the merged ones. - pointer -= count_delete + count_insert; - diffs.splice(pointer, count_delete + count_insert); - if (text_delete.length) { - diffs.splice(pointer, 0, - new diff_match_patch.Diff(DIFF_DELETE, text_delete)); - pointer++; - } - if (text_insert.length) { - diffs.splice(pointer, 0, - new diff_match_patch.Diff(DIFF_INSERT, text_insert)); - pointer++; - } - pointer++; - } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) { - // Merge this equality with the previous one. - diffs[pointer - 1][1] += diffs[pointer][1]; - diffs.splice(pointer, 1); - } else { - pointer++; - } - count_insert = 0; - count_delete = 0; - text_delete = ''; - text_insert = ''; - break; - } - } - if (diffs[diffs.length - 1][1] === '') { - diffs.pop(); // Remove the dummy entry at the end. - } - - // Second pass: look for single edits surrounded on both sides by equalities - // which can be shifted sideways to eliminate an equality. - // e.g: ABAC -> ABAC - var changes = false; - pointer = 1; - // Intentionally ignore the first and last element (don't need checking). - while (pointer < diffs.length - 1) { - if (diffs[pointer - 1][0] == DIFF_EQUAL && - diffs[pointer + 1][0] == DIFF_EQUAL) { - // This is a single edit surrounded by equalities. - if (diffs[pointer][1].substring(diffs[pointer][1].length - - diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) { - // Shift the edit over the previous equality. - diffs[pointer][1] = diffs[pointer - 1][1] + - diffs[pointer][1].substring(0, diffs[pointer][1].length - - diffs[pointer - 1][1].length); - diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; - diffs.splice(pointer - 1, 1); - changes = true; - } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) == - diffs[pointer + 1][1]) { - // Shift the edit over the next equality. - diffs[pointer - 1][1] += diffs[pointer + 1][1]; - diffs[pointer][1] = - diffs[pointer][1].substring(diffs[pointer + 1][1].length) + - diffs[pointer + 1][1]; - diffs.splice(pointer + 1, 1); - changes = true; - } - } - pointer++; - } - // If shifts were made, the diff needs reordering and another shift sweep. - if (changes) { - this.diff_cleanupMerge(diffs); - } -}; - - -/** - * loc is a location in text1, compute and return the equivalent location in - * text2. - * e.g. 'The cat' vs 'The big cat', 1->1, 5->8 - * @param {!Array.} diffs Array of diff tuples. - * @param {number} loc Location within text1. - * @return {number} Location within text2. - */ -diff_match_patch.prototype.diff_xIndex = function(diffs, loc) { - var chars1 = 0; - var chars2 = 0; - var last_chars1 = 0; - var last_chars2 = 0; - var x; - for (x = 0; x < diffs.length; x++) { - if (diffs[x][0] !== DIFF_INSERT) { // Equality or deletion. - chars1 += diffs[x][1].length; - } - if (diffs[x][0] !== DIFF_DELETE) { // Equality or insertion. - chars2 += diffs[x][1].length; - } - if (chars1 > loc) { // Overshot the location. - break; - } - last_chars1 = chars1; - last_chars2 = chars2; - } - // Was the location was deleted? - if (diffs.length != x && diffs[x][0] === DIFF_DELETE) { - return last_chars2; - } - // Add the remaining character length. - return last_chars2 + (loc - last_chars1); -}; - - -/** - * Convert a diff array into a pretty HTML report. - * @param {!Array.} diffs Array of diff tuples. - * @return {string} HTML representation. - */ -diff_match_patch.prototype.diff_prettyHtml = function(diffs) { - var html = []; - var pattern_amp = /&/g; - var pattern_lt = //g; - var pattern_para = /\n/g; - for (var x = 0; x < diffs.length; x++) { - var op = diffs[x][0]; // Operation (insert, delete, equal) - var data = diffs[x][1]; // Text of change. - var text = data.replace(pattern_amp, '&').replace(pattern_lt, '<') - .replace(pattern_gt, '>').replace(pattern_para, '¶
      '); - switch (op) { - case DIFF_INSERT: - html[x] = '' + text + ''; - break; - case DIFF_DELETE: - html[x] = '' + text + ''; - break; - case DIFF_EQUAL: - html[x] = '' + text + ''; - break; - } - } - return html.join(''); -}; - - -/** - * Compute and return the source text (all equalities and deletions). - * @param {!Array.} diffs Array of diff tuples. - * @return {string} Source text. - */ -diff_match_patch.prototype.diff_text1 = function(diffs) { - var text = []; - for (var x = 0; x < diffs.length; x++) { - if (diffs[x][0] !== DIFF_INSERT) { - text[x] = diffs[x][1]; - } - } - return text.join(''); -}; - - -/** - * Compute and return the destination text (all equalities and insertions). - * @param {!Array.} diffs Array of diff tuples. - * @return {string} Destination text. - */ -diff_match_patch.prototype.diff_text2 = function(diffs) { - var text = []; - for (var x = 0; x < diffs.length; x++) { - if (diffs[x][0] !== DIFF_DELETE) { - text[x] = diffs[x][1]; - } - } - return text.join(''); -}; - - -/** - * Compute the Levenshtein distance; the number of inserted, deleted or - * substituted characters. - * @param {!Array.} diffs Array of diff tuples. - * @return {number} Number of changes. - */ -diff_match_patch.prototype.diff_levenshtein = function(diffs) { - var levenshtein = 0; - var insertions = 0; - var deletions = 0; - for (var x = 0; x < diffs.length; x++) { - var op = diffs[x][0]; - var data = diffs[x][1]; - switch (op) { - case DIFF_INSERT: - insertions += data.length; - break; - case DIFF_DELETE: - deletions += data.length; - break; - case DIFF_EQUAL: - // A deletion and an insertion is one substitution. - levenshtein += Math.max(insertions, deletions); - insertions = 0; - deletions = 0; - break; - } - } - levenshtein += Math.max(insertions, deletions); - return levenshtein; -}; - - -/** - * Crush the diff into an encoded string which describes the operations - * required to transform text1 into text2. - * E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'. - * Operations are tab-separated. Inserted text is escaped using %xx notation. - * @param {!Array.} diffs Array of diff tuples. - * @return {string} Delta text. - */ -diff_match_patch.prototype.diff_toDelta = function(diffs) { - var text = []; - for (var x = 0; x < diffs.length; x++) { - switch (diffs[x][0]) { - case DIFF_INSERT: - text[x] = '+' + encodeURI(diffs[x][1]); - break; - case DIFF_DELETE: - text[x] = '-' + diffs[x][1].length; - break; - case DIFF_EQUAL: - text[x] = '=' + diffs[x][1].length; - break; - } - } - return text.join('\t').replace(/%20/g, ' '); -}; - - -/** - * Given the original text1, and an encoded string which describes the - * operations required to transform text1 into text2, compute the full diff. - * @param {string} text1 Source string for the diff. - * @param {string} delta Delta text. - * @return {!Array.} Array of diff tuples. - * @throws {!Error} If invalid input. - */ -diff_match_patch.prototype.diff_fromDelta = function(text1, delta) { - var diffs = []; - var diffsLength = 0; // Keeping our own length var is faster in JS. - var pointer = 0; // Cursor in text1 - var tokens = delta.split(/\t/g); - for (var x = 0; x < tokens.length; x++) { - // Each token begins with a one character parameter which specifies the - // operation of this token (delete, insert, equality). - var param = tokens[x].substring(1); - switch (tokens[x].charAt(0)) { - case '+': - try { - diffs[diffsLength++] = - new diff_match_patch.Diff(DIFF_INSERT, decodeURI(param)); - } catch (ex) { - // Malformed URI sequence. - throw new Error('Illegal escape in diff_fromDelta: ' + param); - } - break; - case '-': - // Fall through. - case '=': - var n = parseInt(param, 10); - if (isNaN(n) || n < 0) { - throw new Error('Invalid number in diff_fromDelta: ' + param); - } - var text = text1.substring(pointer, pointer += n); - if (tokens[x].charAt(0) == '=') { - diffs[diffsLength++] = new diff_match_patch.Diff(DIFF_EQUAL, text); - } else { - diffs[diffsLength++] = new diff_match_patch.Diff(DIFF_DELETE, text); - } - break; - default: - // Blank tokens are ok (from a trailing \t). - // Anything else is an error. - if (tokens[x]) { - throw new Error('Invalid diff operation in diff_fromDelta: ' + - tokens[x]); - } - } - } - if (pointer != text1.length) { - throw new Error('Delta length (' + pointer + - ') does not equal source text length (' + text1.length + ').'); - } - return diffs; -}; - - -// MATCH FUNCTIONS - - -/** - * Locate the best instance of 'pattern' in 'text' near 'loc'. - * @param {string} text The text to search. - * @param {string} pattern The pattern to search for. - * @param {number} loc The location to search around. - * @return {number} Best match index or -1. - */ -diff_match_patch.prototype.match_main = function(text, pattern, loc) { - // Check for null inputs. - if (text == null || pattern == null || loc == null) { - throw new Error('Null input. (match_main)'); - } - - loc = Math.max(0, Math.min(loc, text.length)); - if (text == pattern) { - // Shortcut (potentially not guaranteed by the algorithm) - return 0; - } else if (!text.length) { - // Nothing to match. - return -1; - } else if (text.substring(loc, loc + pattern.length) == pattern) { - // Perfect match at the perfect spot! (Includes case of null pattern) - return loc; - } else { - // Do a fuzzy compare. - return this.match_bitap_(text, pattern, loc); - } -}; - - -/** - * Locate the best instance of 'pattern' in 'text' near 'loc' using the - * Bitap algorithm. - * @param {string} text The text to search. - * @param {string} pattern The pattern to search for. - * @param {number} loc The location to search around. - * @return {number} Best match index or -1. - * @private - */ -diff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) { - if (pattern.length > this.Match_MaxBits) { - throw new Error('Pattern too long for this browser.'); - } - - // Initialise the alphabet. - var s = this.match_alphabet_(pattern); - - var dmp = this; // 'this' becomes 'window' in a closure. - - /** - * Compute and return the score for a match with e errors and x location. - * Accesses loc and pattern through being a closure. - * @param {number} e Number of errors in match. - * @param {number} x Location of match. - * @return {number} Overall score for match (0.0 = good, 1.0 = bad). - * @private - */ - function match_bitapScore_(e, x) { - var accuracy = e / pattern.length; - var proximity = Math.abs(loc - x); - if (!dmp.Match_Distance) { - // Dodge divide by zero error. - return proximity ? 1.0 : accuracy; - } - return accuracy + (proximity / dmp.Match_Distance); - } - - // Highest score beyond which we give up. - var score_threshold = this.Match_Threshold; - // Is there a nearby exact match? (speedup) - var best_loc = text.indexOf(pattern, loc); - if (best_loc != -1) { - score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold); - // What about in the other direction? (speedup) - best_loc = text.lastIndexOf(pattern, loc + pattern.length); - if (best_loc != -1) { - score_threshold = - Math.min(match_bitapScore_(0, best_loc), score_threshold); - } - } - - // Initialise the bit arrays. - var matchmask = 1 << (pattern.length - 1); - best_loc = -1; - - var bin_min, bin_mid; - var bin_max = pattern.length + text.length; - var last_rd; - for (var d = 0; d < pattern.length; d++) { - // Scan for the best match; each iteration allows for one more error. - // Run a binary search to determine how far from 'loc' we can stray at this - // error level. - bin_min = 0; - bin_mid = bin_max; - while (bin_min < bin_mid) { - if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) { - bin_min = bin_mid; - } else { - bin_max = bin_mid; - } - bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min); - } - // Use the result from this iteration as the maximum for the next. - bin_max = bin_mid; - var start = Math.max(1, loc - bin_mid + 1); - var finish = Math.min(loc + bin_mid, text.length) + pattern.length; - - var rd = Array(finish + 2); - rd[finish + 1] = (1 << d) - 1; - for (var j = finish; j >= start; j--) { - // The alphabet (s) is a sparse hash, so the following line generates - // warnings. - var charMatch = s[text.charAt(j - 1)]; - if (d === 0) { // First pass: exact match. - rd[j] = ((rd[j + 1] << 1) | 1) & charMatch; - } else { // Subsequent passes: fuzzy match. - rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) | - (((last_rd[j + 1] | last_rd[j]) << 1) | 1) | - last_rd[j + 1]; - } - if (rd[j] & matchmask) { - var score = match_bitapScore_(d, j - 1); - // This match will almost certainly be better than any existing match. - // But check anyway. - if (score <= score_threshold) { - // Told you so. - score_threshold = score; - best_loc = j - 1; - if (best_loc > loc) { - // When passing loc, don't exceed our current distance from loc. - start = Math.max(1, 2 * loc - best_loc); - } else { - // Already passed loc, downhill from here on in. - break; - } - } - } - } - // No hope for a (better) match at greater error levels. - if (match_bitapScore_(d + 1, loc) > score_threshold) { - break; - } - last_rd = rd; - } - return best_loc; -}; - - -/** - * Initialise the alphabet for the Bitap algorithm. - * @param {string} pattern The text to encode. - * @return {!Object} Hash of character locations. - * @private - */ -diff_match_patch.prototype.match_alphabet_ = function(pattern) { - var s = {}; - for (var i = 0; i < pattern.length; i++) { - s[pattern.charAt(i)] = 0; - } - for (var i = 0; i < pattern.length; i++) { - s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1); - } - return s; -}; - - -// PATCH FUNCTIONS - - -/** - * Increase the context until it is unique, - * but don't let the pattern expand beyond Match_MaxBits. - * @param {!diff_match_patch.patch_obj} patch The patch to grow. - * @param {string} text Source text. - * @private - */ -diff_match_patch.prototype.patch_addContext_ = function(patch, text) { - if (text.length == 0) { - return; - } - if (patch.start2 === null) { - throw Error('patch not initialized'); - } - var pattern = text.substring(patch.start2, patch.start2 + patch.length1); - var padding = 0; - - // Look for the first and last matches of pattern in text. If two different - // matches are found, increase the pattern length. - while (text.indexOf(pattern) != text.lastIndexOf(pattern) && - pattern.length < this.Match_MaxBits - this.Patch_Margin - - this.Patch_Margin) { - padding += this.Patch_Margin; - pattern = text.substring(patch.start2 - padding, - patch.start2 + patch.length1 + padding); - } - // Add one chunk for good luck. - padding += this.Patch_Margin; - - // Add the prefix. - var prefix = text.substring(patch.start2 - padding, patch.start2); - if (prefix) { - patch.diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL, prefix)); - } - // Add the suffix. - var suffix = text.substring(patch.start2 + patch.length1, - patch.start2 + patch.length1 + padding); - if (suffix) { - patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, suffix)); - } - - // Roll back the start points. - patch.start1 -= prefix.length; - patch.start2 -= prefix.length; - // Extend the lengths. - patch.length1 += prefix.length + suffix.length; - patch.length2 += prefix.length + suffix.length; -}; - - -/** - * Compute a list of patches to turn text1 into text2. - * Use diffs if provided, otherwise compute it ourselves. - * There are four ways to call this function, depending on what data is - * available to the caller: - * Method 1: - * a = text1, b = text2 - * Method 2: - * a = diffs - * Method 3 (optimal): - * a = text1, b = diffs - * Method 4 (deprecated, use method 3): - * a = text1, b = text2, c = diffs - * - * @param {string|!Array.} a text1 (methods 1,3,4) or - * Array of diff tuples for text1 to text2 (method 2). - * @param {string|!Array.=} opt_b text2 (methods 1,4) or - * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2). - * @param {string|!Array.=} opt_c Array of diff tuples - * for text1 to text2 (method 4) or undefined (methods 1,2,3). - * @return {!Array.} Array of Patch objects. - */ -diff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) { - var text1, diffs; - if (typeof a == 'string' && typeof opt_b == 'string' && - typeof opt_c == 'undefined') { - // Method 1: text1, text2 - // Compute diffs from text1 and text2. - text1 = /** @type {string} */(a); - diffs = this.diff_main(text1, /** @type {string} */(opt_b), true); - if (diffs.length > 2) { - this.diff_cleanupSemantic(diffs); - this.diff_cleanupEfficiency(diffs); - } - } else if (a && typeof a == 'object' && typeof opt_b == 'undefined' && - typeof opt_c == 'undefined') { - // Method 2: diffs - // Compute text1 from diffs. - diffs = /** @type {!Array.} */(a); - text1 = this.diff_text1(diffs); - } else if (typeof a == 'string' && opt_b && typeof opt_b == 'object' && - typeof opt_c == 'undefined') { - // Method 3: text1, diffs - text1 = /** @type {string} */(a); - diffs = /** @type {!Array.} */(opt_b); - } else if (typeof a == 'string' && typeof opt_b == 'string' && - opt_c && typeof opt_c == 'object') { - // Method 4: text1, text2, diffs - // text2 is not used. - text1 = /** @type {string} */(a); - diffs = /** @type {!Array.} */(opt_c); - } else { - throw new Error('Unknown call format to patch_make.'); - } - - if (diffs.length === 0) { - return []; // Get rid of the null case. - } - var patches = []; - var patch = new diff_match_patch.patch_obj(); - var patchDiffLength = 0; // Keeping our own length var is faster in JS. - var char_count1 = 0; // Number of characters into the text1 string. - var char_count2 = 0; // Number of characters into the text2 string. - // Start with text1 (prepatch_text) and apply the diffs until we arrive at - // text2 (postpatch_text). We recreate the patches one by one to determine - // context info. - var prepatch_text = text1; - var postpatch_text = text1; - for (var x = 0; x < diffs.length; x++) { - var diff_type = diffs[x][0]; - var diff_text = diffs[x][1]; - - if (!patchDiffLength && diff_type !== DIFF_EQUAL) { - // A new patch starts here. - patch.start1 = char_count1; - patch.start2 = char_count2; - } - - switch (diff_type) { - case DIFF_INSERT: - patch.diffs[patchDiffLength++] = diffs[x]; - patch.length2 += diff_text.length; - postpatch_text = postpatch_text.substring(0, char_count2) + diff_text + - postpatch_text.substring(char_count2); - break; - case DIFF_DELETE: - patch.length1 += diff_text.length; - patch.diffs[patchDiffLength++] = diffs[x]; - postpatch_text = postpatch_text.substring(0, char_count2) + - postpatch_text.substring(char_count2 + - diff_text.length); - break; - case DIFF_EQUAL: - if (diff_text.length <= 2 * this.Patch_Margin && - patchDiffLength && diffs.length != x + 1) { - // Small equality inside a patch. - patch.diffs[patchDiffLength++] = diffs[x]; - patch.length1 += diff_text.length; - patch.length2 += diff_text.length; - } else if (diff_text.length >= 2 * this.Patch_Margin) { - // Time for a new patch. - if (patchDiffLength) { - this.patch_addContext_(patch, prepatch_text); - patches.push(patch); - patch = new diff_match_patch.patch_obj(); - patchDiffLength = 0; - // Unlike Unidiff, our patch lists have a rolling context. - // https://github.com/google/diff-match-patch/wiki/Unidiff - // Update prepatch text & pos to reflect the application of the - // just completed patch. - prepatch_text = postpatch_text; - char_count1 = char_count2; - } - } - break; - } - - // Update the current character count. - if (diff_type !== DIFF_INSERT) { - char_count1 += diff_text.length; - } - if (diff_type !== DIFF_DELETE) { - char_count2 += diff_text.length; - } - } - // Pick up the leftover patch if not empty. - if (patchDiffLength) { - this.patch_addContext_(patch, prepatch_text); - patches.push(patch); - } - - return patches; -}; - - -/** - * Given an array of patches, return another array that is identical. - * @param {!Array.} patches Array of Patch objects. - * @return {!Array.} Array of Patch objects. - */ -diff_match_patch.prototype.patch_deepCopy = function(patches) { - // Making deep copies is hard in JavaScript. - var patchesCopy = []; - for (var x = 0; x < patches.length; x++) { - var patch = patches[x]; - var patchCopy = new diff_match_patch.patch_obj(); - patchCopy.diffs = []; - for (var y = 0; y < patch.diffs.length; y++) { - patchCopy.diffs[y] = - new diff_match_patch.Diff(patch.diffs[y][0], patch.diffs[y][1]); - } - patchCopy.start1 = patch.start1; - patchCopy.start2 = patch.start2; - patchCopy.length1 = patch.length1; - patchCopy.length2 = patch.length2; - patchesCopy[x] = patchCopy; - } - return patchesCopy; -}; - - -/** - * Merge a set of patches onto the text. Return a patched text, as well - * as a list of true/false values indicating which patches were applied. - * @param {!Array.} patches Array of Patch objects. - * @param {string} text Old text. - * @return {!Array.>} Two element Array, containing the - * new text and an array of boolean values. - */ -diff_match_patch.prototype.patch_apply = function(patches, text) { - if (patches.length == 0) { - return [text, []]; - } - - // Deep copy the patches so that no changes are made to originals. - patches = this.patch_deepCopy(patches); - - var nullPadding = this.patch_addPadding(patches); - text = nullPadding + text + nullPadding; - - this.patch_splitMax(patches); - // delta keeps track of the offset between the expected and actual location - // of the previous patch. If there are patches expected at positions 10 and - // 20, but the first patch was found at 12, delta is 2 and the second patch - // has an effective expected position of 22. - var delta = 0; - var results = []; - for (var x = 0; x < patches.length; x++) { - var expected_loc = patches[x].start2 + delta; - var text1 = this.diff_text1(patches[x].diffs); - var start_loc; - var end_loc = -1; - if (text1.length > this.Match_MaxBits) { - // patch_splitMax will only provide an oversized pattern in the case of - // a monster delete. - start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits), - expected_loc); - if (start_loc != -1) { - end_loc = this.match_main(text, - text1.substring(text1.length - this.Match_MaxBits), - expected_loc + text1.length - this.Match_MaxBits); - if (end_loc == -1 || start_loc >= end_loc) { - // Can't find valid trailing context. Drop this patch. - start_loc = -1; - } - } - } else { - start_loc = this.match_main(text, text1, expected_loc); - } - if (start_loc == -1) { - // No match found. :( - results[x] = false; - // Subtract the delta for this failed patch from subsequent patches. - delta -= patches[x].length2 - patches[x].length1; - } else { - // Found a match. :) - results[x] = true; - delta = start_loc - expected_loc; - var text2; - if (end_loc == -1) { - text2 = text.substring(start_loc, start_loc + text1.length); - } else { - text2 = text.substring(start_loc, end_loc + this.Match_MaxBits); - } - if (text1 == text2) { - // Perfect match, just shove the replacement text in. - text = text.substring(0, start_loc) + - this.diff_text2(patches[x].diffs) + - text.substring(start_loc + text1.length); - } else { - // Imperfect match. Run a diff to get a framework of equivalent - // indices. - var diffs = this.diff_main(text1, text2, false); - if (text1.length > this.Match_MaxBits && - this.diff_levenshtein(diffs) / text1.length > - this.Patch_DeleteThreshold) { - // The end points match, but the content is unacceptably bad. - results[x] = false; - } else { - this.diff_cleanupSemanticLossless(diffs); - var index1 = 0; - var index2; - for (var y = 0; y < patches[x].diffs.length; y++) { - var mod = patches[x].diffs[y]; - if (mod[0] !== DIFF_EQUAL) { - index2 = this.diff_xIndex(diffs, index1); - } - if (mod[0] === DIFF_INSERT) { // Insertion - text = text.substring(0, start_loc + index2) + mod[1] + - text.substring(start_loc + index2); - } else if (mod[0] === DIFF_DELETE) { // Deletion - text = text.substring(0, start_loc + index2) + - text.substring(start_loc + this.diff_xIndex(diffs, - index1 + mod[1].length)); - } - if (mod[0] !== DIFF_DELETE) { - index1 += mod[1].length; - } - } - } - } - } - } - // Strip the padding off. - text = text.substring(nullPadding.length, text.length - nullPadding.length); - return [text, results]; -}; - - -/** - * Add some padding on text start and end so that edges can match something. - * Intended to be called only from within patch_apply. - * @param {!Array.} patches Array of Patch objects. - * @return {string} The padding string added to each side. - */ -diff_match_patch.prototype.patch_addPadding = function(patches) { - var paddingLength = this.Patch_Margin; - var nullPadding = ''; - for (var x = 1; x <= paddingLength; x++) { - nullPadding += String.fromCharCode(x); - } - - // Bump all the patches forward. - for (var x = 0; x < patches.length; x++) { - patches[x].start1 += paddingLength; - patches[x].start2 += paddingLength; - } - - // Add some padding on start of first diff. - var patch = patches[0]; - var diffs = patch.diffs; - if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) { - // Add nullPadding equality. - diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL, nullPadding)); - patch.start1 -= paddingLength; // Should be 0. - patch.start2 -= paddingLength; // Should be 0. - patch.length1 += paddingLength; - patch.length2 += paddingLength; - } else if (paddingLength > diffs[0][1].length) { - // Grow first equality. - var extraLength = paddingLength - diffs[0][1].length; - diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1]; - patch.start1 -= extraLength; - patch.start2 -= extraLength; - patch.length1 += extraLength; - patch.length2 += extraLength; - } - - // Add some padding on end of last diff. - patch = patches[patches.length - 1]; - diffs = patch.diffs; - if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) { - // Add nullPadding equality. - diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, nullPadding)); - patch.length1 += paddingLength; - patch.length2 += paddingLength; - } else if (paddingLength > diffs[diffs.length - 1][1].length) { - // Grow last equality. - var extraLength = paddingLength - diffs[diffs.length - 1][1].length; - diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength); - patch.length1 += extraLength; - patch.length2 += extraLength; - } - - return nullPadding; -}; - - -/** - * Look through the patches and break up any which are longer than the maximum - * limit of the match algorithm. - * Intended to be called only from within patch_apply. - * @param {!Array.} patches Array of Patch objects. - */ -diff_match_patch.prototype.patch_splitMax = function(patches) { - var patch_size = this.Match_MaxBits; - for (var x = 0; x < patches.length; x++) { - if (patches[x].length1 <= patch_size) { - continue; - } - var bigpatch = patches[x]; - // Remove the big old patch. - patches.splice(x--, 1); - var start1 = bigpatch.start1; - var start2 = bigpatch.start2; - var precontext = ''; - while (bigpatch.diffs.length !== 0) { - // Create one of several smaller patches. - var patch = new diff_match_patch.patch_obj(); - var empty = true; - patch.start1 = start1 - precontext.length; - patch.start2 = start2 - precontext.length; - if (precontext !== '') { - patch.length1 = patch.length2 = precontext.length; - patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, precontext)); - } - while (bigpatch.diffs.length !== 0 && - patch.length1 < patch_size - this.Patch_Margin) { - var diff_type = bigpatch.diffs[0][0]; - var diff_text = bigpatch.diffs[0][1]; - if (diff_type === DIFF_INSERT) { - // Insertions are harmless. - patch.length2 += diff_text.length; - start2 += diff_text.length; - patch.diffs.push(bigpatch.diffs.shift()); - empty = false; - } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 && - patch.diffs[0][0] == DIFF_EQUAL && - diff_text.length > 2 * patch_size) { - // This is a large deletion. Let it pass in one chunk. - patch.length1 += diff_text.length; - start1 += diff_text.length; - empty = false; - patch.diffs.push(new diff_match_patch.Diff(diff_type, diff_text)); - bigpatch.diffs.shift(); - } else { - // Deletion or equality. Only take as much as we can stomach. - diff_text = diff_text.substring(0, - patch_size - patch.length1 - this.Patch_Margin); - patch.length1 += diff_text.length; - start1 += diff_text.length; - if (diff_type === DIFF_EQUAL) { - patch.length2 += diff_text.length; - start2 += diff_text.length; - } else { - empty = false; - } - patch.diffs.push(new diff_match_patch.Diff(diff_type, diff_text)); - if (diff_text == bigpatch.diffs[0][1]) { - bigpatch.diffs.shift(); - } else { - bigpatch.diffs[0][1] = - bigpatch.diffs[0][1].substring(diff_text.length); - } - } - } - // Compute the head context for the next patch. - precontext = this.diff_text2(patch.diffs); - precontext = - precontext.substring(precontext.length - this.Patch_Margin); - // Append the end context for this patch. - var postcontext = this.diff_text1(bigpatch.diffs) - .substring(0, this.Patch_Margin); - if (postcontext !== '') { - patch.length1 += postcontext.length; - patch.length2 += postcontext.length; - if (patch.diffs.length !== 0 && - patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) { - patch.diffs[patch.diffs.length - 1][1] += postcontext; - } else { - patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, postcontext)); - } - } - if (!empty) { - patches.splice(++x, 0, patch); - } - } - } -}; - - -/** - * Take a list of patches and return a textual representation. - * @param {!Array.} patches Array of Patch objects. - * @return {string} Text representation of patches. - */ -diff_match_patch.prototype.patch_toText = function(patches) { - var text = []; - for (var x = 0; x < patches.length; x++) { - text[x] = patches[x]; - } - return text.join(''); -}; - - -/** - * Parse a textual representation of patches and return a list of Patch objects. - * @param {string} textline Text representation of patches. - * @return {!Array.} Array of Patch objects. - * @throws {!Error} If invalid input. - */ -diff_match_patch.prototype.patch_fromText = function(textline) { - var patches = []; - if (!textline) { - return patches; - } - var text = textline.split('\n'); - var textPointer = 0; - var patchHeader = /^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/; - while (textPointer < text.length) { - var m = text[textPointer].match(patchHeader); - if (!m) { - throw new Error('Invalid patch string: ' + text[textPointer]); - } - var patch = new diff_match_patch.patch_obj(); - patches.push(patch); - patch.start1 = parseInt(m[1], 10); - if (m[2] === '') { - patch.start1--; - patch.length1 = 1; - } else if (m[2] == '0') { - patch.length1 = 0; - } else { - patch.start1--; - patch.length1 = parseInt(m[2], 10); - } - - patch.start2 = parseInt(m[3], 10); - if (m[4] === '') { - patch.start2--; - patch.length2 = 1; - } else if (m[4] == '0') { - patch.length2 = 0; - } else { - patch.start2--; - patch.length2 = parseInt(m[4], 10); - } - textPointer++; - - while (textPointer < text.length) { - var sign = text[textPointer].charAt(0); - try { - var line = decodeURI(text[textPointer].substring(1)); - } catch (ex) { - // Malformed URI sequence. - throw new Error('Illegal escape in patch_fromText: ' + line); - } - if (sign == '-') { - // Deletion. - patch.diffs.push(new diff_match_patch.Diff(DIFF_DELETE, line)); - } else if (sign == '+') { - // Insertion. - patch.diffs.push(new diff_match_patch.Diff(DIFF_INSERT, line)); - } else if (sign == ' ') { - // Minor equality. - patch.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL, line)); - } else if (sign == '@') { - // Start of next patch. - break; - } else if (sign === '') { - // Blank line? Whatever. - } else { - // WTF? - throw new Error('Invalid patch mode "' + sign + '" in: ' + line); - } - textPointer++; - } - } - return patches; -}; - - -/** - * Class representing one patch operation. - * @constructor - */ -diff_match_patch.patch_obj = function() { - /** @type {!Array.} */ - this.diffs = []; - /** @type {?number} */ - this.start1 = null; - /** @type {?number} */ - this.start2 = null; - /** @type {number} */ - this.length1 = 0; - /** @type {number} */ - this.length2 = 0; -}; - - -/** - * Emulate GNU diff's format. - * Header: @@ -382,8 +481,9 @@ - * Indices are printed as 1-based, not 0-based. - * @return {string} The GNU diff string. - */ -diff_match_patch.patch_obj.prototype.toString = function() { - var coords1, coords2; - if (this.length1 === 0) { - coords1 = this.start1 + ',0'; - } else if (this.length1 == 1) { - coords1 = this.start1 + 1; - } else { - coords1 = (this.start1 + 1) + ',' + this.length1; - } - if (this.length2 === 0) { - coords2 = this.start2 + ',0'; - } else if (this.length2 == 1) { - coords2 = this.start2 + 1; - } else { - coords2 = (this.start2 + 1) + ',' + this.length2; - } - var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\n']; - var op; - // Escape the body of the patch with %xx notation. - for (var x = 0; x < this.diffs.length; x++) { - switch (this.diffs[x][0]) { - case DIFF_INSERT: - op = '+'; - break; - case DIFF_DELETE: - op = '-'; - break; - case DIFF_EQUAL: - op = ' '; - break; - } - text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\n'; - } - return text.join('').replace(/%20/g, ' '); -}; - -module.exports = { diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL }; diff --git a/packages/playwright-core/src/utils/DEPS.list b/packages/playwright-core/src/utils/DEPS.list index 514f09d407344..7cfdafe4a1ca4 100644 --- a/packages/playwright-core/src/utils/DEPS.list +++ b/packages/playwright-core/src/utils/DEPS.list @@ -1,6 +1,5 @@ [*] ./ -../third_party/diff_match_patch ../third_party/pixelmatch ../image_tools/compare.ts ../utilsBundle.ts diff --git a/packages/playwright-core/src/utils/comparators.ts b/packages/playwright-core/src/utils/comparators.ts index ef63b2d37661e..da707e20c4d13 100644 --- a/packages/playwright-core/src/utils/comparators.ts +++ b/packages/playwright-core/src/utils/comparators.ts @@ -18,7 +18,7 @@ import { colors, jpegjs } from '../utilsBundle'; const pixelmatch = require('../third_party/pixelmatch'); import { compare } from '../image_tools/compare'; -const { diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL } = require('../third_party/diff_match_patch'); +const { diffMatchPatch } = require('../utilsBundle'); import { PNG } from '../utilsBundle'; export type ImageComparatorOptions = { threshold?: number, maxDiffPixels?: number, maxDiffPixelRatio?: number, comparator?: string }; @@ -106,6 +106,7 @@ function validateBuffer(buffer: Buffer, mimeType: string): void { } function compareText(actual: Buffer | string, expectedBuffer: Buffer): ComparatorResult { + const { diff_match_patch } = diffMatchPatch; if (typeof actual !== 'string') return { errorMessage: 'Actual result should be a string' }; const expected = expectedBuffer.toString('utf-8'); @@ -120,6 +121,7 @@ function compareText(actual: Buffer | string, expectedBuffer: Buffer): Comparato } function diff_prettyTerminal(diffs: [number, string][]) { + const { DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL } = diffMatchPatch; const html = []; for (let x = 0; x < diffs.length; x++) { const op = diffs[x][0]; // Operation (insert, delete, equal) diff --git a/packages/playwright-core/src/utils/index.ts b/packages/playwright-core/src/utils/index.ts index 0bc7a75b08e5e..c570e7b32e651 100644 --- a/packages/playwright-core/src/utils/index.ts +++ b/packages/playwright-core/src/utils/index.ts @@ -33,6 +33,7 @@ export * from './isomorphic/stringUtils'; export * from './isomorphic/urlMatch'; export * from './multimap'; export * from './network'; +export * from './patch'; export * from './processLauncher'; export * from './profiler'; export * from './rtti'; diff --git a/packages/playwright-core/src/utils/patch.ts b/packages/playwright-core/src/utils/patch.ts new file mode 100644 index 0000000000000..91fa31b8f3f0f --- /dev/null +++ b/packages/playwright-core/src/utils/patch.ts @@ -0,0 +1,127 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { diffMatchPatch } from '../utilsBundle'; + +type Hunk = { + lines: string[]; + startNew: number; + startOld: number; + contextBefore: number; + contextAfter: number; +}; + +export function generateUnifiedDiff(text1: string, text2: string, relativeName: string = 'file'): string { + const { diff_match_patch, DIFF_EQUAL, DIFF_DELETE, DIFF_INSERT } = diffMatchPatch; + const dmp = new diff_match_patch(); + + const a = text1.replace(/\r\n/g, '\n'); + const b = text2.replace(/\r\n/g, '\n'); + + const { chars1, chars2, lineArray } = dmp.diff_linesToChars_(a, b); + const diffs = dmp.diff_main(chars1, chars2, false); + dmp.diff_charsToLines_(diffs, lineArray); + + const contextSize = 3; + const hunks: Hunk[] = []; + let lineOld = 1; + let lineNew = 1; + let hunk: Hunk | null = null; + let contextBuffer: string[] = []; + + for (const diff of diffs) { + const op = diff[0]; + const data = diff[1]; + const lines = data.split('\n'); + + // Remove the last empty line if data ends with '\n' + if (lines[lines.length - 1] === '') + lines.pop(); + + for (const line of lines) { + if (op === DIFF_EQUAL) { + if (hunk) { + hunk.lines.push(' ' + line); + hunk.contextAfter++; + + if (hunk.contextAfter >= contextSize) { + // Close the hunk + hunks.push(hunk); + hunk = null; + contextBuffer = []; + } + } else { + contextBuffer.push(' ' + line); + if (contextBuffer.length > contextSize) + contextBuffer.shift(); + } + lineOld++; + lineNew++; + } else { + if (!hunk) { + // Start a new hunk + const hunkStartOld = lineOld - contextBuffer.length; + const hunkStartNew = lineNew - contextBuffer.length; + hunk = { + startOld: hunkStartOld, + startNew: hunkStartNew, + lines: [...contextBuffer], + contextBefore: contextBuffer.length, + contextAfter: 0, + }; + } + hunk.contextAfter = 0; + + if (op === DIFF_DELETE) { + hunk.lines.push('-' + line); + lineOld++; + } else if (op === DIFF_INSERT) { + hunk.lines.push('+' + line); + lineNew++; + } + } + } + } + + if (hunk) + hunks.push(hunk); + + // Build the unified diff text + let diffText = `--- a/${relativeName}\n+++ b/${relativeName}\n`; + for (const hunk of hunks) { + // Calculate hunk ranges + const oldRangeStart = hunk.startOld; + const newRangeStart = hunk.startNew; + let oldRangeLines = 0; + let newRangeLines = 0; + + for (const line of hunk.lines) { + if (line.startsWith('-') || line.startsWith(' ')) + oldRangeLines++; + if (line.startsWith('+') || line.startsWith(' ')) + newRangeLines++; + } + + // Adjust starting line numbers when range is empty + const oldStartLine = oldRangeLines === 0 ? oldRangeStart - 1 : oldRangeStart; + const newStartLine = newRangeLines === 0 ? newRangeStart - 1 : newRangeStart; + + diffText += `@@ -${oldStartLine},${oldRangeLines} +${newStartLine},${newRangeLines} @@\n`; + diffText += hunk.lines.map(line => line + '\n').join(''); + } + + return diffText; +} diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts index b330491e0cbed..f9dc8347f7d23 100644 --- a/packages/playwright-core/src/utilsBundle.ts +++ b/packages/playwright-core/src/utilsBundle.ts @@ -19,6 +19,7 @@ import path from 'path'; export const colors: typeof import('../bundles/utils/node_modules/colors/safe') = require('./utilsBundleImpl').colors; export const debug: typeof import('../bundles/utils/node_modules/@types/debug') = require('./utilsBundleImpl').debug; +export const diffMatchPatch: typeof import('../bundles/utils/node_modules/@types/diff-match-patch') = require('./utilsBundleImpl').diffMatchPatch; export const dotenv: typeof import('../bundles/utils/node_modules/dotenv') = require('./utilsBundleImpl').dotenv; export const getProxyForUrl: typeof import('../bundles/utils/node_modules/@types/proxy-from-env').getProxyForUrl = require('./utilsBundleImpl').getProxyForUrl; export const HttpsProxyAgent: typeof import('../bundles/utils/node_modules/https-proxy-agent').HttpsProxyAgent = require('./utilsBundleImpl').HttpsProxyAgent; diff --git a/tests/library/clock.spec.ts b/tests/library/unit/clock.spec.ts similarity index 99% rename from tests/library/clock.spec.ts rename to tests/library/unit/clock.spec.ts index 3db8e968a28b4..cb204cef07a14 100644 --- a/tests/library/clock.spec.ts +++ b/tests/library/unit/clock.spec.ts @@ -15,8 +15,8 @@ */ import { test, expect } from '@playwright/test'; -import { createClock as rawCreateClock, install as rawInstall } from '../../packages/playwright-core/src/server/injected/clock'; -import type { InstallConfig, ClockController, ClockMethods } from '../../packages/playwright-core/src/server/injected/clock'; +import { createClock as rawCreateClock, install as rawInstall } from '../../../packages/playwright-core/src/server/injected/clock'; +import type { InstallConfig, ClockController, ClockMethods } from '../../../packages/playwright-core/src/server/injected/clock'; const createClock = (now?: number): ClockController & ClockMethods => { const { clock, api } = rawCreateClock(globalThis); diff --git a/tests/library/unit/patch.spec.ts b/tests/library/unit/patch.spec.ts new file mode 100644 index 0000000000000..1188faff6bb2c --- /dev/null +++ b/tests/library/unit/patch.spec.ts @@ -0,0 +1,260 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { test as it, expect } from '@playwright/test'; +import { generateUnifiedDiff } from '../../../packages/playwright-core/lib/utils/patch'; + +it('Identical texts should produce an empty diff', () => { + const text1 = `line1 +line2 +line3`; + const text2 = `line1 +line2 +line3`; + + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toBe(`--- a/file ++++ b/file +`); +}); + +it('Text with an inserted line', () => { + const text1 = `line1 +line2 +line3`; + const text2 = `line1 +line2 +line2.5 +line3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,4 @@ + line1 + line2 ++line2.5 + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Text with a deleted line', () => { + const text1 = `line1 +line2 +line3`; + const text2 = `line1 +line3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,2 @@ + line1 +-line2 + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Text with modified line', () => { + const text1 = `line1 +line2 +line3`; + const text2 = `line1 +line2 modified +line3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,3 @@ + line1 +-line2 ++line2 modified + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Empty original text', () => { + const text1 = ``; + const text2 = `line1 +line2`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -0,0 +1,2 @@ ++line1 ++line2 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Empty modified text', () => { + const text1 = `line1 +line2`; + const text2 = ``; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,2 +0,0 @@ +-line1 +-line2 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Handling different line endings (CRLF vs LF)', () => { + const text1 = `line1\r\nline2\r\nline3`; + const text2 = `line1\nline2 modified\nline3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,3 @@ + line1 +-line2 ++line2 modified + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Large text diff', () => { + const text1 = Array(1000) + .fill('line') + .join('\n'); + const text2 = Array(1000) + .fill('line') + .map((line, index) => (index === 500 ? 'modified line' : line)) + .join('\n'); + + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain('-line\n+modified line'); +}); + +it('Unicode characters', () => { + const text1 = `こんにちは +世界`; + const text2 = `こんにちは +世界! +さようなら`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,2 +1,3 @@ + こんにちは +-世界 ++世界! ++さようなら +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Texts with only whitespace differences', () => { + const text1 = `line1 +line2 +line3`; + const text2 = `line1 +line2 +line3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,3 @@ + line1 +-line2 ++line2 + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toBe(expectedDiff); +}); + +it('Custom file names in diff header', () => { + const text1 = `line1 +line2 +line3`; + const text2 = `line1 +line2 modified +line3`; + + const diff = generateUnifiedDiff(text1, text2, 'original.txt'); + expect(diff.startsWith('--- a/original.txt\n+++ b/original.txt\n')).toBe(true); +}); + +it('Multiple consecutive insertions and deletions', () => { + const text1 = `line1 +line2 +line3 +line4 +line5`; + const text2 = `line1 +line2 modified +line3 +line4 modified +line5`; + + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain('-line2\n+line2 modified'); + expect(diff).toContain('-line4\n+line4 modified'); +}); + +it('Handling tabs and special characters', () => { + const text1 = `line1 +line\t2 +line3`; + const text2 = `line1 +line2 +line3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,3 @@ + line1 +-line\t2 ++line2 + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); + +it('Texts with leading and trailing whitespace differences', () => { + const text1 = ` line1 +line2 +line3`; + const text2 = `line1 +line2 +line3`; + + const expectedDiff = `--- a/file ++++ b/file +@@ -1,3 +1,3 @@ +- line1 +-line2 ++line1 ++line2 + line3 +`; + const diff = generateUnifiedDiff(text1, text2); + expect(diff).toContain(expectedDiff); +}); diff --git a/tests/library/sequence.spec.ts b/tests/library/unit/sequence.spec.ts similarity index 98% rename from tests/library/sequence.spec.ts rename to tests/library/unit/sequence.spec.ts index 6004ce4da5195..624722753e4fa 100644 --- a/tests/library/sequence.spec.ts +++ b/tests/library/unit/sequence.spec.ts @@ -16,7 +16,7 @@ import { test as it, expect } from '@playwright/test'; -import { findRepeatedSubsequences } from '../../packages/playwright-core/lib/utils/sequence'; +import { findRepeatedSubsequences } from '../../../packages/playwright-core/lib/utils/sequence'; it('should return an empty array when the input is empty', () => { const input = []; From 9a0a6cec1061f277b43110f442aeee66a52a090f Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 23 Oct 2024 17:34:21 -0700 Subject: [PATCH 361/805] chore: remove the leaf node notion (#33249) --- .../src/server/injected/ariaSnapshot.ts | 60 +++++-------------- tests/page/page-aria-snapshot.spec.ts | 42 +++++++++---- 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index 7156d0cce7e2f..d544c0a82ca35 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -16,7 +16,7 @@ import { escapeWithQuotes } from '@isomorphic/stringUtils'; import * as roleUtils from './roleUtils'; -import { isElementVisible, isElementStyleVisibilityVisible, getElementComputedStyle } from './domUtils'; +import { getElementComputedStyle } from './domUtils'; import type { AriaRole } from './roleUtils'; type AriaProps = { @@ -29,7 +29,7 @@ type AriaProps = { }; type AriaNode = AriaProps & { - role: AriaRole | 'fragment' | 'text'; + role: AriaRole | 'fragment'; name: string; children: (AriaNode | string)[]; }; @@ -56,22 +56,10 @@ export function generateAriaTree(rootElement: Element): AriaNode { if (roleUtils.isElementHiddenForAria(element)) return; - const visible = isElementVisible(element); - const hasVisibleChildren = isElementStyleVisibilityVisible(element); - - if (!hasVisibleChildren) - return; - - if (visible) { - const childAriaNode = toAriaNode(element); - const isHiddenContainer = childAriaNode && hiddenContainerRoles.has(childAriaNode.ariaNode.role); - if (childAriaNode && !isHiddenContainer) - ariaNode.children.push(childAriaNode.ariaNode); - if (isHiddenContainer || !childAriaNode?.isLeaf) - processChildNodes(childAriaNode?.ariaNode || ariaNode, element); - } else { - processChildNodes(ariaNode, element); - } + const childAriaNode = toAriaNode(element); + if (childAriaNode) + ariaNode.children.push(childAriaNode); + processChildNodes(childAriaNode || ariaNode, element); }; function processChildNodes(ariaNode: AriaNode, element: Element) { @@ -101,6 +89,9 @@ export function generateAriaTree(rootElement: Element): AriaNode { if (treatAsBlock) ariaNode.children.push(treatAsBlock); + + if (ariaNode.children.length === 1 && ariaNode.name === ariaNode.children[0]) + ariaNode.children = []; } roleUtils.beginAriaCaches(); @@ -115,19 +106,13 @@ export function generateAriaTree(rootElement: Element): AriaNode { return ariaRoot; } -function toAriaNode(element: Element): { ariaNode: AriaNode, isLeaf: boolean } | null { +function toAriaNode(element: Element): AriaNode | null { const role = roleUtils.getAriaRole(element); if (!role) return null; const name = roleUtils.getElementAccessibleName(element, false) || ''; - const isLeaf = leafRoles.has(role); const result: AriaNode = { role, name, children: [] }; - if (isLeaf && !name) { - const text = roleUtils.accumulatedElementText(element); - if (text) - result.children = [text]; - } if (roleUtils.kAriaCheckedRoles.includes(role)) result.checked = roleUtils.getAriaChecked(element); @@ -147,7 +132,7 @@ function toAriaNode(element: Element): { ariaNode: AriaNode, isLeaf: boolean } | if (roleUtils.kAriaSelectedRoles.includes(role)) result.selected = roleUtils.getAriaSelected(element); - return { isLeaf, ariaNode: result }; + return result; } export function renderedAriaTree(rootElement: Element): string { @@ -178,21 +163,12 @@ function normalizeStringChildren(rootA11yNode: AriaNode) { } flushChildren(buffer, normalizedChildren); ariaNode.children = normalizedChildren.length ? normalizedChildren : []; + if (ariaNode.children.length === 1 && ariaNode.children[0] === ariaNode.name) + ariaNode.children = []; }; visit(rootA11yNode); } -const hiddenContainerRoles = new Set(['none', 'presentation']); - -const leafRoles = new Set([ - 'alert', 'blockquote', 'button', 'caption', 'checkbox', 'code', 'columnheader', - 'definition', 'deletion', 'emphasis', 'generic', 'heading', 'img', 'insertion', - 'link', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'meter', 'option', - 'progressbar', 'radio', 'rowheader', 'scrollbar', 'searchbox', 'separator', - 'slider', 'spinbutton', 'strong', 'subscript', 'superscript', 'switch', 'tab', 'term', - 'textbox', 'time', 'tooltip' -]); - const normalizeWhitespaceWithin = (text: string) => text.replace(/[\s\t\r\n]+/g, ' '); function matchesText(text: string | undefined, template: RegExp | string | undefined) { @@ -305,15 +281,7 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean if (ariaNode.selected === true) line += ` [selected]`; - const stringValue = !ariaNode.children.length || (ariaNode.children?.length === 1 && typeof ariaNode.children[0] === 'string'); - if (stringValue) { - if (!options?.noText && ariaNode.children.length) - line += ': ' + quoteYamlString(ariaNode.children?.[0] as string); - lines.push(line); - return; - } - - lines.push(line + ':'); + lines.push(line + (ariaNode.children.length ? ':' : '')); for (const child of ariaNode.children || []) visit(child, indent + ' '); }; diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index 188808a178e55..2b8790589af38 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -64,8 +64,10 @@ it('should snapshot list with accessible name', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - list "my list": - - listitem: "one" - - listitem: "two" + - listitem: + - text: "one" + - listitem: + - text: "two" `); }); @@ -105,7 +107,8 @@ it('should snapshot details visibility', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - group: "Summary" + - group: + - text: "Summary" `); }); @@ -148,7 +151,8 @@ it('should snapshot integration', async ({ page }) => { - text: "Open source projects and samples from Microsoft" - list: - listitem: - - group: "Verified" + - group: + - text: "Verified" - listitem: - link "Sponsor" `); @@ -164,13 +168,15 @@ it('should support multiline text', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: "Line 1 Line 2 Line 3" + - paragraph: + - text: "Line 1 Line 2 Line 3" `); await expect(page.locator('body')).toMatchAriaSnapshot(` - - paragraph: | - Line 1 - Line 2 - Line 3 + - paragraph: + - text: | + Line 1 + Line 2 + Line 3 `); }); @@ -382,6 +388,22 @@ it('should include pseudo codepoints', async ({ page, server }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: "\ueab2hello" + - paragraph: + - text: "\ueab2hello" + `); +}); + +it('check aria-hidden text', async ({ page, server }) => { + await page.goto(server.EMPTY_PAGE); + await page.setContent(` +

      + hello + +

      + `); + + await checkAndMatchSnapshot(page.locator('body'), ` + - paragraph: + - text: "hello" `); }); From 6ae6b4865cf94695b52ce302e5f3ed856ff8904d Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 23 Oct 2024 17:36:05 -0700 Subject: [PATCH 362/805] chore: always use TestInfoErrorImpl (impl) in @playwright/test (#33255) --- packages/playwright/src/common/ipc.ts | 16 ++++++--- packages/playwright/src/common/process.ts | 5 ++- .../playwright/src/matchers/matcherHint.ts | 20 +++++------ packages/playwright/src/util.ts | 4 +-- packages/playwright/src/worker/DEPS.list | 1 + packages/playwright/src/worker/testInfo.ts | 18 +++++----- packages/playwright/src/worker/testTracing.ts | 6 ++-- packages/playwright/src/worker/util.ts | 33 ++++--------------- packages/playwright/src/worker/workerMain.ts | 16 ++++----- 9 files changed, 53 insertions(+), 66 deletions(-) diff --git a/packages/playwright/src/common/ipc.ts b/packages/playwright/src/common/ipc.ts index 5ce1991f65068..82538bb6ede18 100644 --- a/packages/playwright/src/common/ipc.ts +++ b/packages/playwright/src/common/ipc.ts @@ -15,9 +15,11 @@ */ import util from 'util'; -import { type SerializedCompilationCache, serializeCompilationCache } from '../transform/compilationCache'; +import { serializeCompilationCache } from '../transform/compilationCache'; +import type { SerializedCompilationCache } from '../transform/compilationCache'; import type { ConfigLocation, FullConfigInternal } from './config'; import type { ReporterDescription, TestInfoError, TestStatus } from '../../types/test'; +import type { MatcherResultProperty } from '../matchers/matcherHint'; export type ConfigCLIOverrides = { debug?: boolean; @@ -74,11 +76,15 @@ export type AttachmentPayload = { contentType: string; }; +export type TestInfoErrorImpl = TestInfoError & { + matcherResult?: MatcherResultProperty; +}; + export type TestEndPayload = { testId: string; duration: number; status: TestStatus; - errors: TestInfoError[]; + errors: TestInfoErrorImpl[]; hasNonRetriableError: boolean; expectedStatus: TestStatus; annotations: { type: string, description?: string }[]; @@ -99,7 +105,7 @@ export type StepEndPayload = { testId: string; stepId: string; wallTime: number; // milliseconds since unix epoch - error?: TestInfoError; + error?: TestInfoErrorImpl; }; export type TestEntry = { @@ -113,7 +119,7 @@ export type RunPayload = { }; export type DonePayload = { - fatalErrors: TestInfoError[]; + fatalErrors: TestInfoErrorImpl[]; skipTestsDueToSetupFailure: string[]; // test ids fatalUnknownTestIds?: string[]; }; @@ -124,7 +130,7 @@ export type TestOutputPayload = { }; export type TeardownErrorsPayload = { - fatalErrors: TestInfoError[]; + fatalErrors: TestInfoErrorImpl[]; }; export type EnvProducedPayload = [string, string | null][]; diff --git a/packages/playwright/src/common/process.ts b/packages/playwright/src/common/process.ts index 14ad995fedd3c..a372139698af8 100644 --- a/packages/playwright/src/common/process.ts +++ b/packages/playwright/src/common/process.ts @@ -14,9 +14,8 @@ * limitations under the License. */ -import type { EnvProducedPayload, ProcessInitParams } from './ipc'; +import type { EnvProducedPayload, ProcessInitParams, TestInfoErrorImpl } from './ipc'; import { startProfiling, stopProfiling } from 'playwright-core/lib/utils'; -import type { TestInfoError } from '../../types/test'; import { serializeError } from '../util'; import { registerESMLoader } from './esmLoaderHost'; import { execArgvWithoutExperimentalLoaderOptions } from '../transform/esmUtils'; @@ -29,7 +28,7 @@ export type ProtocolRequest = { export type ProtocolResponse = { id?: number; - error?: TestInfoError; + error?: TestInfoErrorImpl; method?: string; params?: any; result?: any; diff --git a/packages/playwright/src/matchers/matcherHint.ts b/packages/playwright/src/matchers/matcherHint.ts index 5ffc745263cda..200501c1bc2ae 100644 --- a/packages/playwright/src/matchers/matcherHint.ts +++ b/packages/playwright/src/matchers/matcherHint.ts @@ -45,18 +45,18 @@ export type MatcherResult = { printedDiff?: string; }; +export type MatcherResultProperty = Omit, 'message'> & { + message: string; +}; + +type JestError = Error & { + matcherResult: MatcherResultProperty; +}; + export class ExpectError extends Error { - matcherResult: { - message: string; - pass: boolean; - name?: string; - expected?: any; - actual?: any; - log?: string[]; - timeout?: number; - }; + matcherResult: MatcherResultProperty; - constructor(jestError: ExpectError, customMessage: string, stackFrames: StackFrame[]) { + constructor(jestError: JestError, customMessage: string, stackFrames: StackFrame[]) { super(''); // Copy to erase the JestMatcherError constructor name from the console.log(error). this.name = jestError.name; diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index 460b3de07e746..40468094335ea 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -21,10 +21,10 @@ import path from 'path'; import url from 'url'; import { debug, mime, minimatch, parseStackTraceLine } from 'playwright-core/lib/utilsBundle'; import { formatCallLog } from 'playwright-core/lib/utils'; -import type { TestInfoError } from './../types/test'; import type { Location } from './../types/testReporter'; import { calculateSha1, isRegExp, isString, sanitizeForFilePath, stringifyStackFrames } from 'playwright-core/lib/utils'; import type { RawStack } from 'playwright-core/lib/utils'; +import type { TestInfoErrorImpl } from './common/ipc'; const PLAYWRIGHT_TEST_PATH = path.join(__dirname, '..'); const PLAYWRIGHT_CORE_PATH = path.dirname(require.resolve('playwright-core/package.json')); @@ -62,7 +62,7 @@ export function filteredStackTrace(rawStack: RawStack): StackFrame[] { return frames; } -export function serializeError(error: Error | any): TestInfoError { +export function serializeError(error: Error | any): TestInfoErrorImpl { if (error instanceof Error) return filterStackTrace(error); return { diff --git a/packages/playwright/src/worker/DEPS.list b/packages/playwright/src/worker/DEPS.list index fb352ac3898e3..ed3973d1fc4f2 100644 --- a/packages/playwright/src/worker/DEPS.list +++ b/packages/playwright/src/worker/DEPS.list @@ -3,3 +3,4 @@ ../transform/ ../util.ts ../utilBundle.ts +../matchers/** diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index e41f1a9a523e9..ed71b1a751a1a 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -17,8 +17,8 @@ import fs from 'fs'; import path from 'path'; import { captureRawStack, monotonicTime, zones, sanitizeForFilePath, stringifyStackFrames } from 'playwright-core/lib/utils'; -import type { TestInfoError, TestInfo, TestStatus, FullProject } from '../../types/test'; -import type { AttachmentPayload, StepBeginPayload, StepEndPayload, WorkerInitParams } from '../common/ipc'; +import type { TestInfo, TestStatus, FullProject } from '../../types/test'; +import type { AttachmentPayload, StepBeginPayload, StepEndPayload, TestInfoErrorImpl, WorkerInitParams } from '../common/ipc'; import type { TestCase } from '../common/test'; import { TimeoutManager, TimeoutManagerError, kMaxDeadline } from './timeoutManager'; import type { RunnableDescription } from './timeoutManager'; @@ -28,7 +28,7 @@ import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normal import { TestTracing } from './testTracing'; import type { Attachment } from './testTracing'; import type { StackFrame } from '@protocol/channels'; -import { serializeWorkerError } from './util'; +import { testInfoError } from './util'; export interface TestStepInternal { complete(result: { error?: Error | unknown, attachments?: Attachment[] }): void; @@ -41,7 +41,7 @@ export interface TestStepInternal { endWallTime?: number; apiName?: string; params?: Record; - error?: TestInfoError; + error?: TestInfoErrorImpl; infectParentStepsWithError?: boolean; box?: boolean; isStage?: boolean; @@ -97,14 +97,14 @@ export class TestInfoImpl implements TestInfo { snapshotSuffix: string = ''; readonly outputDir: string; readonly snapshotDir: string; - errors: TestInfoError[] = []; + errors: TestInfoErrorImpl[] = []; readonly _attachmentsPush: (...items: TestInfo['attachments']) => number; - get error(): TestInfoError | undefined { + get error(): TestInfoErrorImpl | undefined { return this.errors[0]; } - set error(e: TestInfoError | undefined) { + set error(e: TestInfoErrorImpl | undefined) { if (e === undefined) throw new Error('Cannot assign testInfo.error undefined value!'); this.errors[0] = e; @@ -273,7 +273,7 @@ export class TestInfoImpl implements TestInfo { if (result.error) { if (typeof result.error === 'object' && !(result.error as any)?.[stepSymbol]) (result.error as any)[stepSymbol] = step; - const error = serializeWorkerError(result.error); + const error = testInfoError(result.error); if (data.boxedStack) error.stack = `${error.message}\n${stringifyStackFrames(data.boxedStack).join('\n')}`; step.error = error; @@ -331,7 +331,7 @@ export class TestInfoImpl implements TestInfo { _failWithError(error: Error | unknown) { if (this.status === 'passed' || this.status === 'skipped') this.status = error instanceof TimeoutManagerError ? 'timedOut' : 'failed'; - const serialized = serializeWorkerError(error); + const serialized = testInfoError(error); const step: TestStepInternal | undefined = typeof error === 'object' ? (error as any)?.[stepSymbol] : undefined; if (step && step.boxedStack) serialized.stack = `${(error as Error).name}: ${(error as Error).message}\n${stringifyStackFrames(step.boxedStack).join('\n')}`; diff --git a/packages/playwright/src/worker/testTracing.ts b/packages/playwright/src/worker/testTracing.ts index fed7fdde7e982..5e7a3d80db55e 100644 --- a/packages/playwright/src/worker/testTracing.ts +++ b/packages/playwright/src/worker/testTracing.ts @@ -21,10 +21,10 @@ import fs from 'fs'; import path from 'path'; import { ManualPromise, calculateSha1, monotonicTime, createGuid, SerializedFS } from 'playwright-core/lib/utils'; import { yauzl, yazl } from 'playwright-core/lib/zipBundle'; -import type { TestInfo, TestInfoError } from '../../types/test'; import { filteredStackTrace } from '../util'; -import type { TraceMode, PlaywrightWorkerOptions } from '../../types/test'; +import type { TestInfo, TraceMode, PlaywrightWorkerOptions } from '../../types/test'; import type { TestInfoImpl } from './testInfo'; +import type { TestInfoErrorImpl } from '../common/ipc'; export type Attachment = TestInfo['attachments'][0]; export const testTraceEntryName = 'test.trace'; @@ -219,7 +219,7 @@ export class TestTracing { this._testInfo.attachments.push({ name: 'trace', path: tracePath, contentType: 'application/zip' }); } - appendForError(error: TestInfoError) { + appendForError(error: TestInfoErrorImpl) { const rawStack = error.stack?.split('\n') || []; const stack = rawStack ? filteredStackTrace(rawStack) : []; this._appendTraceEvent({ diff --git a/packages/playwright/src/worker/util.ts b/packages/playwright/src/worker/util.ts index d24d3371911d7..a271f62c48ab4 100644 --- a/packages/playwright/src/worker/util.ts +++ b/packages/playwright/src/worker/util.ts @@ -14,32 +14,13 @@ * limitations under the License. */ -import type { TestError } from '../../types/testReporter'; -import type { TestInfoError } from '../../types/test'; -import type { MatcherResult } from '../matchers/matcherHint'; +import type { TestInfoErrorImpl } from '../common/ipc'; +import { ExpectError } from '../matchers/matcherHint'; import { serializeError } from '../util'; - -type MatcherResultDetails = Pick; - -export function serializeWorkerError(error: Error | any): TestInfoError & MatcherResultDetails { - return { - ...serializeError(error), - ...serializeExpectDetails(error), - }; +export function testInfoError(error: Error | any): TestInfoErrorImpl { + const result = serializeError(error); + if (error instanceof ExpectError) + result.matcherResult = error.matcherResult; + return result; } - -function serializeExpectDetails(e: Error): MatcherResultDetails { - const matcherResult = (e as any).matcherResult as MatcherResult; - if (!matcherResult) - return {}; - return { - timeout: matcherResult.timeout, - matcherName: matcherResult.name, - locator: matcherResult.locator, - expected: matcherResult.printedExpected, - received: matcherResult.printedReceived, - log: matcherResult.log, - }; -} - diff --git a/packages/playwright/src/worker/workerMain.ts b/packages/playwright/src/worker/workerMain.ts index 5680c3ddb39bb..ed323a701bb94 100644 --- a/packages/playwright/src/worker/workerMain.ts +++ b/packages/playwright/src/worker/workerMain.ts @@ -16,7 +16,8 @@ import { colors } from 'playwright-core/lib/utilsBundle'; import { debugTest, relativeFilePath } from '../util'; -import { type TestBeginPayload, type TestEndPayload, type RunPayload, type DonePayload, type WorkerInitParams, type TeardownErrorsPayload, stdioChunkToParams } from '../common/ipc'; +import type { TestBeginPayload, TestEndPayload, RunPayload, DonePayload, WorkerInitParams, TeardownErrorsPayload, TestInfoErrorImpl } from '../common/ipc'; +import { stdioChunkToParams } from '../common/ipc'; import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals'; import { deserializeConfig } from '../common/configLoader'; import type { Suite, TestCase } from '../common/test'; @@ -28,11 +29,10 @@ import { ProcessRunner } from '../common/process'; import { loadTestFile } from '../common/testLoader'; import { applyRepeatEachIndex, bindFileSuiteToProject, filterTestsRemoveEmptySuites } from '../common/suiteUtils'; import { PoolBuilder } from '../common/poolBuilder'; -import type { TestInfoError } from '../../types/test'; import type { Location } from '../../types/testReporter'; import { inheritFixtureNames } from '../common/fixtures'; import { type TimeSlot } from './timeoutManager'; -import { serializeWorkerError } from './util'; +import { testInfoError } from './util'; export class WorkerMain extends ProcessRunner { private _params: WorkerInitParams; @@ -42,7 +42,7 @@ export class WorkerMain extends ProcessRunner { private _fixtureRunner: FixtureRunner; // Accumulated fatal errors that cannot be attributed to a test. - private _fatalErrors: TestInfoError[] = []; + private _fatalErrors: TestInfoErrorImpl[] = []; // Whether we should skip running remaining tests in this suite because // of a setup error, usually beforeAll hook. private _skipRemainingTestsInSuite: Suite | undefined; @@ -113,7 +113,7 @@ export class WorkerMain extends ProcessRunner { await fakeTestInfo._runAsStage({ title: 'worker cleanup', runnable }, () => gracefullyCloseAll()).catch(() => {}); this._fatalErrors.push(...fakeTestInfo.errors); } catch (e) { - this._fatalErrors.push(serializeWorkerError(e)); + this._fatalErrors.push(testInfoError(e)); } if (this._fatalErrors.length) { @@ -123,7 +123,7 @@ export class WorkerMain extends ProcessRunner { } } - private _appendProcessTeardownDiagnostics(error: TestInfoError) { + private _appendProcessTeardownDiagnostics(error: TestInfoErrorImpl) { if (!this._lastRunningTests.length) return; const count = this._totalRunningTests === 1 ? '1 test' : `${this._totalRunningTests} tests`; @@ -154,7 +154,7 @@ export class WorkerMain extends ProcessRunner { // No current test - fatal error. if (!this._currentTest) { if (!this._fatalErrors.length) - this._fatalErrors.push(serializeWorkerError(error)); + this._fatalErrors.push(testInfoError(error)); void this._stop(); return; } @@ -225,7 +225,7 @@ export class WorkerMain extends ProcessRunner { // In theory, we should run above code without any errors. // However, in the case we screwed up, or loadTestFile failed in the worker // but not in the runner, let's do a fatal error. - this._fatalErrors.push(serializeWorkerError(e)); + this._fatalErrors.push(testInfoError(e)); void this._stop(); } finally { const donePayload: DonePayload = { From 69f56b9f6366858709cb39b5b1054592b029a447 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 24 Oct 2024 10:52:54 +0200 Subject: [PATCH 363/805] fix(locator generator): handle `frameLocator()` and `locator().contentFrame()` (#33208) --- .../src/utils/isomorphic/locatorGenerators.ts | 32 +++++++++++++++---- tests/library/locator-generator.spec.ts | 19 +++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts index 930abaaba6e00..04f3040547d16 100644 --- a/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts +++ b/packages/playwright-core/src/utils/isomorphic/locatorGenerators.ts @@ -19,7 +19,7 @@ import { type NestedSelectorBody, parseAttributeSelector, parseSelector, stringi import type { ParsedSelector } from './selectorParser'; export type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl'; -export type LocatorType = 'default' | 'role' | 'text' | 'label' | 'placeholder' | 'alt' | 'title' | 'test-id' | 'nth' | 'first' | 'last' | 'has-text' | 'has-not-text' | 'has' | 'hasNot' | 'frame' | 'and' | 'or' | 'chain'; +export type LocatorType = 'default' | 'role' | 'text' | 'label' | 'placeholder' | 'alt' | 'title' | 'test-id' | 'nth' | 'first' | 'last' | 'has-text' | 'has-not-text' | 'has' | 'hasNot' | 'frame' | 'frame-locator' | 'and' | 'or' | 'chain'; export type LocatorBase = 'page' | 'locator' | 'frame-locator'; export type Quote = '\'' | '"' | '`'; @@ -158,19 +158,29 @@ function innerAsLocators(factory: LocatorFactory, parsed: ParsedSelector, isFram } } if (part.name === 'internal:control' && (part.body as string) === 'enter-frame') { - tokens.push([factory.generateLocator(base, 'frame', '')]); + // transform last tokens from `${selector}` into `${selector}.contentFrame()` and `frameLocator(${selector})` + const lastTokens = tokens[tokens.length - 1]; + const lastPart = parts[index - 1]; + + const transformed = lastTokens.map(token => factory.chainLocators([token, factory.generateLocator(base, 'frame', '')])); + if (['xpath', 'css'].includes(lastPart.name)) { + transformed.push( + factory.generateLocator(base, 'frame-locator', stringifySelector({ parts: [lastPart] })), + factory.generateLocator(base, 'frame-locator', stringifySelector({ parts: [lastPart] }, true)) + ); + } + + lastTokens.splice(0, lastTokens.length, ...transformed); nextBase = 'frame-locator'; continue; } - const locatorType: LocatorType = 'default'; - const nextPart = parts[index + 1]; const selectorPart = stringifySelector({ parts: [part] }); - const locatorPart = factory.generateLocator(base, locatorType, selectorPart); + const locatorPart = factory.generateLocator(base, 'default', selectorPart); - if (locatorType === 'default' && nextPart && ['internal:has-text', 'internal:has-not-text'].includes(nextPart.name)) { + if (nextPart && ['internal:has-text', 'internal:has-not-text'].includes(nextPart.name)) { const { exact, text } = detectExact(nextPart.body as string); // There is no locator equivalent for strict has-text and has-not-text, leave it as is. if (!exact) { @@ -194,7 +204,7 @@ function innerAsLocators(factory: LocatorFactory, parsed: ParsedSelector, isFram let locatorPartWithEngine: string | undefined; if (['xpath', 'css'].includes(part.name)) { const selectorPart = stringifySelector({ parts: [part] }, /* forceEngineName */ true); - locatorPartWithEngine = factory.generateLocator(base, locatorType, selectorPart); + locatorPartWithEngine = factory.generateLocator(base, 'default', selectorPart); } tokens.push([locatorPart, locatorPartWithEngine].filter(Boolean) as string[]); @@ -253,6 +263,8 @@ export class JavaScriptLocatorFactory implements LocatorFactory { if (options.hasNotText !== undefined) return `locator(${this.quote(body as string)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`; return `locator(${this.quote(body as string)})`; + case 'frame-locator': + return `frameLocator(${this.quote(body as string)})`; case 'frame': return `contentFrame()`; case 'nth': @@ -345,6 +357,8 @@ export class PythonLocatorFactory implements LocatorFactory { if (options.hasNotText !== undefined) return `locator(${this.quote(body as string)}, has_not_text=${this.toHasText(options.hasNotText)})`; return `locator(${this.quote(body as string)})`; + case 'frame-locator': + return `frame_locator(${this.quote(body as string)})`; case 'frame': return `content_frame`; case 'nth': @@ -450,6 +464,8 @@ export class JavaLocatorFactory implements LocatorFactory { if (options.hasNotText !== undefined) return `locator(${this.quote(body as string)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`; return `locator(${this.quote(body as string)})`; + case 'frame-locator': + return `frameLocator(${this.quote(body as string)})`; case 'frame': return `contentFrame()`; case 'nth': @@ -545,6 +561,8 @@ export class CSharpLocatorFactory implements LocatorFactory { if (options.hasNotText !== undefined) return `Locator(${this.quote(body as string)}, new() { ${this.toHasNotText(options.hasNotText)} })`; return `Locator(${this.quote(body as string)})`; + case 'frame-locator': + return `FrameLocator(${this.quote(body as string)})`; case 'frame': return `ContentFrame`; case 'nth': diff --git a/tests/library/locator-generator.spec.ts b/tests/library/locator-generator.spec.ts index d177fa7489e29..4df72977f40a6 100644 --- a/tests/library/locator-generator.spec.ts +++ b/tests/library/locator-generator.spec.ts @@ -584,3 +584,22 @@ it('parse locators strictly', () => { expect.soft(parseLocator('javascript', `locator('div').filter({ hasText: 'Goodbye world' }}).locator('span')`)).not.toBe(selector); expect.soft(parseLocator('python', `locator("div").filter(has_text=="Goodbye world").locator("span")`)).not.toBe(selector); }); + +it('parseLocator frames', async () => { + expect.soft(parseLocator('javascript', `locator('iframe').contentFrame().getByText('foo')`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('javascript', `frameLocator('iframe').getByText('foo')`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('javascript', `frameLocator('css=iframe').getByText('foo')`, '')).toBe(`css=iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('javascript', `getByTitle('iframe title').contentFrame()`)).toBe(`internal:attr=[title=\"iframe title\"i] >> internal:control=enter-frame`); + + expect.soft(asLocators('javascript', 'internal:attr=[title=\"iframe title\"i] >> internal:control=enter-frame')).toEqual([`getByTitle('iframe title').contentFrame()`]); + + expect.soft(parseLocator('python', `locator("iframe").content_frame.get_by_text("foo")`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('python', `frame_locator("iframe").get_by_text("foo")`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('python', `frame_locator("css=iframe").get_by_text("foo")`, '')).toBe(`css=iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + + expect.soft(parseLocator('csharp', `Locator("iframe").ContentFrame.GetByText("foo")`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('csharp', `FrameLocator("iframe").GetByText("foo")`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + + expect.soft(parseLocator('java', `locator("iframe").contentFrame().getByText("foo")`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); + expect.soft(parseLocator('java', `frameLocator("iframe").getByText("foo")`, '')).toBe(`iframe >> internal:control=enter-frame >> internal:text=\"foo\"i`); +}); From 487134fbafcd8840fd1caf34443578608f0cc92d Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 24 Oct 2024 11:34:41 +0200 Subject: [PATCH 364/805] devops: add chromium-headless-shell bots (#33242) --- .github/workflows/tests_secondary.yml | 21 +++++++++++++++++++++ tests/library/chromium/launcher.spec.ts | 12 ++++++++---- tests/library/headful.spec.ts | 1 + tests/library/launcher.spec.ts | 3 ++- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index 8b8555eb86017..71c7ed105fe14 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -284,3 +284,24 @@ jobs: flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} env: PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1 + + test_linux_chromium_headless_shell: + name: Chromium Headless Shell + environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} + strategy: + fail-fast: false + matrix: + runs-on: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.runs-on }} + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/run-test + with: + browsers-to-install: chromium-headless-shell + command: npm run ctest + bot-name: "headless-shell-${{ matrix.runs-on }}" + flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }} + flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }} + flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }} + env: + PWTEST_CHANNEL: chromium-headless-shell diff --git a/tests/library/chromium/launcher.spec.ts b/tests/library/chromium/launcher.spec.ts index f36a089fa7115..8758e63c12bdf 100644 --- a/tests/library/chromium/launcher.spec.ts +++ b/tests/library/chromium/launcher.spec.ts @@ -52,7 +52,8 @@ it('should open devtools when "devtools: true" option is given', async ({ browse await browser.close(); }); -it('should return background pages', async ({ browserType, createUserDataDir, asset }) => { +it('should return background pages', async ({ browserType, createUserDataDir, asset, channel }) => { + it.skip(channel === 'chromium-headless-shell', 'Headless Shell has no support for extensions'); const userDataDir = await createUserDataDir(); const extensionPath = asset('simple-extension'); const extensionOptions = { @@ -75,7 +76,8 @@ it('should return background pages', async ({ browserType, createUserDataDir, as expect(context.backgroundPages().length).toBe(0); }); -it('should return background pages when recording video', async ({ browserType, createUserDataDir, asset }, testInfo) => { +it('should return background pages when recording video', async ({ browserType, createUserDataDir, asset, channel }, testInfo) => { + it.skip(channel === 'chromium-headless-shell', 'Headless Shell has no support for extensions'); const userDataDir = await createUserDataDir(); const extensionPath = asset('simple-extension'); const extensionOptions = { @@ -99,7 +101,8 @@ it('should return background pages when recording video', async ({ browserType, await context.close(); }); -it('should support request/response events when using backgroundPage()', async ({ browserType, createUserDataDir, asset, server }) => { +it('should support request/response events when using backgroundPage()', async ({ browserType, createUserDataDir, asset, server, channel }) => { + it.skip(channel === 'chromium-headless-shell', 'Headless Shell has no support for extensions'); server.setRoute('/empty.html', (req, res) => { res.writeHead(200, { 'Content-Type': 'text/html', 'x-response-foobar': 'BarFoo' }); res.end(`hello world!`); @@ -148,7 +151,8 @@ it('should support request/response events when using backgroundPage()', async ( it('should report console messages from content script', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32762' } -}, async ({ browserType, createUserDataDir, asset, server }) => { +}, async ({ browserType, createUserDataDir, asset, server, channel }) => { + it.skip(channel === 'chromium-headless-shell', 'Headless Shell has no support for extensions'); const userDataDir = await createUserDataDir(); const extensionPath = asset('extension-with-logging'); const extensionOptions = { diff --git a/tests/library/headful.spec.ts b/tests/library/headful.spec.ts index 5832ef44da4e2..92f2e044e0f77 100644 --- a/tests/library/headful.spec.ts +++ b/tests/library/headful.spec.ts @@ -19,6 +19,7 @@ import { PNG } from 'playwright-core/lib/utilsBundle'; import { expect, playwrightTest as it } from '../config/browserTest'; it.use({ headless: false }); +it.skip(({ channel }) => channel === 'chromium-headless-shell'); it('should have default url when launching browser @smoke', async ({ launchPersistent }) => { const { context } = await launchPersistent(); diff --git a/tests/library/launcher.spec.ts b/tests/library/launcher.spec.ts index 54b74c636620a..e7d71182cbedb 100644 --- a/tests/library/launcher.spec.ts +++ b/tests/library/launcher.spec.ts @@ -41,9 +41,10 @@ it('should kill browser process on timeout after close', async ({ browserType, m expect(stalled).toBeTruthy(); }); -it('should throw a friendly error if its headed and there is no xserver on linux running', async ({ mode, browserType, platform }) => { +it('should throw a friendly error if its headed and there is no xserver on linux running', async ({ mode, browserType, platform, channel }) => { it.skip(platform !== 'linux'); it.skip(mode.startsWith('service')); + it.skip(channel === 'chromium-headless-shell', 'Headless Shell is always headless'); const error: Error = await browserType.launch({ headless: false, From 1950bbdc6e07c120d590b6aa7b594d4acfe2d3a2 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 24 Oct 2024 02:47:34 -0700 Subject: [PATCH 365/805] test: unflake "should not leak recorders" (#33264) --- tests/library/trace-viewer.spec.ts | 31 ++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index eb81fa8b9cd65..c13eb778d1068 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -1415,26 +1415,37 @@ test('should not leak recorders', { }, async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer([traceFile]); - const counts = async () => { + const aliveCount = async () => { return await traceViewer.page.evaluate(() => { const weakSet = (window as any)._weakRecordersForTest || new Set(); const weakList = [...weakSet]; const aliveList = weakList.filter(r => !!r.deref()); - return { total: weakList.length, alive: aliveList.length }; + return aliveList.length; }); }; - await traceViewer.snapshotFrame('page.goto'); - await traceViewer.snapshotFrame('page.evaluate'); + await expect(traceViewer.snapshotContainer.contentFrame().locator('body')).toContainText(`Hi, I'm frame`); + + const frame1 = await traceViewer.snapshotFrame('page.goto'); + await expect(frame1.locator('body')).toContainText('Hello world'); + + const frame2 = await traceViewer.snapshotFrame('page.evaluate'); + await expect(frame2.locator('button')).toBeVisible(); + await traceViewer.page.requestGC(); - await expect.poll(() => counts()).toEqual({ total: 4, alive: 1 }); + await expect.poll(() => aliveCount()).toBeLessThanOrEqual(2); // two snapshot iframes + + const frame3 = await traceViewer.snapshotFrame('page.setViewportSize'); + await expect(frame3.locator('body')).toContainText(`Hi, I'm frame`); + + const frame4 = await traceViewer.snapshotFrame('page.goto'); + await expect(frame4.locator('body')).toContainText('Hello world'); + + const frame5 = await traceViewer.snapshotFrame('page.evaluate'); + await expect(frame5.locator('button')).toBeVisible(); - await traceViewer.snapshotFrame('page.setContent'); - await traceViewer.snapshotFrame('page.goto'); - await traceViewer.snapshotFrame('page.evaluate'); - await traceViewer.snapshotFrame('page.setContent'); await traceViewer.page.requestGC(); - await expect.poll(() => counts()).toEqual({ total: 8, alive: 1 }); + await expect.poll(() => aliveCount()).toBeLessThanOrEqual(2); // two snapshot iframes }); test('should serve css without content-type', async ({ page, runAndTrace, server }) => { From 2e01154bb57f5cb34c805092e0119742c46b95d8 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 24 Oct 2024 04:41:35 -0700 Subject: [PATCH 366/805] feat: screenshot:on-first-failure (#33266) --- docs/src/test-api/class-testoptions.md | 5 ++-- packages/playwright/src/index.ts | 13 ++++++--- packages/playwright/types/test.d.ts | 3 ++- .../playwright.artifacts.spec.ts | 27 +++++++++++++++++++ utils/generate_types/overrides-test.d.ts | 2 +- 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/docs/src/test-api/class-testoptions.md b/docs/src/test-api/class-testoptions.md index 47bfd1f377ab6..20dad210e7958 100644 --- a/docs/src/test-api/class-testoptions.md +++ b/docs/src/test-api/class-testoptions.md @@ -479,8 +479,8 @@ export default defineConfig({ ## property: TestOptions.screenshot * since: v1.10 -- type: <[Object]|[ScreenshotMode]<"off"|"on"|"only-on-failure">> - - `mode` <[ScreenshotMode]<"off"|"on"|"only-on-failure">> Automatic screenshot mode. +- type: <[Object]|[ScreenshotMode]<"off"|"on"|"only-on-failure"|"on-first-failure">> + - `mode` <[ScreenshotMode]<"off"|"on"|"only-on-failure"|"on-first-failure">> Automatic screenshot mode. - `fullPage` ?<[boolean]> When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to `false`. - `omitBackground` ?<[boolean]> Hides default white background and allows capturing screenshots with transparency. Not applicable to `jpeg` images. Defaults to `false`. @@ -488,6 +488,7 @@ Whether to automatically capture a screenshot after each test. Defaults to `'off * `'off'`: Do not capture screenshots. * `'on'`: Capture screenshot after each test. * `'only-on-failure'`: Capture screenshot after each test failure. +* `'on-first-failure'`: Capture screenshot after each test's first failure. **Usage** diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index add1661502828..c2c9596b6e844 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -571,7 +571,7 @@ class ArtifactsRecorder { if (this._reusedContexts.has(context)) return; await this._stopTracing(context.tracing); - if (this._screenshotMode === 'on' || this._screenshotMode === 'only-on-failure') { + if (this._screenshotMode === 'on' || this._screenshotMode === 'only-on-failure' || (this._screenshotMode === 'on-first-failure' && this._testInfo.retry === 0)) { // Capture screenshot for now. We'll know whether we have to preserve them // after the test finishes. await Promise.all(context.pages().map(page => this._screenshotPage(page, true))); @@ -588,14 +588,19 @@ class ArtifactsRecorder { await this._stopTracing(tracing); } + private _shouldCaptureScreenshotUponFinish() { + return this._screenshotMode === 'on' || + (this._screenshotMode === 'only-on-failure' && this._testInfo._isFailure()) || + (this._screenshotMode === 'on-first-failure' && this._testInfo._isFailure() && this._testInfo.retry === 0); + } + async didFinishTestFunction() { - const captureScreenshots = this._screenshotMode === 'on' || (this._screenshotMode === 'only-on-failure' && this._testInfo._isFailure()); - if (captureScreenshots) + if (this._shouldCaptureScreenshotUponFinish()) await this._screenshotOnTestFailure(); } async didFinishTest() { - const captureScreenshots = this._screenshotMode === 'on' || (this._screenshotMode === 'only-on-failure' && this._testInfo._isFailure()); + const captureScreenshots = this._shouldCaptureScreenshotUponFinish(); if (captureScreenshots) await this._screenshotOnTestFailure(); diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index ae02d1506ee67..5db30f72e2c4b 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -5863,6 +5863,7 @@ export interface PlaywrightWorkerOptions { * - `'off'`: Do not capture screenshots. * - `'on'`: Capture screenshot after each test. * - `'only-on-failure'`: Capture screenshot after each test failure. + * - `'on-first-failure'`: Capture screenshot after each test's first failure. * * **Usage** * @@ -5938,7 +5939,7 @@ export interface PlaywrightWorkerOptions { video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize }; } -export type ScreenshotMode = 'off' | 'on' | 'only-on-failure'; +export type ScreenshotMode = 'off' | 'on' | 'only-on-failure' | 'on-first-failure'; export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure'; export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry'; diff --git a/tests/playwright-test/playwright.artifacts.spec.ts b/tests/playwright-test/playwright.artifacts.spec.ts index b666aa4b70e6d..2e3d99766bfe2 100644 --- a/tests/playwright-test/playwright.artifacts.spec.ts +++ b/tests/playwright-test/playwright.artifacts.spec.ts @@ -192,6 +192,33 @@ test('should work with screenshot: only-on-failure', async ({ runInlineTest }, t ]); }); +test('should work with screenshot: on-first-failure', async ({ runInlineTest }, testInfo) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('fails', async ({ page }) => { + await page.setContent('I am the page'); + expect(1).toBe(2); + }); + `, + 'playwright.config.ts': ` + module.exports = { + retries: 1, + use: { screenshot: 'on-first-failure' } + }; + `, + }, { workers: 1 }); + + expect(result.exitCode).toBe(1); + expect(result.passed).toBe(0); + expect(result.failed).toBe(1); + expect(listFiles(testInfo.outputPath('test-results'))).toEqual([ + '.last-run.json', + 'a-fails', + ' test-failed-1.png', + ]); +}); + test('should work with screenshot: only-on-failure & fullPage', async ({ runInlineTest, server }, testInfo) => { const result = await runInlineTest({ 'artifacts.spec.ts': ` diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index ff46ba0e5c2d7..49a7093dd35bb 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -236,7 +236,7 @@ export interface PlaywrightWorkerOptions { video: VideoMode | /** deprecated */ 'retry-with-video' | { mode: VideoMode, size?: ViewportSize }; } -export type ScreenshotMode = 'off' | 'on' | 'only-on-failure'; +export type ScreenshotMode = 'off' | 'on' | 'only-on-failure' | 'on-first-failure'; export type TraceMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry' | 'on-all-retries' | 'retain-on-first-failure'; export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry'; From 3641e5984fa7c371e11b5eac3e95139c03e2512c Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Thu, 24 Oct 2024 14:34:59 +0200 Subject: [PATCH 367/805] chore: HMR for Trace Viewer (#33228) --- .../src/server/trace/viewer/traceViewer.ts | 9 ++++++- packages/trace-viewer/.gitignore | 2 ++ packages/trace-viewer/src/embedded.tsx | 2 +- packages/trace-viewer/src/index.tsx | 2 +- packages/trace-viewer/src/recorder.tsx | 2 +- .../trace-viewer/src/sw/traceModelBackends.ts | 27 ++++++++++++------- packages/trace-viewer/src/ui/uiModeView.tsx | 7 +++-- packages/trace-viewer/src/uiMode.tsx | 2 +- packages/trace-viewer/vite.config.ts | 3 +++ packages/trace-viewer/vite.sw.config.ts | 2 +- .../playwright-test/ui-mode-test-run.spec.ts | 11 ++++++++ utils/build/build.js | 26 ++++++++++++++++++ 12 files changed, 77 insertions(+), 18 deletions(-) diff --git a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts index a49148e061e6d..32cbba0982ee7 100644 --- a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts +++ b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts @@ -125,7 +125,14 @@ export async function installRootRedirect(server: HttpServer, traceUrls: string[ for (const reporter of options.reporter || []) params.append('reporter', reporter); - const urlPath = `./trace/${options.webApp || 'index.html'}?${params.toString()}`; + let baseUrl = ''; + if (process.env.PW_HMR === '1') { + params.set('testServerPort', '' + server.port()); + baseUrl = 'http://localhost:44223'; // port is hardcoded in build.js + } + + const urlPath = `${baseUrl}/trace/${options.webApp || 'index.html'}?${params.toString()}`; + server.routePath('/', (_, response) => { response.statusCode = 302; response.setHeader('Location', urlPath); diff --git a/packages/trace-viewer/.gitignore b/packages/trace-viewer/.gitignore index a547bf36d8d11..1e3942879c827 100644 --- a/packages/trace-viewer/.gitignore +++ b/packages/trace-viewer/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? + +public/sw.bundle.js* diff --git a/packages/trace-viewer/src/embedded.tsx b/packages/trace-viewer/src/embedded.tsx index 4f1503dcf27fe..cc61703bafc01 100644 --- a/packages/trace-viewer/src/embedded.tsx +++ b/packages/trace-viewer/src/embedded.tsx @@ -45,7 +45,7 @@ import { EmbeddedWorkbenchLoader } from './ui/embeddedWorkbenchLoader'; if (window.location.protocol !== 'file:') { if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js'); + navigator.serviceWorker.register('sw.bundle.js' + window.location.search); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/src/index.tsx b/packages/trace-viewer/src/index.tsx index a737d9017f76c..2296cb0090b4a 100644 --- a/packages/trace-viewer/src/index.tsx +++ b/packages/trace-viewer/src/index.tsx @@ -27,7 +27,7 @@ import { WorkbenchLoader } from './ui/workbenchLoader'; await new Promise(f => setTimeout(f, 1000)); if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js'); + navigator.serviceWorker.register('sw.bundle.js' + window.location.search); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/src/recorder.tsx b/packages/trace-viewer/src/recorder.tsx index 5e6b9764e3431..6239df86ab7a5 100644 --- a/packages/trace-viewer/src/recorder.tsx +++ b/packages/trace-viewer/src/recorder.tsx @@ -26,7 +26,7 @@ import { RecorderView } from './ui/recorder/recorderView'; if (window.location.protocol !== 'file:') { if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the Recorder (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js'); + navigator.serviceWorker.register('sw.bundle.js' + window.location.search); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/src/sw/traceModelBackends.ts b/packages/trace-viewer/src/sw/traceModelBackends.ts index 19c5fc2deec52..4f5bd49624078 100644 --- a/packages/trace-viewer/src/sw/traceModelBackends.ts +++ b/packages/trace-viewer/src/sw/traceModelBackends.ts @@ -30,9 +30,8 @@ export class ZipTraceModelBackend implements TraceModelBackend { constructor(traceURL: string, progress: Progress) { this._traceURL = traceURL; - zipjs.configure({ baseURL: self.location.href } as any); this._zipReader = new zipjs.ZipReader( - new zipjs.HttpReader(formatUrl(traceURL), { mode: 'cors', preventHeadRequest: true } as any), + new zipjs.HttpReader(formatTraceFileUrl(traceURL), { mode: 'cors', preventHeadRequest: true } as any), { useWebWorkers: false }); this._entriesPromise = this._zipReader.getEntries({ onprogress: progress }).then(entries => { const map = new Map(); @@ -87,7 +86,7 @@ export class FetchTraceModelBackend implements TraceModelBackend { constructor(traceURL: string) { this._traceURL = traceURL; - this._entriesPromise = fetch('/trace/file?path=' + encodeURIComponent(traceURL)).then(async response => { + this._entriesPromise = fetch(formatTraceFileUrl(traceURL)).then(async response => { const json = JSON.parse(await response.text()); const entries = new Map(); for (const entry of json.entries) @@ -129,14 +128,22 @@ export class FetchTraceModelBackend implements TraceModelBackend { const fileName = entries.get(entryName); if (!fileName) return; - return fetch('/trace/file?path=' + encodeURIComponent(fileName)); + + return fetch(formatTraceFileUrl(fileName)); } } -function formatUrl(trace: string) { - let url = trace.startsWith('http') || trace.startsWith('blob') ? trace : `file?path=${encodeURIComponent(trace)}`; - // Dropbox does not support cors. - if (url.startsWith('https://www.dropbox.com/')) - url = 'https://dl.dropboxusercontent.com/' + url.substring('https://www.dropbox.com/'.length); - return url; +const baseURL = new URL(self.location.href); +baseURL.port = baseURL.searchParams.get('testServerPort') ?? baseURL.port; + +function formatTraceFileUrl(trace: string) { + if (trace.startsWith('https://www.dropbox.com/')) + return 'https://dl.dropboxusercontent.com/' + trace.substring('https://www.dropbox.com/'.length); + + if (trace.startsWith('http') || trace.startsWith('blob')) + return trace; + + const url = new URL('/trace/file', baseURL); + url.searchParams.set('path', trace); + return url.toString(); } diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index 69a598864145f..37b6a6bcf61b7 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -50,6 +50,7 @@ const searchParams = new URLSearchParams(window.location.search); const guid = searchParams.get('ws'); const wsURL = new URL(`../${guid}`, window.location.toString()); wsURL.protocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:'); +wsURL.port = searchParams.get('testServerPort') ?? window.location.port; const queryParams = { args: searchParams.getAll('arg'), grep: searchParams.get('grep') || undefined, @@ -68,6 +69,7 @@ const isMac = navigator.platform === 'MacIntel'; export const UIModeView: React.FC<{}> = ({ }) => { + const isJokesDay = new Date().getMonth() === 3 && new Date().getDate() === 1; const [filterText, setFilterText] = React.useState(''); const [isShowingOutput, setIsShowingOutput] = React.useState(false); const [outputContainsError, setOutputContainsError] = React.useState(false); @@ -440,7 +442,7 @@ export const UIModeView: React.FC<{}> = ({ sidebar={
      Playwright logo -
      Playwright
      +
      {isJokesDay ? 'Claywright' : 'Playwright'}
      reloadTests()} disabled={isRunningTest || isLoading}>
      { setIsShowingOutput(!isShowingOutput); }} /> @@ -516,10 +518,11 @@ export const UIModeView: React.FC<{}> = ({ style={{ marginLeft: 5 }} title={settingsVisible ? 'Hide Settings' : 'Show Settings'} /> -
      Settings
      +
      {isJokesDay ? 'Schmettings' : 'Settings'}
      {settingsVisible && }
      } diff --git a/packages/trace-viewer/src/uiMode.tsx b/packages/trace-viewer/src/uiMode.tsx index 5dac2082e81ee..4702621e5d05c 100644 --- a/packages/trace-viewer/src/uiMode.tsx +++ b/packages/trace-viewer/src/uiMode.tsx @@ -27,7 +27,7 @@ import { UIModeView } from './ui/uiModeView'; await new Promise(f => setTimeout(f, 1000)); if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the website (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js'); + navigator.serviceWorker.register('sw.bundle.js' + window.location.search); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/vite.config.ts b/packages/trace-viewer/vite.config.ts index 0e2e9cb642770..541b1ab6b6d56 100644 --- a/packages/trace-viewer/vite.config.ts +++ b/packages/trace-viewer/vite.config.ts @@ -26,6 +26,9 @@ export default defineConfig({ react(), bundle() ], + define: { + 'process.env': {}, + }, resolve: { alias: { '@injected': path.resolve(__dirname, '../playwright-core/src/server/injected'), diff --git a/packages/trace-viewer/vite.sw.config.ts b/packages/trace-viewer/vite.sw.config.ts index dc621448b9ee1..a0dd99036a67f 100644 --- a/packages/trace-viewer/vite.sw.config.ts +++ b/packages/trace-viewer/vite.sw.config.ts @@ -36,7 +36,7 @@ export default defineConfig({ }, }, build: { - outDir: path.resolve(__dirname, '../playwright-core/lib/vite/traceViewer'), + outDir: path.resolve(__dirname, 'public'), // Output dir is shared with vite.config.ts, clearing it here is racy. emptyOutDir: false, rollupOptions: { diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index 3673faab45477..0da2940e964f3 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -778,3 +778,14 @@ test('should respect --ignore-snapshots option', { - treeitem ${/\[icon-check\] snapshot \d+ms/} `); }); + +test('should show funny messages', async ({ runUITest }) => { + const { page } = await runUITest(basicTestTree); + await page.clock.setFixedTime('2025-04-01'); + + await expect(page.getByText('Claywright')).toBeVisible(); + const schmettingsHeader = page.getByText('Schmettings'); + await expect(schmettingsHeader).toBeVisible(); + await schmettingsHeader.click(); + await expect(page.getByRole('checkbox', { name: 'Fart mode' })).toBeVisible(); +}); \ No newline at end of file diff --git a/utils/build/build.js b/utils/build/build.js index 7a289bd5edaa1..a1ba052d51fc2 100644 --- a/utils/build/build.js +++ b/utils/build/build.js @@ -275,6 +275,21 @@ for (const bundle of bundles) { }); } +// initial service worker build. +steps.push({ + command: 'npx', + args: [ + 'vite', + '--config', + 'vite.sw.config.ts', + 'build', + ...(withSourceMaps ? ['--sourcemap=inline'] : []), + ], + shell: true, + cwd: path.join(__dirname, '..', '..', 'packages', 'trace-viewer'), + concurrent: false, +}); + // Build/watch web packages. for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) { steps.push({ @@ -290,6 +305,7 @@ for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) { concurrent: true, }); } + // Build/watch trace viewer service worker. steps.push({ command: 'npx', @@ -306,6 +322,16 @@ steps.push({ concurrent: true, }); +// web packages dev server +if (watchMode) { + steps.push({ + command: 'npx', + args: ['vite', '--port', '44223', '--base', '/trace/'], + shell: true, + cwd: path.join(__dirname, '..', '..', 'packages', 'trace-viewer'), + concurrent: true, + }); +} // Generate injected. onChanges.push({ From 67471cb3c5fae0e90057a034723e4c0e26779325 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Thu, 24 Oct 2024 06:03:36 -0700 Subject: [PATCH 368/805] test: make a few tests headed/headless agnostic (#33268) --- tests/playwright-test/expect.spec.ts | 8 ++++---- tests/playwright-test/playwright.trace.spec.ts | 16 +++++++++++----- tests/playwright-test/ui-mode-test-setup.spec.ts | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/playwright-test/expect.spec.ts b/tests/playwright-test/expect.spec.ts index 1886651f95934..08ce16e7ec11f 100644 --- a/tests/playwright-test/expect.spec.ts +++ b/tests/playwright-test/expect.spec.ts @@ -511,13 +511,13 @@ test('should support toHaveURL with baseURL from webServer', async ({ runInlineT import { test, expect } from '@playwright/test'; test('pass', async ({ page }) => { - await page.goto('/foobar'); - await expect(page).toHaveURL('/foobar'); - await expect(page).toHaveURL('http://localhost:${port}/foobar'); + await page.goto('/hello'); + await expect(page).toHaveURL('/hello'); + await expect(page).toHaveURL('http://localhost:${port}/hello'); }); test('fail', async ({ page }) => { - await page.goto('/foobar'); + await page.goto('/hello'); await expect(page).toHaveURL('/kek', { timeout: 1000 }); }); `, diff --git a/tests/playwright-test/playwright.trace.spec.ts b/tests/playwright-test/playwright.trace.spec.ts index ba6020fadef89..5c5d6c304a2d5 100644 --- a/tests/playwright-test/playwright.trace.spec.ts +++ b/tests/playwright-test/playwright.trace.spec.ts @@ -735,28 +735,34 @@ test('should not throw when attachment is missing', async ({ runInlineTest }, te }); test('should not throw when screenshot on failure fails', async ({ runInlineTest, server }, testInfo) => { + server.setRoute('/download', (req, res) => { + res.setHeader('Content-Type', 'application/octet-stream'); + res.setHeader('Content-Disposition', 'attachment; filename=file.txt'); + res.end(`Hello world`); + }); + const result = await runInlineTest({ 'playwright.config.ts': ` module.exports = { use: { trace: 'on', screenshot: 'on' } }; `, 'a.spec.ts': ` import { test, expect } from '@playwright/test'; - test('has pdf page', async ({ page }) => { + test('has download page', async ({ page }) => { await page.goto("${server.EMPTY_PAGE}"); - await page.setContent('open me!'); + await page.setContent('open me!'); const downloadPromise = page.waitForEvent('download'); await page.click('a'); const download = await downloadPromise; - expect(download.suggestedFilename()).toBe('empty.pdf'); + expect(download.suggestedFilename()).toBe('file.txt'); }); `, }, { workers: 1 }); expect(result.exitCode).toBe(0); expect(result.passed).toBe(1); - const trace = await parseTrace(testInfo.outputPath('test-results', 'a-has-pdf-page', 'trace.zip')); + const trace = await parseTrace(testInfo.outputPath('test-results', 'a-has-download-page', 'trace.zip')); const attachedScreenshots = trace.actionTree.filter(s => s.trim() === `attach "screenshot"`); - // One screenshot for the page, no screenshot for pdf page since it should have failed. + // One screenshot for the page, no screenshot for the download page since it should have failed. expect(attachedScreenshots.length).toBe(1); }); diff --git a/tests/playwright-test/ui-mode-test-setup.spec.ts b/tests/playwright-test/ui-mode-test-setup.spec.ts index 65c6aa25330a6..9ed1dadb0d9ec 100644 --- a/tests/playwright-test/ui-mode-test-setup.spec.ts +++ b/tests/playwright-test/ui-mode-test-setup.spec.ts @@ -276,7 +276,7 @@ test('should restart webserver on reload', async ({ runUITest }) => { 'a.test.js': ` import { test, expect } from '@playwright/test'; test('should work', async ({ page }) => { - await page.goto('http://localhost:${port}'); + await page.goto('http://localhost:${port}/hello'); }); ` }, { DEBUG: 'pw:webserver' }); From adc38cfd8b6428a1fa063d785513454503789b06 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 24 Oct 2024 16:49:35 +0200 Subject: [PATCH 369/805] test: rebaseline test expectations (#33270) --- tests/library/capabilities.spec.ts | 1 + tests/page/page-screenshot.spec.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/library/capabilities.spec.ts b/tests/library/capabilities.spec.ts index cdc97d15237d1..72eb73724c98b 100644 --- a/tests/library/capabilities.spec.ts +++ b/tests/library/capabilities.spec.ts @@ -401,6 +401,7 @@ it('should be able to render avif images', { }, async ({ page, server, browserName, platform }) => { it.fixme(browserName === 'webkit' && platform === 'win32'); it.skip(browserName === 'webkit' && hostPlatform.startsWith('ubuntu20.04'), 'Ubuntu 20.04 is frozen'); + it.skip(browserName === 'webkit' && hostPlatform.startsWith('debian11'), 'Debian 11 is too old'); await page.goto(server.EMPTY_PAGE); await page.setContent(``); await expect.poll(() => page.locator('img').boundingBox()).toEqual(expect.objectContaining({ diff --git a/tests/page/page-screenshot.spec.ts b/tests/page/page-screenshot.spec.ts index 879307aa916f3..7e6856c24c196 100644 --- a/tests/page/page-screenshot.spec.ts +++ b/tests/page/page-screenshot.spec.ts @@ -286,7 +286,7 @@ it.describe('page screenshot', () => { await page.goto(server.PREFIX + '/screenshots/canvas.html'); const screenshot = await page.screenshot(); if ((!headless && browserName === 'chromium' && isMac && os.arch() === 'arm64' && macVersion >= 14) || - (browserName === 'webkit' && isLinux)) + (browserName === 'webkit' && isLinux && os.arch() === 'x64')) expect(screenshot).toMatchSnapshot('screenshot-canvas-with-accurate-corners.png'); else expect(screenshot).toMatchSnapshot('screenshot-canvas.png'); From 0509eca9b690aa0efc47fd7bb0b6cd555d1de848 Mon Sep 17 00:00:00 2001 From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com> Date: Thu, 24 Oct 2024 08:47:34 -0700 Subject: [PATCH 370/805] feat(chromium): roll to r1145 (#33274) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 4 +- packages/playwright-core/browsers.json | 4 +- .../src/server/deviceDescriptorsSource.json | 96 +++++++++---------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index e4f15a6d9746a..df47df912199e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-131.0.6778.3-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-131.0.6778.13-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 131.0.6778.3 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 131.0.6778.13 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 131.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json index 6cd5bc321d200..5677f6ec7fa63 100644 --- a/packages/playwright-core/browsers.json +++ b/packages/playwright-core/browsers.json @@ -3,9 +3,9 @@ "browsers": [ { "name": "chromium", - "revision": "1143", + "revision": "1145", "installByDefault": true, - "browserVersion": "131.0.6778.3" + "browserVersion": "131.0.6778.13" }, { "name": "chromium-tip-of-tree", diff --git a/packages/playwright-core/src/server/deviceDescriptorsSource.json b/packages/playwright-core/src/server/deviceDescriptorsSource.json index aef1b4c62b862..90608d052dce8 100644 --- a/packages/playwright-core/src/server/deviceDescriptorsSource.json +++ b/packages/playwright-core/src/server/deviceDescriptorsSource.json @@ -110,7 +110,7 @@ "defaultBrowserType": "webkit" }, "Galaxy S5": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -121,7 +121,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -132,7 +132,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 360, "height": 740 @@ -143,7 +143,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S8 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 740, "height": 360 @@ -154,7 +154,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 320, "height": 658 @@ -165,7 +165,7 @@ "defaultBrowserType": "chromium" }, "Galaxy S9+ landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 658, "height": 320 @@ -176,7 +176,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "viewport": { "width": 712, "height": 1138 @@ -187,7 +187,7 @@ "defaultBrowserType": "chromium" }, "Galaxy Tab S4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "viewport": { "width": 1138, "height": 712 @@ -1098,7 +1098,7 @@ "defaultBrowserType": "webkit" }, "LG Optimus L70": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1109,7 +1109,7 @@ "defaultBrowserType": "chromium" }, "LG Optimus L70 landscape": { - "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1120,7 +1120,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1131,7 +1131,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 550 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1142,7 +1142,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 360, "height": 640 @@ -1153,7 +1153,7 @@ "defaultBrowserType": "chromium" }, "Microsoft Lumia 950 landscape": { - "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36 Edge/14.14263", + "userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36 Edge/14.14263", "viewport": { "width": 640, "height": 360 @@ -1164,7 +1164,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "viewport": { "width": 800, "height": 1280 @@ -1175,7 +1175,7 @@ "defaultBrowserType": "chromium" }, "Nexus 10 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "viewport": { "width": 1280, "height": 800 @@ -1186,7 +1186,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 384, "height": 640 @@ -1197,7 +1197,7 @@ "defaultBrowserType": "chromium" }, "Nexus 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 640, "height": 384 @@ -1208,7 +1208,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1219,7 +1219,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1230,7 +1230,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1241,7 +1241,7 @@ "defaultBrowserType": "chromium" }, "Nexus 5X landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1252,7 +1252,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1263,7 +1263,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1274,7 +1274,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 412, "height": 732 @@ -1285,7 +1285,7 @@ "defaultBrowserType": "chromium" }, "Nexus 6P landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 732, "height": 412 @@ -1296,7 +1296,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "viewport": { "width": 600, "height": 960 @@ -1307,7 +1307,7 @@ "defaultBrowserType": "chromium" }, "Nexus 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "viewport": { "width": 960, "height": 600 @@ -1362,7 +1362,7 @@ "defaultBrowserType": "webkit" }, "Pixel 2": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 411, "height": 731 @@ -1373,7 +1373,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 731, "height": 411 @@ -1384,7 +1384,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 411, "height": 823 @@ -1395,7 +1395,7 @@ "defaultBrowserType": "chromium" }, "Pixel 2 XL landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 823, "height": 411 @@ -1406,7 +1406,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 393, "height": 786 @@ -1417,7 +1417,7 @@ "defaultBrowserType": "chromium" }, "Pixel 3 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 786, "height": 393 @@ -1428,7 +1428,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 353, "height": 745 @@ -1439,7 +1439,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 745, "height": 353 @@ -1450,7 +1450,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G)": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "screen": { "width": 412, "height": 892 @@ -1465,7 +1465,7 @@ "defaultBrowserType": "chromium" }, "Pixel 4a (5G) landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "screen": { "height": 892, "width": 412 @@ -1480,7 +1480,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "screen": { "width": 393, "height": 851 @@ -1495,7 +1495,7 @@ "defaultBrowserType": "chromium" }, "Pixel 5 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "screen": { "width": 851, "height": 393 @@ -1510,7 +1510,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "screen": { "width": 412, "height": 915 @@ -1525,7 +1525,7 @@ "defaultBrowserType": "chromium" }, "Pixel 7 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "screen": { "width": 915, "height": 412 @@ -1540,7 +1540,7 @@ "defaultBrowserType": "chromium" }, "Moto G4": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 360, "height": 640 @@ -1551,7 +1551,7 @@ "defaultBrowserType": "chromium" }, "Moto G4 landscape": { - "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Mobile Safari/537.36", + "userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Mobile Safari/537.36", "viewport": { "width": 640, "height": 360 @@ -1562,7 +1562,7 @@ "defaultBrowserType": "chromium" }, "Desktop Chrome HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "screen": { "width": 1792, "height": 1120 @@ -1577,7 +1577,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge HiDPI": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36 Edg/131.0.6778.3", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36 Edg/131.0.6778.13", "screen": { "width": 1792, "height": 1120 @@ -1622,7 +1622,7 @@ "defaultBrowserType": "webkit" }, "Desktop Chrome": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36", "screen": { "width": 1920, "height": 1080 @@ -1637,7 +1637,7 @@ "defaultBrowserType": "chromium" }, "Desktop Edge": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.3 Safari/537.36 Edg/131.0.6778.3", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.13 Safari/537.36 Edg/131.0.6778.13", "screen": { "width": 1920, "height": 1080 From a2dec8da63b171b75a32ae66a50336b059c90383 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 24 Oct 2024 19:23:19 +0200 Subject: [PATCH 371/805] fix(codegen): SIGINT handling was leading to zombie processes (#33269) --- packages/playwright-core/src/cli/program.ts | 2 ++ packages/playwright-core/src/protocol/validator.ts | 1 + packages/playwright-core/src/server/recorder.ts | 2 ++ packages/playwright-core/src/server/recorder/recorderApp.ts | 2 +- .../playwright-core/src/server/recorder/recorderFrontend.ts | 1 + packages/protocol/src/channels.ts | 2 ++ packages/protocol/src/protocol.yml | 1 + 7 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/playwright-core/src/cli/program.ts b/packages/playwright-core/src/cli/program.ts index 1895f2dfcfe18..59ad0cd9f81f0 100644 --- a/packages/playwright-core/src/cli/program.ts +++ b/packages/playwright-core/src/cli/program.ts @@ -554,6 +554,7 @@ async function open(options: Options, url: string | undefined, language: string) contextOptions, device: options.device, saveStorage: options.saveStorage, + handleSIGINT: false, }); await openPage(context, url); } @@ -577,6 +578,7 @@ async function codegen(options: Options & { target: string, output?: string, tes codegenMode: process.env.PW_RECORDER_IS_TRACE_VIEWER ? 'trace-events' : 'actions', testIdAttributeName, outputFile: outputFile ? path.resolve(outputFile) : undefined, + handleSIGINT: false, }); await openPage(context, url); } diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 24ddf0014c0d1..7bad26f4987b9 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -976,6 +976,7 @@ scheme.BrowserContextEnableRecorderParams = tObject({ device: tOptional(tString), saveStorage: tOptional(tString), outputFile: tOptional(tString), + handleSIGINT: tOptional(tBoolean), omitCallTracking: tOptional(tBoolean), }); scheme.BrowserContextEnableRecorderResult = tOptional(tObject({})); diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 74ebefee86c0c..a2be2992e6ef4 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -34,6 +34,7 @@ import { buildFullSelector } from '../utils/isomorphic/recorderUtils'; const recorderSymbol = Symbol('recorderSymbol'); export class Recorder implements InstrumentationListener, IRecorder { + readonly handleSIGINT: boolean | undefined; private _context: BrowserContext; private _mode: Mode; private _highlightedSelector = ''; @@ -75,6 +76,7 @@ export class Recorder implements InstrumentationListener, IRecorder { constructor(codegenMode: 'actions' | 'trace-events', context: BrowserContext, params: channels.BrowserContextEnableRecorderParams) { this._mode = params.mode || 'none'; + this.handleSIGINT = params.handleSIGINT; this._contextRecorder = new ContextRecorder(codegenMode, context, params, {}); this._context = context; this._omitCallTracking = !!params.omitCallTracking; diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index df27a96c6c8f0..6b6b73e241d86 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -111,7 +111,7 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { noDefaultViewport: true, headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !headed), useWebSocket: isUnderTest(), - handleSIGINT: false, + handleSIGINT: recorder.handleSIGINT, executablePath: inspectedContext._browser.options.isChromium ? inspectedContext._browser.options.customExecutablePath : undefined, } }); diff --git a/packages/playwright-core/src/server/recorder/recorderFrontend.ts b/packages/playwright-core/src/server/recorder/recorderFrontend.ts index dbba78ceeb4e9..b3dc0daad9bd8 100644 --- a/packages/playwright-core/src/server/recorder/recorderFrontend.ts +++ b/packages/playwright-core/src/server/recorder/recorderFrontend.ts @@ -21,6 +21,7 @@ import type { EventEmitter } from 'events'; export interface IRecorder { setMode(mode: Mode): void; mode(): Mode; + readonly handleSIGINT: boolean | undefined; } export interface IRecorderApp extends EventEmitter { diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index 5ecc2f4077e07..7fcb815468560 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -1777,6 +1777,7 @@ export type BrowserContextEnableRecorderParams = { device?: string, saveStorage?: string, outputFile?: string, + handleSIGINT?: boolean, omitCallTracking?: boolean, }; export type BrowserContextEnableRecorderOptions = { @@ -1790,6 +1791,7 @@ export type BrowserContextEnableRecorderOptions = { device?: string, saveStorage?: string, outputFile?: string, + handleSIGINT?: boolean, omitCallTracking?: boolean, }; export type BrowserContextEnableRecorderResult = void; diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index c91cecbe6cab7..98428cae2f75b 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -1208,6 +1208,7 @@ BrowserContext: device: string? saveStorage: string? outputFile: string? + handleSIGINT: boolean? omitCallTracking: boolean? newCDPSession: From ff5f1628dc8dbbb0217554adc3105bff4e0a504c Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 24 Oct 2024 16:49:10 -0700 Subject: [PATCH 372/805] chore: allow aria snapshot rebaselines (#33256) --- .../src/server/injected/ariaSnapshot.ts | 23 +++-- packages/playwright/src/common/ipc.ts | 1 + packages/playwright/src/matchers/expect.ts | 11 ++- .../playwright/src/matchers/matcherHint.ts | 3 +- .../src/matchers/toMatchAriaSnapshot.ts | 21 +++- packages/playwright/src/runner/dispatcher.ts | 3 + packages/playwright/src/runner/rebase.ts | 95 +++++++++++++++++++ packages/playwright/src/runner/runner.ts | 3 + packages/playwright/src/worker/testInfo.ts | 3 +- tests/page/page-aria-snapshot.spec.ts | 24 ++--- tests/page/to-match-aria-snapshot.spec.ts | 8 +- .../playwright-test/ui-mode-test-run.spec.ts | 76 +++++++-------- .../update-aria-snapshot.spec.ts | 48 ++++++++++ 13 files changed, 245 insertions(+), 74 deletions(-) create mode 100644 packages/playwright/src/runner/rebase.ts create mode 100644 tests/playwright-test/update-aria-snapshot.spec.ts diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index d544c0a82ca35..a8d9e81bcd6eb 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { escapeWithQuotes } from '@isomorphic/stringUtils'; import * as roleUtils from './roleUtils'; import { getElementComputedStyle } from './domUtils'; import type { AriaRole } from './roleUtils'; @@ -184,7 +183,7 @@ function matchesText(text: string | undefined, template: RegExp | string | undef export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode): { matches: boolean, received: string } { const root = generateAriaTree(rootElement); const matches = matchesNodeDeep(root, template); - return { matches, received: renderAriaTree(root, { noText: true }) }; + return { matches, received: renderAriaTree(root) }; } function matchesNode(node: AriaNode | string, template: AriaTemplateNode | RegExp | string, depth: number): boolean { @@ -252,17 +251,16 @@ function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): boolean { return !!results.length; } -export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean }): string { +export function renderAriaTree(ariaNode: AriaNode): string { const lines: string[] = []; const visit = (ariaNode: AriaNode | string, indent: string) => { if (typeof ariaNode === 'string') { - if (!options?.noText) - lines.push(indent + '- text: ' + quoteYamlString(ariaNode)); + lines.push(indent + '- text: ' + quoteYamlString(ariaNode)); return; } let line = `${indent}- ${ariaNode.role}`; if (ariaNode.name) - line += ` ${escapeWithQuotes(ariaNode.name, '"')}`; + line += ` ${quoteYamlString(ariaNode.name)}`; if (ariaNode.checked === 'mixed') line += ` [checked=mixed]`; @@ -281,9 +279,16 @@ export function renderAriaTree(ariaNode: AriaNode, options?: { noText?: boolean if (ariaNode.selected === true) line += ` [selected]`; - lines.push(line + (ariaNode.children.length ? ':' : '')); - for (const child of ariaNode.children || []) - visit(child, indent + ' '); + if (!ariaNode.children.length) { + lines.push(line); + } else if (ariaNode.children.length === 1 && typeof ariaNode.children[0] === 'string') { + line += ': ' + quoteYamlString(ariaNode.children[0]); + lines.push(line); + } else { + lines.push(line + ':'); + for (const child of ariaNode.children || []) + visit(child, indent + ' '); + } }; if (ariaNode.role === 'fragment') { diff --git a/packages/playwright/src/common/ipc.ts b/packages/playwright/src/common/ipc.ts index 82538bb6ede18..dcde2b28d4924 100644 --- a/packages/playwright/src/common/ipc.ts +++ b/packages/playwright/src/common/ipc.ts @@ -106,6 +106,7 @@ export type StepEndPayload = { stepId: string; wallTime: number; // milliseconds since unix epoch error?: TestInfoErrorImpl; + suggestedRebaseline?: string; }; export type TestEntry = { diff --git a/packages/playwright/src/matchers/expect.ts b/packages/playwright/src/matchers/expect.ts index 0d276d4101ab0..0bd116e7a1f62 100644 --- a/packages/playwright/src/matchers/expect.ts +++ b/packages/playwright/src/matchers/expect.ts @@ -61,7 +61,7 @@ import { } from '../common/expectBundle'; import { zones } from 'playwright-core/lib/utils'; import { TestInfoImpl } from '../worker/testInfo'; -import { ExpectError, isExpectError } from './matcherHint'; +import { ExpectError, isJestError } from './matcherHint'; import { toMatchAriaSnapshot } from './toMatchAriaSnapshot'; // #region @@ -323,8 +323,13 @@ class ExpectMetaInfoProxyHandler implements ProxyHandler { const step = testInfo._addStep(stepInfo); - const reportStepError = (jestError: Error | unknown) => { - const error = isExpectError(jestError) ? new ExpectError(jestError, customMessage, stackFrames) : jestError; + const reportStepError = (e: Error | unknown) => { + const jestError = isJestError(e) ? e : null; + const error = jestError ? new ExpectError(jestError, customMessage, stackFrames) : e; + if (jestError?.matcherResult.suggestedRebaseline) { + step.complete({ suggestedRebaseline: jestError?.matcherResult.suggestedRebaseline }); + return; + } step.complete({ error }); if (this._info.isSoft) testInfo._failWithError(error); diff --git a/packages/playwright/src/matchers/matcherHint.ts b/packages/playwright/src/matchers/matcherHint.ts index 200501c1bc2ae..c4f5afd4b4bd6 100644 --- a/packages/playwright/src/matchers/matcherHint.ts +++ b/packages/playwright/src/matchers/matcherHint.ts @@ -43,6 +43,7 @@ export type MatcherResult = { printedReceived?: string; printedExpected?: string; printedDiff?: string; + suggestedRebaseline?: string; }; export type MatcherResultProperty = Omit, 'message'> & { @@ -69,6 +70,6 @@ export class ExpectError extends Error { } } -export function isExpectError(e: unknown): e is ExpectError { +export function isJestError(e: unknown): e is JestError { return e instanceof Error && 'matcherResult' in e; } diff --git a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts index 5b2c2044106db..2c92d562d646d 100644 --- a/packages/playwright/src/matchers/toMatchAriaSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchAriaSnapshot.ts @@ -22,6 +22,7 @@ import { colors } from 'playwright-core/lib/utilsBundle'; import { EXPECTED_COLOR } from '../common/expectBundle'; import { callLogText } from '../util'; import { printReceivedStringContainExpectedSubstring } from './expect'; +import { currentTestInfo } from '../common/globals'; export async function toMatchAriaSnapshot( this: ExpectMatcherState, @@ -31,6 +32,15 @@ export async function toMatchAriaSnapshot( ): Promise> { const matcherName = 'toMatchAriaSnapshot'; + const testInfo = currentTestInfo(); + if (!testInfo) + throw new Error(`toMatchSnapshot() must be called during the test`); + + if (testInfo._projectInternal.ignoreSnapshots) + return { pass: !this.isNot, message: () => '', name: 'toMatchSnapshot', expected }; + + const updateSnapshots = testInfo.config.updateSnapshots; + const matcherOptions = { isNot: this.isNot, promise: this.promise, @@ -65,6 +75,12 @@ export async function toMatchAriaSnapshot( } }; + let suggestedRebaseline: string | undefined; + if (!this.isNot && pass === this.isNot) { + if (updateSnapshots === 'all' || (updateSnapshots === 'missing' && !expected.trim())) + suggestedRebaseline = `toMatchAriaSnapshot(\`\n${unshift(received, '${indent} ')}\n\${indent}\`)`; + } + return { name: matcherName, expected, @@ -72,6 +88,7 @@ export async function toMatchAriaSnapshot( pass, actual: received, log, + suggestedRebaseline, timeout: timedOut ? timeout : undefined, }; } @@ -80,7 +97,7 @@ function escapePrivateUsePoints(str: string) { return str.replace(/[\uE000-\uF8FF]/g, char => `\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`); } -function unshift(snapshot: string): string { +function unshift(snapshot: string, indent: string = ''): string { const lines = snapshot.split('\n'); let whitespacePrefixLength = 100; for (const line of lines) { @@ -91,5 +108,5 @@ function unshift(snapshot: string): string { whitespacePrefixLength = match[1].length; break; } - return lines.filter(t => t.trim()).map(line => line.substring(whitespacePrefixLength)).join('\n'); + return lines.filter(t => t.trim()).map(line => indent + line.substring(whitespacePrefixLength)).join('\n'); } diff --git a/packages/playwright/src/runner/dispatcher.ts b/packages/playwright/src/runner/dispatcher.ts index 4e971f24757ac..98e0ec1546c88 100644 --- a/packages/playwright/src/runner/dispatcher.ts +++ b/packages/playwright/src/runner/dispatcher.ts @@ -27,6 +27,7 @@ import type { FullConfigInternal } from '../common/config'; import type { ReporterV2 } from '../reporters/reporterV2'; import type { FailureTracker } from './failureTracker'; import { colors } from 'playwright-core/lib/utilsBundle'; +import { addSuggestedRebaseline } from './rebase'; export type EnvByProjectId = Map>; @@ -341,6 +342,8 @@ class JobDispatcher { step.duration = params.wallTime - step.startTime.getTime(); if (params.error) step.error = params.error; + if (params.suggestedRebaseline) + addSuggestedRebaseline(step.location!, params.suggestedRebaseline); steps.delete(params.stepId); this._reporter.onStepEnd?.(test, result, step); } diff --git a/packages/playwright/src/runner/rebase.ts b/packages/playwright/src/runner/rebase.ts new file mode 100644 index 0000000000000..17717e977e018 --- /dev/null +++ b/packages/playwright/src/runner/rebase.ts @@ -0,0 +1,95 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import path from 'path'; +import fs from 'fs'; +import type { T } from '../transform/babelBundle'; +import { types, traverse, parse } from '../transform/babelBundle'; +import { MultiMap } from 'playwright-core/lib/utils'; +import { generateUnifiedDiff } from 'playwright-core/lib/utils'; +import type { FullConfigInternal } from '../common/config'; +import { filterProjects } from './projectUtils'; +const t: typeof T = types; + +type Location = { + file: string; + line: number; + column: number; +}; + +type Replacement = { + // Points to the call expression. + location: Location; + code: string; +}; + +const suggestedRebaselines = new MultiMap(); + +export function addSuggestedRebaseline(location: Location, suggestedRebaseline: string) { + suggestedRebaselines.set(location.file, { location, code: suggestedRebaseline }); +} + +export async function applySuggestedRebaselines(config: FullConfigInternal) { + if (config.config.updateSnapshots !== 'all' && config.config.updateSnapshots !== 'missing') + return; + const [project] = filterProjects(config.projects, config.cliProjectFilter); + if (!project) + return; + + for (const fileName of suggestedRebaselines.keys()) { + const source = await fs.promises.readFile(fileName, 'utf8'); + const lines = source.split('\n'); + const replacements = suggestedRebaselines.get(fileName); + const fileNode = parse(source, { sourceType: 'module' }); + const ranges: { start: number, end: number, oldText: string, newText: string }[] = []; + + traverse(fileNode, { + CallExpression: path => { + const node = path.node; + if (node.arguments.length !== 1) + return; + if (!t.isMemberExpression(node.callee)) + return; + const argument = node.arguments[0]; + if (!t.isStringLiteral(argument) && !t.isTemplateLiteral(argument)) + return; + + const matcher = node.callee.property; + for (const replacement of replacements) { + // In Babel, rows are 1-based, columns are 0-based. + if (matcher.loc!.start.line !== replacement.location.line) + continue; + if (matcher.loc!.start.column + 1 !== replacement.location.column) + continue; + const indent = lines[matcher.loc!.start.line - 1].match(/^\s*/)![0]; + const newText = replacement.code.replace(/\$\{indent\}/g, indent); + ranges.push({ start: matcher.start!, end: node.end!, oldText: source.substring(matcher.start!, node.end!), newText }); + } + } + }); + + ranges.sort((a, b) => b.start - a.start); + let result = source; + for (const range of ranges) + result = result.substring(0, range.start) + range.newText + result.substring(range.end); + + const relativeName = path.relative(process.cwd(), fileName); + + const patchFile = path.join(project.project.outputDir, 'rebaselines.patch'); + await fs.promises.mkdir(path.dirname(patchFile), { recursive: true }); + await fs.promises.writeFile(patchFile, generateUnifiedDiff(source, result, relativeName)); + } +} diff --git a/packages/playwright/src/runner/runner.ts b/packages/playwright/src/runner/runner.ts index 923bf36072cd6..966fb13e92292 100644 --- a/packages/playwright/src/runner/runner.ts +++ b/packages/playwright/src/runner/runner.ts @@ -24,6 +24,7 @@ import type { FullConfigInternal } from '../common/config'; import { affectedTestFiles } from '../transform/compilationCache'; import { InternalReporter } from '../reporters/internalReporter'; import { LastRunReporter } from './lastRun'; +import { applySuggestedRebaselines } from './rebase'; type ProjectConfigWithFiles = { name: string; @@ -88,6 +89,8 @@ export class Runner { ]; const status = await runTasks(new TestRun(config, reporter), tasks, config.config.globalTimeout); + await applySuggestedRebaselines(config); + // Calling process.exit() might truncate large stdout/stderr output. // See https://github.com/nodejs/node/issues/6456. // See https://github.com/nodejs/node/issues/12921 diff --git a/packages/playwright/src/worker/testInfo.ts b/packages/playwright/src/worker/testInfo.ts index ed71b1a751a1a..b5b1010ff255c 100644 --- a/packages/playwright/src/worker/testInfo.ts +++ b/packages/playwright/src/worker/testInfo.ts @@ -31,7 +31,7 @@ import type { StackFrame } from '@protocol/channels'; import { testInfoError } from './util'; export interface TestStepInternal { - complete(result: { error?: Error | unknown, attachments?: Attachment[] }): void; + complete(result: { error?: Error | unknown, attachments?: Attachment[], suggestedRebaseline?: string }): void; stepId: string; title: string; category: 'hook' | 'fixture' | 'test.step' | 'expect' | 'attach' | string; @@ -297,6 +297,7 @@ export class TestInfoImpl implements TestInfo { stepId, wallTime: step.endWallTime, error: step.error, + suggestedRebaseline: result.suggestedRebaseline, }; this._onStepEnd(payload); const errorForTrace = step.error ? { name: '', message: step.error.message || '', stack: step.error.stack } : undefined; diff --git a/tests/page/page-aria-snapshot.spec.ts b/tests/page/page-aria-snapshot.spec.ts index 2b8790589af38..e4ee122b0c998 100644 --- a/tests/page/page-aria-snapshot.spec.ts +++ b/tests/page/page-aria-snapshot.spec.ts @@ -64,10 +64,8 @@ it('should snapshot list with accessible name', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - list "my list": - - listitem: - - text: "one" - - listitem: - - text: "two" + - listitem: "one" + - listitem: "two" `); }); @@ -107,8 +105,7 @@ it('should snapshot details visibility', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - group: - - text: "Summary" + - group: "Summary" `); }); @@ -151,8 +148,7 @@ it('should snapshot integration', async ({ page }) => { - text: "Open source projects and samples from Microsoft" - list: - listitem: - - group: - - text: "Verified" + - group: "Verified" - listitem: - link "Sponsor" `); @@ -168,12 +164,10 @@ it('should support multiline text', async ({ page }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: - - text: "Line 1 Line 2 Line 3" + - paragraph: "Line 1 Line 2 Line 3" `); await expect(page.locator('body')).toMatchAriaSnapshot(` - - paragraph: - - text: | + - paragraph: | Line 1 Line 2 Line 3 @@ -388,8 +382,7 @@ it('should include pseudo codepoints', async ({ page, server }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: - - text: "\ueab2hello" + - paragraph: "\ueab2hello" `); }); @@ -403,7 +396,6 @@ it('check aria-hidden text', async ({ page, server }) => { `); await checkAndMatchSnapshot(page.locator('body'), ` - - paragraph: - - text: "hello" + - paragraph: "hello" `); }); diff --git a/tests/page/to-match-aria-snapshot.spec.ts b/tests/page/to-match-aria-snapshot.spec.ts index 1335be5a59c9a..8050c3b5693ad 100644 --- a/tests/page/to-match-aria-snapshot.spec.ts +++ b/tests/page/to-match-aria-snapshot.spec.ts @@ -43,8 +43,8 @@ test('should match list with accessible name', async ({ page }) => { `); await expect(page.locator('body')).toMatchAriaSnapshot(` - list "my list": - - listitem: one - - listitem: two + - listitem: "one" + - listitem: "two" `); }); @@ -90,7 +90,7 @@ test('should allow text nodes', async ({ page }) => { await expect(page.locator('body')).toMatchAriaSnapshot(` - heading "Microsoft" - - text: Open source projects and samples from Microsoft + - text: "Open source projects and samples from Microsoft" `); }); @@ -103,7 +103,7 @@ test('details visibility', async ({ page }) => { `); await expect(page.locator('body')).toMatchAriaSnapshot(` - - group: Summary + - group: "Summary" `); }); diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index 0da2940e964f3..b30f901654a7f 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -65,19 +65,19 @@ test('should run visible', async ({ runUITest }) => { - tree: - treeitem "[icon-error] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - treeitem ${/\[icon-check\] passes/} + - treeitem ${/\[icon-error\] fails/} [selected]: - button "Run" - button "Show source" - button "Watch" - treeitem "[icon-error] suite" - treeitem "[icon-error] b.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem ${/\[icon-check\] passes/} + - treeitem ${/\[icon-error\] fails/} - treeitem "[icon-check] c.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-check\] passes/} - treeitem "[icon-circle-slash] skipped" `); @@ -125,7 +125,7 @@ test('should run on hover', async ({ runUITest }) => { - tree: - treeitem "[icon-circle-outline] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/}: + - treeitem ${/\[icon-check\] passes/}: - button "Run" - button "Show source" - button "Watch" @@ -185,7 +185,7 @@ test('should run on Enter', async ({ runUITest }) => { - treeitem "[icon-error] a.test.ts" [expanded]: - group: - treeitem "[icon-circle-outline] passes" - - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - treeitem ${/\[icon-error\] fails/} [selected]: - button "Run" - button "Show source" - button "Watch" @@ -225,19 +225,19 @@ test('should run by project', async ({ runUITest }) => { - tree: - treeitem "[icon-error] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - treeitem ${/\[icon-check\] passes/} + - treeitem ${/\[icon-error\] fails/} [selected]: - button "Run" - button "Show source" - button "Watch" - treeitem "[icon-error] suite" - treeitem "[icon-error] b.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem ${/\[icon-check\] passes/} + - treeitem ${/\[icon-error\] fails/} - treeitem "[icon-check] c.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-check\] passes/} - treeitem "[icon-circle-slash] skipped" `); @@ -299,14 +299,14 @@ test('should run by project', async ({ runUITest }) => { - tree: - treeitem "[icon-error] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-circle-outline\] passes \d+ms/} [expanded] [selected]: + - treeitem ${/\[icon-circle-outline\] passes/} [expanded] [selected]: - button "Run" - button "Show source" - button "Watch" - group: - - treeitem ${/\[icon-check\] foo \d+ms/} + - treeitem ${/\[icon-check\] foo/} - treeitem ${/\[icon-circle-outline\] bar/} - - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem ${/\[icon-error\] fails/} `); await expect(page.getByText('Projects: foo bar')).toBeVisible(); @@ -333,17 +333,17 @@ test('should run by project', async ({ runUITest }) => { - tree: - treeitem "[icon-error] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} [expanded]: + - treeitem ${/\[icon-check\] passes/} [expanded]: - group: - - treeitem ${/\[icon-check\] foo \d+ms/} - - treeitem ${/\[icon-check\] bar \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} [expanded]: + - treeitem ${/\[icon-check\] foo/} + - treeitem ${/\[icon-check\] bar/} + - treeitem ${/\[icon-error\] fails/} [expanded]: - group: - - treeitem ${/\[icon-error\] foo \d+ms/} [selected]: + - treeitem ${/\[icon-error\] foo/} [selected]: - button "Run" - button "Show source" - button "Watch" - - treeitem ${/\[icon-error\] bar \d+ms/} + - treeitem ${/\[icon-error\] bar/} - treeitem ${/\[icon-error\] suite/} - treeitem "[icon-error] b.test.ts" [expanded]: - group: @@ -385,7 +385,7 @@ test('should stop', async ({ runUITest }) => { - treeitem "[icon-loading] a.test.ts" [expanded]: - group: - treeitem "[icon-circle-slash] test 0" - - treeitem ${/\[icon-check\] test 1 \d+ms/} + - treeitem ${/\[icon-check\] test 1/} - treeitem ${/\[icon-loading\] test 2/} - treeitem ${/\[icon-clock\] test 3/} `); @@ -408,7 +408,7 @@ test('should stop', async ({ runUITest }) => { - treeitem "[icon-circle-outline] a.test.ts" [expanded]: - group: - treeitem "[icon-circle-slash] test 0" - - treeitem ${/\[icon-check\] test 1 \d+ms/} + - treeitem ${/\[icon-check\] test 1/} - treeitem ${/\[icon-circle-outline\] test 2/} - treeitem ${/\[icon-circle-outline\] test 3/} `); @@ -478,19 +478,19 @@ test('should show time', async ({ runUITest }) => { - tree: - treeitem "[icon-error] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} [selected]: + - treeitem ${/\[icon-check\] passes \d+m?s/} + - treeitem ${/\[icon-error\] fails \d+m?s/} [selected]: - button "Run" - button "Show source" - button "Watch" - treeitem "[icon-error] suite" - treeitem "[icon-error] b.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} - - treeitem ${/\[icon-error\] fails \d+ms/} + - treeitem ${/\[icon-check\] passes \d+m?s/} + - treeitem ${/\[icon-error\] fails \d+m?s/} - treeitem "[icon-check] c.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] passes \d+ms/} + - treeitem ${/\[icon-check\] passes \d+m?s/} - treeitem "[icon-circle-slash] skipped" `); @@ -522,7 +522,7 @@ test('should show test.fail as passing', async ({ runUITest }) => { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] should fail \d+ms/} + - treeitem ${/\[icon-check\] should fail \d+m?s/} `); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); @@ -558,7 +558,7 @@ test('should ignore repeatEach', async ({ runUITest }) => { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] should pass \d+ms/} + - treeitem ${/\[icon-check\] should pass/} `); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); @@ -593,7 +593,7 @@ test('should remove output folder before test run', async ({ runUITest }) => { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] should pass \d+ms/} + - treeitem ${/\[icon-check\] should pass/} `); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); @@ -608,7 +608,7 @@ test('should remove output folder before test run', async ({ runUITest }) => { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] should pass \d+ms/} + - treeitem ${/\[icon-check\] should pass/} `); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); @@ -656,7 +656,7 @@ test('should show proper total when using deps', async ({ runUITest }) => { - tree: - treeitem "[icon-circle-outline] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] run @setup setup \d+ms/} [selected]: + - treeitem ${/\[icon-check\] run @setup setup/} [selected]: - button "Run" - button "Show source" - button "Watch" @@ -676,8 +676,8 @@ test('should show proper total when using deps', async ({ runUITest }) => { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] run @setup setup \d+ms/} - - treeitem ${/\[icon-check\] run @chromium chromium \d+ms/} [selected]: + - treeitem ${/\[icon-check\] run @setup setup/} + - treeitem ${/\[icon-check\] run @chromium chromium/} [selected]: - button "Run" - button "Show source" - button "Watch" @@ -746,7 +746,7 @@ test('should respect --tsconfig option', { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] test \d+ms/} + - treeitem ${/\[icon-check\] test/} `); await expect(page.getByTestId('status-line')).toHaveText('1/1 passed (100%)'); @@ -775,7 +775,7 @@ test('should respect --ignore-snapshots option', { - tree: - treeitem "[icon-check] a.test.ts" [expanded]: - group: - - treeitem ${/\[icon-check\] snapshot \d+ms/} + - treeitem ${/\[icon-check\] snapshot/} `); }); @@ -788,4 +788,4 @@ test('should show funny messages', async ({ runUITest }) => { await expect(schmettingsHeader).toBeVisible(); await schmettingsHeader.click(); await expect(page.getByRole('checkbox', { name: 'Fart mode' })).toBeVisible(); -}); \ No newline at end of file +}); diff --git a/tests/playwright-test/update-aria-snapshot.spec.ts b/tests/playwright-test/update-aria-snapshot.spec.ts new file mode 100644 index 0000000000000..092d408191deb --- /dev/null +++ b/tests/playwright-test/update-aria-snapshot.spec.ts @@ -0,0 +1,48 @@ +/** + * Copyright Microsoft Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as fs from 'fs'; +import { test, expect } from './playwright-test-fixtures'; + +test('should update snapshot with the update-snapshots flag', async ({ runInlineTest }, testInfo) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('test', async ({ page }) => { + await page.setContent(\`

      hello

      \`); + await expect(page.locator('body')).toMatchAriaSnapshot(\` + - heading "world" + \`); + }); + ` + }, { 'update-snapshots': true }); + + expect(result.exitCode).toBe(0); + const patchPath = testInfo.outputPath('test-results/rebaselines.patch'); + const data = fs.readFileSync(patchPath, 'utf-8'); + expect(data).toBe(`--- a/a.spec.ts ++++ b/a.spec.ts +@@ -3,7 +3,7 @@ + test('test', async ({ page }) => { + await page.setContent(\`

      hello

      \`); + await expect(page.locator('body')).toMatchAriaSnapshot(\` +- - heading "world" ++ - heading "hello" [level=1] + \`); + }); + +`); +}); From 9707e978671bb77b44537086839610b730eca544 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 25 Oct 2024 00:36:03 -0700 Subject: [PATCH 373/805] chore: revert #33228 - it needs a proper review (#33284) --- .../src/server/trace/viewer/traceViewer.ts | 9 +------ packages/trace-viewer/.gitignore | 2 -- packages/trace-viewer/src/embedded.tsx | 2 +- packages/trace-viewer/src/index.tsx | 2 +- packages/trace-viewer/src/recorder.tsx | 2 +- .../trace-viewer/src/sw/traceModelBackends.ts | 27 +++++++------------ packages/trace-viewer/src/ui/uiModeView.tsx | 7 ++--- packages/trace-viewer/src/uiMode.tsx | 2 +- packages/trace-viewer/vite.config.ts | 3 --- packages/trace-viewer/vite.sw.config.ts | 2 +- .../playwright-test/ui-mode-test-run.spec.ts | 11 -------- utils/build/build.js | 26 ------------------ 12 files changed, 18 insertions(+), 77 deletions(-) diff --git a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts index 32cbba0982ee7..a49148e061e6d 100644 --- a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts +++ b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts @@ -125,14 +125,7 @@ export async function installRootRedirect(server: HttpServer, traceUrls: string[ for (const reporter of options.reporter || []) params.append('reporter', reporter); - let baseUrl = ''; - if (process.env.PW_HMR === '1') { - params.set('testServerPort', '' + server.port()); - baseUrl = 'http://localhost:44223'; // port is hardcoded in build.js - } - - const urlPath = `${baseUrl}/trace/${options.webApp || 'index.html'}?${params.toString()}`; - + const urlPath = `./trace/${options.webApp || 'index.html'}?${params.toString()}`; server.routePath('/', (_, response) => { response.statusCode = 302; response.setHeader('Location', urlPath); diff --git a/packages/trace-viewer/.gitignore b/packages/trace-viewer/.gitignore index 1e3942879c827..a547bf36d8d11 100644 --- a/packages/trace-viewer/.gitignore +++ b/packages/trace-viewer/.gitignore @@ -22,5 +22,3 @@ dist-ssr *.njsproj *.sln *.sw? - -public/sw.bundle.js* diff --git a/packages/trace-viewer/src/embedded.tsx b/packages/trace-viewer/src/embedded.tsx index cc61703bafc01..4f1503dcf27fe 100644 --- a/packages/trace-viewer/src/embedded.tsx +++ b/packages/trace-viewer/src/embedded.tsx @@ -45,7 +45,7 @@ import { EmbeddedWorkbenchLoader } from './ui/embeddedWorkbenchLoader'; if (window.location.protocol !== 'file:') { if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js' + window.location.search); + navigator.serviceWorker.register('sw.bundle.js'); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/src/index.tsx b/packages/trace-viewer/src/index.tsx index 2296cb0090b4a..a737d9017f76c 100644 --- a/packages/trace-viewer/src/index.tsx +++ b/packages/trace-viewer/src/index.tsx @@ -27,7 +27,7 @@ import { WorkbenchLoader } from './ui/workbenchLoader'; await new Promise(f => setTimeout(f, 1000)); if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the Trace Viewer (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js' + window.location.search); + navigator.serviceWorker.register('sw.bundle.js'); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/src/recorder.tsx b/packages/trace-viewer/src/recorder.tsx index 6239df86ab7a5..5e6b9764e3431 100644 --- a/packages/trace-viewer/src/recorder.tsx +++ b/packages/trace-viewer/src/recorder.tsx @@ -26,7 +26,7 @@ import { RecorderView } from './ui/recorder/recorderView'; if (window.location.protocol !== 'file:') { if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the Recorder (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js' + window.location.search); + navigator.serviceWorker.register('sw.bundle.js'); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/src/sw/traceModelBackends.ts b/packages/trace-viewer/src/sw/traceModelBackends.ts index 4f5bd49624078..19c5fc2deec52 100644 --- a/packages/trace-viewer/src/sw/traceModelBackends.ts +++ b/packages/trace-viewer/src/sw/traceModelBackends.ts @@ -30,8 +30,9 @@ export class ZipTraceModelBackend implements TraceModelBackend { constructor(traceURL: string, progress: Progress) { this._traceURL = traceURL; + zipjs.configure({ baseURL: self.location.href } as any); this._zipReader = new zipjs.ZipReader( - new zipjs.HttpReader(formatTraceFileUrl(traceURL), { mode: 'cors', preventHeadRequest: true } as any), + new zipjs.HttpReader(formatUrl(traceURL), { mode: 'cors', preventHeadRequest: true } as any), { useWebWorkers: false }); this._entriesPromise = this._zipReader.getEntries({ onprogress: progress }).then(entries => { const map = new Map(); @@ -86,7 +87,7 @@ export class FetchTraceModelBackend implements TraceModelBackend { constructor(traceURL: string) { this._traceURL = traceURL; - this._entriesPromise = fetch(formatTraceFileUrl(traceURL)).then(async response => { + this._entriesPromise = fetch('/trace/file?path=' + encodeURIComponent(traceURL)).then(async response => { const json = JSON.parse(await response.text()); const entries = new Map(); for (const entry of json.entries) @@ -128,22 +129,14 @@ export class FetchTraceModelBackend implements TraceModelBackend { const fileName = entries.get(entryName); if (!fileName) return; - - return fetch(formatTraceFileUrl(fileName)); + return fetch('/trace/file?path=' + encodeURIComponent(fileName)); } } -const baseURL = new URL(self.location.href); -baseURL.port = baseURL.searchParams.get('testServerPort') ?? baseURL.port; - -function formatTraceFileUrl(trace: string) { - if (trace.startsWith('https://www.dropbox.com/')) - return 'https://dl.dropboxusercontent.com/' + trace.substring('https://www.dropbox.com/'.length); - - if (trace.startsWith('http') || trace.startsWith('blob')) - return trace; - - const url = new URL('/trace/file', baseURL); - url.searchParams.set('path', trace); - return url.toString(); +function formatUrl(trace: string) { + let url = trace.startsWith('http') || trace.startsWith('blob') ? trace : `file?path=${encodeURIComponent(trace)}`; + // Dropbox does not support cors. + if (url.startsWith('https://www.dropbox.com/')) + url = 'https://dl.dropboxusercontent.com/' + url.substring('https://www.dropbox.com/'.length); + return url; } diff --git a/packages/trace-viewer/src/ui/uiModeView.tsx b/packages/trace-viewer/src/ui/uiModeView.tsx index 37b6a6bcf61b7..69a598864145f 100644 --- a/packages/trace-viewer/src/ui/uiModeView.tsx +++ b/packages/trace-viewer/src/ui/uiModeView.tsx @@ -50,7 +50,6 @@ const searchParams = new URLSearchParams(window.location.search); const guid = searchParams.get('ws'); const wsURL = new URL(`../${guid}`, window.location.toString()); wsURL.protocol = (window.location.protocol === 'https:' ? 'wss:' : 'ws:'); -wsURL.port = searchParams.get('testServerPort') ?? window.location.port; const queryParams = { args: searchParams.getAll('arg'), grep: searchParams.get('grep') || undefined, @@ -69,7 +68,6 @@ const isMac = navigator.platform === 'MacIntel'; export const UIModeView: React.FC<{}> = ({ }) => { - const isJokesDay = new Date().getMonth() === 3 && new Date().getDate() === 1; const [filterText, setFilterText] = React.useState(''); const [isShowingOutput, setIsShowingOutput] = React.useState(false); const [outputContainsError, setOutputContainsError] = React.useState(false); @@ -442,7 +440,7 @@ export const UIModeView: React.FC<{}> = ({ sidebar={
      Playwright logo -
      {isJokesDay ? 'Claywright' : 'Playwright'}
      +
      Playwright
      reloadTests()} disabled={isRunningTest || isLoading}>
      { setIsShowingOutput(!isShowingOutput); }} /> @@ -518,11 +516,10 @@ export const UIModeView: React.FC<{}> = ({ style={{ marginLeft: 5 }} title={settingsVisible ? 'Hide Settings' : 'Show Settings'} /> -
      {isJokesDay ? 'Schmettings' : 'Settings'}
      +
      Settings
      {settingsVisible && }
      } diff --git a/packages/trace-viewer/src/uiMode.tsx b/packages/trace-viewer/src/uiMode.tsx index 4702621e5d05c..5dac2082e81ee 100644 --- a/packages/trace-viewer/src/uiMode.tsx +++ b/packages/trace-viewer/src/uiMode.tsx @@ -27,7 +27,7 @@ import { UIModeView } from './ui/uiModeView'; await new Promise(f => setTimeout(f, 1000)); if (!navigator.serviceWorker) throw new Error(`Service workers are not supported.\nMake sure to serve the website (${window.location}) via HTTPS or localhost.`); - navigator.serviceWorker.register('sw.bundle.js' + window.location.search); + navigator.serviceWorker.register('sw.bundle.js'); if (!navigator.serviceWorker.controller) { await new Promise(f => { navigator.serviceWorker.oncontrollerchange = () => f(); diff --git a/packages/trace-viewer/vite.config.ts b/packages/trace-viewer/vite.config.ts index 541b1ab6b6d56..0e2e9cb642770 100644 --- a/packages/trace-viewer/vite.config.ts +++ b/packages/trace-viewer/vite.config.ts @@ -26,9 +26,6 @@ export default defineConfig({ react(), bundle() ], - define: { - 'process.env': {}, - }, resolve: { alias: { '@injected': path.resolve(__dirname, '../playwright-core/src/server/injected'), diff --git a/packages/trace-viewer/vite.sw.config.ts b/packages/trace-viewer/vite.sw.config.ts index a0dd99036a67f..dc621448b9ee1 100644 --- a/packages/trace-viewer/vite.sw.config.ts +++ b/packages/trace-viewer/vite.sw.config.ts @@ -36,7 +36,7 @@ export default defineConfig({ }, }, build: { - outDir: path.resolve(__dirname, 'public'), + outDir: path.resolve(__dirname, '../playwright-core/lib/vite/traceViewer'), // Output dir is shared with vite.config.ts, clearing it here is racy. emptyOutDir: false, rollupOptions: { diff --git a/tests/playwright-test/ui-mode-test-run.spec.ts b/tests/playwright-test/ui-mode-test-run.spec.ts index b30f901654a7f..72eeda46559a4 100644 --- a/tests/playwright-test/ui-mode-test-run.spec.ts +++ b/tests/playwright-test/ui-mode-test-run.spec.ts @@ -778,14 +778,3 @@ test('should respect --ignore-snapshots option', { - treeitem ${/\[icon-check\] snapshot/} `); }); - -test('should show funny messages', async ({ runUITest }) => { - const { page } = await runUITest(basicTestTree); - await page.clock.setFixedTime('2025-04-01'); - - await expect(page.getByText('Claywright')).toBeVisible(); - const schmettingsHeader = page.getByText('Schmettings'); - await expect(schmettingsHeader).toBeVisible(); - await schmettingsHeader.click(); - await expect(page.getByRole('checkbox', { name: 'Fart mode' })).toBeVisible(); -}); diff --git a/utils/build/build.js b/utils/build/build.js index a1ba052d51fc2..7a289bd5edaa1 100644 --- a/utils/build/build.js +++ b/utils/build/build.js @@ -275,21 +275,6 @@ for (const bundle of bundles) { }); } -// initial service worker build. -steps.push({ - command: 'npx', - args: [ - 'vite', - '--config', - 'vite.sw.config.ts', - 'build', - ...(withSourceMaps ? ['--sourcemap=inline'] : []), - ], - shell: true, - cwd: path.join(__dirname, '..', '..', 'packages', 'trace-viewer'), - concurrent: false, -}); - // Build/watch web packages. for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) { steps.push({ @@ -305,7 +290,6 @@ for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) { concurrent: true, }); } - // Build/watch trace viewer service worker. steps.push({ command: 'npx', @@ -322,16 +306,6 @@ steps.push({ concurrent: true, }); -// web packages dev server -if (watchMode) { - steps.push({ - command: 'npx', - args: ['vite', '--port', '44223', '--base', '/trace/'], - shell: true, - cwd: path.join(__dirname, '..', '..', 'packages', 'trace-viewer'), - concurrent: true, - }); -} // Generate injected. onChanges.push({ From 7e00112fec03d4f7581c065d8796159488aa6fb5 Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Fri, 25 Oct 2024 23:27:14 +1000 Subject: [PATCH 374/805] docs(python): improve the typing example with the pytest plugin (#33296) --- docs/src/test-runners-python.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/src/test-runners-python.md b/docs/src/test-runners-python.md index 0ad4043066ba9..d07fa2e53faab 100644 --- a/docs/src/test-runners-python.md +++ b/docs/src/test-runners-python.md @@ -99,7 +99,7 @@ See [Running Tests](./running-tests.md) for general information on `pytest` opti ## Examples -### Configure Mypy typings for auto-completion +### Configure typings for auto-completion ```py title="test_my_application.py" from playwright.sync_api import Page @@ -109,6 +109,8 @@ def test_visit_admin_dashboard(page: Page): # ... ``` +If you're using VSCode with Pylance, these types can be inferred by enabling the `python.testing.pytestEnabled` setting so you don't need the type annotation. + ### Configure slow mo Run tests with slow mo with the `--slowmo` argument. From f98531baee31163d1b64a5120c70a0707379c4ed Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 25 Oct 2024 10:33:43 -0700 Subject: [PATCH 375/805] chore: remove check for node < 16 (#33301) --- packages/playwright-core/src/utilsBundle.ts | 4 ---- packages/playwright/src/common/configLoader.ts | 5 ----- tests/config/browserTest.ts | 6 ++++++ tests/library/browsercontext-fetch.spec.ts | 9 ++++----- tests/library/browsercontext-storage-state.spec.ts | 4 ++-- tests/library/browsertype-launch.spec.ts | 5 ++--- tests/library/client-certificates.spec.ts | 4 ++-- 7 files changed, 16 insertions(+), 21 deletions(-) diff --git a/packages/playwright-core/src/utilsBundle.ts b/packages/playwright-core/src/utilsBundle.ts index f9dc8347f7d23..f57a6346f731c 100644 --- a/packages/playwright-core/src/utilsBundle.ts +++ b/packages/playwright-core/src/utilsBundle.ts @@ -43,12 +43,8 @@ import type { StackFrame } from '@protocol/channels'; const StackUtils: typeof import('../bundles/utils/node_modules/@types/stack-utils') = require('./utilsBundleImpl').StackUtils; const stackUtils = new StackUtils({ internals: StackUtils.nodeInternals() }); -const nodeInternals = StackUtils.nodeInternals(); -const nodeMajorVersion = +process.versions.node.split('.')[0]; export function parseStackTraceLine(line: string): StackFrame | null { - if (!process.env.PWDEBUGIMPL && nodeMajorVersion < 16 && nodeInternals.some(internal => internal.test(line))) - return null; const frame = stackUtils.parseLine(line); if (!frame) return null; diff --git a/packages/playwright/src/common/configLoader.ts b/packages/playwright/src/common/configLoader.ts index 37a886d3e8ab1..13d7eac1879a9 100644 --- a/packages/playwright/src/common/configLoader.ts +++ b/packages/playwright/src/common/configLoader.ts @@ -378,11 +378,6 @@ export function restartWithExperimentalTsEsm(configFile: string | undefined, for // Now check for the newer API presence. if (!require('node:module').register) { - // Older API is experimental, only supported on Node 16+. - const nodeVersion = +process.versions.node.split('.')[0]; - if (nodeVersion < 16) - return false; - // With older API requiring a process restart, do so conditionally on the config. const configIsModule = !!configFile && fileIsModule(configFile); if (!force && !configIsModule) diff --git a/tests/config/browserTest.ts b/tests/config/browserTest.ts index 6a178bbaf2641..8e79da1f8e2d0 100644 --- a/tests/config/browserTest.ts +++ b/tests/config/browserTest.ts @@ -36,6 +36,7 @@ export type BrowserTestWorkerFixtures = PageWorkerFixtures & { browserType: BrowserType; isAndroid: boolean; isElectron: boolean; + nodeVersion: { major: number, minor: number, patch: number }; bidiTestSkipPredicate: (info: TestInfo) => boolean; }; @@ -96,6 +97,11 @@ const test = baseTest.extend await run(Number(browserVersion.split('.')[0])); }, { scope: 'worker' }], + nodeVersion: [async ({}, use) => { + const [major, minor, patch] = process.versions.node.split('.'); + await use({ major: +major, minor: +minor, patch: +patch }); + }, { scope: 'worker' }], + isAndroid: [false, { scope: 'worker' }], isElectron: [false, { scope: 'worker' }], electronMajorVersion: [0, { scope: 'worker' }], diff --git a/tests/library/browsercontext-fetch.spec.ts b/tests/library/browsercontext-fetch.spec.ts index ae5cf5e7d55cd..abbc4f64a4d72 100644 --- a/tests/library/browsercontext-fetch.spec.ts +++ b/tests/library/browsercontext-fetch.spec.ts @@ -880,9 +880,9 @@ it('should respect timeout after redirects', async function({ context, server }) expect(error.message).toContain(`Request timed out after 100ms`); }); -it('should not hang on a brotli encoded Range request', async ({ context, server }) => { +it('should not hang on a brotli encoded Range request', async ({ context, server, nodeVersion }) => { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/18190' }); - it.skip(+process.versions.node.split('.')[0] < 18); + it.skip(nodeVersion.major < 18); const encodedRequestPayload = zlib.brotliCompressSync(Buffer.from('A')); server.setRoute('/brotli', (req, res) => { @@ -1094,10 +1094,9 @@ it('should support multipart/form-data and keep the order', async function({ con expect(response.status()).toBe(200); }); -it('should support repeating names in multipart/form-data', async function({ context, server }) { +it('should support repeating names in multipart/form-data', async function({ context, server, nodeVersion }) { it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/28070' }); - const nodeVersion = +process.versions.node.split('.')[0]; - it.skip(nodeVersion < 20, 'File is not available in Node.js < 20. FormData is not available in Node.js < 18'); + it.skip(nodeVersion.major < 20, 'File is not available in Node.js < 20. FormData is not available in Node.js < 18'); const postBodyPromise = new Promise(resolve => { server.setRoute('/empty.html', async (req, res) => { resolve((await req.postBody).toString('utf-8')); diff --git a/tests/library/browsercontext-storage-state.spec.ts b/tests/library/browsercontext-storage-state.spec.ts index 02db42506dd50..d71657d1be55c 100644 --- a/tests/library/browsercontext-storage-state.spec.ts +++ b/tests/library/browsercontext-storage-state.spec.ts @@ -204,13 +204,13 @@ it('should handle missing file', async ({ contextFactory }, testInfo) => { expect(error.message).toContain(`Error reading storage state from ${file}:\nENOENT`); }); -it('should handle malformed file', async ({ contextFactory }, testInfo) => { +it('should handle malformed file', async ({ contextFactory, nodeVersion }, testInfo) => { const file = testInfo.outputPath('state.json'); fs.writeFileSync(file, 'not-json', 'utf-8'); const error = await contextFactory({ storageState: file, }).catch(e => e); - if (+process.versions.node.split('.')[0] > 18) + if (nodeVersion.major > 18) expect(error.message).toContain(`Error reading storage state from ${file}:\nUnexpected token 'o', \"not-json\" is not valid JSON`); else expect(error.message).toContain(`Error reading storage state from ${file}:\nUnexpected token o in JSON at position 1`); diff --git a/tests/library/browsertype-launch.spec.ts b/tests/library/browsertype-launch.spec.ts index 011bc8a50d865..75198f4f8be03 100644 --- a/tests/library/browsertype-launch.spec.ts +++ b/tests/library/browsertype-launch.spec.ts @@ -130,9 +130,8 @@ it('should be callable twice', async ({ browserType }) => { await browser.close(); }); -it('should allow await using', async ({ browserType }) => { - const nodeVersion = +process.versions.node.split('.')[0]; - it.skip(nodeVersion < 18); +it('should allow await using', async ({ browserType, nodeVersion }) => { + it.skip(nodeVersion.major < 18); let b: Browser; let c: BrowserContext; diff --git a/tests/library/client-certificates.spec.ts b/tests/library/client-certificates.spec.ts index 8e0a4cdf47c31..648fef0d752ab 100644 --- a/tests/library/client-certificates.spec.ts +++ b/tests/library/client-certificates.spec.ts @@ -727,9 +727,9 @@ test.describe('browser', () => { await browser.close(); }); - test('should return target connection errors when using http2', async ({ browser, startCCServer, asset, browserName, isMac, isLinux }) => { + test('should return target connection errors when using http2', async ({ browser, startCCServer, asset, browserName, isMac, nodeVersion }) => { test.skip(browserName === 'webkit' && isMac, 'WebKit on macOS does not proxy localhost'); - test.skip(+process.versions.node.split('.')[0] < 20, 'http2.performServerHandshake is not supported in older Node.js versions'); + test.skip(nodeVersion.major < 20, 'http2.performServerHandshake is not supported in older Node.js versions'); const serverURL = await startCCServer({ http2: true }); const page = await browser.newPage({ From 1e8884621a2a151837fc7d80617b0c5a669013e3 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 25 Oct 2024 12:36:39 -0700 Subject: [PATCH 376/805] chore: unify toHaveScreenshot error formatting (#33300) --- packages/html-reporter/src/testResultView.tsx | 3 +- packages/playwright-core/src/client/page.ts | 3 +- .../playwright-core/src/protocol/validator.ts | 3 +- packages/playwright-core/src/server/page.ts | 3 +- .../src/matchers/toMatchSnapshot.ts | 39 ++++++++++--------- packages/protocol/src/channels.ts | 4 +- packages/protocol/src/protocol.yml | 3 +- tests/page/expect-matcher-result.spec.ts | 4 +- tests/playwright-test/golden.spec.ts | 5 ++- tests/playwright-test/reporter-html.spec.ts | 4 +- .../to-have-screenshot.spec.ts | 2 +- 11 files changed, 41 insertions(+), 32 deletions(-) diff --git a/packages/html-reporter/src/testResultView.tsx b/packages/html-reporter/src/testResultView.tsx index bb18422dd084f..3a562f3fcf789 100644 --- a/packages/html-reporter/src/testResultView.tsx +++ b/packages/html-reporter/src/testResultView.tsx @@ -152,7 +152,8 @@ export const TestResultView: React.FC<{ function classifyErrors(testErrors: string[], diffs: ImageDiff[]) { return testErrors.map(error => { - if (error.includes('Screenshot comparison failed:')) { + const firstLine = error.split('\n')[0]; + if (firstLine.includes('toHaveScreenshot') || firstLine.includes('toMatchSnapshot')) { const matchingDiff = diffs.find(diff => { const attachmentName = diff.actual?.attachment.name; return attachmentName && error.includes(attachmentName); diff --git a/packages/playwright-core/src/client/page.ts b/packages/playwright-core/src/client/page.ts index 6654294edd3e4..c8d816f62ac9e 100644 --- a/packages/playwright-core/src/client/page.ts +++ b/packages/playwright-core/src/client/page.ts @@ -63,6 +63,7 @@ type PDFOptions = Omit & export type ExpectScreenshotOptions = Omit & { expected?: Buffer, locator?: api.Locator, + timeout: number, isNot: boolean, mask?: api.Locator[], }; @@ -589,7 +590,7 @@ export class Page extends ChannelOwner implements api.Page return result.binary; } - async _expectScreenshot(options: ExpectScreenshotOptions): Promise<{ actual?: Buffer, previous?: Buffer, diff?: Buffer, errorMessage?: string, log?: string[]}> { + async _expectScreenshot(options: ExpectScreenshotOptions): Promise<{ actual?: Buffer, previous?: Buffer, diff?: Buffer, errorMessage?: string, log?: string[], timedOut?: boolean}> { const mask = options?.mask ? options?.mask.map(locator => ({ frame: (locator as Locator)._frame._channel, selector: (locator as Locator)._selector, diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts index 7bad26f4987b9..fd30bbba09bd1 100644 --- a/packages/playwright-core/src/protocol/validator.ts +++ b/packages/playwright-core/src/protocol/validator.ts @@ -1165,7 +1165,7 @@ scheme.PageReloadResult = tObject({ }); scheme.PageExpectScreenshotParams = tObject({ expected: tOptional(tBinary), - timeout: tOptional(tNumber), + timeout: tNumber, isNot: tBoolean, locator: tOptional(tObject({ frame: tChannel(['Frame']), @@ -1193,6 +1193,7 @@ scheme.PageExpectScreenshotResult = tObject({ errorMessage: tOptional(tString), actual: tOptional(tBinary), previous: tOptional(tBinary), + timedOut: tOptional(tBoolean), log: tOptional(tArray(tString)), }); scheme.PageScreenshotParams = tObject({ diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index b78bd91ee17cc..55f99250c8e42 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -674,11 +674,12 @@ export class Page extends SdkObject { throw e; let errorMessage = e.message; if (e instanceof TimeoutError && intermediateResult?.previous) - errorMessage = `Failed to take two consecutive stable screenshots. ${e.message}`; + errorMessage = `Failed to take two consecutive stable screenshots.`; return { log: e.message ? [...metadata.log, e.message] : metadata.log, ...intermediateResult, errorMessage, + timedOut: (e instanceof TimeoutError), }; }); } diff --git a/packages/playwright/src/matchers/toMatchSnapshot.ts b/packages/playwright/src/matchers/toMatchSnapshot.ts index 86504062d30d7..24b387f3ea45d 100644 --- a/packages/playwright/src/matchers/toMatchSnapshot.ts +++ b/packages/playwright/src/matchers/toMatchSnapshot.ts @@ -18,7 +18,7 @@ import type { Locator, Page } from 'playwright-core'; import type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page'; import { currentTestInfo } from '../common/globals'; import type { ImageComparatorOptions, Comparator } from 'playwright-core/lib/utils'; -import { getComparator, sanitizeForFilePath } from 'playwright-core/lib/utils'; +import { getComparator, isString, sanitizeForFilePath } from 'playwright-core/lib/utils'; import { addSuffixToFilePath, trimLongString, callLogText, @@ -31,7 +31,7 @@ import path from 'path'; import { mime } from 'playwright-core/lib/utilsBundle'; import type { TestInfoImpl } from '../worker/testInfo'; import type { ExpectMatcherState } from '../../types/test'; -import type { MatcherResult } from './matcherHint'; +import { matcherHint, type MatcherResult } from './matcherHint'; import type { FullProjectInternal } from '../common/config'; type NameOrSegments = string | string[]; @@ -250,16 +250,10 @@ class SnapshotHelper { expected: Buffer | string | undefined, previous: Buffer | string | undefined, diff: Buffer | string | undefined, - diffError: string | undefined, - log: string[] | undefined, - title = `${this.kind} comparison failed:`): ImageMatcherResult { - const output = [ - colors.red(title), - '', - ]; - if (diffError) - output.push(indent(diffError, ' ')); - + header: string, + diffError: string, + log: string[] | undefined): ImageMatcherResult { + const output = [`${header}${indent(diffError, ' ')}`]; if (expected !== undefined) { // Copy the expectation inside the `test-results/` folder for backwards compatibility, // so that one can upload `test-results/` directory and have all the data inside. @@ -338,7 +332,9 @@ export function toMatchSnapshot( return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true); } - return helper.handleDifferent(received, expected, undefined, result.diff, result.errorMessage, undefined); + const receiver = isString(received) ? 'string' : 'Buffer'; + const header = matcherHint(this, undefined, 'toMatchSnapshot', receiver, undefined, undefined); + return helper.handleDifferent(received, expected, undefined, result.diff, header, result.errorMessage, undefined); } export function toHaveScreenshotStepTitle( @@ -374,6 +370,7 @@ export async function toHaveScreenshot( throw new Error(`Screenshot name "${path.basename(helper.expectedPath)}" must have '.png' extension`); expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot'); const style = await loadScreenshotStyles(helper.options.stylePath); + const timeout = helper.options.timeout ?? this.timeout; const expectScreenshotOptions: ExpectScreenshotOptions = { locator, animations: helper.options.animations ?? 'disabled', @@ -386,7 +383,7 @@ export async function toHaveScreenshot( scale: helper.options.scale ?? 'css', style, isNot: !!this.isNot, - timeout: helper.options.timeout ?? this.timeout, + timeout, comparator: helper.options.comparator, maxDiffPixels: helper.options.maxDiffPixels, maxDiffPixelRatio: helper.options.maxDiffPixelRatio, @@ -410,13 +407,16 @@ export async function toHaveScreenshot( if (helper.updateSnapshots === 'none' && !hasSnapshot) return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false); + const receiver = locator ? 'locator' : 'page'; if (!hasSnapshot) { // Regenerate a new screenshot by waiting until two screenshots are the same. - const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions); + const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions); // We tried re-generating new snapshot but failed. // This can be due to e.g. spinning animation, so we want to show it as a diff. - if (errorMessage) - return helper.handleDifferent(actual, undefined, previous, diff, undefined, log, errorMessage); + if (errorMessage) { + const header = matcherHint(this, locator, 'toHaveScreenshot', receiver, undefined, undefined, timedOut ? timeout : undefined); + return helper.handleDifferent(actual, undefined, previous, diff, header, errorMessage, log); + } // We successfully generated new screenshot. return helper.handleMissing(actual!); @@ -427,7 +427,7 @@ export async function toHaveScreenshot( // - regular matcher (i.e. not a `.not`) // - perhaps an 'all' flag to update non-matching screenshots expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath); - const { actual, previous, diff, errorMessage, log } = await page._expectScreenshot(expectScreenshotOptions); + const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions); if (!errorMessage) return helper.handleMatching(); @@ -440,7 +440,8 @@ export async function toHaveScreenshot( return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true); } - return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, errorMessage, log); + const header = matcherHint(this, undefined, 'toHaveScreenshot', receiver, undefined, undefined, timedOut ? timeout : undefined); + return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log); } function writeFileSync(aPath: string, content: Buffer | string) { diff --git a/packages/protocol/src/channels.ts b/packages/protocol/src/channels.ts index 7fcb815468560..43e878a97a0d9 100644 --- a/packages/protocol/src/channels.ts +++ b/packages/protocol/src/channels.ts @@ -2141,7 +2141,7 @@ export type PageReloadResult = { }; export type PageExpectScreenshotParams = { expected?: Binary, - timeout?: number, + timeout: number, isNot: boolean, locator?: { frame: FrameChannel, @@ -2166,7 +2166,6 @@ export type PageExpectScreenshotParams = { }; export type PageExpectScreenshotOptions = { expected?: Binary, - timeout?: number, locator?: { frame: FrameChannel, selector: string, @@ -2193,6 +2192,7 @@ export type PageExpectScreenshotResult = { errorMessage?: string, actual?: Binary, previous?: Binary, + timedOut?: boolean, log?: string[], }; export type PageScreenshotParams = { diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml index 98428cae2f75b..69830cf8e8bbc 100644 --- a/packages/protocol/src/protocol.yml +++ b/packages/protocol/src/protocol.yml @@ -1482,7 +1482,7 @@ Page: expectScreenshot: parameters: expected: binary? - timeout: number? + timeout: number isNot: boolean locator: type: object? @@ -1501,6 +1501,7 @@ Page: errorMessage: string? actual: binary? previous: binary? + timedOut: boolean? log: type: array? items: string diff --git a/tests/page/expect-matcher-result.spec.ts b/tests/page/expect-matcher-result.spec.ts index 7767ecf5f62a0..fe983c6f6386f 100644 --- a/tests/page/expect-matcher-result.spec.ts +++ b/tests/page/expect-matcher-result.spec.ts @@ -295,7 +295,7 @@ test('toHaveScreenshot should populate matcherResult', async ({ page, server, is actual: expect.stringContaining('screenshot-sanity-actual'), expected: expect.stringContaining('screenshot-sanity-'), diff: expect.stringContaining('screenshot-sanity-diff'), - message: expect.stringContaining(`Screenshot comparison failed`), + message: expect.stringContaining(`expect(page).toHaveScreenshot(expected)`), name: 'toHaveScreenshot', pass: false, log: expect.any(Array), @@ -303,7 +303,7 @@ test('toHaveScreenshot should populate matcherResult', async ({ page, server, is printedReceived: expect.stringContaining('screenshot-sanity-actual'), }); - expect.soft(stripAnsi(e.toString())).toContain(`Error: Screenshot comparison failed: + expect.soft(stripAnsi(e.toString())).toContain(`Error: expect(page).toHaveScreenshot(expected) 23362 pixels (ratio 0.10 of all image pixels) are different. diff --git a/tests/playwright-test/golden.spec.ts b/tests/playwright-test/golden.spec.ts index 205eeee7f0520..340851e384025 100644 --- a/tests/playwright-test/golden.spec.ts +++ b/tests/playwright-test/golden.spec.ts @@ -223,7 +223,7 @@ test('should write detailed failure result to an output folder', async ({ runInl expect(result.exitCode).toBe(1); const outputText = result.output; - expect(outputText).toContain('Snapshot comparison failed:'); + expect(outputText).toContain('Error: expect(string).toMatchSnapshot(expected)'); const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.txt'); const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.txt'); expect(outputText).toMatch(/Expected:.*a\.spec\.js-snapshots.snapshot\.txt/); @@ -635,7 +635,8 @@ test('should compare different PNG images', async ({ runInlineTest }, testInfo) const outputText = result.output; expect(result.exitCode).toBe(1); - expect(outputText).toContain('Screenshot comparison failed:'); + expect(outputText).toContain('Error: expect(Buffer).toMatchSnapshot(expected)'); + expect(outputText).toContain('1 pixels (ratio 1.00 of all image pixels) are different.'); const expectedSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-expected.png'); const actualSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-actual.png'); const diffSnapshotArtifactPath = testInfo.outputPath('test-results', 'a-is-a-test', 'snapshot-diff.png'); diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index 11169fadffa0e..51734be9ffee7 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -330,7 +330,9 @@ for (const useIntermediateMergeReport of [true, false] as const) { await expect(page.locator('text=Image mismatch')).toHaveCount(1); await expect(page.locator('text=Snapshot mismatch')).toHaveCount(0); await expect(page.locator('.chip-header', { hasText: 'Screenshots' })).toHaveCount(0); - await expect(page.getByTestId('test-result-image-mismatch-tabs').locator('div')).toHaveText([ + const errorChip = page.getByTestId('test-screenshot-error-view'); + await expect(errorChip).toContainText('Failed to take two consecutive stable screenshots.'); + await expect(errorChip.getByTestId('test-result-image-mismatch-tabs').locator('div')).toHaveText([ 'Diff', 'Actual', 'Previous', diff --git a/tests/playwright-test/to-have-screenshot.spec.ts b/tests/playwright-test/to-have-screenshot.spec.ts index a4eb131f07bdc..ee053cc1304fa 100644 --- a/tests/playwright-test/to-have-screenshot.spec.ts +++ b/tests/playwright-test/to-have-screenshot.spec.ts @@ -551,7 +551,7 @@ test('should fail when screenshot is different pixels', async ({ runInlineTest } ` }); expect(result.exitCode).toBe(1); - expect(result.output).toContain('Screenshot comparison failed'); + expect(result.output).toContain('Error: expect(page).toHaveScreenshot(expected)'); expect(result.output).toContain('12345 pixels'); expect(result.output).toContain('Call log'); expect(result.output).toContain('ratio 0.02'); From 87b896e597f3d60f55505dae5b7e9f57abe03790 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 25 Oct 2024 13:31:55 -0700 Subject: [PATCH 377/805] chore: remove playwright-ct-vue2 (#33302) --- docs/src/test-components-js.md | 35 --- package-lock.json | 80 ------- packages/playwright-ct-vue2/.npmignore | 12 - packages/playwright-ct-vue2/README.md | 3 - packages/playwright-ct-vue2/cli.js | 20 -- packages/playwright-ct-vue2/hooks.d.ts | 37 --- packages/playwright-ct-vue2/hooks.mjs | 29 --- packages/playwright-ct-vue2/index.d.ts | 66 ------ packages/playwright-ct-vue2/index.js | 33 --- packages/playwright-ct-vue2/package.json | 42 ---- packages/playwright-ct-vue2/register.d.ts | 24 -- packages/playwright-ct-vue2/register.mjs | 21 -- .../playwright-ct-vue2/registerSource.mjs | 212 ------------------ tests/components/ct-vue2-cli/.gitignore | 23 -- tests/components/ct-vue2-cli/README.md | 24 -- tests/components/ct-vue2-cli/babel.config.js | 5 - tests/components/ct-vue2-cli/package.json | 45 ---- .../ct-vue2-cli/playwright.config.ts | 49 ---- .../ct-vue2-cli/playwright/index.html | 12 - .../ct-vue2-cli/playwright/index.js | 17 -- .../components/ct-vue2-cli/public/favicon.ico | Bin 4286 -> 0 bytes .../components/ct-vue2-cli/public/index.html | 17 -- tests/components/ct-vue2-cli/src/App.vue | 10 - .../ct-vue2-cli/src/assets/index.css | 20 -- .../ct-vue2-cli/src/assets/logo.png | Bin 6849 -> 0 bytes .../ct-vue2-cli/src/components/Button.vue | 10 - .../ct-vue2-cli/src/components/Component.vue | 3 - .../ct-vue2-cli/src/components/Counter.vue | 23 -- .../src/components/DefaultSlot.vue | 11 - .../src/components/EmptyTemplate.vue | 8 - .../ct-vue2-cli/src/components/NamedSlots.vue | 13 -- tests/components/ct-vue2-cli/src/main.js | 14 -- .../ct-vue2-cli/src/pages/DashboardPage.vue | 3 - .../ct-vue2-cli/src/pages/LoginPage.vue | 3 - .../ct-vue2-cli/src/router/index.js | 12 - .../components/ct-vue2-cli/src/shims-vue.d.ts | 4 - .../ct-vue2-cli/tests/events/events.spec.ts | 16 -- .../ct-vue2-cli/tests/events/events.spec.tsx | 28 --- .../ct-vue2-cli/tests/render/render.spec.ts | 25 --- .../ct-vue2-cli/tests/render/render.spec.tsx | 21 -- .../ct-vue2-cli/tests/slots/slots.spec.ts | 35 --- .../ct-vue2-cli/tests/slots/slots.spec.tsx | 48 ---- .../ct-vue2-cli/tests/unmount/unmount.spec.ts | 38 ---- .../tests/unmount/unmount.spec.tsx | 22 -- .../ct-vue2-cli/tests/update/update.spec.ts | 52 ----- .../ct-vue2-cli/tests/update/update.spec.tsx | 53 ----- .../tests/vue-router/vue-router.spec.ts | 13 -- .../tests/vue-router/vue-router.spec.tsx | 13 -- .../components/ct-vue2-cli/tsconfig.app.json | 12 - .../ct-vue2-cli/tsconfig.config.json | 8 - tests/components/ct-vue2-cli/tsconfig.json | 14 -- .../components/ct-vue2-cli/tsconfig.test.json | 11 - tests/components/ct-vue2-cli/vue.config.js | 4 - utils/workspace.js | 5 - 54 files changed, 1358 deletions(-) delete mode 100644 packages/playwright-ct-vue2/.npmignore delete mode 100644 packages/playwright-ct-vue2/README.md delete mode 100755 packages/playwright-ct-vue2/cli.js delete mode 100644 packages/playwright-ct-vue2/hooks.d.ts delete mode 100644 packages/playwright-ct-vue2/hooks.mjs delete mode 100644 packages/playwright-ct-vue2/index.d.ts delete mode 100644 packages/playwright-ct-vue2/index.js delete mode 100644 packages/playwright-ct-vue2/package.json delete mode 100644 packages/playwright-ct-vue2/register.d.ts delete mode 100644 packages/playwright-ct-vue2/register.mjs delete mode 100644 packages/playwright-ct-vue2/registerSource.mjs delete mode 100644 tests/components/ct-vue2-cli/.gitignore delete mode 100644 tests/components/ct-vue2-cli/README.md delete mode 100644 tests/components/ct-vue2-cli/babel.config.js delete mode 100644 tests/components/ct-vue2-cli/package.json delete mode 100644 tests/components/ct-vue2-cli/playwright.config.ts delete mode 100644 tests/components/ct-vue2-cli/playwright/index.html delete mode 100644 tests/components/ct-vue2-cli/playwright/index.js delete mode 100644 tests/components/ct-vue2-cli/public/favicon.ico delete mode 100644 tests/components/ct-vue2-cli/public/index.html delete mode 100644 tests/components/ct-vue2-cli/src/App.vue delete mode 100644 tests/components/ct-vue2-cli/src/assets/index.css delete mode 100644 tests/components/ct-vue2-cli/src/assets/logo.png delete mode 100644 tests/components/ct-vue2-cli/src/components/Button.vue delete mode 100644 tests/components/ct-vue2-cli/src/components/Component.vue delete mode 100644 tests/components/ct-vue2-cli/src/components/Counter.vue delete mode 100644 tests/components/ct-vue2-cli/src/components/DefaultSlot.vue delete mode 100644 tests/components/ct-vue2-cli/src/components/EmptyTemplate.vue delete mode 100644 tests/components/ct-vue2-cli/src/components/NamedSlots.vue delete mode 100644 tests/components/ct-vue2-cli/src/main.js delete mode 100644 tests/components/ct-vue2-cli/src/pages/DashboardPage.vue delete mode 100644 tests/components/ct-vue2-cli/src/pages/LoginPage.vue delete mode 100644 tests/components/ct-vue2-cli/src/router/index.js delete mode 100644 tests/components/ct-vue2-cli/src/shims-vue.d.ts delete mode 100644 tests/components/ct-vue2-cli/tests/events/events.spec.ts delete mode 100644 tests/components/ct-vue2-cli/tests/events/events.spec.tsx delete mode 100644 tests/components/ct-vue2-cli/tests/render/render.spec.ts delete mode 100644 tests/components/ct-vue2-cli/tests/render/render.spec.tsx delete mode 100644 tests/components/ct-vue2-cli/tests/slots/slots.spec.ts delete mode 100644 tests/components/ct-vue2-cli/tests/slots/slots.spec.tsx delete mode 100644 tests/components/ct-vue2-cli/tests/unmount/unmount.spec.ts delete mode 100644 tests/components/ct-vue2-cli/tests/unmount/unmount.spec.tsx delete mode 100644 tests/components/ct-vue2-cli/tests/update/update.spec.ts delete mode 100644 tests/components/ct-vue2-cli/tests/update/update.spec.tsx delete mode 100644 tests/components/ct-vue2-cli/tests/vue-router/vue-router.spec.ts delete mode 100644 tests/components/ct-vue2-cli/tests/vue-router/vue-router.spec.tsx delete mode 100644 tests/components/ct-vue2-cli/tsconfig.app.json delete mode 100644 tests/components/ct-vue2-cli/tsconfig.config.json delete mode 100644 tests/components/ct-vue2-cli/tsconfig.json delete mode 100644 tests/components/ct-vue2-cli/tsconfig.test.json delete mode 100644 tests/components/ct-vue2-cli/vue.config.js diff --git a/docs/src/test-components-js.md b/docs/src/test-components-js.md index 91d1860a26544..e4f19d6fc22b7 100644 --- a/docs/src/test-components-js.md +++ b/docs/src/test-components-js.md @@ -521,7 +521,6 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let {label: 'React', value: 'react'}, {label: 'Solid', value: 'solid'}, {label: 'Vue3', value: 'vue3'}, - {label: 'Vue2', value: 'vue2'}, ] }> @@ -617,40 +616,6 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let - - - ```js title="playwright/index.ts" - import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks'; - import Router from 'vue-router'; - import { router } from '../src/router'; - - export type HooksConfig = { - enableRouting?: boolean; - } - - beforeMount(async ({ app, hooksConfig }) => { - if (hooksConfig?.enableRouting) { - Vue.use(Router); - return { router } - } - }); - ``` - - ```js title="src/pages/ProductsPage.spec.ts" - import { test, expect } from '@playwright/experimental-ct-vue2'; - import type { HooksConfig } from '../playwright'; - import ProductsPage from './pages/ProductsPage.vue'; - - test('configure routing through hooks config', async ({ page, mount }) => { - const component = await mount(ProductsPage, { - hooksConfig: { enableRouting: true }, - }); - await expect(component.getByRole('link')).toHaveAttribute('href', '/products/42'); - }); - ``` - - - ### unmount diff --git a/package-lock.json b/package-lock.json index 57046ec2f8241..3f503e4c093ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1508,10 +1508,6 @@ "resolved": "packages/playwright-ct-vue", "link": true }, - "node_modules/@playwright/experimental-ct-vue2": { - "resolved": "packages/playwright-ct-vue2", - "link": true - }, "node_modules/@playwright/test": { "resolved": "packages/playwright-test", "link": true @@ -5964,21 +5960,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "optional": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -6593,14 +6574,6 @@ "solid-js": "^1.3" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -8097,59 +8070,6 @@ "node": ">=18" } }, - "packages/playwright-ct-vue2": { - "name": "@playwright/experimental-ct-vue2", - "version": "1.49.0-next", - "license": "Apache-2.0", - "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", - "@vitejs/plugin-vue2": "^2.2.0" - }, - "bin": { - "playwright": "cli.js" - }, - "devDependencies": { - "vue": "^2.7.14" - }, - "engines": { - "node": ">=18" - } - }, - "packages/playwright-ct-vue2/node_modules/@vitejs/plugin-vue2": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue2/-/plugin-vue2-2.3.1.tgz", - "integrity": "sha512-/ksaaz2SRLN11JQhLdEUhDzOn909WEk99q9t9w+N12GjQCljzv7GyvAbD/p20aBUjHkvpGOoQ+FCOkG+mjDF4A==", - "engines": { - "node": "^14.18.0 || >= 16.0.0" - }, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0", - "vue": "^2.7.0-0" - } - }, - "packages/playwright-ct-vue2/node_modules/@vue/compiler-sfc": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz", - "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==", - "dependencies": { - "@babel/parser": "^7.23.5", - "postcss": "^8.4.14", - "source-map": "^0.6.1" - }, - "optionalDependencies": { - "prettier": "^1.18.2 || ^2.0.0" - } - }, - "packages/playwright-ct-vue2/node_modules/vue": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz", - "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==", - "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.", - "dependencies": { - "@vue/compiler-sfc": "2.7.16", - "csstype": "^3.1.0" - } - }, "packages/playwright-firefox": { "version": "1.49.0-next", "hasInstallScript": true, diff --git a/packages/playwright-ct-vue2/.npmignore b/packages/playwright-ct-vue2/.npmignore deleted file mode 100644 index 62701eb493652..0000000000000 --- a/packages/playwright-ct-vue2/.npmignore +++ /dev/null @@ -1,12 +0,0 @@ -**/* - -!README.md -!LICENSE -!cli.js -!register.d.ts -!register.mjs -!registerSource.mjs -!index.d.ts -!index.js -!hooks.d.ts -!hooks.mjs diff --git a/packages/playwright-ct-vue2/README.md b/packages/playwright-ct-vue2/README.md deleted file mode 100644 index 23ae82312d5c6..0000000000000 --- a/packages/playwright-ct-vue2/README.md +++ /dev/null @@ -1,3 +0,0 @@ -> **BEWARE** This package is EXPERIMENTAL and does not respect semver. - -Read more at https://playwright.dev/docs/test-components diff --git a/packages/playwright-ct-vue2/cli.js b/packages/playwright-ct-vue2/cli.js deleted file mode 100755 index 9cc834ee95e85..0000000000000 --- a/packages/playwright-ct-vue2/cli.js +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const { program } = require('@playwright/experimental-ct-core/lib/program'); - -program.parse(process.argv); diff --git a/packages/playwright-ct-vue2/hooks.d.ts b/packages/playwright-ct-vue2/hooks.d.ts deleted file mode 100644 index 5009f44348d37..0000000000000 --- a/packages/playwright-ct-vue2/hooks.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { ComponentOptions } from 'vue'; -import type { CombinedVueInstance, Vue, VueConstructor } from 'vue/types/vue'; - -export declare function beforeMount( - callback: (params: { - hooksConfig?: HooksConfig, - Vue: VueConstructor, - }) => Promise & Record> -): void; -export declare function afterMount( - callback: (params: { - hooksConfig?: HooksConfig; - instance: CombinedVueInstance< - Vue, - object, - object, - object, - Record - >; - }) => Promise -): void; diff --git a/packages/playwright-ct-vue2/hooks.mjs b/packages/playwright-ct-vue2/hooks.mjs deleted file mode 100644 index b7cea242c41e0..0000000000000 --- a/packages/playwright-ct-vue2/hooks.mjs +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const __pw_hooks_before_mount = []; -const __pw_hooks_after_mount = []; - -window.__pw_hooks_before_mount = __pw_hooks_before_mount; -window.__pw_hooks_after_mount = __pw_hooks_after_mount; - -export const beforeMount = callback => { - __pw_hooks_before_mount.push(callback); -}; - -export const afterMount = callback => { - __pw_hooks_after_mount.push(callback); -}; diff --git a/packages/playwright-ct-vue2/index.d.ts b/packages/playwright-ct-vue2/index.d.ts deleted file mode 100644 index 133b4a60f20d4..0000000000000 --- a/packages/playwright-ct-vue2/index.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { TestType, Locator } from '@playwright/experimental-ct-core'; - -type Slot = string | string[]; -type ComponentSlots = Record & { default?: Slot }; - -type ComponentEvents = Record; - -// Copied from: https://github.com/vuejs/language-tools/blob/master/packages/vue-component-type-helpers/index.d.ts#L10-L13 -type ComponentProps = - T extends new (...angs: any) => { $props: infer P; } ? NonNullable

      : - T extends (props: infer P, ...args: any) => any ? P : - {}; - -export interface MountOptions { - props?: ComponentProps; - slots?: ComponentSlots; - on?: ComponentEvents; - hooksConfig?: HooksConfig; -} - -export interface MountOptionsJsx { - hooksConfig?: HooksConfig; -} - -export interface MountResult extends Locator { - unmount(): Promise; - update(options: { - props?: Partial>; - slots?: Partial; - on?: Partial; - }): Promise; -} - -export interface MountResultJsx extends Locator { - unmount(): Promise; - update(component: JSX.Element): Promise; -} - -export const test: TestType<{ - mount( - component: JSX.Element, - options?: MountOptionsJsx - ): Promise; - mount( - component: Component, - options?: MountOptions - ): Promise>; -}>; - -export { defineConfig, PlaywrightTestConfig, expect, devices } from '@playwright/experimental-ct-core'; diff --git a/packages/playwright-ct-vue2/index.js b/packages/playwright-ct-vue2/index.js deleted file mode 100644 index 2eeabb0d08b55..0000000000000 --- a/packages/playwright-ct-vue2/index.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const { test, expect, devices, defineConfig: originalDefineConfig } = require('@playwright/experimental-ct-core'); -const path = require('path'); - -const defineConfig = (config, ...configs) => { - return originalDefineConfig({ - ...config, - '@playwright/test': { - packageJSON: require.resolve('./package.json'), - }, - '@playwright/experimental-ct-core': { - registerSourceFile: path.join(__dirname, 'registerSource.mjs'), - frameworkPluginFactory: () => import('@vitejs/plugin-vue2').then(plugin => plugin.default()), - }, - }, ...configs); -}; - -module.exports = { test, expect, devices, defineConfig }; diff --git a/packages/playwright-ct-vue2/package.json b/packages/playwright-ct-vue2/package.json deleted file mode 100644 index 9ec30191ad560..0000000000000 --- a/packages/playwright-ct-vue2/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "@playwright/experimental-ct-vue2", - "version": "1.49.0-next", - "description": "Playwright Component Testing for Vue2", - "repository": { - "type": "git", - "url": "git+https://github.com/microsoft/playwright.git" - }, - "homepage": "https://playwright.dev", - "engines": { - "node": ">=18" - }, - "author": { - "name": "Microsoft Corporation" - }, - "license": "Apache-2.0", - "exports": { - ".": { - "types": "./index.d.ts", - "default": "./index.js" - }, - "./register": { - "types": "./register.d.ts", - "default": "./register.mjs" - }, - "./hooks": { - "types": "./hooks.d.ts", - "default": "./hooks.mjs" - }, - "./package.json": "./package.json" - }, - "dependencies": { - "@playwright/experimental-ct-core": "1.49.0-next", - "@vitejs/plugin-vue2": "^2.2.0" - }, - "devDependencies": { - "vue": "^2.7.14" - }, - "bin": { - "playwright": "cli.js" - } -} diff --git a/packages/playwright-ct-vue2/register.d.ts b/packages/playwright-ct-vue2/register.d.ts deleted file mode 100644 index f88e9be59d3b3..0000000000000 --- a/packages/playwright-ct-vue2/register.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export default function pwRegister( - components: Record, - options?: { - createApp: any, - setDevtoolsHook: any, - h: any, - } -): void; diff --git a/packages/playwright-ct-vue2/register.mjs b/packages/playwright-ct-vue2/register.mjs deleted file mode 100644 index ca6a6a12d9933..0000000000000 --- a/packages/playwright-ct-vue2/register.mjs +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { pwRegister } from './registerSource.mjs'; - -export default components => { - pwRegister(components); -}; diff --git a/packages/playwright-ct-vue2/registerSource.mjs b/packages/playwright-ct-vue2/registerSource.mjs deleted file mode 100644 index 19b4d41c085c5..0000000000000 --- a/packages/playwright-ct-vue2/registerSource.mjs +++ /dev/null @@ -1,212 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// @ts-check - -// This file is injected into the registry as text, no dependencies are allowed. - -import __pwVue, { h as __pwH } from 'vue'; - -/** @typedef {import('../playwright-ct-core/types/component').Component} Component */ -/** @typedef {import('../playwright-ct-core/types/component').JsxComponent} JsxComponent */ -/** @typedef {import('../playwright-ct-core/types/component').ObjectComponent} ObjectComponent */ -/** @typedef {import('vue').Component} FrameworkComponent */ - -/** - * @param {any} component - * @returns {component is ObjectComponent} - */ -function isObjectComponent(component) { - return typeof component === 'object' && component && component.__pw_type === 'object-component'; -} - -/** - * @param {any} component - * @returns {component is JsxComponent} - */ -function isJsxComponent(component) { - return typeof component === 'object' && component && component.__pw_type === 'jsx'; -} - -/** - * @param {any} child - */ -function __pwCreateChild(child) { - if (Array.isArray(child)) - return child.map(grandChild => __pwCreateChild(grandChild)); - if (isJsxComponent(child) || isObjectComponent(child)) - return __pwCreateWrapper(child); - return child; -} - -/** - * Exists to support fallthrough attributes: - * https://vuejs.org/guide/components/attrs.html#fallthrough-attributes - * @param {any} Component - * @param {string} key - * @return {boolean} - */ -function __pwComponentHasKeyInProps(Component, key) { - return typeof Component.props === 'object' && Component.props && key in Component.props; -} - -/** - * @param {JsxComponent} component - * @returns {any[] | undefined} - */ -function __pwJsxChildArray(component) { - if (!component.props.children) - return; - if (Array.isArray(component.props.children)) - return component.props.children; - return [component.props.children]; -} - -/** - * @param {Component} component - */ -function __pwCreateComponent(component) { - const isVueComponent = typeof component.type !== 'string'; - - /** - * @type {(import('vue').VNode | string)[]} - */ - const children = []; - - /** @type {import('vue').VNodeData} */ - const nodeData = {}; - nodeData.attrs = {}; - nodeData.props = {}; - nodeData.scopedSlots = {}; - nodeData.on = {}; - - if (component.__pw_type === 'jsx') { - for (const child of __pwJsxChildArray(component) || []) { - if (isJsxComponent(child) && child.type === 'template') { - const slotProperty = Object.keys(child.props).find(k => k.startsWith('v-slot:')); - const slot = slotProperty ? slotProperty.substring('v-slot:'.length) : 'default'; - nodeData.scopedSlots[slot] = () => __pwJsxChildArray(child)?.map(c => __pwCreateChild(c)); - } else { - children.push(__pwCreateChild(child)); - } - } - - for (const [key, value] of Object.entries(component.props)) { - if (key.startsWith('v-on:')) { - const event = key.substring('v-on:'.length); - nodeData.on[event] = value; - } else { - if (isVueComponent && __pwComponentHasKeyInProps(component.type, key)) - nodeData.props[key] = value; - else - nodeData.attrs[key] = value; - } - } - } - - if (component.__pw_type === 'object-component') { - // Vue test util syntax. - for (const [key, value] of Object.entries(component.slots || {})) { - const list = (Array.isArray(value) ? value : [value]).map(v => __pwCreateChild(v)); - if (key === 'default') - children.push(...list); - else - nodeData.scopedSlots[key] = () => list; - } - nodeData.props = component.props || {}; - for (const [key, value] of Object.entries(component.on || {})) - nodeData.on[key] = value; - } - - /** @type {(string|import('vue').VNode)[] | undefined} */ - let lastArg; - if (Object.entries(nodeData.scopedSlots).length) { - if (children.length) - nodeData.scopedSlots.default = () => children; - } else if (children.length) { - lastArg = children; - } - - return { Component: component.type, nodeData, slots: lastArg }; -} - -/** - * @param {Component} component - * @returns {import('vue').VNode} - */ -function __pwCreateWrapper(component) { - const { Component, nodeData, slots } = __pwCreateComponent(component); - const wrapper = __pwH(Component, nodeData, slots); - return wrapper; -} - -const instanceKey = Symbol('instanceKey'); -const wrapperKey = Symbol('wrapperKey'); - -window.playwrightMount = async (component, rootElement, hooksConfig) => { - let options = {}; - for (const hook of window.__pw_hooks_before_mount || []) - options = await hook({ hooksConfig, Vue: __pwVue }); - - const instance = new __pwVue({ - ...options, - render: () => { - const wrapper = __pwCreateWrapper(component); - /** @type {any} */ (rootElement)[wrapperKey] = wrapper; - return wrapper; - }, - }).$mount(); - rootElement.appendChild(instance.$el); - /** @type {any} */ (rootElement)[instanceKey] = instance; - - for (const hook of window.__pw_hooks_after_mount || []) - await hook({ hooksConfig, instance }); -}; - -window.playwrightUnmount = async rootElement => { - const component = rootElement[instanceKey]; - if (!component) - throw new Error('Component was not mounted'); - component.$destroy(); - component.$el.remove(); - delete rootElement[instanceKey]; -}; - -window.playwrightUpdate = async (element, options) => { - const wrapper = /** @type {any} */(element)[wrapperKey]; - if (!wrapper) - throw new Error('Component was not mounted'); - - const component = wrapper.componentInstance; - if (!component) - throw new Error('Updating a native HTML element is not supported'); - - const { nodeData, slots } = __pwCreateComponent(options); - - for (const [name, value] of Object.entries(nodeData.on || {})) { - component.$on(name, value); - component.$listeners[name] = value; - } - - Object.assign(component.$scopedSlots, nodeData.scopedSlots); - component.$slots.default = slots; - - for (const [key, value] of Object.entries(nodeData.props || {})) - component[key] = value; - - if (!Object.keys(nodeData.props || {}).length) - component.$forceUpdate(); -}; diff --git a/tests/components/ct-vue2-cli/.gitignore b/tests/components/ct-vue2-cli/.gitignore deleted file mode 100644 index 7e2a946d8ee19..0000000000000 --- a/tests/components/ct-vue2-cli/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -.DS_Store -node_modules -/dist -*.tsbuildinfo - -# local env files -.env.local -.env.*.local - -# Log files -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* - -# Editor directories and files -.idea -.vscode -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/tests/components/ct-vue2-cli/README.md b/tests/components/ct-vue2-cli/README.md deleted file mode 100644 index c9a7da714eda3..0000000000000 --- a/tests/components/ct-vue2-cli/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# ct-vue2-cli - -## Project setup -``` -npm install -``` - -### Compiles and hot-reloads for development -``` -npm run serve -``` - -### Compiles and minifies for production -``` -npm run build -``` - -### Lints and fixes files -``` -npm run lint -``` - -### Customize configuration -See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/tests/components/ct-vue2-cli/babel.config.js b/tests/components/ct-vue2-cli/babel.config.js deleted file mode 100644 index e9558405fdcc0..0000000000000 --- a/tests/components/ct-vue2-cli/babel.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - presets: [ - '@vue/cli-plugin-babel/preset' - ] -} diff --git a/tests/components/ct-vue2-cli/package.json b/tests/components/ct-vue2-cli/package.json deleted file mode 100644 index 472d30f92b239..0000000000000 --- a/tests/components/ct-vue2-cli/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "ct-vue2-cli", - "version": "0.1.0", - "private": true, - "scripts": { - "serve": "vue-cli-service serve", - "build": "vue-cli-service build", - "lint": "vue-cli-service lint", - "typecheck": "tsc --noEmit --project tsconfig.test.json" - }, - "dependencies": { - "core-js": "^3.8.3", - "vue": "^2.7.13", - "vue-router": "^3.6.5" - }, - "devDependencies": { - "@babel/core": "^7.23.2", - "@babel/eslint-parser": "^7.22.15", - "@vue/cli-plugin-babel": "~5.0.0", - "@vue/cli-plugin-eslint": "~5.0.0", - "@vue/cli-service": "~5.0.0", - "@vue/tsconfig": "^0.1.3", - "eslint": "^7.32.0", - "eslint-plugin-vue": "^8.0.3" - }, - "eslintConfig": { - "root": true, - "env": { - "node": true - }, - "extends": [ - "plugin:vue/essential", - "eslint:recommended" - ], - "parserOptions": { - "parser": "@babel/eslint-parser" - }, - "rules": {} - }, - "browserslist": [ - "> 1%", - "last 2 versions", - "not dead" - ] -} diff --git a/tests/components/ct-vue2-cli/playwright.config.ts b/tests/components/ct-vue2-cli/playwright.config.ts deleted file mode 100644 index 307bc9726d368..0000000000000 --- a/tests/components/ct-vue2-cli/playwright.config.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { defineConfig, devices } from '@playwright/experimental-ct-vue2'; -import { resolve } from 'path'; - -export default defineConfig({ - testDir: 'tests', - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, - reporter: process.env.CI ? 'html' : 'line', - use: { - trace: 'on-first-retry', - ctViteConfig: { - resolve: { - alias: { - '@': resolve(__dirname, './src'), - } - } - } - }, - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - }, - ], -}); diff --git a/tests/components/ct-vue2-cli/playwright/index.html b/tests/components/ct-vue2-cli/playwright/index.html deleted file mode 100644 index 9ee6c8206eb9d..0000000000000 --- a/tests/components/ct-vue2-cli/playwright/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - -

      - - - diff --git a/tests/components/ct-vue2-cli/playwright/index.js b/tests/components/ct-vue2-cli/playwright/index.js deleted file mode 100644 index f5bd21d70d054..0000000000000 --- a/tests/components/ct-vue2-cli/playwright/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import { beforeMount, afterMount } from '@playwright/experimental-ct-vue2/hooks'; -import Router from 'vue-router'; -import { router } from '../src/router'; -import '../src/assets/index.css'; - -beforeMount(async ({ Vue, hooksConfig }) => { - console.log(`Before mount: ${JSON.stringify(hooksConfig)}`); - - if (hooksConfig?.routing) { - Vue.use(Router); - return { router } - } -}); - -afterMount(async ({ instance }) => { - console.log(`After mount el: ${instance.$el.constructor.name}`); -}); diff --git a/tests/components/ct-vue2-cli/public/favicon.ico b/tests/components/ct-vue2-cli/public/favicon.ico deleted file mode 100644 index df36fcfb72584e00488330b560ebcf34a41c64c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S diff --git a/tests/components/ct-vue2-cli/public/index.html b/tests/components/ct-vue2-cli/public/index.html deleted file mode 100644 index 3e5a139621971..0000000000000 --- a/tests/components/ct-vue2-cli/public/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - <%= htmlWebpackPlugin.options.title %> - - - -
      - - - diff --git a/tests/components/ct-vue2-cli/src/App.vue b/tests/components/ct-vue2-cli/src/App.vue deleted file mode 100644 index c2209eb5d7956..0000000000000 --- a/tests/components/ct-vue2-cli/src/App.vue +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/tests/components/ct-vue2-cli/src/assets/index.css b/tests/components/ct-vue2-cli/src/assets/index.css deleted file mode 100644 index 97495c44b8634..0000000000000 --- a/tests/components/ct-vue2-cli/src/assets/index.css +++ /dev/null @@ -1,20 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} - -@media (prefers-color-scheme: light) { - :root { - color: #e3e3e3; - background-color: #1b1b1d; - } -} diff --git a/tests/components/ct-vue2-cli/src/assets/logo.png b/tests/components/ct-vue2-cli/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b5053b0837ebea6e87a2d339a43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6849 zcmaKRcUV(fvo}bjDT-7nLI_nlK}sT_69H+`qzVWDA|yaU?}j417wLi^B1KB1SLsC& zL0ag7$U(XW5YR7p&Ux?sP$d4lvMt8C^+TcQu4F zQqv!UF!I+kw)c0jhd6+g6oCr9P?7)?!qX1ui*iL{p}sKCAGuJ{{W)0z1pLF|=>h}& zt(2Lr0Z`2ig8<5i%Zk}cO5Fm=LByqGWaS`oqChZdEFmc`0hSb#gg|Aap^{+WKOYcj zHjINK)KDG%&s?Mt4CL(T=?;~U@bU2x_mLKN!#GJuK_CzbNw5SMEJorG!}_5;?R>@1 zSl)jns3WlU7^J%=(hUtfmuUCU&C3%8B5C^f5>W2Cy8jW3#{Od{lF1}|?c61##3dzA zsPlFG;l_FzBK}8>|H_Ru_H#!_7$UH4UKo3lKOA}g1(R&|e@}GINYVzX?q=_WLZCgh z)L|eJMce`D0EIwgRaNETDsr+?vQknSGAi=7H00r`QnI%oQnFxm`G2umXso9l+8*&Q z7WqF|$p49js$mdzo^BXpH#gURy=UO;=IMrYc5?@+sR4y_?d*~0^YP7d+y0{}0)zBM zIKVM(DBvICK#~7N0a+PY6)7;u=dutmNqK3AlsrUU9U`d;msiucB_|8|2kY=(7XA;G zwDA8AR)VCA#JOkxm#6oHNS^YVuOU;8p$N)2{`;oF|rQ?B~K$%rHDxXs+_G zF5|-uqHZvSzq}L;5Kcy_P+x0${33}Ofb6+TX&=y;;PkEOpz%+_bCw_{<&~ zeLV|!bP%l1qxywfVr9Z9JI+++EO^x>ZuCK);=$VIG1`kxK8F2M8AdC$iOe3cj1fo(ce4l-9 z7*zKy3={MixvUk=enQE;ED~7tv%qh&3lR<0m??@w{ILF|e#QOyPkFYK!&Up7xWNtL zOW%1QMC<3o;G9_S1;NkPB6bqbCOjeztEc6TsBM<(q9((JKiH{01+Ud=uw9B@{;(JJ z-DxI2*{pMq`q1RQc;V8@gYAY44Z!%#W~M9pRxI(R?SJ7sy7em=Z5DbuDlr@*q|25V)($-f}9c#?D%dU^RS<(wz?{P zFFHtCab*!rl(~j@0(Nadvwg8q|4!}L^>d?0al6}Rrv9$0M#^&@zjbfJy_n!%mVHK4 z6pLRIQ^Uq~dnyy$`ay51Us6WaP%&O;@49m&{G3z7xV3dLtt1VTOMYl3UW~Rm{Eq4m zF?Zl_v;?7EFx1_+#WFUXxcK78IV)FO>42@cm@}2I%pVbZqQ}3;p;sDIm&knay03a^ zn$5}Q$G!@fTwD$e(x-~aWP0h+4NRz$KlnO_H2c< z(XX#lPuW_%H#Q+c&(nRyX1-IadKR-%$4FYC0fsCmL9ky3 zKpxyjd^JFR+vg2!=HWf}2Z?@Td`0EG`kU?{8zKrvtsm)|7>pPk9nu@2^z96aU2<#` z2QhvH5w&V;wER?mopu+nqu*n8p~(%QkwSs&*0eJwa zMXR05`OSFpfyRb!Y_+H@O%Y z0=K^y6B8Gcbl?SA)qMP3Z+=C(?8zL@=74R=EVnE?vY!1BQy2@q*RUgRx4yJ$k}MnL zs!?74QciNb-LcG*&o<9=DSL>1n}ZNd)w1z3-0Pd^4ED1{qd=9|!!N?xnXjM!EuylY z5=!H>&hSofh8V?Jofyd!h`xDI1fYAuV(sZwwN~{$a}MX^=+0TH*SFp$vyxmUv7C*W zv^3Gl0+eTFgBi3FVD;$nhcp)ka*4gSskYIqQ&+M}xP9yLAkWzBI^I%zR^l1e?bW_6 zIn{mo{dD=)9@V?s^fa55jh78rP*Ze<3`tRCN4*mpO$@7a^*2B*7N_|A(Ve2VB|)_o z$=#_=aBkhe(ifX}MLT()@5?OV+~7cXC3r!%{QJxriXo9I%*3q4KT4Xxzyd{ z9;_%=W%q!Vw$Z7F3lUnY+1HZ*lO;4;VR2+i4+D(m#01OYq|L_fbnT;KN<^dkkCwtd zF7n+O7KvAw8c`JUh6LmeIrk4`F3o|AagKSMK3))_5Cv~y2Bb2!Ibg9BO7Vkz?pAYX zoI=B}+$R22&IL`NCYUYjrdhwjnMx_v=-Qcx-jmtN>!Zqf|n1^SWrHy zK|MwJ?Z#^>)rfT5YSY{qjZ&`Fjd;^vv&gF-Yj6$9-Dy$<6zeP4s+78gS2|t%Z309b z0^fp~ue_}i`U9j!<|qF92_3oB09NqgAoehQ`)<)dSfKoJl_A6Ec#*Mx9Cpd-p#$Ez z={AM*r-bQs6*z$!*VA4|QE7bf@-4vb?Q+pPKLkY2{yKsw{&udv_2v8{Dbd zm~8VAv!G~s)`O3|Q6vFUV%8%+?ZSVUa(;fhPNg#vab@J*9XE4#D%)$UU-T5`fwjz! z6&gA^`OGu6aUk{l*h9eB?opVdrHK>Q@U>&JQ_2pR%}TyOXGq_6s56_`U(WoOaAb+K zXQr#6H}>a-GYs9^bGP2Y&hSP5gEtW+GVC4=wy0wQk=~%CSXj=GH6q z-T#s!BV`xZVxm{~jr_ezYRpqqIcXC=Oq`b{lu`Rt(IYr4B91hhVC?yg{ol4WUr3v9 zOAk2LG>CIECZ-WIs0$N}F#eoIUEtZudc7DPYIjzGqDLWk_A4#(LgacooD z2K4IWs@N`Bddm-{%oy}!k0^i6Yh)uJ1S*90>|bm3TOZxcV|ywHUb(+CeX-o1|LTZM zwU>dY3R&U)T(}5#Neh?-CWT~@{6Ke@sI)uSuzoah8COy)w)B)aslJmp`WUcjdia-0 zl2Y}&L~XfA`uYQboAJ1;J{XLhYjH){cObH3FDva+^8ioOQy%Z=xyjGLmWMrzfFoH; zEi3AG`_v+%)&lDJE;iJWJDI@-X9K5O)LD~j*PBe(wu+|%ar~C+LK1+-+lK=t# z+Xc+J7qp~5q=B~rD!x78)?1+KUIbYr^5rcl&tB-cTtj+e%{gpZZ4G~6r15+d|J(ky zjg@@UzMW0k9@S#W(1H{u;Nq(7llJbq;;4t$awM;l&(2s+$l!Ay9^Ge|34CVhr7|BG z?dAR83smef^frq9V(OH+a+ki#q&-7TkWfFM=5bsGbU(8mC;>QTCWL5ydz9s6k@?+V zcjiH`VI=59P-(-DWXZ~5DH>B^_H~;4$)KUhnmGo*G!Tq8^LjfUDO)lASN*=#AY_yS zqW9UX(VOCO&p@kHdUUgsBO0KhXxn1sprK5h8}+>IhX(nSXZKwlNsjk^M|RAaqmCZB zHBolOHYBas@&{PT=R+?d8pZu zUHfyucQ`(umXSW7o?HQ3H21M`ZJal+%*)SH1B1j6rxTlG3hx1IGJN^M7{$j(9V;MZ zRKybgVuxKo#XVM+?*yTy{W+XHaU5Jbt-UG33x{u(N-2wmw;zzPH&4DE103HV@ER86 z|FZEmQb|&1s5#`$4!Cm}&`^{(4V}OP$bk`}v6q6rm;P!H)W|2i^e{7lTk2W@jo_9q z*aw|U7#+g59Fv(5qI`#O-qPj#@_P>PC#I(GSp3DLv7x-dmYK=C7lPF8a)bxb=@)B1 zUZ`EqpXV2dR}B&r`uM}N(TS99ZT0UB%IN|0H%DcVO#T%L_chrgn#m6%x4KE*IMfjX zJ%4veCEqbXZ`H`F_+fELMC@wuy_ch%t*+Z+1I}wN#C+dRrf2X{1C8=yZ_%Pt6wL_~ zZ2NN-hXOT4P4n$QFO7yYHS-4wF1Xfr-meG9Pn;uK51?hfel`d38k{W)F*|gJLT2#T z<~>spMu4(mul-8Q3*pf=N4DcI)zzjqAgbE2eOT7~&f1W3VsdD44Ffe;3mJp-V@8UC z)|qnPc12o~$X-+U@L_lWqv-RtvB~%hLF($%Ew5w>^NR82qC_0FB z)=hP1-OEx?lLi#jnLzH}a;Nvr@JDO-zQWd}#k^an$Kwml;MrD&)sC5b`s0ZkVyPkb zt}-jOq^%_9>YZe7Y}PhW{a)c39G`kg(P4@kxjcYfgB4XOOcmezdUI7j-!gs7oAo2o zx(Ph{G+YZ`a%~kzK!HTAA5NXE-7vOFRr5oqY$rH>WI6SFvWmahFav!CfRMM3%8J&c z*p+%|-fNS_@QrFr(at!JY9jCg9F-%5{nb5Bo~z@Y9m&SHYV`49GAJjA5h~h4(G!Se zZmK{Bo7ivCfvl}@A-ptkFGcWXAzj3xfl{evi-OG(TaCn1FAHxRc{}B|x+Ua1D=I6M z!C^ZIvK6aS_c&(=OQDZfm>O`Nxsw{ta&yiYPA~@e#c%N>>#rq)k6Aru-qD4(D^v)y z*>Rs;YUbD1S8^D(ps6Jbj0K3wJw>L4m)0e(6Pee3Y?gy9i0^bZO?$*sv+xKV?WBlh zAp*;v6w!a8;A7sLB*g-^<$Z4L7|5jXxxP1}hQZ<55f9<^KJ>^mKlWSGaLcO0=$jem zWyZkRwe~u{{tU63DlCaS9$Y4CP4f?+wwa(&1ou)b>72ydrFvm`Rj-0`kBJgK@nd(*Eh!(NC{F-@=FnF&Y!q`7){YsLLHf0_B6aHc# z>WIuHTyJwIH{BJ4)2RtEauC7Yq7Cytc|S)4^*t8Va3HR zg=~sN^tp9re@w=GTx$;zOWMjcg-7X3Wk^N$n;&Kf1RgVG2}2L-(0o)54C509C&77i zrjSi{X*WV=%C17((N^6R4Ya*4#6s_L99RtQ>m(%#nQ#wrRC8Y%yxkH;d!MdY+Tw@r zjpSnK`;C-U{ATcgaxoEpP0Gf+tx);buOMlK=01D|J+ROu37qc*rD(w`#O=3*O*w9?biwNoq3WN1`&Wp8TvKj3C z3HR9ssH7a&Vr<6waJrU zdLg!ieYz%U^bmpn%;(V%%ugMk92&?_XX1K@mwnVSE6!&%P%Wdi7_h`CpScvspMx?N zQUR>oadnG17#hNc$pkTp+9lW+MBKHRZ~74XWUryd)4yd zj98$%XmIL4(9OnoeO5Fnyn&fpQ9b0h4e6EHHw*l68j;>(ya`g^S&y2{O8U>1*>4zR zq*WSI_2o$CHQ?x0!wl9bpx|Cm2+kFMR)oMud1%n2=qn5nE&t@Fgr#=Zv2?}wtEz^T z9rrj=?IH*qI5{G@Rn&}^Z{+TW}mQeb9=8b<_a`&Cm#n%n~ zU47MvCBsdXFB1+adOO)03+nczfWa#vwk#r{o{dF)QWya9v2nv43Zp3%Ps}($lA02*_g25t;|T{A5snSY?3A zrRQ~(Ygh_ebltHo1VCbJb*eOAr;4cnlXLvI>*$-#AVsGg6B1r7@;g^L zFlJ_th0vxO7;-opU@WAFe;<}?!2q?RBrFK5U{*ai@NLKZ^};Ul}beukveh?TQn;$%9=R+DX07m82gP$=}Uo_%&ngV`}Hyv8g{u z3SWzTGV|cwQuFIs7ZDOqO_fGf8Q`8MwL}eUp>q?4eqCmOTcwQuXtQckPy|4F1on8l zP*h>d+cH#XQf|+6c|S{7SF(Lg>bR~l(0uY?O{OEVlaxa5@e%T&xju=o1`=OD#qc16 zSvyH*my(dcp6~VqR;o(#@m44Lug@~_qw+HA=mS#Z^4reBy8iV?H~I;{LQWk3aKK8$bLRyt$g?- - - - - diff --git a/tests/components/ct-vue2-cli/src/components/Component.vue b/tests/components/ct-vue2-cli/src/components/Component.vue deleted file mode 100644 index 133c8e26707c9..0000000000000 --- a/tests/components/ct-vue2-cli/src/components/Component.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/tests/components/ct-vue2-cli/src/components/Counter.vue b/tests/components/ct-vue2-cli/src/components/Counter.vue deleted file mode 100644 index a048a43535630..0000000000000 --- a/tests/components/ct-vue2-cli/src/components/Counter.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/tests/components/ct-vue2-cli/src/components/DefaultSlot.vue b/tests/components/ct-vue2-cli/src/components/DefaultSlot.vue deleted file mode 100644 index 287b84beafaa7..0000000000000 --- a/tests/components/ct-vue2-cli/src/components/DefaultSlot.vue +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/tests/components/ct-vue2-cli/src/components/EmptyTemplate.vue b/tests/components/ct-vue2-cli/src/components/EmptyTemplate.vue deleted file mode 100644 index 9b4c59695ec37..0000000000000 --- a/tests/components/ct-vue2-cli/src/components/EmptyTemplate.vue +++ /dev/null @@ -1,8 +0,0 @@ - - - diff --git a/tests/components/ct-vue2-cli/src/components/NamedSlots.vue b/tests/components/ct-vue2-cli/src/components/NamedSlots.vue deleted file mode 100644 index 582608df32fc4..0000000000000 --- a/tests/components/ct-vue2-cli/src/components/NamedSlots.vue +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/tests/components/ct-vue2-cli/src/main.js b/tests/components/ct-vue2-cli/src/main.js deleted file mode 100644 index b92d6e3e04738..0000000000000 --- a/tests/components/ct-vue2-cli/src/main.js +++ /dev/null @@ -1,14 +0,0 @@ -import Vue from 'vue'; -import Router from 'vue-router'; -import App from './App.vue'; -import { router } from './router'; -import './assets/index.css'; - -Vue.config.productionTip = false; - -Vue.use(Router); - -new Vue({ - router, - render: h => h(App), -}).$mount('#app'); diff --git a/tests/components/ct-vue2-cli/src/pages/DashboardPage.vue b/tests/components/ct-vue2-cli/src/pages/DashboardPage.vue deleted file mode 100644 index 0dcf8cc990a48..0000000000000 --- a/tests/components/ct-vue2-cli/src/pages/DashboardPage.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/tests/components/ct-vue2-cli/src/pages/LoginPage.vue b/tests/components/ct-vue2-cli/src/pages/LoginPage.vue deleted file mode 100644 index aaa18be8ab3ac..0000000000000 --- a/tests/components/ct-vue2-cli/src/pages/LoginPage.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/tests/components/ct-vue2-cli/src/router/index.js b/tests/components/ct-vue2-cli/src/router/index.js deleted file mode 100644 index 3e5680ca8e4f8..0000000000000 --- a/tests/components/ct-vue2-cli/src/router/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import Router from 'vue-router'; -import LoginPage from '../pages/LoginPage.vue'; -import DashboardPage from '../pages/DashboardPage.vue'; - -export const router = new Router({ - mode: 'history', - base: '/', - routes: [ - { path: '/', component: LoginPage }, - { path: '/dashboard', component: DashboardPage } - ] -}); diff --git a/tests/components/ct-vue2-cli/src/shims-vue.d.ts b/tests/components/ct-vue2-cli/src/shims-vue.d.ts deleted file mode 100644 index 8f6f410263712..0000000000000 --- a/tests/components/ct-vue2-cli/src/shims-vue.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '*.vue' { - import Vue from 'vue'; - export default Vue; -} diff --git a/tests/components/ct-vue2-cli/tests/events/events.spec.ts b/tests/components/ct-vue2-cli/tests/events/events.spec.ts deleted file mode 100644 index 71c4c958a9d80..0000000000000 --- a/tests/components/ct-vue2-cli/tests/events/events.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { test, expect } from '@playwright/experimental-ct-vue2'; -import Button from '@/components/Button.vue'; - -test('emit an submit event when the button is clicked', async ({ mount }) => { - const messages: string[] = []; - const component = await mount(Button, { - props: { - title: 'Submit', - }, - on: { - submit: (data: string) => messages.push(data), - }, - }); - await component.click(); - expect(messages).toEqual(['hello']); -}); diff --git a/tests/components/ct-vue2-cli/tests/events/events.spec.tsx b/tests/components/ct-vue2-cli/tests/events/events.spec.tsx deleted file mode 100644 index 9d31d708fb180..0000000000000 --- a/tests/components/ct-vue2-cli/tests/events/events.spec.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { test, expect } from '@playwright/experimental-ct-vue2'; -import Button from '@/components/Button.vue'; -import DefaultSlot from '@/components/DefaultSlot.vue'; - -test('emit an submit event when the button is clicked', async ({ mount }) => { - const messages: string[] = []; - const component = await mount( -
      } sidebar={} />; diff --git a/packages/trace-viewer/src/ui/uiModeFiltersView.tsx b/packages/trace-viewer/src/ui/uiModeFiltersView.tsx index 7671c2e9bae4f..314fce3a96930 100644 --- a/packages/trace-viewer/src/ui/uiModeFiltersView.tsx +++ b/packages/trace-viewer/src/ui/uiModeFiltersView.tsx @@ -58,9 +58,9 @@ export const FiltersView: React.FC<{ Projects: {projectsLine}
      {expanded &&
      -
      +
      {[...statusFilters.entries()].map(([status, value]) => { - return
      + return
      ; })}
      -
      +
      {[...projectFilters.entries()].map(([projectName, value]) => { - return
      + return
    \`); +- await expect(page.locator('body')).toMatchAriaSnapshot(\`\`); ++ await expect(page.locator('body')).toMatchAriaSnapshot(\` ++ - list: ++ - listitem: Item 1 ++ - listitem: Item 2 ++ - listitem: /Time \\d+:\\d+/ ++ - listitem: /Year \\d+/ ++ - listitem: /Duration \\d+[hms]+/ ++ - listitem: /\\d+,\\d+/ ++ - listitem: /2,\\d+\\.\\d+/ ++ - listitem: /Total \\d+/ ++ - listitem: /Regex 1/ ++ - listitem: /\\/Regex \\d+[hms]+\\// ++ \`); + }); + +`); +}); + +test('should generate baseline with special characters', async ({ runInlineTest }, testInfo) => { + const result = await runInlineTest({ + 'a.spec.ts': ` + import { test, expect } from '@playwright/test'; + test('test', async ({ page }) => { + await page.setContent(\`
      + +
    • Item: 1
    • +
    • Item {a: b}
    • +
    \`); + await expect(page.locator('body')).toMatchAriaSnapshot(\`\`); + }); + ` + }); + + expect(result.exitCode).toBe(0); + const patchPath = testInfo.outputPath('test-results/rebaselines.patch'); + const data = fs.readFileSync(patchPath, 'utf-8'); + expect(data).toBe(`--- a/a.spec.ts ++++ b/a.spec.ts +@@ -6,6 +6,11 @@ +
  • Item: 1
  • +
  • Item {a: b}
  • +
\`); +- await expect(page.locator('body')).toMatchAriaSnapshot(\`\`); ++ await expect(page.locator('body')).toMatchAriaSnapshot(\` ++ - list: ++ - 'button "Click: me"' ++ - listitem: \"Item: 1\" ++ - listitem: \"Item {a: b}\" ++ \`); + }); + +`); +}); From 6f5c7b43588d2e8b95d716a21c6d2f4682042c1b Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 29 Oct 2024 18:29:07 -0700 Subject: [PATCH 394/805] feat(html): render prev/next test buttons (#33356) --- packages/html-reporter/src/headerView.tsx | 4 +- packages/html-reporter/src/index.tsx | 5 +- packages/html-reporter/src/links.tsx | 23 ++++-- packages/html-reporter/src/reportView.tsx | 73 +++++++++++++------ packages/html-reporter/src/testCaseView.css | 2 +- .../html-reporter/src/testCaseView.spec.tsx | 36 +++++++-- packages/html-reporter/src/testCaseView.tsx | 15 +++- packages/html-reporter/src/testFileView.tsx | 23 +++--- packages/html-reporter/src/testFilesView.tsx | 54 +++++++------- 9 files changed, 158 insertions(+), 77 deletions(-) diff --git a/packages/html-reporter/src/headerView.tsx b/packages/html-reporter/src/headerView.tsx index 925bc64721ec9..01f92f1ecb6ba 100644 --- a/packages/html-reporter/src/headerView.tsx +++ b/packages/html-reporter/src/headerView.tsx @@ -20,7 +20,7 @@ import './colors.css'; import './common.css'; import './headerView.css'; import * as icons from './icons'; -import { Link, navigate } from './links'; +import { Link, navigate, SearchParamsContext } from './links'; import { statusIcon } from './statusIcon'; import { filterWithToken } from './filter'; @@ -65,7 +65,7 @@ export const HeaderView: React.FC = ({ stats }) => { - const searchParams = new URLSearchParams(window.location.hash.slice(1)); + const searchParams = React.useContext(SearchParamsContext); const q = searchParams.get('q')?.toString() || ''; const tokens = q.split(' '); return