diff --git a/docs/src/api/class-browsercontext.md b/docs/src/api/class-browsercontext.md
index aa98489296176..d822d9aa504b4 100644
--- a/docs/src/api/class-browsercontext.md
+++ b/docs/src/api/class-browsercontext.md
@@ -1495,6 +1495,29 @@ its geolocation.
Whether to emulate network being offline for the browser context.
+
+## async method: BrowserContext.setStorageState
+* since: v1.55
+
+Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage state.
+
+### param: BrowserContext.setStorageState.storageState = %%-js-python-context-option-storage-state-%%
+* since: v1.55
+
+### param: BrowserContext.setStorageState.storageState = %%-csharp-java-context-option-storage-state-%%
+* since: v1.55
+
+
+## async method: BrowserContext.setStorageStatePath
+* since: v1.55
+* langs: csharp, java
+
+Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage state from a file.
+
+### param: BrowserContext.setStorageStatePath.storageStatePath = %%-csharp-java-context-option-storage-state-path-%%
+* since: v1.55
+
+
## async method: BrowserContext.storageState
* since: v1.8
- returns: <[Object]>
diff --git a/docs/src/getting-started-vscode-js.md b/docs/src/getting-started-vscode-js.md
index 03e29ff2e9660..7cdbeda3be720 100644
--- a/docs/src/getting-started-vscode-js.md
+++ b/docs/src/getting-started-vscode-js.md
@@ -7,229 +7,166 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
## Introduction
-Playwright Test was created specifically to accommodate the needs of end-to-end testing. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS, locally or on CI, headless or headed with native mobile emulation of Google Chrome for Android and Mobile Safari.
-
-Get started by installing Playwright and generating a test to see it in action. Alternatively you can also get started and run your tests using the [CLI](./intro.md).
+The Playwright VS Code extension brings the power of Playwright Test directly into your editor, allowing you to run, debug, and generate tests with a seamless UI-driven experience. This guide will walk you through setting up the extension and using its core features to supercharge your end-to-end testing workflow.
-## Installation
-
-Playwright has a VS Code extension which is available when testing with Node.js. Install [it from the VS Code marketplace](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) or from the extensions tab in VS Code.
-
-
-
-Once installed, open the command panel and type:
-
-```bash
-Install Playwright
-```
-
-
+## Prerequisites
+Before you begin, make sure you have the following installed:
+- [Node.js](https://nodejs.org/) (LTS version recommended)
+- [Visual Studio Code](https://code.visualstudio.com/)
-Select **Test: Install Playwright** and Choose the browsers you would like to run your tests on. These can be later configured in the [playwright.config](./test-configuration.md) file. You can also choose if you would like to have a GitHub Actions setup to [run your tests on CI](./ci-intro.md).
+## Getting Started
-
+### Installation & Setup
-### Opening the testing sidebar
+1. **Install the Extension**: Open the Extensions view in VS Code (`Ctrl+Shift+X` or `Cmd+Shift+X`) and search for "Playwright". [Install the official extension from Microsoft](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright).
-The testing sidebar can be opened by clicking on the testing icon in the activity bar. This will give you access to the test explorer, which will show you all the tests in your project as well as the Playwright sidebar which includes projects, settings, tools and setup.
-
+
-## Running tests
-
-You can run a single test by clicking the green triangle next to your test block to run your test. Playwright will run through each line of the test and when it finishes you will see a green tick next to your test block as well as the time it took to run the test.
-
-
-
+1. **Install Playwright**: Once the extension is installed, open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`) and run the **Test: Install Playwright** command.
+
-### Run tests and show browsers
+3. **Select Browsers**: Choose the browsers you want for your tests (e.g., Chromium, Firefox, WebKit). You can also add a GitHub Actions workflow to run tests in CI. These settings can be changed later in your `playwright.config.ts` file.
-You can also run your tests and show the browsers by selecting the option **Show Browsers** in the testing sidebar. Then when you click the green triangle to run your test the browser will open and you will visually see it run through your test. Leave this selected if you want browsers open for all your tests or uncheck it if you prefer your tests to run in headless mode with no browser open.
+
-
+### Opening the Testing Sidebar
-Use the **Close all browsers** button to close all browsers.
+Click the **Testing icon** in the VS Code Activity Bar to open the Test Explorer. Here, you'll find your tests, as well as the Playwright sidebar for managing projects, tools, and settings.
-### View and run all tests
+
-View all tests in the testing sidebar and extend the tests by clicking on each test. Tests that have not been run will not have the green check next to them. Run all tests by clicking on the white triangle as you hover over the tests in the testing sidebar.
+## Core Features
-
+### Running Your Tests
-### Running tests on multiple browsers
-
-The first section in the Playwright sidebar is the projects section. Here you can see all your projects as defined in your Playwright config file. The default config when installing Playwright gives you 3 projects, Chromium, Firefox and WebKit. The first project is selected by default.
-
-
-
-To run tests on multiple projects, select each project by checking the checkboxes next to the project name. Then when you run your tests from the sidebar or by pressing the play button next to the test name, the tests will run on all the selected projects.
-
-
-
-You can also individually run a test on a specific project by clicking the grey play button next to the project name of the test.
-
-
-
-### Run tests with trace viewer
+
-For a better developer experience you can run your tests with the **Show Trace Viewer** option.
+- **Run a Single Test**: Click the green "play" icon next to any test to run it. The play button will change to a green checkmark if the test passes or a red X if the test fails. You'll be able to see how long the test took to run displayed next to the test name. Additionally, the Test Results panel will automatically open at the bottom of VS Code, showing a summary of the test execution including how many tests ran, how many passed, failed, or were skipped, along with the total execution time.
-
+
-This will open up a full trace of your test where you can step through each action of your tests, explore the timeline, source code and more.
+- **Run All Tests**: You can run all tests at different levels. Click the play icon next to a specific test file to run all tests within that file, or click the play icon at the very top of the Test Explorer to run all tests across your entire project.
-
+
-To learn more about the trace viewer see our [Trace Viewer guide](./trace-viewer.md).
+- **Run on Multiple Browsers**: In the Playwright sidebar, check the boxes for the projects (browsers) you want to test against. Projects in Playwright represent different browser configurations - each project typically corresponds to a specific browser (like Chromium, Firefox, or WebKit) with its own settings such as viewport size, device emulation, or other browser-specific options. When you run a test, it will execute across all selected projects, allowing you to verify your application works consistently across different browsers and configurations.
+
+- **Show Browser**: To watch your tests execute in a live browser window, enable the **Show Browser** option in the sidebar. Disable it to run in headless mode (where tests run in the background without opening a visible browser window).
-## Debugging tests
+
-With the VS Code extension you can debug your tests right in VS Code see error messages, create breakpoints and live debug your tests.
+### Debugging Your Tests
-### Error messages
-
-If your test fails VS Code will show you error messages right in the editor showing what was expected, what was received as well as a complete call log.
+The VS Code extension provides powerful debugging tools to help you identify and fix issues in your tests. You can set breakpoints, inspect variables, view detailed error messages, get AI-powered suggestions to resolve test failures, and use the comprehensive trace viewer to analyze test execution step-by-step.
-
+- **Using Breakpoints**: Set a breakpoint by clicking in the gutter next to a line number. Right-click the test and select **Debug Test**. The test will pause at your breakpoint, allowing you to inspect variables and step through the code.
-### Live debugging
+ 
-You can debug your test live in VS Code. After running a test with the `Show Browser` option checked, click on any of the locators in VS Code and it will be highlighted in the Browser window. Playwright will highlight it if it exists and show you if there is more than one result
+- **Live Debugging**: With **Show Browsers** enabled, click on a locator in your code. Playwright will highlight the corresponding element in the browser, making it easy to verify locators.
-
+ 
-You can also edit the locators in VS Code and Playwright will show you the changes live in the browser window.
+- **Viewing Error Messages**: If a test fails, the extension displays detailed error messages, including the expected vs. received values and a full call log, directly in the editor.
-### Run in debug mode
+
-To set a breakpoint click next to the line number where you want the breakpoint to be until a red dot appears. Run the tests in debug mode by right clicking on the line next to the test you want to run.
+- **Fix with AI**: When a test fails, click the sparkle icon next to the error to get an AI-powered fix suggestion from Copilot. Copilot analyzes the error and suggests a code change to resolve the issue.
-
+
-A browser window will open and the test will run and pause at where the breakpoint is set. You can step through the tests, pause the test and rerun the tests from the menu in VS Code.
+- **Debugging with Trace Viewer**: For comprehensive debugging, enable the **Show Trace Viewer** option in the Playwright sidebar. When your test finishes, a detailed trace will automatically open, providing you with a complete timeline of your test execution. The trace viewer is particularly useful for:
+ - **Step-by-step analysis**: Navigate through each action your test performed with precise timestamps
+ - **DOM inspection**: View DOM snapshots at any point during test execution to see exactly what the page looked like
+ - **Network monitoring**: Examine all network requests and responses that occurred during the test
+ - **Console logs**: Access all console messages and errors from the browser
+ - **Source mapping**: Jump directly to the source code that executed each action
+ - **Visual debugging**: See screenshots and understand what the user would have seen at each step
-
+ The trace viewer is especially valuable when debugging flaky tests or understanding complex user interactions.
-
+
-To learn more about debugging, see [Debugging in Visual Studio Code](https://code.visualstudio.com/docs/editor/debugging).
+To learn more, see our [Trace Viewer guide](./trace-viewer.md).
-### Debug with trace viewer
+### Generating Tests with CodeGen
-For a better developer experience you can debug your tests with the **Show Trace Viewer** option.
-
-
-
-This will open up a full trace of your test where you can step through each action and see what happened before and after the action. You can also inspect the DOM snapshot, see console logs, network requests, the source code and more.
-
-
-
-To learn more about the trace viewer see our [Trace Viewer guide](./trace-viewer.md).
-
-## Generating tests
-
-CodeGen will auto generate your tests for you as you perform actions in the browser and is a great way to quickly get started. The viewport for the browser window is set to a specific width and height. See the [configuration guide](./test-configuration.md) to change the viewport or emulate different environments.
+CodeGen is Playwright's powerful test generation tool that automatically creates test code by recording your interactions with a web page. Instead of writing tests from scratch, you can simply navigate through your application while CodeGen captures your actions and converts them into reliable test code with proper locators and assertions.
-### Record a new test
-
-To record a test click on the **Record new** button from the Testing sidebar. This will create a `test-1.spec.ts` file as well as open up a browser window. In the browser go to the URL you wish to test and start clicking around. Playwright will record your actions and generate the test code directly in VS Code. You can also generate assertions by choosing one of the icons in the toolbar and then clicking on an element on the page to assert against. The following assertions can be generated:
- * `'assert visibility'` to assert that an element is visible
- * `'assert text'` to assert that an element contains specific text
- * `'assert value'` to assert that an element has a specific value
-
-Once you are done recording click the **cancel** button or close the browser window. You can then inspect your `test-1.spec.ts` file and see your generated test.
-
-
-
-
-### Record at cursor
-
-To record from a specific point in your test file click the **Record at cursor** button from the Testing sidebar. This generates actions into the existing test at the current cursor position. You can run the test, position the cursor at the end of the test and continue generating the test.
-
-
-
-### Picking a locator
-
-Pick a [locator](./locators.md) and copy it into your test file by clicking the **Pick locator** button form the testing sidebar. Then in the browser click the element you require and it will now show up in the **Pick locator** box in VS Code. Press 'enter' on your keyboard to copy the locator into the clipboard and then paste anywhere in your code. Or press 'escape' if you want to cancel.
-
-
-
-
-Playwright will look at your page and figure out the best locator, prioritizing [role, text and test id locators](./locators.md). If the generator finds multiple elements matching the locator, it will improve the locator to make it resilient and uniquely identify the target element, so you don't have to worry about failing tests due to locators.
-
-## Project Dependencies
-
-You can use [project dependencies](./test-projects.md) to run tests that depend on other tests. This is useful for **setup** tests such as logging in to a website.
-
-### Running setup tests
-
-To run your setup tests select the **setup** project, as defined in your configuration file, from the project section in the Playwright sidebar. This will give you access to the **setup** tests in the test explorer.
-
-
+- **Record a New Test**: Click **Record new** in the sidebar. A browser window will open. As you interact with the page, Playwright will automatically generate the test code. You can also generate assertions from the recording toolbar.
-When you run a test that depends on the **setup** tests, the **setup** test will run first. Each time you run the test, the **setup** test will run again.
+
-
+- **Record at Cursor**: Place your cursor inside an existing test and click **Record at cursor** to add new actions at that specific point.
+
-### Running setup tests only once
+- **Pick a Locator**: Use the **Pick locator** tool to click on any element in the opened browser. Playwright will determine the best locator and copy it to your clipboard, ready to be pasted into your code.
-To run the **setup** test only once, deselect it from the projects section in the Playwright sidebar. The **setup** test is now removed from the test explorer. When you run a test that depends on the **setup** test, it will no longer run the **setup** test, making it much faster and therefore a much better developer experience.
+
-
+To learn more, see our [CodeGen guide](./codegen.md).
-## Global Setup
-**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.
+## Advanced Features
-Global setup will re-run when you debug tests as this ensures an isolated environment and dedicated setup for the test.
+### Project Dependencies
-
+Use [project dependencies](./test-projects.md) to define setup tests that run before other tests. For example, you can create a login test that runs first, then reuse that authenticated state across multiple tests without having to log in again for each test. In VS Code, you can see these setup tests in the Test Explorer and run them independently when needed.
-## Multiple configurations
+
-If your project contains more than one playwright configuration file, you can switch between them by first clicking on the gear icon in the top right corner of the Playwright sidebar. This will show you all the configuration files in your project. Select the configuration files you want to use by checking the checkbox next to each one and clicking on the 'ok' button.
+To learn more, see our [Project Dependencies guide](./test-projects.md).
-
+### Global Setup
-You will now have access to all your tests in the test explorer. To run a test click on the grey triangle next to the file or project name.
+For tasks that need to run only once before all tests (like seeding a database), use **Global Setup**. You can trigger the global setup and teardown manually from the Playwright sidebar.
-
+
-To run all tests from all configurations click on the grey triangle at the top of the test explorer.
+### Multiple Configurations
-
+If you have multiple `playwright.config.ts` files, you can switch between them using the gear icon in the Playwright sidebar. This allows you to easily work with different test suites or environments.
-To choose a configuration file to work with simply toggle between them by clicking on the configuration file name in the Playwright sidebar. Now when you use the tools, such as Record a test, it will record a test for the selected configuration file.
+
-
+## Quick Reference
-You can easily toggle back and forth between configurations by clicking on the configuration file name in the Playwright sidebar.
+| Action | How to do it in VS Code |
+| ----------------------- | ----------------------------------------------------------- |
+| **Install Playwright** | Command Palette → `Test: Install Playwright` |
+| **Run a Test** | Click the "play" icon next to the test |
+| **Debug a Test** | Set a breakpoint, right-click the test → `Debug Test` |
+| **Show Live Browser** | Enable `Show Browsers` in the Playwright sidebar |
+| **Record a New Test** | Click `Record new` in the Playwright sidebar |
+| **Pick a Locator** | Click `Pick locator` in the Playwright sidebar |
+| **View Test Trace** | Enable `Show Trace Viewer` in the Playwright sidebar |
-## What's next
+## What's Next
-- [Write tests using web first assertions, page fixtures and locators](./writing-tests.md)
-- [Run your tests on CI](./ci-intro.md)
-- [Learn more about the Trace Viewer](./trace-viewer.md)
+- [Write tests using web-first assertions, page fixtures, and locators](./writing-tests.md)
+- [Run your tests on CI](./ci-intro.md)
+- [Learn more about the Trace Viewer](./trace-viewer.md)
diff --git a/docs/src/images/getting-started/debug-mode.png b/docs/src/images/getting-started/debug-mode.png
new file mode 100644
index 0000000000000..73c48a568df46
Binary files /dev/null and b/docs/src/images/getting-started/debug-mode.png differ
diff --git a/docs/src/images/getting-started/error-messaging.png b/docs/src/images/getting-started/error-messaging.png
new file mode 100644
index 0000000000000..ced1f2f8c8a7f
Binary files /dev/null and b/docs/src/images/getting-started/error-messaging.png differ
diff --git a/docs/src/images/getting-started/fix-with-ai.png b/docs/src/images/getting-started/fix-with-ai.png
new file mode 100644
index 0000000000000..d1adcdbe3815c
Binary files /dev/null and b/docs/src/images/getting-started/fix-with-ai.png differ
diff --git a/docs/src/images/getting-started/global-setup.png b/docs/src/images/getting-started/global-setup.png
new file mode 100644
index 0000000000000..35d6aa885709f
Binary files /dev/null and b/docs/src/images/getting-started/global-setup.png differ
diff --git a/docs/src/images/getting-started/install-browsers.png b/docs/src/images/getting-started/install-browsers.png
new file mode 100644
index 0000000000000..715e620229f60
Binary files /dev/null and b/docs/src/images/getting-started/install-browsers.png differ
diff --git a/docs/src/images/getting-started/install-playwright.png b/docs/src/images/getting-started/install-playwright.png
new file mode 100644
index 0000000000000..38c2363909d1e
Binary files /dev/null and b/docs/src/images/getting-started/install-playwright.png differ
diff --git a/docs/src/images/getting-started/live-debugging.png b/docs/src/images/getting-started/live-debugging.png
new file mode 100644
index 0000000000000..41f6d8e7e4ed4
Binary files /dev/null and b/docs/src/images/getting-started/live-debugging.png differ
diff --git a/docs/src/images/getting-started/pick-locator.png b/docs/src/images/getting-started/pick-locator.png
new file mode 100644
index 0000000000000..26408dd356be9
Binary files /dev/null and b/docs/src/images/getting-started/pick-locator.png differ
diff --git a/docs/src/images/getting-started/record-at-cursor.png b/docs/src/images/getting-started/record-at-cursor.png
new file mode 100644
index 0000000000000..0ab2fc09394c0
Binary files /dev/null and b/docs/src/images/getting-started/record-at-cursor.png differ
diff --git a/docs/src/images/getting-started/record-new-test.png b/docs/src/images/getting-started/record-new-test.png
new file mode 100644
index 0000000000000..085ff97aa56fb
Binary files /dev/null and b/docs/src/images/getting-started/record-new-test.png differ
diff --git a/docs/src/images/getting-started/run-all-tests.png b/docs/src/images/getting-started/run-all-tests.png
new file mode 100644
index 0000000000000..d339bf77b56fd
Binary files /dev/null and b/docs/src/images/getting-started/run-all-tests.png differ
diff --git a/docs/src/images/getting-started/run-single-test.png b/docs/src/images/getting-started/run-single-test.png
new file mode 100644
index 0000000000000..32c226c9605c0
Binary files /dev/null and b/docs/src/images/getting-started/run-single-test.png differ
diff --git a/docs/src/images/getting-started/select-projects.png b/docs/src/images/getting-started/select-projects.png
new file mode 100644
index 0000000000000..813b8553f04ab
Binary files /dev/null and b/docs/src/images/getting-started/select-projects.png differ
diff --git a/docs/src/images/getting-started/selecting-configuration.png b/docs/src/images/getting-started/selecting-configuration.png
new file mode 100644
index 0000000000000..6fa106d57d498
Binary files /dev/null and b/docs/src/images/getting-started/selecting-configuration.png differ
diff --git a/docs/src/images/getting-started/setup-tests.png b/docs/src/images/getting-started/setup-tests.png
new file mode 100644
index 0000000000000..f90faa7190835
Binary files /dev/null and b/docs/src/images/getting-started/setup-tests.png differ
diff --git a/docs/src/images/getting-started/show-browser.png b/docs/src/images/getting-started/show-browser.png
new file mode 100644
index 0000000000000..c5389d371e711
Binary files /dev/null and b/docs/src/images/getting-started/show-browser.png differ
diff --git a/docs/src/images/getting-started/testing-sidebar.png b/docs/src/images/getting-started/testing-sidebar.png
new file mode 100644
index 0000000000000..3dcc449cca918
Binary files /dev/null and b/docs/src/images/getting-started/testing-sidebar.png differ
diff --git a/docs/src/images/getting-started/trace-viewer-debug.png b/docs/src/images/getting-started/trace-viewer-debug.png
new file mode 100644
index 0000000000000..9dbcbcaf1faed
Binary files /dev/null and b/docs/src/images/getting-started/trace-viewer-debug.png differ
diff --git a/docs/src/images/getting-started/trace-viewer.png b/docs/src/images/getting-started/trace-viewer.png
new file mode 100644
index 0000000000000..cb282aa18c7c1
Binary files /dev/null and b/docs/src/images/getting-started/trace-viewer.png differ
diff --git a/docs/src/images/getting-started/vscode-extension.png b/docs/src/images/getting-started/vscode-extension.png
new file mode 100644
index 0000000000000..9f360e5a0dd2c
Binary files /dev/null and b/docs/src/images/getting-started/vscode-extension.png differ
diff --git a/docs/src/running-tests-js.md b/docs/src/running-tests-js.md
index 4ad9ea9c67c46..5cdc008bdc19c 100644
--- a/docs/src/running-tests-js.md
+++ b/docs/src/running-tests-js.md
@@ -94,9 +94,9 @@ npx playwright test --last-failed
### Run tests in VS Code
-Tests can be run right from VS Code using the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright). Once installed you can simply click the green triangle next to the test you want to run or run all tests from the testing sidebar. Check out our [Getting Started with VS Code](./getting-started-vscode.md#running-tests) guide for more details.
+Tests can be run right from VS Code using the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright). Once installed you can simply click the green triangle next to the test you want to run or run all tests from the testing sidebar. Check out our [Getting Started with VS Code](./getting-started-vscode.md) guide for more details.
-
+
## Debugging tests
diff --git a/packages/playwright-client/types/types.d.ts b/packages/playwright-client/types/types.d.ts
index 01cc047648030..a72dc2a485e37 100644
--- a/packages/playwright-client/types/types.d.ts
+++ b/packages/playwright-client/types/types.d.ts
@@ -9273,6 +9273,64 @@ export interface BrowserContext {
*/
setOffline(offline: boolean): Promise;
+ /**
+ * Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage
+ * state.
+ * @param storageState Learn more about [storage state and auth](https://playwright.dev/docs/auth).
+ *
+ * Populates context with given storage state. This option can be used to initialize context with logged-in
+ * information obtained via
+ * [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state).
+ */
+ setStorageState(storageState: string|{
+ /**
+ * Cookies to set for context
+ */
+ cookies: Array<{
+ name: string;
+
+ value: string;
+
+ /**
+ * Domain and path are required. For the cookie to apply to all subdomains as well, prefix domain with a dot, like
+ * this: ".example.com"
+ */
+ domain: string;
+
+ /**
+ * Domain and path are required
+ */
+ path: string;
+
+ /**
+ * Unix time in seconds.
+ */
+ expires: number;
+
+ httpOnly: boolean;
+
+ secure: boolean;
+
+ /**
+ * sameSite flag
+ */
+ sameSite: "Strict"|"Lax"|"None";
+ }>;
+
+ origins: Array<{
+ origin: string;
+
+ /**
+ * localStorage to set for context
+ */
+ localStorage: Array<{
+ name: string;
+
+ value: string;
+ }>;
+ }>;
+ }): Promise;
+
/**
* Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB
* snapshot.
diff --git a/packages/playwright-core/browsers.json b/packages/playwright-core/browsers.json
index d04f9eb2b625d..9835ac736af43 100644
--- a/packages/playwright-core/browsers.json
+++ b/packages/playwright-core/browsers.json
@@ -15,15 +15,15 @@
},
{
"name": "chromium-tip-of-tree",
- "revision": "1354",
+ "revision": "1355",
"installByDefault": false,
- "browserVersion": "140.0.7325.0"
+ "browserVersion": "140.0.7329.0"
},
{
"name": "chromium-tip-of-tree-headless-shell",
- "revision": "1354",
+ "revision": "1355",
"installByDefault": false,
- "browserVersion": "140.0.7325.0"
+ "browserVersion": "140.0.7329.0"
},
{
"name": "firefox",
diff --git a/packages/playwright-core/src/client/browserContext.ts b/packages/playwright-core/src/client/browserContext.ts
index 1d177df991bcd..5a1bad8987459 100644
--- a/packages/playwright-core/src/client/browserContext.ts
+++ b/packages/playwright-core/src/client/browserContext.ts
@@ -41,7 +41,7 @@ import { urlMatchesEqual } from '../utils/isomorphic/urlMatch';
import { isRegExp, isString } from '../utils/isomorphic/rtti';
import { rewriteErrorMessage } from '../utils/isomorphic/stackTrace';
-import type { BrowserContextOptions, Headers, StorageState, WaitForEventOptions } from './types';
+import type { BrowserContextOptions, Headers, SetStorageState, StorageState, WaitForEventOptions } from './types';
import type * as structs from '../../types/structs';
import type * as api from '../../types/types';
import type { URLMatch } from '../utils/isomorphic/urlMatch';
@@ -455,6 +455,10 @@ export class BrowserContext extends ChannelOwner
return state;
}
+ async setStorageState(storageState: string | SetStorageState) {
+ await this._channel.setStorageState({ storageState: await prepareStorageState(this._platform, storageState) });
+ }
+
backgroundPages(): Page[] {
return [...this._backgroundPages];
}
@@ -527,13 +531,13 @@ export class BrowserContext extends ChannelOwner
}
}
-async function prepareStorageState(platform: Platform, options: BrowserContextOptions): Promise {
- if (typeof options.storageState !== 'string')
- return options.storageState as any;
+async function prepareStorageState(platform: Platform, storageState: string | SetStorageState): Promise> {
+ if (typeof storageState !== 'string')
+ return storageState as any;
try {
- return JSON.parse(await platform.fs().promises.readFile(options.storageState, 'utf8'));
+ return JSON.parse(await platform.fs().promises.readFile(storageState, 'utf8'));
} catch (e) {
- rewriteErrorMessage(e, `Error reading storage state from ${options.storageState}:\n` + e.message);
+ rewriteErrorMessage(e, `Error reading storage state from ${storageState}:\n` + e.message);
throw e;
}
}
@@ -548,7 +552,7 @@ export async function prepareBrowserContextParams(platform: Platform, options: B
viewport: options.viewport === null ? undefined : options.viewport,
noDefaultViewport: options.viewport === null,
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
- storageState: await prepareStorageState(platform, options),
+ storageState: options.storageState ? await prepareStorageState(platform, options.storageState) : undefined,
serviceWorkers: options.serviceWorkers,
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
diff --git a/packages/playwright-core/src/protocol/validator.ts b/packages/playwright-core/src/protocol/validator.ts
index 8eb22ce61a918..77a60cc858180 100644
--- a/packages/playwright-core/src/protocol/validator.ts
+++ b/packages/playwright-core/src/protocol/validator.ts
@@ -16,42 +16,42 @@
// This file is generated by generate_channels.js, do not edit manually.
-import { scheme, tOptional, tObject, tBoolean, tNumber, tString, tAny, tEnum, tArray, tBinary, tChannel, tType } from './validatorPrimitives';
+import { scheme, tOptional, tObject, tBoolean, tInt, tFloat, tString, tAny, tEnum, tArray, tBinary, tChannel, tType } from './validatorPrimitives';
export type { Validator, ValidatorContext } from './validatorPrimitives';
export { ValidationError, findValidator, maybeFindValidator, createMetadataValidator } from './validatorPrimitives';
scheme.StackFrame = tObject({
file: tString,
- line: tNumber,
- column: tNumber,
+ line: tInt,
+ column: tInt,
function: tOptional(tString),
});
scheme.Metadata = tObject({
location: tOptional(tObject({
file: tString,
- line: tOptional(tNumber),
- column: tOptional(tNumber),
+ line: tOptional(tInt),
+ column: tOptional(tInt),
})),
title: tOptional(tString),
internal: tOptional(tBoolean),
stepId: tOptional(tString),
});
scheme.ClientSideCallMetadata = tObject({
- id: tNumber,
+ id: tInt,
stack: tOptional(tArray(tType('StackFrame'))),
});
scheme.Point = tObject({
- x: tNumber,
- y: tNumber,
+ x: tFloat,
+ y: tFloat,
});
scheme.Rect = tObject({
- x: tNumber,
- y: tNumber,
- width: tNumber,
- height: tNumber,
+ x: tFloat,
+ y: tFloat,
+ width: tFloat,
+ height: tFloat,
});
scheme.SerializedValue = tObject({
- n: tOptional(tNumber),
+ n: tOptional(tFloat),
b: tOptional(tBoolean),
s: tOptional(tString),
v: tOptional(tEnum(['null', 'undefined', 'NaN', 'Infinity', '-Infinity', '-0'])),
@@ -76,9 +76,9 @@ scheme.SerializedValue = tObject({
k: tString,
v: tType('SerializedValue'),
}))),
- h: tOptional(tNumber),
- id: tOptional(tNumber),
- ref: tOptional(tNumber),
+ h: tOptional(tInt),
+ id: tOptional(tInt),
+ ref: tOptional(tInt),
});
scheme.SerializedArgument = tObject({
value: tType('SerializedValue'),
@@ -101,7 +101,7 @@ scheme.AXNode = tObject({
role: tString,
name: tString,
valueString: tOptional(tString),
- valueNumber: tOptional(tNumber),
+ valueNumber: tOptional(tFloat),
description: tOptional(tString),
keyshortcuts: tOptional(tString),
roledescription: tOptional(tString),
@@ -117,9 +117,9 @@ scheme.AXNode = tObject({
selected: tOptional(tBoolean),
checked: tOptional(tEnum(['checked', 'unchecked', 'mixed'])),
pressed: tOptional(tEnum(['pressed', 'released', 'mixed'])),
- level: tOptional(tNumber),
- valuemin: tOptional(tNumber),
- valuemax: tOptional(tNumber),
+ level: tOptional(tInt),
+ valuemin: tOptional(tFloat),
+ valuemax: tOptional(tFloat),
autocomplete: tOptional(tString),
haspopup: tOptional(tString),
invalid: tOptional(tString),
@@ -132,7 +132,7 @@ scheme.SetNetworkCookie = tObject({
url: tOptional(tString),
domain: tOptional(tString),
path: tOptional(tString),
- expires: tOptional(tNumber),
+ expires: tOptional(tFloat),
httpOnly: tOptional(tBoolean),
secure: tOptional(tBoolean),
sameSite: tOptional(tEnum(['Strict', 'Lax', 'None'])),
@@ -144,7 +144,7 @@ scheme.NetworkCookie = tObject({
value: tString,
domain: tString,
path: tString,
- expires: tNumber,
+ expires: tFloat,
httpOnly: tBoolean,
secure: tBoolean,
sameSite: tEnum(['Strict', 'Lax', 'None']),
@@ -157,7 +157,7 @@ scheme.NameValue = tObject({
});
scheme.IndexedDBDatabase = tObject({
name: tString,
- version: tNumber,
+ version: tInt,
stores: tArray(tObject({
name: tString,
autoIncrement: tBoolean,
@@ -227,11 +227,11 @@ scheme.APIRequestContextFetchParams = tObject({
jsonData: tOptional(tString),
formData: tOptional(tArray(tType('NameValue'))),
multipartData: tOptional(tArray(tType('FormField'))),
- timeout: tNumber,
+ timeout: tFloat,
failOnStatusCode: tOptional(tBoolean),
ignoreHTTPSErrors: tOptional(tBoolean),
- maxRedirects: tOptional(tNumber),
- maxRetries: tOptional(tNumber),
+ maxRedirects: tOptional(tInt),
+ maxRetries: tOptional(tInt),
});
scheme.APIRequestContextFetchResult = tObject({
response: tType('APIResponse'),
@@ -266,7 +266,7 @@ scheme.APIRequestContextDisposeResult = tOptional(tObject({}));
scheme.APIResponse = tObject({
fetchUid: tString,
url: tString,
- status: tNumber,
+ status: tInt,
statusText: tString,
headers: tArray(tType('NameValue')),
});
@@ -277,14 +277,14 @@ scheme.LocalUtilsInitializer = tObject({
descriptor: tObject({
userAgent: tString,
viewport: tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
}),
screen: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
- deviceScaleFactor: tNumber,
+ deviceScaleFactor: tFloat,
isMobile: tBoolean,
hasTouch: tBoolean,
defaultBrowserType: tEnum(['chromium', 'firefox', 'webkit']),
@@ -318,7 +318,7 @@ scheme.LocalUtilsHarLookupResult = tObject({
action: tEnum(['error', 'redirect', 'fulfill', 'noentry']),
message: tOptional(tString),
redirectURL: tOptional(tString),
- status: tOptional(tNumber),
+ status: tOptional(tInt),
headers: tOptional(tArray(tType('NameValue'))),
body: tOptional(tBinary),
});
@@ -335,9 +335,9 @@ scheme.LocalUtilsConnectParams = tObject({
wsEndpoint: tString,
headers: tOptional(tAny),
exposeNetwork: tOptional(tString),
- slowMo: tOptional(tNumber),
- timeout: tNumber,
- socksProxyRedirectPortForTest: tOptional(tNumber),
+ slowMo: tOptional(tFloat),
+ timeout: tFloat,
+ socksProxyRedirectPortForTest: tOptional(tInt),
});
scheme.LocalUtilsConnectResult = tObject({
pipe: tChannel(['JsonPipe']),
@@ -391,7 +391,7 @@ scheme.PlaywrightNewRequestParams = tObject({
passphrase: tOptional(tString),
pfx: tOptional(tBinary),
}))),
- maxRedirects: tOptional(tNumber),
+ maxRedirects: tOptional(tInt),
httpCredentials: tOptional(tObject({
username: tString,
password: tString,
@@ -420,10 +420,10 @@ scheme.RecorderSource = tObject({
text: tString,
language: tString,
highlight: tArray(tObject({
- line: tNumber,
+ line: tInt,
type: tString,
})),
- revealLine: tOptional(tNumber),
+ revealLine: tOptional(tInt),
group: tOptional(tString),
});
scheme.DebugControllerInitializer = tOptional(tObject({}));
@@ -436,7 +436,7 @@ scheme.DebugControllerSetModeRequestedEvent = tObject({
mode: tString,
});
scheme.DebugControllerStateChangedEvent = tObject({
- pageCount: tNumber,
+ pageCount: tInt,
});
scheme.DebugControllerSourceChangedEvent = tObject({
text: tString,
@@ -476,7 +476,7 @@ scheme.SocksSupportInitializer = tOptional(tObject({}));
scheme.SocksSupportSocksRequestedEvent = tObject({
uid: tString,
host: tString,
- port: tNumber,
+ port: tInt,
});
scheme.SocksSupportSocksDataEvent = tObject({
uid: tString,
@@ -488,7 +488,7 @@ scheme.SocksSupportSocksClosedEvent = tObject({
scheme.SocksSupportSocksConnectedParams = tObject({
uid: tString,
host: tString,
- port: tNumber,
+ port: tInt,
});
scheme.SocksSupportSocksConnectedResult = tOptional(tObject({}));
scheme.SocksSupportSocksFailedParams = tObject({
@@ -524,7 +524,7 @@ scheme.BrowserTypeLaunchParams = tObject({
handleSIGINT: tOptional(tBoolean),
handleSIGTERM: tOptional(tBoolean),
handleSIGHUP: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
env: tOptional(tArray(tType('NameValue'))),
headless: tOptional(tBoolean),
devtools: tOptional(tBoolean),
@@ -538,8 +538,8 @@ scheme.BrowserTypeLaunchParams = tObject({
tracesDir: tOptional(tString),
chromiumSandbox: tOptional(tBoolean),
firefoxUserPrefs: tOptional(tAny),
- cdpPort: tOptional(tNumber),
- slowMo: tOptional(tNumber),
+ cdpPort: tOptional(tInt),
+ slowMo: tOptional(tFloat),
});
scheme.BrowserTypeLaunchResult = tObject({
browser: tChannel(['Browser']),
@@ -554,7 +554,7 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
handleSIGINT: tOptional(tBoolean),
handleSIGTERM: tOptional(tBoolean),
handleSIGHUP: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
env: tOptional(tArray(tType('NameValue'))),
headless: tOptional(tBoolean),
devtools: tOptional(tBoolean),
@@ -568,15 +568,15 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
tracesDir: tOptional(tString),
chromiumSandbox: tOptional(tBoolean),
firefoxUserPrefs: tOptional(tAny),
- cdpPort: tOptional(tNumber),
+ cdpPort: tOptional(tInt),
noDefaultViewport: tOptional(tBoolean),
viewport: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
screen: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
clientCertificates: tOptional(tArray(tObject({
@@ -592,9 +592,9 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
locale: tOptional(tString),
timezoneId: tOptional(tString),
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
permissions: tOptional(tArray(tString)),
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
@@ -605,7 +605,7 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
origin: tOptional(tString),
send: tOptional(tEnum(['always', 'unauthorized'])),
})),
- deviceScaleFactor: tOptional(tNumber),
+ deviceScaleFactor: tOptional(tFloat),
isMobile: tOptional(tBoolean),
hasTouch: tOptional(tBoolean),
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
@@ -617,8 +617,8 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
recordVideo: tOptional(tObject({
dir: tString,
size: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
})),
strictSelectors: tOptional(tBoolean),
@@ -626,7 +626,7 @@ scheme.BrowserTypeLaunchPersistentContextParams = tObject({
selectorEngines: tOptional(tArray(tType('SelectorEngine'))),
testIdAttributeName: tOptional(tString),
userDataDir: tString,
- slowMo: tOptional(tNumber),
+ slowMo: tOptional(tFloat),
});
scheme.BrowserTypeLaunchPersistentContextResult = tObject({
browser: tChannel(['Browser']),
@@ -635,8 +635,8 @@ scheme.BrowserTypeLaunchPersistentContextResult = tObject({
scheme.BrowserTypeConnectOverCDPParams = tObject({
endpointURL: tString,
headers: tOptional(tArray(tType('NameValue'))),
- slowMo: tOptional(tNumber),
- timeout: tNumber,
+ slowMo: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.BrowserTypeConnectOverCDPResult = tObject({
browser: tChannel(['Browser']),
@@ -663,12 +663,12 @@ scheme.BrowserDefaultUserAgentForTestResult = tObject({
scheme.BrowserNewContextParams = tObject({
noDefaultViewport: tOptional(tBoolean),
viewport: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
screen: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
clientCertificates: tOptional(tArray(tObject({
@@ -684,9 +684,9 @@ scheme.BrowserNewContextParams = tObject({
locale: tOptional(tString),
timezoneId: tOptional(tString),
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
permissions: tOptional(tArray(tString)),
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
@@ -697,7 +697,7 @@ scheme.BrowserNewContextParams = tObject({
origin: tOptional(tString),
send: tOptional(tEnum(['always', 'unauthorized'])),
})),
- deviceScaleFactor: tOptional(tNumber),
+ deviceScaleFactor: tOptional(tFloat),
isMobile: tOptional(tBoolean),
hasTouch: tOptional(tBoolean),
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
@@ -709,8 +709,8 @@ scheme.BrowserNewContextParams = tObject({
recordVideo: tOptional(tObject({
dir: tString,
size: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
})),
strictSelectors: tOptional(tBoolean),
@@ -734,12 +734,12 @@ scheme.BrowserNewContextResult = tObject({
scheme.BrowserNewContextForReuseParams = tObject({
noDefaultViewport: tOptional(tBoolean),
viewport: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
screen: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
clientCertificates: tOptional(tArray(tObject({
@@ -755,9 +755,9 @@ scheme.BrowserNewContextForReuseParams = tObject({
locale: tOptional(tString),
timezoneId: tOptional(tString),
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
permissions: tOptional(tArray(tString)),
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
@@ -768,7 +768,7 @@ scheme.BrowserNewContextForReuseParams = tObject({
origin: tOptional(tString),
send: tOptional(tEnum(['always', 'unauthorized'])),
})),
- deviceScaleFactor: tOptional(tNumber),
+ deviceScaleFactor: tOptional(tFloat),
isMobile: tOptional(tBoolean),
hasTouch: tOptional(tBoolean),
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
@@ -780,8 +780,8 @@ scheme.BrowserNewContextForReuseParams = tObject({
recordVideo: tOptional(tObject({
dir: tString,
size: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
})),
strictSelectors: tOptional(tBoolean),
@@ -848,12 +848,12 @@ scheme.BrowserContextInitializer = tObject({
options: tObject({
noDefaultViewport: tOptional(tBoolean),
viewport: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
screen: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
clientCertificates: tOptional(tArray(tObject({
@@ -869,9 +869,9 @@ scheme.BrowserContextInitializer = tObject({
locale: tOptional(tString),
timezoneId: tOptional(tString),
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
permissions: tOptional(tArray(tString)),
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
@@ -882,7 +882,7 @@ scheme.BrowserContextInitializer = tObject({
origin: tOptional(tString),
send: tOptional(tEnum(['always', 'unauthorized'])),
})),
- deviceScaleFactor: tOptional(tNumber),
+ deviceScaleFactor: tOptional(tFloat),
isMobile: tOptional(tBoolean),
hasTouch: tOptional(tBoolean),
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
@@ -894,8 +894,8 @@ scheme.BrowserContextInitializer = tObject({
recordVideo: tOptional(tObject({
dir: tString,
size: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
})),
strictSelectors: tOptional(tBoolean),
@@ -913,8 +913,8 @@ scheme.BrowserContextConsoleEvent = tObject({
args: tArray(tChannel(['ElementHandle', 'JSHandle'])),
location: tObject({
url: tString,
- lineNumber: tNumber,
- columnNumber: tNumber,
+ lineNumber: tInt,
+ columnNumber: tInt,
}),
page: tChannel(['Page']),
});
@@ -951,13 +951,13 @@ scheme.BrowserContextRequestEvent = tObject({
scheme.BrowserContextRequestFailedEvent = tObject({
request: tChannel(['Request']),
failureText: tOptional(tString),
- responseEndTiming: tNumber,
+ responseEndTiming: tFloat,
page: tOptional(tChannel(['Page'])),
});
scheme.BrowserContextRequestFinishedEvent = tObject({
request: tChannel(['Request']),
response: tOptional(tChannel(['Response'])),
- responseEndTiming: tNumber,
+ responseEndTiming: tFloat,
page: tOptional(tChannel(['Page'])),
});
scheme.BrowserContextResponseEvent = tObject({
@@ -1030,9 +1030,9 @@ scheme.BrowserContextSetExtraHTTPHeadersParams = tObject({
scheme.BrowserContextSetExtraHTTPHeadersResult = tOptional(tObject({}));
scheme.BrowserContextSetGeolocationParams = tObject({
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
});
scheme.BrowserContextSetGeolocationResult = tOptional(tObject({}));
@@ -1071,6 +1071,13 @@ scheme.BrowserContextStorageStateResult = tObject({
cookies: tArray(tType('NetworkCookie')),
origins: tArray(tType('OriginStorage')),
});
+scheme.BrowserContextSetStorageStateParams = tObject({
+ storageState: tObject({
+ cookies: tOptional(tArray(tType('SetNetworkCookie'))),
+ origins: tOptional(tArray(tType('SetOriginStorage'))),
+ }),
+});
+scheme.BrowserContextSetStorageStateResult = tOptional(tObject({}));
scheme.BrowserContextPauseParams = tOptional(tObject({}));
scheme.BrowserContextPauseResult = tOptional(tObject({}));
scheme.BrowserContextEnableRecorderParams = tObject({
@@ -1114,7 +1121,7 @@ scheme.BrowserContextCreateTempFilesParams = tObject({
rootDirName: tOptional(tString),
items: tArray(tObject({
name: tString,
- lastModifiedMs: tOptional(tNumber),
+ lastModifiedMs: tOptional(tFloat),
})),
});
scheme.BrowserContextCreateTempFilesResult = tObject({
@@ -1127,34 +1134,34 @@ scheme.BrowserContextUpdateSubscriptionParams = tObject({
});
scheme.BrowserContextUpdateSubscriptionResult = tOptional(tObject({}));
scheme.BrowserContextClockFastForwardParams = tObject({
- ticksNumber: tOptional(tNumber),
+ ticksNumber: tOptional(tFloat),
ticksString: tOptional(tString),
});
scheme.BrowserContextClockFastForwardResult = tOptional(tObject({}));
scheme.BrowserContextClockInstallParams = tObject({
- timeNumber: tOptional(tNumber),
+ timeNumber: tOptional(tFloat),
timeString: tOptional(tString),
});
scheme.BrowserContextClockInstallResult = tOptional(tObject({}));
scheme.BrowserContextClockPauseAtParams = tObject({
- timeNumber: tOptional(tNumber),
+ timeNumber: tOptional(tFloat),
timeString: tOptional(tString),
});
scheme.BrowserContextClockPauseAtResult = tOptional(tObject({}));
scheme.BrowserContextClockResumeParams = tOptional(tObject({}));
scheme.BrowserContextClockResumeResult = tOptional(tObject({}));
scheme.BrowserContextClockRunForParams = tObject({
- ticksNumber: tOptional(tNumber),
+ ticksNumber: tOptional(tFloat),
ticksString: tOptional(tString),
});
scheme.BrowserContextClockRunForResult = tOptional(tObject({}));
scheme.BrowserContextClockSetFixedTimeParams = tObject({
- timeNumber: tOptional(tNumber),
+ timeNumber: tOptional(tFloat),
timeString: tOptional(tString),
});
scheme.BrowserContextClockSetFixedTimeResult = tOptional(tObject({}));
scheme.BrowserContextClockSetSystemTimeParams = tObject({
- timeNumber: tOptional(tNumber),
+ timeNumber: tOptional(tFloat),
timeString: tOptional(tString),
});
scheme.BrowserContextClockSetSystemTimeResult = tOptional(tObject({}));
@@ -1163,8 +1170,8 @@ scheme.BrowserContextClockUninstallResult = tOptional(tObject({}));
scheme.PageInitializer = tObject({
mainFrame: tChannel(['Frame']),
viewportSize: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
isClosed: tBoolean,
opener: tOptional(tChannel(['Page'])),
@@ -1181,8 +1188,8 @@ scheme.PageDownloadEvent = tObject({
});
scheme.PageViewportSizeChangedEvent = tObject({
viewportSize: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
});
scheme.PageFileChooserEvent = tObject({
@@ -1196,7 +1203,7 @@ scheme.PageFrameDetachedEvent = tObject({
frame: tChannel(['Frame']),
});
scheme.PageLocatorHandlerTriggeredEvent = tObject({
- uid: tNumber,
+ uid: tInt,
});
scheme.PageRouteEvent = tObject({
route: tChannel(['Route']),
@@ -1236,14 +1243,14 @@ scheme.PageExposeBindingParams = tObject({
});
scheme.PageExposeBindingResult = tOptional(tObject({}));
scheme.PageGoBackParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
waitUntil: tOptional(tType('LifecycleEvent')),
});
scheme.PageGoBackResult = tObject({
response: tOptional(tChannel(['Response'])),
});
scheme.PageGoForwardParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
waitUntil: tOptional(tType('LifecycleEvent')),
});
scheme.PageGoForwardResult = tObject({
@@ -1256,19 +1263,19 @@ scheme.PageRegisterLocatorHandlerParams = tObject({
noWaitAfter: tOptional(tBoolean),
});
scheme.PageRegisterLocatorHandlerResult = tObject({
- uid: tNumber,
+ uid: tInt,
});
scheme.PageResolveLocatorHandlerNoReplyParams = tObject({
- uid: tNumber,
+ uid: tInt,
remove: tOptional(tBoolean),
});
scheme.PageResolveLocatorHandlerNoReplyResult = tOptional(tObject({}));
scheme.PageUnregisterLocatorHandlerParams = tObject({
- uid: tNumber,
+ uid: tInt,
});
scheme.PageUnregisterLocatorHandlerResult = tOptional(tObject({}));
scheme.PageReloadParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
waitUntil: tOptional(tType('LifecycleEvent')),
});
scheme.PageReloadResult = tObject({
@@ -1276,16 +1283,16 @@ scheme.PageReloadResult = tObject({
});
scheme.PageExpectScreenshotParams = tObject({
expected: tOptional(tBinary),
- timeout: tNumber,
+ timeout: tFloat,
isNot: tBoolean,
locator: tOptional(tObject({
frame: tChannel(['Frame']),
selector: tString,
})),
comparator: tOptional(tString),
- maxDiffPixels: tOptional(tNumber),
- maxDiffPixelRatio: tOptional(tNumber),
- threshold: tOptional(tNumber),
+ maxDiffPixels: tOptional(tInt),
+ maxDiffPixelRatio: tOptional(tFloat),
+ threshold: tOptional(tFloat),
fullPage: tOptional(tBoolean),
clip: tOptional(tType('Rect')),
omitBackground: tOptional(tBoolean),
@@ -1308,9 +1315,9 @@ scheme.PageExpectScreenshotResult = tObject({
log: tOptional(tArray(tString)),
});
scheme.PageScreenshotParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
type: tOptional(tEnum(['png', 'jpeg'])),
- quality: tOptional(tNumber),
+ quality: tOptional(tInt),
fullPage: tOptional(tBoolean),
clip: tOptional(tType('Rect')),
omitBackground: tOptional(tBoolean),
@@ -1349,8 +1356,8 @@ scheme.PageSetWebSocketInterceptionPatternsParams = tObject({
scheme.PageSetWebSocketInterceptionPatternsResult = tOptional(tObject({}));
scheme.PageSetViewportSizeParams = tObject({
viewportSize: tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
}),
});
scheme.PageSetViewportSizeResult = tOptional(tObject({}));
@@ -1368,46 +1375,46 @@ scheme.PageKeyboardInsertTextParams = tObject({
scheme.PageKeyboardInsertTextResult = tOptional(tObject({}));
scheme.PageKeyboardTypeParams = tObject({
text: tString,
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
});
scheme.PageKeyboardTypeResult = tOptional(tObject({}));
scheme.PageKeyboardPressParams = tObject({
key: tString,
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
});
scheme.PageKeyboardPressResult = tOptional(tObject({}));
scheme.PageMouseMoveParams = tObject({
- x: tNumber,
- y: tNumber,
- steps: tOptional(tNumber),
+ x: tFloat,
+ y: tFloat,
+ steps: tOptional(tInt),
});
scheme.PageMouseMoveResult = tOptional(tObject({}));
scheme.PageMouseDownParams = tObject({
button: tOptional(tEnum(['left', 'right', 'middle'])),
- clickCount: tOptional(tNumber),
+ clickCount: tOptional(tInt),
});
scheme.PageMouseDownResult = tOptional(tObject({}));
scheme.PageMouseUpParams = tObject({
button: tOptional(tEnum(['left', 'right', 'middle'])),
- clickCount: tOptional(tNumber),
+ clickCount: tOptional(tInt),
});
scheme.PageMouseUpResult = tOptional(tObject({}));
scheme.PageMouseClickParams = tObject({
- x: tNumber,
- y: tNumber,
- delay: tOptional(tNumber),
+ x: tFloat,
+ y: tFloat,
+ delay: tOptional(tFloat),
button: tOptional(tEnum(['left', 'right', 'middle'])),
- clickCount: tOptional(tNumber),
+ clickCount: tOptional(tInt),
});
scheme.PageMouseClickResult = tOptional(tObject({}));
scheme.PageMouseWheelParams = tObject({
- deltaX: tNumber,
- deltaY: tNumber,
+ deltaX: tFloat,
+ deltaY: tFloat,
});
scheme.PageMouseWheelResult = tOptional(tObject({}));
scheme.PageTouchscreenTapParams = tObject({
- x: tNumber,
- y: tNumber,
+ x: tFloat,
+ y: tFloat,
});
scheme.PageTouchscreenTapResult = tOptional(tObject({}));
scheme.PageAccessibilitySnapshotParams = tObject({
@@ -1418,7 +1425,7 @@ scheme.PageAccessibilitySnapshotResult = tObject({
rootAXNode: tOptional(tType('AXNode')),
});
scheme.PagePdfParams = tObject({
- scale: tOptional(tNumber),
+ scale: tOptional(tFloat),
displayHeaderFooter: tOptional(tBoolean),
headerTemplate: tOptional(tString),
footerTemplate: tOptional(tString),
@@ -1442,7 +1449,7 @@ scheme.PagePdfResult = tObject({
pdf: tBinary,
});
scheme.PageSnapshotForAIParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.PageSnapshotForAIResult = tObject({
snapshot: tString,
@@ -1462,9 +1469,9 @@ scheme.PageStopJSCoverageResult = tObject({
functionName: tString,
isBlockCoverage: tBoolean,
ranges: tArray(tObject({
- startOffset: tNumber,
- endOffset: tNumber,
- count: tNumber,
+ startOffset: tInt,
+ endOffset: tInt,
+ count: tInt,
})),
})),
})),
@@ -1479,8 +1486,8 @@ scheme.PageStopCSSCoverageResult = tObject({
url: tString,
text: tOptional(tString),
ranges: tArray(tObject({
- start: tNumber,
- end: tNumber,
+ start: tInt,
+ end: tInt,
})),
})),
});
@@ -1545,7 +1552,7 @@ scheme.FrameAddStyleTagResult = tObject({
});
scheme.FrameAriaSnapshotParams = tObject({
selector: tString,
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameAriaSnapshotResult = tObject({
snapshot: tString,
@@ -1553,7 +1560,7 @@ scheme.FrameAriaSnapshotResult = tObject({
scheme.FrameBlurParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameBlurResult = tOptional(tObject({}));
scheme.FrameCheckParams = tObject({
@@ -1561,7 +1568,7 @@ scheme.FrameCheckParams = tObject({
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.FrameCheckResult = tOptional(tObject({}));
@@ -1572,10 +1579,10 @@ scheme.FrameClickParams = tObject({
noWaitAfter: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
button: tOptional(tEnum(['left', 'right', 'middle'])),
- clickCount: tOptional(tNumber),
- timeout: tNumber,
+ clickCount: tOptional(tInt),
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.FrameClickResult = tOptional(tObject({}));
@@ -1587,7 +1594,7 @@ scheme.FrameDragAndDropParams = tObject({
source: tString,
target: tString,
force: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
sourcePosition: tOptional(tType('Point')),
targetPosition: tOptional(tType('Point')),
@@ -1600,9 +1607,9 @@ scheme.FrameDblclickParams = tObject({
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
button: tOptional(tEnum(['left', 'right', 'middle'])),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.FrameDblclickResult = tOptional(tObject({}));
@@ -1611,7 +1618,7 @@ scheme.FrameDispatchEventParams = tObject({
strict: tOptional(tBoolean),
type: tString,
eventInit: tType('SerializedArgument'),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameDispatchEventResult = tOptional(tObject({}));
scheme.FrameEvaluateExpressionParams = tObject({
@@ -1635,13 +1642,13 @@ scheme.FrameFillParams = tObject({
strict: tOptional(tBoolean),
value: tString,
force: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameFillResult = tOptional(tObject({}));
scheme.FrameFocusParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameFocusResult = tOptional(tObject({}));
scheme.FrameFrameElementParams = tOptional(tObject({}));
@@ -1662,14 +1669,14 @@ scheme.FrameGetAttributeParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
name: tString,
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameGetAttributeResult = tObject({
value: tOptional(tString),
});
scheme.FrameGotoParams = tObject({
url: tString,
- timeout: tNumber,
+ timeout: tFloat,
waitUntil: tOptional(tType('LifecycleEvent')),
referer: tOptional(tString),
});
@@ -1682,14 +1689,14 @@ scheme.FrameHoverParams = tObject({
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.FrameHoverResult = tOptional(tObject({}));
scheme.FrameInnerHTMLParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameInnerHTMLResult = tObject({
value: tString,
@@ -1697,7 +1704,7 @@ scheme.FrameInnerHTMLResult = tObject({
scheme.FrameInnerTextParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameInnerTextResult = tObject({
value: tString,
@@ -1705,7 +1712,7 @@ scheme.FrameInnerTextResult = tObject({
scheme.FrameInputValueParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameInputValueResult = tObject({
value: tString,
@@ -1713,7 +1720,7 @@ scheme.FrameInputValueResult = tObject({
scheme.FrameIsCheckedParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameIsCheckedResult = tObject({
value: tBoolean,
@@ -1721,7 +1728,7 @@ scheme.FrameIsCheckedResult = tObject({
scheme.FrameIsDisabledParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameIsDisabledResult = tObject({
value: tBoolean,
@@ -1729,7 +1736,7 @@ scheme.FrameIsDisabledResult = tObject({
scheme.FrameIsEnabledParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameIsEnabledResult = tObject({
value: tBoolean,
@@ -1751,7 +1758,7 @@ scheme.FrameIsVisibleResult = tObject({
scheme.FrameIsEditableParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameIsEditableResult = tObject({
value: tBoolean,
@@ -1760,9 +1767,9 @@ scheme.FramePressParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
key: tString,
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
noWaitAfter: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FramePressResult = tOptional(tObject({}));
scheme.FrameQuerySelectorParams = tObject({
@@ -1782,7 +1789,7 @@ scheme.FrameQueryCountParams = tObject({
selector: tString,
});
scheme.FrameQueryCountResult = tObject({
- value: tNumber,
+ value: tInt,
});
scheme.FrameSelectOptionParams = tObject({
selector: tString,
@@ -1792,17 +1799,17 @@ scheme.FrameSelectOptionParams = tObject({
valueOrLabel: tOptional(tString),
value: tOptional(tString),
label: tOptional(tString),
- index: tOptional(tNumber),
+ index: tOptional(tInt),
}))),
force: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameSelectOptionResult = tObject({
values: tArray(tString),
});
scheme.FrameSetContentParams = tObject({
html: tString,
- timeout: tNumber,
+ timeout: tFloat,
waitUntil: tOptional(tType('LifecycleEvent')),
});
scheme.FrameSetContentResult = tOptional(tObject({}));
@@ -1818,7 +1825,7 @@ scheme.FrameSetInputFilesParams = tObject({
directoryStream: tOptional(tChannel(['WritableStream'])),
localPaths: tOptional(tArray(tString)),
streams: tOptional(tArray(tChannel(['WritableStream']))),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameSetInputFilesResult = tOptional(tObject({}));
scheme.FrameTapParams = tObject({
@@ -1827,14 +1834,14 @@ scheme.FrameTapParams = tObject({
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.FrameTapResult = tOptional(tObject({}));
scheme.FrameTextContentParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameTextContentResult = tObject({
value: tOptional(tString),
@@ -1847,8 +1854,8 @@ scheme.FrameTypeParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
text: tString,
- delay: tOptional(tNumber),
- timeout: tNumber,
+ delay: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.FrameTypeResult = tOptional(tObject({}));
scheme.FrameUncheckParams = tObject({
@@ -1856,20 +1863,20 @@ scheme.FrameUncheckParams = tObject({
strict: tOptional(tBoolean),
force: tOptional(tBoolean),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.FrameUncheckResult = tOptional(tObject({}));
scheme.FrameWaitForTimeoutParams = tObject({
- waitTimeout: tNumber,
+ waitTimeout: tFloat,
});
scheme.FrameWaitForTimeoutResult = tOptional(tObject({}));
scheme.FrameWaitForFunctionParams = tObject({
expression: tString,
isFunction: tOptional(tBoolean),
arg: tType('SerializedArgument'),
- timeout: tNumber,
- pollingInterval: tOptional(tNumber),
+ timeout: tFloat,
+ pollingInterval: tOptional(tFloat),
});
scheme.FrameWaitForFunctionResult = tObject({
handle: tChannel(['ElementHandle', 'JSHandle']),
@@ -1877,7 +1884,7 @@ scheme.FrameWaitForFunctionResult = tObject({
scheme.FrameWaitForSelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
omitReturnValue: tOptional(tBoolean),
});
@@ -1889,11 +1896,11 @@ scheme.FrameExpectParams = tObject({
expression: tString,
expressionArg: tOptional(tAny),
expectedText: tOptional(tArray(tType('ExpectedTextValue'))),
- expectedNumber: tOptional(tNumber),
+ expectedNumber: tOptional(tFloat),
expectedValue: tOptional(tType('SerializedArgument')),
useInnerText: tOptional(tBoolean),
isNot: tBoolean,
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.FrameExpectResult = tObject({
matches: tBoolean,
@@ -2004,7 +2011,7 @@ scheme.ElementHandleBoundingBoxResult = tObject({
scheme.ElementHandleCheckParams = tObject({
force: tOptional(tBoolean),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.ElementHandleCheckResult = tOptional(tObject({}));
@@ -2013,10 +2020,10 @@ scheme.ElementHandleClickParams = tObject({
noWaitAfter: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
button: tOptional(tEnum(['left', 'right', 'middle'])),
- clickCount: tOptional(tNumber),
- timeout: tNumber,
+ clickCount: tOptional(tInt),
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.ElementHandleClickResult = tOptional(tObject({}));
@@ -2028,9 +2035,9 @@ scheme.ElementHandleDblclickParams = tObject({
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- delay: tOptional(tNumber),
+ delay: tOptional(tFloat),
button: tOptional(tEnum(['left', 'right', 'middle'])),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.ElementHandleDblclickResult = tOptional(tObject({}));
@@ -2042,7 +2049,7 @@ scheme.ElementHandleDispatchEventResult = tOptional(tObject({}));
scheme.ElementHandleFillParams = tObject({
value: tString,
force: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.ElementHandleFillResult = tOptional(tObject({}));
scheme.ElementHandleFocusParams = tOptional(tObject({}));
@@ -2057,7 +2064,7 @@ scheme.ElementHandleHoverParams = tObject({
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.ElementHandleHoverResult = tOptional(tObject({}));
@@ -2103,8 +2110,8 @@ scheme.ElementHandleOwnerFrameResult = tObject({
});
scheme.ElementHandlePressParams = tObject({
key: tString,
- delay: tOptional(tNumber),
- timeout: tNumber,
+ delay: tOptional(tFloat),
+ timeout: tFloat,
noWaitAfter: tOptional(tBoolean),
});
scheme.ElementHandlePressResult = tOptional(tObject({}));
@@ -2122,9 +2129,9 @@ scheme.ElementHandleQuerySelectorAllResult = tObject({
elements: tArray(tChannel(['ElementHandle'])),
});
scheme.ElementHandleScreenshotParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
type: tOptional(tEnum(['png', 'jpeg'])),
- quality: tOptional(tNumber),
+ quality: tOptional(tInt),
omitBackground: tOptional(tBoolean),
caret: tOptional(tEnum(['hide', 'initial'])),
animations: tOptional(tEnum(['disabled', 'allow'])),
@@ -2140,7 +2147,7 @@ scheme.ElementHandleScreenshotResult = tObject({
binary: tBinary,
});
scheme.ElementHandleScrollIntoViewIfNeededParams = tObject({
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.ElementHandleScrollIntoViewIfNeededResult = tOptional(tObject({}));
scheme.ElementHandleSelectOptionParams = tObject({
@@ -2149,17 +2156,17 @@ scheme.ElementHandleSelectOptionParams = tObject({
valueOrLabel: tOptional(tString),
value: tOptional(tString),
label: tOptional(tString),
- index: tOptional(tNumber),
+ index: tOptional(tInt),
}))),
force: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.ElementHandleSelectOptionResult = tObject({
values: tArray(tString),
});
scheme.ElementHandleSelectTextParams = tObject({
force: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.ElementHandleSelectTextResult = tOptional(tObject({}));
scheme.ElementHandleSetInputFilesParams = tObject({
@@ -2172,14 +2179,14 @@ scheme.ElementHandleSetInputFilesParams = tObject({
directoryStream: tOptional(tChannel(['WritableStream'])),
localPaths: tOptional(tArray(tString)),
streams: tOptional(tArray(tChannel(['WritableStream']))),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.ElementHandleSetInputFilesResult = tOptional(tObject({}));
scheme.ElementHandleTapParams = tObject({
force: tOptional(tBoolean),
modifiers: tOptional(tArray(tEnum(['Alt', 'Control', 'ControlOrMeta', 'Meta', 'Shift']))),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.ElementHandleTapResult = tOptional(tObject({}));
@@ -2189,26 +2196,26 @@ scheme.ElementHandleTextContentResult = tObject({
});
scheme.ElementHandleTypeParams = tObject({
text: tString,
- delay: tOptional(tNumber),
- timeout: tNumber,
+ delay: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.ElementHandleTypeResult = tOptional(tObject({}));
scheme.ElementHandleUncheckParams = tObject({
force: tOptional(tBoolean),
position: tOptional(tType('Point')),
- timeout: tNumber,
+ timeout: tFloat,
trial: tOptional(tBoolean),
});
scheme.ElementHandleUncheckResult = tOptional(tObject({}));
scheme.ElementHandleWaitForElementStateParams = tObject({
state: tEnum(['visible', 'hidden', 'stable', 'enabled', 'disabled', 'editable']),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.ElementHandleWaitForElementStateResult = tOptional(tObject({}));
scheme.ElementHandleWaitForSelectorParams = tObject({
selector: tString,
strict: tOptional(tBoolean),
- timeout: tNumber,
+ timeout: tFloat,
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
});
scheme.ElementHandleWaitForSelectorResult = tObject({
@@ -2253,7 +2260,7 @@ scheme.RouteContinueParams = tObject({
});
scheme.RouteContinueResult = tOptional(tObject({}));
scheme.RouteFulfillParams = tObject({
- status: tOptional(tNumber),
+ status: tOptional(tInt),
headers: tOptional(tArray(tType('NameValue'))),
body: tOptional(tString),
isBase64: tOptional(tBoolean),
@@ -2272,12 +2279,12 @@ scheme.WebSocketRouteMessageFromServerEvent = tObject({
isBase64: tBoolean,
});
scheme.WebSocketRouteClosePageEvent = tObject({
- code: tOptional(tNumber),
+ code: tOptional(tInt),
reason: tOptional(tString),
wasClean: tBoolean,
});
scheme.WebSocketRouteCloseServerEvent = tObject({
- code: tOptional(tNumber),
+ code: tOptional(tInt),
reason: tOptional(tString),
wasClean: tBoolean,
});
@@ -2296,31 +2303,31 @@ scheme.WebSocketRouteSendToServerParams = tObject({
});
scheme.WebSocketRouteSendToServerResult = tOptional(tObject({}));
scheme.WebSocketRouteClosePageParams = tObject({
- code: tOptional(tNumber),
+ code: tOptional(tInt),
reason: tOptional(tString),
wasClean: tBoolean,
});
scheme.WebSocketRouteClosePageResult = tOptional(tObject({}));
scheme.WebSocketRouteCloseServerParams = tObject({
- code: tOptional(tNumber),
+ code: tOptional(tInt),
reason: tOptional(tString),
wasClean: tBoolean,
});
scheme.WebSocketRouteCloseServerResult = tOptional(tObject({}));
scheme.ResourceTiming = tObject({
- startTime: tNumber,
- domainLookupStart: tNumber,
- domainLookupEnd: tNumber,
- connectStart: tNumber,
- secureConnectionStart: tNumber,
- connectEnd: tNumber,
- requestStart: tNumber,
- responseStart: tNumber,
+ startTime: tFloat,
+ domainLookupStart: tFloat,
+ domainLookupEnd: tFloat,
+ connectStart: tFloat,
+ secureConnectionStart: tFloat,
+ connectEnd: tFloat,
+ requestStart: tFloat,
+ responseStart: tFloat,
});
scheme.ResponseInitializer = tObject({
request: tChannel(['Request']),
url: tString,
- status: tNumber,
+ status: tInt,
statusText: tString,
headers: tArray(tType('NameValue')),
timing: tType('ResourceTiming'),
@@ -2350,29 +2357,29 @@ scheme.SecurityDetails = tObject({
issuer: tOptional(tString),
protocol: tOptional(tString),
subjectName: tOptional(tString),
- validFrom: tOptional(tNumber),
- validTo: tOptional(tNumber),
+ validFrom: tOptional(tFloat),
+ validTo: tOptional(tFloat),
});
scheme.RequestSizes = tObject({
- requestBodySize: tNumber,
- requestHeadersSize: tNumber,
- responseBodySize: tNumber,
- responseHeadersSize: tNumber,
+ requestBodySize: tInt,
+ requestHeadersSize: tInt,
+ responseBodySize: tInt,
+ responseHeadersSize: tInt,
});
scheme.RemoteAddr = tObject({
ipAddress: tString,
- port: tNumber,
+ port: tInt,
});
scheme.WebSocketInitializer = tObject({
url: tString,
});
scheme.WebSocketOpenEvent = tOptional(tObject({}));
scheme.WebSocketFrameSentEvent = tObject({
- opcode: tNumber,
+ opcode: tInt,
data: tString,
});
scheme.WebSocketFrameReceivedEvent = tObject({
- opcode: tNumber,
+ opcode: tInt,
data: tString,
});
scheme.WebSocketSocketErrorEvent = tObject({
@@ -2424,8 +2431,8 @@ scheme.TracingTracingGroupParams = tObject({
name: tString,
location: tOptional(tObject({
file: tString,
- line: tOptional(tNumber),
- column: tOptional(tNumber),
+ line: tOptional(tInt),
+ column: tOptional(tInt),
})),
});
scheme.TracingTracingGroupResult = tOptional(tObject({}));
@@ -2469,7 +2476,7 @@ scheme.ArtifactDeleteParams = tOptional(tObject({}));
scheme.ArtifactDeleteResult = tOptional(tObject({}));
scheme.StreamInitializer = tOptional(tObject({}));
scheme.StreamReadParams = tObject({
- size: tOptional(tNumber),
+ size: tOptional(tInt),
});
scheme.StreamReadResult = tObject({
binary: tBinary,
@@ -2503,15 +2510,15 @@ scheme.ElectronLaunchParams = tObject({
args: tOptional(tArray(tString)),
cwd: tOptional(tString),
env: tOptional(tArray(tType('NameValue'))),
- timeout: tNumber,
+ timeout: tFloat,
acceptDownloads: tOptional(tEnum(['accept', 'deny', 'internal-browser-default'])),
bypassCSP: tOptional(tBoolean),
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
httpCredentials: tOptional(tObject({
username: tString,
@@ -2524,8 +2531,8 @@ scheme.ElectronLaunchParams = tObject({
recordVideo: tOptional(tObject({
dir: tString,
size: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
})),
strictSelectors: tOptional(tBoolean),
@@ -2547,8 +2554,8 @@ scheme.ElectronApplicationConsoleEvent = tObject({
args: tArray(tChannel(['ElementHandle', 'JSHandle'])),
location: tObject({
url: tString,
- lineNumber: tNumber,
- columnNumber: tNumber,
+ lineNumber: tInt,
+ columnNumber: tInt,
}),
});
scheme.ElectronApplicationBrowserWindowParams = tObject({
@@ -2581,7 +2588,7 @@ scheme.ElectronApplicationUpdateSubscriptionResult = tOptional(tObject({}));
scheme.AndroidInitializer = tOptional(tObject({}));
scheme.AndroidDevicesParams = tObject({
host: tOptional(tString),
- port: tOptional(tNumber),
+ port: tOptional(tInt),
omitDriverInstall: tOptional(tBoolean),
});
scheme.AndroidDevicesResult = tObject({
@@ -2612,68 +2619,68 @@ scheme.AndroidDeviceWebViewRemovedEvent = tObject({
scheme.AndroidDeviceWaitParams = tObject({
androidSelector: tType('AndroidSelector'),
state: tOptional(tEnum(['gone'])),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.AndroidDeviceWaitResult = tOptional(tObject({}));
scheme.AndroidDeviceFillParams = tObject({
androidSelector: tType('AndroidSelector'),
text: tString,
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.AndroidDeviceFillResult = tOptional(tObject({}));
scheme.AndroidDeviceTapParams = tObject({
androidSelector: tType('AndroidSelector'),
- duration: tOptional(tNumber),
- timeout: tNumber,
+ duration: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDeviceTapResult = tOptional(tObject({}));
scheme.AndroidDeviceDragParams = tObject({
androidSelector: tType('AndroidSelector'),
dest: tType('Point'),
- speed: tOptional(tNumber),
- timeout: tNumber,
+ speed: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDeviceDragResult = tOptional(tObject({}));
scheme.AndroidDeviceFlingParams = tObject({
androidSelector: tType('AndroidSelector'),
direction: tEnum(['up', 'down', 'left', 'right']),
- speed: tOptional(tNumber),
- timeout: tNumber,
+ speed: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDeviceFlingResult = tOptional(tObject({}));
scheme.AndroidDeviceLongTapParams = tObject({
androidSelector: tType('AndroidSelector'),
- timeout: tNumber,
+ timeout: tFloat,
});
scheme.AndroidDeviceLongTapResult = tOptional(tObject({}));
scheme.AndroidDevicePinchCloseParams = tObject({
androidSelector: tType('AndroidSelector'),
- percent: tNumber,
- speed: tOptional(tNumber),
- timeout: tNumber,
+ percent: tFloat,
+ speed: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDevicePinchCloseResult = tOptional(tObject({}));
scheme.AndroidDevicePinchOpenParams = tObject({
androidSelector: tType('AndroidSelector'),
- percent: tNumber,
- speed: tOptional(tNumber),
- timeout: tNumber,
+ percent: tFloat,
+ speed: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDevicePinchOpenResult = tOptional(tObject({}));
scheme.AndroidDeviceScrollParams = tObject({
androidSelector: tType('AndroidSelector'),
direction: tEnum(['up', 'down', 'left', 'right']),
- percent: tNumber,
- speed: tOptional(tNumber),
- timeout: tNumber,
+ percent: tFloat,
+ speed: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDeviceScrollResult = tOptional(tObject({}));
scheme.AndroidDeviceSwipeParams = tObject({
androidSelector: tType('AndroidSelector'),
direction: tEnum(['up', 'down', 'left', 'right']),
- percent: tNumber,
- speed: tOptional(tNumber),
- timeout: tNumber,
+ percent: tFloat,
+ speed: tOptional(tFloat),
+ timeout: tFloat,
});
scheme.AndroidDeviceSwipeResult = tOptional(tObject({}));
scheme.AndroidDeviceInfoParams = tObject({
@@ -2700,24 +2707,24 @@ scheme.AndroidDeviceInputTapParams = tObject({
scheme.AndroidDeviceInputTapResult = tOptional(tObject({}));
scheme.AndroidDeviceInputSwipeParams = tObject({
segments: tArray(tType('Point')),
- steps: tNumber,
+ steps: tInt,
});
scheme.AndroidDeviceInputSwipeResult = tOptional(tObject({}));
scheme.AndroidDeviceInputDragParams = tObject({
from: tType('Point'),
to: tType('Point'),
- steps: tNumber,
+ steps: tInt,
});
scheme.AndroidDeviceInputDragResult = tOptional(tObject({}));
scheme.AndroidDeviceLaunchBrowserParams = tObject({
noDefaultViewport: tOptional(tBoolean),
viewport: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
screen: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
ignoreHTTPSErrors: tOptional(tBoolean),
clientCertificates: tOptional(tArray(tObject({
@@ -2733,9 +2740,9 @@ scheme.AndroidDeviceLaunchBrowserParams = tObject({
locale: tOptional(tString),
timezoneId: tOptional(tString),
geolocation: tOptional(tObject({
- longitude: tNumber,
- latitude: tNumber,
- accuracy: tOptional(tNumber),
+ longitude: tFloat,
+ latitude: tFloat,
+ accuracy: tOptional(tFloat),
})),
permissions: tOptional(tArray(tString)),
extraHTTPHeaders: tOptional(tArray(tType('NameValue'))),
@@ -2746,7 +2753,7 @@ scheme.AndroidDeviceLaunchBrowserParams = tObject({
origin: tOptional(tString),
send: tOptional(tEnum(['always', 'unauthorized'])),
})),
- deviceScaleFactor: tOptional(tNumber),
+ deviceScaleFactor: tOptional(tFloat),
isMobile: tOptional(tBoolean),
hasTouch: tOptional(tBoolean),
colorScheme: tOptional(tEnum(['dark', 'light', 'no-preference', 'no-override'])),
@@ -2758,8 +2765,8 @@ scheme.AndroidDeviceLaunchBrowserParams = tObject({
recordVideo: tOptional(tObject({
dir: tString,
size: tOptional(tObject({
- width: tNumber,
- height: tNumber,
+ width: tInt,
+ height: tInt,
})),
})),
strictSelectors: tOptional(tBoolean),
@@ -2798,7 +2805,7 @@ scheme.AndroidDeviceInstallApkResult = tOptional(tObject({}));
scheme.AndroidDevicePushParams = tObject({
file: tBinary,
path: tString,
- mode: tOptional(tNumber),
+ mode: tOptional(tInt),
});
scheme.AndroidDevicePushResult = tOptional(tObject({}));
scheme.AndroidDeviceConnectToWebViewParams = tObject({
@@ -2810,7 +2817,7 @@ scheme.AndroidDeviceConnectToWebViewResult = tObject({
scheme.AndroidDeviceCloseParams = tOptional(tObject({}));
scheme.AndroidDeviceCloseResult = tOptional(tObject({}));
scheme.AndroidWebView = tObject({
- pid: tNumber,
+ pid: tInt,
pkg: tString,
socketName: tString,
});
@@ -2819,7 +2826,7 @@ scheme.AndroidSelector = tObject({
checked: tOptional(tBoolean),
clazz: tOptional(tString),
clickable: tOptional(tBoolean),
- depth: tOptional(tNumber),
+ depth: tOptional(tInt),
desc: tOptional(tString),
enabled: tOptional(tBoolean),
focusable: tOptional(tBoolean),
@@ -2829,7 +2836,7 @@ scheme.AndroidSelector = tObject({
})),
hasDescendant: tOptional(tObject({
androidSelector: tType('AndroidSelector'),
- maxDepth: tOptional(tNumber),
+ maxDepth: tOptional(tInt),
})),
longClickable: tOptional(tBoolean),
pkg: tOptional(tString),
diff --git a/packages/playwright-core/src/protocol/validatorPrimitives.ts b/packages/playwright-core/src/protocol/validatorPrimitives.ts
index eadd2e014e67d..3c96c0748f8de 100644
--- a/packages/playwright-core/src/protocol/validatorPrimitives.ts
+++ b/packages/playwright-core/src/protocol/validatorPrimitives.ts
@@ -37,12 +37,24 @@ export function createMetadataValidator(): Validator {
return tOptional(scheme['Metadata']);
}
-export const tNumber: Validator = (arg: any, path: string, context: ValidatorContext) => {
+export const tFloat: Validator = (arg: any, path: string, context: ValidatorContext) => {
if (arg instanceof Number)
return arg.valueOf();
if (typeof arg === 'number')
return arg;
- throw new ValidationError(`${path}: expected number, got ${typeof arg}`);
+ throw new ValidationError(`${path}: expected float, got ${typeof arg}`);
+};
+export const tInt: Validator = (arg: any, path: string, context: ValidatorContext) => {
+ let value: number;
+ if (arg instanceof Number)
+ value = arg.valueOf();
+ else if (typeof arg === 'number')
+ value = arg;
+ else
+ throw new ValidationError(`${path}: expected integer, got ${typeof arg}`);
+ if (!Number.isInteger(value))
+ throw new ValidationError(`${path}: expected integer, got float ${value}`);
+ return value;
};
export const tBoolean: Validator = (arg: any, path: string, context: ValidatorContext) => {
if (arg instanceof Boolean)
diff --git a/packages/playwright-core/src/server/bidi/bidiBrowser.ts b/packages/playwright-core/src/server/bidi/bidiBrowser.ts
index 5235b74a88dc8..76847bd5d36f1 100644
--- a/packages/playwright-core/src/server/bidi/bidiBrowser.ts
+++ b/packages/playwright-core/src/server/bidi/bidiBrowser.ts
@@ -199,6 +199,12 @@ export class BidiBrowserContext extends BrowserContext {
promises.push(this.doUpdateDefaultViewport());
if (this._options.geolocation)
promises.push(this.setGeolocation(this._options.geolocation));
+ if (this._options.locale) {
+ promises.push(this._browser._browserSession.send('emulation.setLocaleOverride', {
+ locale: this._options.locale,
+ userContexts: [this._userContextId()],
+ }));
+ }
await Promise.all(promises);
}
@@ -295,7 +301,7 @@ export class BidiBrowserContext extends BrowserContext {
},
state,
origin,
- userContext: this._browserContextId || 'default',
+ userContext: this._userContextId(),
});
}
@@ -310,7 +316,7 @@ export class BidiBrowserContext extends BrowserContext {
longitude: geolocation.longitude,
accuracy: geolocation.accuracy,
} : null,
- userContexts: [this._browserContextId || 'default'],
+ userContexts: [this._userContextId()],
});
}
@@ -333,7 +339,7 @@ export class BidiBrowserContext extends BrowserContext {
const { script } = await this._browser._browserSession.send('script.addPreloadScript', {
// TODO: remove function call from the source.
functionDeclaration: `() => { return ${initScript.source} }`,
- userContexts: [this._browserContextId || 'default'],
+ userContexts: [this._userContextId()],
});
this._initScriptIds.set(initScript, script);
}
diff --git a/packages/playwright-core/src/server/bidi/bidiNetworkManager.ts b/packages/playwright-core/src/server/bidi/bidiNetworkManager.ts
index 8456787030898..f4e4a801d6428 100644
--- a/packages/playwright-core/src/server/bidi/bidiNetworkManager.ts
+++ b/packages/playwright-core/src/server/bidi/bidiNetworkManager.ts
@@ -31,17 +31,15 @@ export class BidiNetworkManager {
private readonly _requests: Map;
private readonly _page: Page;
private readonly _eventListeners: RegisteredListener[];
- private readonly _onNavigationResponseStarted: (params: bidi.Network.ResponseStartedParameters) => void;
private _userRequestInterceptionEnabled: boolean = false;
private _protocolRequestInterceptionEnabled: boolean = false;
private _credentials: types.Credentials | undefined;
private _intercepId: bidi.Network.Intercept | undefined;
- constructor(bidiSession: BidiSession, page: Page, onNavigationResponseStarted: (params: bidi.Network.ResponseStartedParameters) => void) {
+ constructor(bidiSession: BidiSession, page: Page) {
this._session = bidiSession;
this._requests = new Map();
this._page = page;
- this._onNavigationResponseStarted = onNavigationResponseStarted;
this._eventListeners = [
eventsHelper.addEventListener(bidiSession, 'network.beforeRequestSent', this._onBeforeRequestSent.bind(this)),
eventsHelper.addEventListener(bidiSession, 'network.responseStarted', this._onResponseStarted.bind(this)),
@@ -116,8 +114,6 @@ export class BidiNetworkManager {
response.setRawResponseHeaders(null);
response.setResponseHeadersSize(params.response.headersSize);
this._page.frameManager.requestReceivedResponse(response);
- if (params.navigation)
- this._onNavigationResponseStarted(params);
}
private _onResponseCompleted(params: bidi.Network.ResponseCompletedParameters) {
diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts
index f1cdc14dfe256..97d07698f1dd5 100644
--- a/packages/playwright-core/src/server/bidi/bidiPage.ts
+++ b/packages/playwright-core/src/server/bidi/bidiPage.ts
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import { assert } from '../../utils';
import { eventsHelper } from '../utils/eventsHelper';
import * as dialog from '../dialog';
import * as dom from '../dom';
@@ -61,7 +60,7 @@ export class BidiPage implements PageDelegate {
this._realmToContext = new Map();
this._page = new Page(this, browserContext);
this._browserContext = browserContext;
- this._networkManager = new BidiNetworkManager(this._session, this._page, this._onNavigationResponseStarted.bind(this));
+ this._networkManager = new BidiNetworkManager(this._session, this._page);
this._pdf = new BidiPDF(this._session);
this._page.on(Page.Events.FrameDetached, (frame: frames.Frame) => this._removeContextsForFrame(frame, false));
this._sessionListeners = [
@@ -69,6 +68,7 @@ export class BidiPage implements PageDelegate {
eventsHelper.addEventListener(bidiSession, 'script.message', this._onScriptMessage.bind(this)),
eventsHelper.addEventListener(bidiSession, 'browsingContext.contextDestroyed', this._onBrowsingContextDestroyed.bind(this)),
eventsHelper.addEventListener(bidiSession, 'browsingContext.navigationStarted', this._onNavigationStarted.bind(this)),
+ eventsHelper.addEventListener(bidiSession, 'browsingContext.navigationCommitted', this._onNavigationCommitted.bind(this)),
eventsHelper.addEventListener(bidiSession, 'browsingContext.navigationAborted', this._onNavigationAborted.bind(this)),
eventsHelper.addEventListener(bidiSession, 'browsingContext.navigationFailed', this._onNavigationFailed.bind(this)),
eventsHelper.addEventListener(bidiSession, 'browsingContext.fragmentNavigated', this._onFragmentNavigated.bind(this)),
@@ -178,25 +178,11 @@ export class BidiPage implements PageDelegate {
private _onNavigationStarted(params: bidi.BrowsingContext.NavigationInfo) {
const frameId = params.context;
this._page.frameManager.frameRequestedNavigation(frameId, params.navigation!);
-
- const url = params.url.toLowerCase();
- if (url.startsWith('file:') || url.startsWith('data:') || url === 'about:blank') {
- // Navigation to file urls doesn't emit network events, so we fire 'commit' event right when navigation is started.
- // Doing it in domcontentload would be too late as we'd clear frame tree.
- const frame = this._page.frameManager.frame(frameId)!;
- if (frame)
- this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.url, '', params.navigation!, /* initial */ false);
- }
}
- // TODO: there is no separate event for committed navigation, so we approximate it with responseStarted.
- private _onNavigationResponseStarted(params: bidi.Network.ResponseStartedParameters) {
- const frameId = params.context!;
- const frame = this._page.frameManager.frame(frameId);
- assert(frame);
- this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.response.url, '', params.navigation!, /* initial */ false);
- // if (!initial)
- // this._firstNonInitialNavigationCommittedFulfill();
+ private _onNavigationCommitted(params: bidi.BrowsingContext.NavigationInfo) {
+ const frameId = params.context;
+ this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.url, '', params.navigation!, /* initial */ false);
}
private _onDomContentLoaded(params: bidi.BrowsingContext.NavigationInfo) {
diff --git a/packages/playwright-core/src/server/bidi/third_party/bidiCommands.d.ts b/packages/playwright-core/src/server/bidi/third_party/bidiCommands.d.ts
index 5463cbaf7791b..5be629678aeaf 100644
--- a/packages/playwright-core/src/server/bidi/third_party/bidiCommands.d.ts
+++ b/packages/playwright-core/src/server/bidi/third_party/bidiCommands.d.ts
@@ -118,6 +118,11 @@ export interface Commands {
returnType: Bidi.EmptyResult;
};
+ 'emulation.setLocaleOverride': {
+ params: Bidi.Emulation.SetLocaleOverrideParameters;
+ returnType: Bidi.EmptyResult;
+ };
+
'permissions.setPermission': {
params: Bidi.Permissions.SetPermissionParameters;
returnType: Bidi.EmptyResult;
diff --git a/packages/playwright-core/src/server/bidi/third_party/bidiProtocolCore.ts b/packages/playwright-core/src/server/bidi/third_party/bidiProtocolCore.ts
index 81e9e8b713009..5d9bedd66261e 100644
--- a/packages/playwright-core/src/server/bidi/third_party/bidiProtocolCore.ts
+++ b/packages/playwright-core/src/server/bidi/third_party/bidiProtocolCore.ts
@@ -1,8 +1,18 @@
/**
- * @license
- * Copyright 2024 Google Inc.
- * Modifications copyright (c) Microsoft Corporation.
- * SPDX-License-Identifier: Apache-2.0
+ * Copyright 2024 Google LLC.
+ * 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.
*/
// Copied from upstream: https://github.com/GoogleChromeLabs/chromium-bidi/blob/main/src/protocol/generated/webdriver-bidi.ts
@@ -80,11 +90,13 @@ export const enum ErrorCode {
InvalidWebExtension = 'invalid web extension',
MoveTargetOutOfBounds = 'move target out of bounds',
NoSuchAlert = 'no such alert',
+ NoSuchNetworkCollector = 'no such network collector',
NoSuchElement = 'no such element',
NoSuchFrame = 'no such frame',
NoSuchHandle = 'no such handle',
NoSuchHistoryEntry = 'no such history entry',
NoSuchIntercept = 'no such intercept',
+ NoSuchNetworkData = 'no such network data',
NoSuchNode = 'no such node',
NoSuchRequest = 'no such request',
NoSuchScript = 'no such script',
@@ -96,6 +108,7 @@ export const enum ErrorCode {
UnableToCloseBrowser = 'unable to close browser',
UnableToSetCookie = 'unable to set cookie',
UnableToSetFileInput = 'unable to set file input',
+ UnavailableNetworkData = 'unavailable network data',
UnderspecifiedStoragePartition = 'underspecified storage partition',
UnknownCommand = 'unknown command',
UnknownError = 'unknown error',
@@ -148,7 +161,6 @@ export namespace Session {
export namespace Session {
export type ManualProxyConfiguration = {
proxyType: 'manual';
- ftpProxy?: string;
httpProxy?: string;
sslProxy?: string;
} & ({} | Session.SocksProxyConfiguration) & {
@@ -334,6 +346,7 @@ export namespace Browser {
export type CreateUserContextParameters = {
acceptInsecureCerts?: boolean;
proxy?: Session.ProxyConfiguration;
+ unhandledPromptBehavior?: Session.UserPromptHandler;
};
}
export namespace Browser {
@@ -414,6 +427,7 @@ export type BrowsingContextEvent =
| BrowsingContext.ContextCreated
| BrowsingContext.ContextDestroyed
| BrowsingContext.DomContentLoaded
+ | BrowsingContext.DownloadEnd
| BrowsingContext.DownloadWillBegin
| BrowsingContext.FragmentNavigated
| BrowsingContext.HistoryUpdated
@@ -866,6 +880,7 @@ export namespace BrowsingContext {
export namespace BrowsingContext {
export type HistoryUpdatedParameters = {
context: BrowsingContext.BrowsingContext;
+ timestamp: JsUint;
url: string;
};
}
@@ -892,6 +907,28 @@ export namespace BrowsingContext {
suggestedFilename: string;
} & BrowsingContext.BaseNavigationInfo;
}
+export namespace BrowsingContext {
+ export type DownloadEnd = {
+ method: 'browsingContext.downloadEnd';
+ params: BrowsingContext.DownloadEndParams;
+ };
+}
+export namespace BrowsingContext {
+ export type DownloadEndParams =
+ | BrowsingContext.DownloadCanceledParams
+ | BrowsingContext.DownloadCompleteParams;
+}
+export namespace BrowsingContext {
+ export type DownloadCanceledParams = {
+ status: 'canceled';
+ } & BrowsingContext.BaseNavigationInfo;
+}
+export namespace BrowsingContext {
+ export type DownloadCompleteParams = {
+ status: 'complete';
+ filepath: string | null;
+ } & BrowsingContext.BaseNavigationInfo;
+}
export namespace BrowsingContext {
export type NavigationAborted = {
method: 'browsingContext.navigationAborted';
@@ -939,7 +976,34 @@ export namespace BrowsingContext {
defaultValue?: string;
};
}
-export type EmulationCommand = Emulation.SetGeolocationOverride;
+export type EmulationCommand =
+ | Emulation.SetForcedColorsModeThemeOverride
+ | Emulation.SetGeolocationOverride
+ | Emulation.SetLocaleOverride
+ | Emulation.SetScreenOrientationOverride
+ | Emulation.SetTimezoneOverride;
+export namespace Emulation {
+ export type SetForcedColorsModeThemeOverride = {
+ method: 'emulation.setForcedColorsModeThemeOverride';
+ params: Emulation.SetForcedColorsModeThemeOverrideParameters;
+ };
+}
+export namespace Emulation {
+ export type SetForcedColorsModeThemeOverrideParameters = {
+ theme: Emulation.ForcedColorsModeTheme | null;
+ contexts?: [
+ BrowsingContext.BrowsingContext,
+ ...BrowsingContext.BrowsingContext[],
+ ];
+ userContexts?: [Browser.UserContext, ...Browser.UserContext[]];
+ };
+}
+export namespace Emulation {
+ export const enum ForcedColorsModeTheme {
+ Light = 'light',
+ Dark = 'dark',
+ }
+}
export namespace Emulation {
export type SetGeolocationOverride = {
method: 'emulation.setGeolocationOverride';
@@ -1007,15 +1071,87 @@ export namespace Emulation {
type: 'positionUnavailable';
};
}
+export namespace Emulation {
+ export type SetLocaleOverride = {
+ method: 'emulation.setLocaleOverride';
+ params: Emulation.SetLocaleOverrideParameters;
+ };
+}
+export namespace Emulation {
+ export type SetLocaleOverrideParameters = {
+ locale: string | null;
+ contexts?: [
+ BrowsingContext.BrowsingContext,
+ ...BrowsingContext.BrowsingContext[],
+ ];
+ userContexts?: [Browser.UserContext, ...Browser.UserContext[]];
+ };
+}
+export namespace Emulation {
+ export type SetScreenOrientationOverride = {
+ method: 'emulation.setScreenOrientationOverride';
+ params: Emulation.SetScreenOrientationOverrideParameters;
+ };
+}
+export namespace Emulation {
+ export const enum ScreenOrientationNatural {
+ Portrait = 'portrait',
+ Landscape = 'landscape',
+ }
+}
+export namespace Emulation {
+ export type ScreenOrientationType =
+ | 'portrait-primary'
+ | 'portrait-secondary'
+ | 'landscape-primary'
+ | 'landscape-secondary';
+}
+export namespace Emulation {
+ export type ScreenOrientation = {
+ natural: Emulation.ScreenOrientationNatural;
+ type: Emulation.ScreenOrientationType;
+ };
+}
+export namespace Emulation {
+ export type SetScreenOrientationOverrideParameters = {
+ screenOrientation: Emulation.ScreenOrientation | null;
+ contexts?: [
+ BrowsingContext.BrowsingContext,
+ ...BrowsingContext.BrowsingContext[],
+ ];
+ userContexts?: [Browser.UserContext, ...Browser.UserContext[]];
+ };
+}
+export namespace Emulation {
+ export type SetTimezoneOverride = {
+ method: 'emulation.setTimezoneOverride';
+ params: Emulation.SetTimezoneOverrideParameters;
+ };
+}
+export namespace Emulation {
+ export type SetTimezoneOverrideParameters = {
+ timezone: string | null;
+ contexts?: [
+ BrowsingContext.BrowsingContext,
+ ...BrowsingContext.BrowsingContext[],
+ ];
+ userContexts?: [Browser.UserContext, ...Browser.UserContext[]];
+ };
+}
export type NetworkCommand =
+ | Network.AddDataCollector
| Network.AddIntercept
| Network.ContinueRequest
| Network.ContinueResponse
| Network.ContinueWithAuth
+ | Network.DisownData
| Network.FailRequest
+ | Network.GetData
| Network.ProvideResponse
+ | Network.RemoveDataCollector
| Network.RemoveIntercept
- | Network.SetCacheBehavior;
+ | Network.SetCacheBehavior
+ | Network.SetExtraHeaders;
export type NetworkEvent =
| Network.AuthRequired
| Network.BeforeRequestSent
@@ -1062,11 +1198,20 @@ export namespace Network {
value: string;
};
}
+export namespace Network {
+ export type Collector = string;
+}
+export namespace Network {
+ export const enum CollectorType {
+ Blob = 'blob',
+ }
+}
export namespace Network {
export const enum SameSite {
Strict = 'strict',
Lax = 'lax',
None = 'none',
+ Default = 'default',
}
}
export namespace Network {
@@ -1088,6 +1233,11 @@ export namespace Network {
value: Network.BytesValue;
};
}
+export namespace Network {
+ export const enum DataType {
+ Response = 'response',
+ }
+}
export namespace Network {
export type FetchTimingInfo = {
timeOrigin: number;
@@ -1193,6 +1343,32 @@ export namespace Network {
pattern: string;
};
}
+export namespace Network {
+ export type AddDataCollector = {
+ method: 'network.addDataCollector';
+ params: Network.AddDataCollectorParameters;
+ };
+}
+export namespace Network {
+ export type AddDataCollectorParameters = {
+ dataTypes: [Network.DataType, ...Network.DataType[]];
+ maxEncodedDataSize: JsUint;
+ /**
+ * @defaultValue `"blob"`
+ */
+ collectorType?: Network.CollectorType;
+ contexts?: [
+ BrowsingContext.BrowsingContext,
+ ...BrowsingContext.BrowsingContext[],
+ ];
+ userContexts?: [Browser.UserContext, ...Browser.UserContext[]];
+ };
+}
+export namespace Network {
+ export type AddDataCollectorResult = {
+ collector: Network.Collector;
+ };
+}
export namespace Network {
export type AddInterceptParameters = {
phases: [Network.InterceptPhase, ...Network.InterceptPhase[]];
@@ -1278,6 +1454,19 @@ export namespace Network {
action: 'default' | 'cancel';
};
}
+export namespace Network {
+ export type DisownData = {
+ method: 'network.disownData';
+ params: Network.DisownDataParameters;
+ };
+}
+export namespace Network {
+ export type DisownDataParameters = {
+ dataType: Network.DataType;
+ collector: Network.Collector;
+ request: Network.Request;
+ };
+}
export namespace Network {
export type FailRequest = {
method: 'network.failRequest';
@@ -1289,6 +1478,28 @@ export namespace Network {
request: Network.Request;
};
}
+export namespace Network {
+ export type GetData = {
+ method: 'network.getData';
+ params: Network.GetDataParameters;
+ };
+}
+export namespace Network {
+ export type GetDataParameters = {
+ dataType: Network.DataType;
+ collector?: Network.Collector;
+ /**
+ * @defaultValue `false`
+ */
+ disown?: boolean;
+ request: Network.Request;
+ };
+}
+export namespace Network {
+ export type GetDataResult = {
+ bytes: Network.BytesValue;
+ };
+}
export namespace Network {
export type ProvideResponse = {
method: 'network.provideResponse';
@@ -1305,6 +1516,17 @@ export namespace Network {
statusCode?: JsUint;
};
}
+export namespace Network {
+ export type RemoveDataCollector = {
+ method: 'network.removeDataCollector';
+ params: Network.RemoveDataCollectorParameters;
+ };
+}
+export namespace Network {
+ export type RemoveDataCollectorParameters = {
+ collector: Network.Collector;
+ };
+}
export namespace Network {
export type RemoveIntercept = {
method: 'network.removeIntercept';
@@ -1331,6 +1553,22 @@ export namespace Network {
];
};
}
+export namespace Network {
+ export type SetExtraHeaders = {
+ method: 'network.setExtraHeaders';
+ params: Network.SetExtraHeadersParameters;
+ };
+}
+export namespace Network {
+ export type SetExtraHeadersParameters = {
+ headers: [Network.Header, ...Network.Header[]];
+ contexts?: [
+ BrowsingContext.BrowsingContext,
+ ...BrowsingContext.BrowsingContext[],
+ ];
+ userContexts?: [Browser.UserContext, ...Browser.UserContext[]];
+ };
+}
export type ScriptEvent =
| Script.Message
| Script.RealmCreated
diff --git a/packages/playwright-core/src/server/browserContext.ts b/packages/playwright-core/src/server/browserContext.ts
index 3ae466f74ba90..d91f2f9668c67 100644
--- a/packages/playwright-core/src/server/browserContext.ts
+++ b/packages/playwright-core/src/server/browserContext.ts
@@ -213,7 +213,7 @@ export abstract class BrowserContext extends SdkObject {
await progress.race(this.setUserAgent(this._options.userAgent));
await progress.race(this.doUpdateDefaultEmulatedMedia());
await progress.race(this.doUpdateDefaultViewport());
- await this.setStorageState(progress, this._options.storageState, 'reset');
+ await this.setStorageState(progress, this._options.storageState, 'resetForReuse');
await page?.resetForReuse(progress);
}
@@ -612,11 +612,11 @@ export abstract class BrowserContext extends SdkObject {
return this._creatingStorageStatePage;
}
- async setStorageState(progress: Progress, state: channels.BrowserNewContextParams['storageState'], mode: 'initial' | 'reset') {
+ async setStorageState(progress: Progress, state: channels.BrowserNewContextParams['storageState'], mode: 'initial' | 'resetForReuse' | 'update') {
let page: Page | undefined;
let interceptor: network.RouteHandler | undefined;
try {
- if (mode === 'reset') {
+ if (mode !== 'initial') {
await progress.race(this.clearCache());
await progress.race(this.doClearCookies());
}
@@ -627,11 +627,11 @@ export abstract class BrowserContext extends SdkObject {
const newOrigins = new Map(state?.origins?.map(p => [p.origin, p]) || []);
const allOrigins = new Set([...this._origins, ...newOrigins.keys()]);
if (allOrigins.size) {
- if (mode === 'reset')
+ if (mode === 'resetForReuse')
page = this.pages()[0];
if (!page) {
try {
- this._creatingStorageStatePage = mode === 'initial';
+ this._creatingStorageStatePage = mode !== 'resetForReuse';
page = await this.newPage(progress, this._creatingStorageStatePage);
} finally {
this._creatingStorageStatePage = false;
@@ -660,7 +660,7 @@ export abstract class BrowserContext extends SdkObject {
rewriteErrorMessage(error, `Error setting storage state:\n` + error.message);
throw error;
} finally {
- if (mode === 'initial')
+ if (mode !== 'resetForReuse')
await page?.close();
else if (interceptor)
await page?.removeRequestInterceptor(interceptor);
diff --git a/packages/playwright-core/src/server/chromium/chromiumSwitches.ts b/packages/playwright-core/src/server/chromium/chromiumSwitches.ts
index f490971ba3913..cedf70082c0f8 100644
--- a/packages/playwright-core/src/server/chromium/chromiumSwitches.ts
+++ b/packages/playwright-core/src/server/chromium/chromiumSwitches.ts
@@ -38,6 +38,8 @@ const disabledFeatures = (assistantMode?: boolean) => [
'ThirdPartyStoragePartitioning',
// See https://github.com/microsoft/playwright/issues/16126
'Translate',
+ // See https://issues.chromium.org/u/1/issues/435410220
+ 'AutoDeElevate',
assistantMode ? 'AutomationControlled' : '',
].filter(Boolean);
diff --git a/packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts b/packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts
index 15c8f84fd0054..6803d00e52429 100644
--- a/packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts
+++ b/packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts
@@ -330,6 +330,10 @@ export class BrowserContextDispatcher extends Dispatcher {
+ await this._context.setStorageState(progress, params.storageState, 'update');
+ }
+
async close(params: channels.BrowserContextCloseParams, progress: Progress): Promise {
progress.metadata.potentiallyClosesScope = true;
await this._context.close(params);
diff --git a/packages/playwright-core/src/server/instrumentation.ts b/packages/playwright-core/src/server/instrumentation.ts
index 9dc29950c86fc..947c929390b66 100644
--- a/packages/playwright-core/src/server/instrumentation.ts
+++ b/packages/playwright-core/src/server/instrumentation.ts
@@ -121,6 +121,5 @@ export function serverSideCallMetadata(): CallMetadata {
method: '',
params: {},
log: [],
- isServerSide: true,
};
}
diff --git a/packages/playwright-core/src/server/launchApp.ts b/packages/playwright-core/src/server/launchApp.ts
index 8eee438d84022..1dc29e983f54b 100644
--- a/packages/playwright-core/src/server/launchApp.ts
+++ b/packages/playwright-core/src/server/launchApp.ts
@@ -17,9 +17,9 @@
import fs from 'fs';
import path from 'path';
-import { isUnderTest } from '../utils';
+import { isUnderTest, rewriteErrorMessage, wrapInASCIIBox } from '../utils';
import { serverSideCallMetadata } from './instrumentation';
-import { findChromiumChannel } from './registry';
+import { buildPlaywrightCLICommand, findChromiumChannelBestEffort } from './registry';
import { registryDirectory } from './registry';
import { ProgressController } from './progress';
@@ -46,19 +46,32 @@ export async function launchApp(browserType: BrowserType, options: {
'--test-type=',
);
if (!channel && !options.persistentContextOptions?.executablePath)
- channel = findChromiumChannel(options.sdkLanguage);
+ channel = findChromiumChannelBestEffort(options.sdkLanguage);
}
const controller = new ProgressController(serverSideCallMetadata(), browserType);
- const context = await controller.run(progress => browserType.launchPersistentContext(progress, '', {
- ignoreDefaultArgs: ['--enable-automation'],
- ...options?.persistentContextOptions,
- channel,
- noDefaultViewport: options.persistentContextOptions?.noDefaultViewport ?? true,
- acceptDownloads: options?.persistentContextOptions?.acceptDownloads ?? (isUnderTest() ? 'accept' : 'internal-browser-default'),
- colorScheme: options?.persistentContextOptions?.colorScheme ?? 'no-override',
- args,
- }), 0); // Deliberately no timeout for our apps.
+ let context;
+ try {
+ context = await controller.run(progress => browserType.launchPersistentContext(progress, '', {
+ ignoreDefaultArgs: ['--enable-automation'],
+ ...options?.persistentContextOptions,
+ channel,
+ noDefaultViewport: options.persistentContextOptions?.noDefaultViewport ?? true,
+ acceptDownloads: options?.persistentContextOptions?.acceptDownloads ?? (isUnderTest() ? 'accept' : 'internal-browser-default'),
+ colorScheme: options?.persistentContextOptions?.colorScheme ?? 'no-override',
+ args,
+ }), 0); // Deliberately no timeout for our apps.
+ } catch (error) {
+ if (channel) {
+ error = rewriteErrorMessage(error, [
+ `Failed to launch "${channel}" channel.`,
+ 'Using custom channels could lead to unexpected behavior due to Enterprise policies (chrome://policy).',
+ 'Install the default browser instead:',
+ wrapInASCIIBox(`${buildPlaywrightCLICommand(options.sdkLanguage, 'install')}`, 2),
+ ].join('\n'));
+ }
+ throw error;
+ }
const [page] = context.pages();
// Chromium on macOS opens a new tab when clicking on the dock icon.
// See https://github.com/microsoft/playwright/issues/9434
diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts
index fde6b2f1017de..36ee1d92d5e38 100644
--- a/packages/playwright-core/src/server/registry/index.ts
+++ b/packages/playwright-core/src/server/registry/index.ts
@@ -1363,7 +1363,8 @@ export async function installBrowsersForNpmInstall(browsers: string[]) {
await registry.install(executables, false /* forceReinstall */);
}
-export function findChromiumChannel(sdkLanguage: string): string | undefined {
+// for launchApp -> UI Mode / Trace Viewer
+export function findChromiumChannelBestEffort(sdkLanguage: string): string | undefined {
// Fall back to the stable channels of popular vendors to work out of the box.
// Null means no installation and no channels found.
let channel = null;
diff --git a/packages/playwright-core/src/server/trace/recorder/tracing.ts b/packages/playwright-core/src/server/trace/recorder/tracing.ts
index 37148ddb448cf..219438ef0b14a 100644
--- a/packages/playwright-core/src/server/trace/recorder/tracing.ts
+++ b/packages/playwright-core/src/server/trace/recorder/tracing.ts
@@ -459,7 +459,9 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps
}
onCallLog(sdkObject: SdkObject, metadata: CallMetadata, logName: string, message: string) {
- if (metadata.isServerSide || metadata.internal)
+ if (!this._state?.callIds.has(metadata.id))
+ return;
+ if (metadata.internal)
return;
if (logName !== 'api')
return;
diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts
index 4037c44c14c2c..db049937ce068 100644
--- a/packages/playwright-core/src/utils.ts
+++ b/packages/playwright-core/src/utils.ts
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-export * from './utils/isomorphic/colors';
+export * from './utils/isomorphic/ariaSnapshot';
export * from './utils/isomorphic/assert';
+export * from './utils/isomorphic/colors';
export * from './utils/isomorphic/headers';
export * from './utils/isomorphic/locatorGenerators';
export * from './utils/isomorphic/manualPromise';
diff --git a/packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts b/packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts
index 87121b0bed5bb..c85f04c599144 100644
--- a/packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts
+++ b/packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts
@@ -82,6 +82,7 @@ export const methodMetainfo = new Map;
+ /**
+ * Resets storage state in the context by clearing cookies, cache and storage, and then applying the new storage
+ * state.
+ * @param storageState Learn more about [storage state and auth](https://playwright.dev/docs/auth).
+ *
+ * Populates context with given storage state. This option can be used to initialize context with logged-in
+ * information obtained via
+ * [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state).
+ */
+ setStorageState(storageState: string|{
+ /**
+ * Cookies to set for context
+ */
+ cookies: Array<{
+ name: string;
+
+ value: string;
+
+ /**
+ * Domain and path are required. For the cookie to apply to all subdomains as well, prefix domain with a dot, like
+ * this: ".example.com"
+ */
+ domain: string;
+
+ /**
+ * Domain and path are required
+ */
+ path: string;
+
+ /**
+ * Unix time in seconds.
+ */
+ expires: number;
+
+ httpOnly: boolean;
+
+ secure: boolean;
+
+ /**
+ * sameSite flag
+ */
+ sameSite: "Strict"|"Lax"|"None";
+ }>;
+
+ origins: Array<{
+ origin: string;
+
+ /**
+ * localStorage to set for context
+ */
+ localStorage: Array<{
+ name: string;
+
+ value: string;
+ }>;
+ }>;
+ }): Promise;
+
/**
* Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB
* snapshot.
diff --git a/packages/protocol/src/callMetadata.d.ts b/packages/protocol/src/callMetadata.d.ts
index 076abd2dc656a..f0a26b47ad524 100644
--- a/packages/protocol/src/callMetadata.d.ts
+++ b/packages/protocol/src/callMetadata.d.ts
@@ -29,9 +29,6 @@ export type CallMetadata = {
// Client is making an internal call that should not show up in
// the inspector or trace.
internal?: boolean;
- // Service-side is making a call to itself, this metadata does not go
- // through the dispatcher, so is always excluded from inspector / tracing.
- isServerSide?: boolean;
// Test runner step id.
stepId?: string;
location?: { file: string, line?: number, column?: number };
diff --git a/packages/protocol/src/channels.d.ts b/packages/protocol/src/channels.d.ts
index 33fce000bfee0..f753e2825535f 100644
--- a/packages/protocol/src/channels.d.ts
+++ b/packages/protocol/src/channels.d.ts
@@ -1612,6 +1612,7 @@ export interface BrowserContextChannel extends BrowserContextEventTarget, EventT
setWebSocketInterceptionPatterns(params: BrowserContextSetWebSocketInterceptionPatternsParams, progress?: Progress): Promise;
setOffline(params: BrowserContextSetOfflineParams, progress?: Progress): Promise;
storageState(params: BrowserContextStorageStateParams, progress?: Progress): Promise;
+ setStorageState(params: BrowserContextSetStorageStateParams, progress?: Progress): Promise;
pause(params?: BrowserContextPauseParams, progress?: Progress): Promise;
enableRecorder(params: BrowserContextEnableRecorderParams, progress?: Progress): Promise;
disableRecorder(params?: BrowserContextDisableRecorderParams, progress?: Progress): Promise;
@@ -1862,6 +1863,16 @@ export type BrowserContextStorageStateResult = {
cookies: NetworkCookie[],
origins: OriginStorage[],
};
+export type BrowserContextSetStorageStateParams = {
+ storageState: {
+ cookies?: SetNetworkCookie[],
+ origins?: SetOriginStorage[],
+ },
+};
+export type BrowserContextSetStorageStateOptions = {
+
+};
+export type BrowserContextSetStorageStateResult = void;
export type BrowserContextPauseParams = {};
export type BrowserContextPauseOptions = {};
export type BrowserContextPauseResult = void;
diff --git a/packages/protocol/src/protocol.yml b/packages/protocol/src/protocol.yml
index 5bd36be29a415..ab25ad60502e5 100644
--- a/packages/protocol/src/protocol.yml
+++ b/packages/protocol/src/protocol.yml
@@ -16,8 +16,8 @@ StackFrame:
type: object
properties:
file: string
- line: number
- column: number
+ line: int
+ column: int
function: string?
# This object can be send with any rpc call in the "metadata" field.
@@ -29,8 +29,8 @@ Metadata:
type: object?
properties:
file: string
- line: number?
- column: number?
+ line: int?
+ column: int?
title: string?
internal: boolean?
# Test runner step id.
@@ -39,7 +39,7 @@ Metadata:
ClientSideCallMetadata:
type: object
properties:
- id: number
+ id: int
stack:
type: array?
items: StackFrame
@@ -47,24 +47,24 @@ ClientSideCallMetadata:
Point:
type: object
properties:
- x: number
- y: number
+ x: float
+ y: float
Rect:
type: object
properties:
- x: number
- y: number
- width: number
- height: number
+ x: float
+ y: float
+ width: float
+ height: float
SerializedValue:
type: object
# Exactly one of the properties must be present.
properties:
- n: number?
+ n: float?
b: boolean?
s: string?
v:
@@ -126,11 +126,11 @@ SerializedValue:
k: string
v: SerializedValue
# An index in the handles array from SerializedArgument.
- h: number?
+ h: int?
# Index of the object in value-type for circular reference resolution.
- id: number?
+ id: int?
# Ref to the object in value-type for circular reference resolution.
- ref: number?
+ ref: int?
# Represents a value with handle references.
@@ -168,7 +168,7 @@ AXNode:
role: string
name: string
valueString: string?
- valueNumber: number?
+ valueNumber: float?
description: string?
keyshortcuts: string?
roledescription: string?
@@ -194,9 +194,9 @@ AXNode:
- pressed
- released
- mixed
- level: number?
- valuemin: number?
- valuemax: number?
+ level: int?
+ valuemin: float?
+ valuemax: float?
autocomplete: string?
haspopup: string?
invalid: string?
@@ -214,7 +214,7 @@ SetNetworkCookie:
url: string?
domain: string?
path: string?
- expires: number?
+ expires: float?
httpOnly: boolean?
secure: boolean?
sameSite:
@@ -234,7 +234,7 @@ NetworkCookie:
value: string
domain: string
path: string
- expires: number
+ expires: float
httpOnly: boolean
secure: boolean
sameSite:
@@ -257,7 +257,7 @@ IndexedDBDatabase:
type: object
properties:
name: string
- version: number
+ version: int
stores:
type: array
items:
@@ -393,11 +393,11 @@ APIRequestContext:
multipartData:
type: array?
items: FormField
- timeout: number
+ timeout: float
failOnStatusCode: boolean?
ignoreHTTPSErrors: boolean?
- maxRedirects: number?
- maxRetries: number?
+ maxRedirects: int?
+ maxRetries: int?
returns:
response: APIResponse
@@ -445,7 +445,7 @@ APIResponse:
properties:
fetchUid: string
url: string
- status: number
+ status: int
statusText: string
headers:
type: array
@@ -505,7 +505,7 @@ LaunchOptions:
handleSIGINT: boolean?
handleSIGTERM: boolean?
handleSIGHUP: boolean?
- timeout: number
+ timeout: float
env:
type: array?
items: NameValue
@@ -522,7 +522,7 @@ LaunchOptions:
tracesDir: string?
chromiumSandbox: boolean?
firefoxUserPrefs: json?
- cdpPort: number?
+ cdpPort: int?
ContextOptions:
@@ -532,13 +532,13 @@ ContextOptions:
viewport:
type: object?
properties:
- width: number
- height: number
+ width: int
+ height: int
screen:
type: object?
properties:
- width: number
- height: number
+ width: int
+ height: int
ignoreHTTPSErrors: boolean?
clientCertificates:
type: array?
@@ -558,9 +558,9 @@ ContextOptions:
geolocation:
type: object?
properties:
- longitude: number
- latitude: number
- accuracy: number?
+ longitude: float
+ latitude: float
+ accuracy: float?
permissions:
type: array?
items: string
@@ -579,7 +579,7 @@ ContextOptions:
literals:
- always
- unauthorized
- deviceScaleFactor: number?
+ deviceScaleFactor: float?
isMobile: boolean?
hasTouch: boolean?
colorScheme:
@@ -621,8 +621,8 @@ ContextOptions:
size:
type: object?
properties:
- width: number
- height: number
+ width: int
+ height: int
strictSelectors: boolean?
serviceWorkers:
type: enum?
@@ -652,14 +652,14 @@ LocalUtils:
viewport:
type: object
properties:
- width: number
- height: number
+ width: int
+ height: int
screen:
type: object?
properties:
- width: number
- height: number
- deviceScaleFactor: number
+ width: int
+ height: int
+ deviceScaleFactor: float
isMobile: boolean
hasTouch: boolean
defaultBrowserType:
@@ -715,7 +715,7 @@ LocalUtils:
- noentry
message: string?
redirectURL: string?
- status: number?
+ status: int?
headers:
type: array?
items: NameValue
@@ -738,9 +738,9 @@ LocalUtils:
wsEndpoint: string
headers: json?
exposeNetwork: string?
- slowMo: number?
- timeout: number
- socksProxyRedirectPortForTest: number?
+ slowMo: float?
+ timeout: float
+ socksProxyRedirectPortForTest: int?
returns:
pipe: JsonPipe
headers:
@@ -818,7 +818,7 @@ Playwright:
key: binary?
passphrase: string?
pfx: binary?
- maxRedirects: number?
+ maxRedirects: int?
httpCredentials:
type: object?
properties:
@@ -864,9 +864,9 @@ RecorderSource:
items:
type: object
properties:
- line: number
+ line: int
type: string
- revealLine: number?
+ revealLine: int?
group: string?
DebugController:
@@ -923,7 +923,7 @@ DebugController:
stateChanged:
parameters:
- pageCount: number
+ pageCount: int
sourceChanged:
parameters:
@@ -947,7 +947,7 @@ SocksSupport:
parameters:
uid: string
host: string
- port: number
+ port: int
socksFailed:
internal: true
@@ -977,7 +977,7 @@ SocksSupport:
parameters:
uid: string
host: string
- port: number
+ port: int
socksData:
parameters:
@@ -1002,7 +1002,7 @@ BrowserType:
title: Launch browser
parameters:
$mixin: LaunchOptions
- slowMo: number?
+ slowMo: float?
returns:
browser: Browser
@@ -1012,7 +1012,7 @@ BrowserType:
$mixin1: LaunchOptions
$mixin2: ContextOptions
userDataDir: string
- slowMo: number?
+ slowMo: float?
returns:
browser: Browser
context: BrowserContext
@@ -1024,8 +1024,8 @@ BrowserType:
headers:
type: array?
items: NameValue
- slowMo: number?
- timeout: number
+ slowMo: float?
+ timeout: float
returns:
browser: Browser
defaultContext: BrowserContext?
@@ -1143,8 +1143,8 @@ ConsoleMessage:
type: object
properties:
url: string
- lineNumber: number
- columnNumber: number
+ lineNumber: int
+ columnNumber: int
EventTarget:
@@ -1272,9 +1272,9 @@ BrowserContext:
geolocation:
type: object?
properties:
- longitude: number
- latitude: number
- accuracy: number?
+ longitude: float
+ latitude: float
+ accuracy: float?
setHTTPCredentials:
title: Set HTTP credentials
@@ -1327,6 +1327,19 @@ BrowserContext:
type: array
items: OriginStorage
+ setStorageState:
+ title: Set storage state
+ parameters:
+ storageState:
+ type: object
+ properties:
+ cookies:
+ type: array?
+ items: SetNetworkCookie
+ origins:
+ type: array?
+ items: SetOriginStorage
+
pause:
title: Pause
@@ -1390,7 +1403,7 @@ BrowserContext:
type: object
properties:
name: string
- lastModifiedMs: number?
+ lastModifiedMs: float?
returns:
rootDir: WritableStream?
writableStreams:
@@ -1414,19 +1427,19 @@ BrowserContext:
clockFastForward:
title: Fast forward clock "{ticksNumber}{ticksString}"
parameters:
- ticksNumber: number?
+ ticksNumber: float?
ticksString: string?
clockInstall:
title: Install clock "{timeNumber}{timeString}"
parameters:
- timeNumber: number?
+ timeNumber: float?
timeString: string?
clockPauseAt:
title: Pause clock "{timeNumber}{timeString}"
parameters:
- timeNumber: number?
+ timeNumber: float?
timeString: string?
clockResume:
@@ -1435,19 +1448,19 @@ BrowserContext:
clockRunFor:
title: Run clock "{ticksNumber}{ticksString}"
parameters:
- ticksNumber: number?
+ ticksNumber: float?
ticksString: string?
clockSetFixedTime:
title: Set fixed time "{timeNumber}{timeString}"
parameters:
- timeNumber: number?
+ timeNumber: float?
timeString: string?
clockSetSystemTime:
title: Set system time "{timeNumber}{timeString}"
parameters:
- timeNumber: number?
+ timeNumber: float?
timeString: string?
clockUninstall:
@@ -1508,14 +1521,14 @@ BrowserContext:
parameters:
request: Request
failureText: string?
- responseEndTiming: number
+ responseEndTiming: float
page: Page?
requestFinished:
parameters:
request: Request
response: Response?
- responseEndTiming: number
+ responseEndTiming: float
page: Page?
response:
@@ -1545,8 +1558,8 @@ Page:
viewportSize:
type: object?
properties:
- width: number
- height: number
+ width: int
+ height: int
isClosed: boolean
opener: Page?
@@ -1608,7 +1621,7 @@ Page:
goBack:
title: Go back
parameters:
- timeout: number
+ timeout: float
waitUntil: LifecycleEvent?
returns:
response: Response?
@@ -1619,7 +1632,7 @@ Page:
goForward:
title: Go forward
parameters:
- timeout: number
+ timeout: float
waitUntil: LifecycleEvent?
returns:
response: Response?
@@ -1636,23 +1649,23 @@ Page:
selector: string
noWaitAfter: boolean?
returns:
- uid: number
+ uid: int
resolveLocatorHandlerNoReply:
internal: true
parameters:
- uid: number
+ uid: int
remove: boolean?
unregisterLocatorHandler:
title: Unregister locator handler
parameters:
- uid: number
+ uid: int
reload:
title: Reload
parameters:
- timeout: number
+ timeout: float
waitUntil: LifecycleEvent?
returns:
response: Response?
@@ -1664,7 +1677,7 @@ Page:
title: Expect screenshot
parameters:
expected: binary?
- timeout: number
+ timeout: float
isNot: boolean
locator:
type: object?
@@ -1672,9 +1685,9 @@ Page:
frame: Frame
selector: string
comparator: string?
- maxDiffPixels: number?
- maxDiffPixelRatio: number?
- threshold: number?
+ maxDiffPixels: int?
+ maxDiffPixelRatio: float?
+ threshold: float?
fullPage: boolean?
clip: Rect?
$mixin: CommonScreenshotOptions
@@ -1693,13 +1706,13 @@ Page:
screenshot:
title: Screenshot
parameters:
- timeout: number
+ timeout: float
type:
type: enum?
literals:
- png
- jpeg
- quality: number?
+ quality: int?
fullPage: boolean?
clip: Rect?
$mixin: CommonScreenshotOptions
@@ -1745,8 +1758,8 @@ Page:
viewportSize:
type: object
properties:
- width: number
- height: number
+ width: int
+ height: int
flags:
snapshot: true
@@ -1778,7 +1791,7 @@ Page:
title: Type "{text}"
parameters:
text: string
- delay: number?
+ delay: float?
flags:
slowMo: true
snapshot: true
@@ -1787,7 +1800,7 @@ Page:
title: Press "{key}"
parameters:
key: string
- delay: number?
+ delay: float?
flags:
slowMo: true
snapshot: true
@@ -1795,9 +1808,9 @@ Page:
mouseMove:
title: Mouse move
parameters:
- x: number
- y: number
- steps: number?
+ x: float
+ y: float
+ steps: int?
flags:
slowMo: true
snapshot: true
@@ -1811,7 +1824,7 @@ Page:
- left
- right
- middle
- clickCount: number?
+ clickCount: int?
flags:
slowMo: true
snapshot: true
@@ -1825,7 +1838,7 @@ Page:
- left
- right
- middle
- clickCount: number?
+ clickCount: int?
flags:
slowMo: true
snapshot: true
@@ -1833,16 +1846,16 @@ Page:
mouseClick:
title: Click
parameters:
- x: number
- y: number
- delay: number?
+ x: float
+ y: float
+ delay: float?
button:
type: enum?
literals:
- left
- right
- middle
- clickCount: number?
+ clickCount: int?
flags:
slowMo: true
snapshot: true
@@ -1850,8 +1863,8 @@ Page:
mouseWheel:
title: Mouse wheel
parameters:
- deltaX: number
- deltaY: number
+ deltaX: float
+ deltaY: float
flags:
slowMo: true
snapshot: true
@@ -1859,8 +1872,8 @@ Page:
touchscreenTap:
title: Tap
parameters:
- x: number
- y: number
+ x: float
+ y: float
flags:
slowMo: true
snapshot: true
@@ -1878,7 +1891,7 @@ Page:
pdf:
title: PDF
parameters:
- scale: number?
+ scale: float?
displayHeaderFooter: boolean?
headerTemplate: string?
footerTemplate: string?
@@ -1904,7 +1917,7 @@ Page:
snapshotForAI:
internal: true
parameters:
- timeout: number
+ timeout: float
returns:
snapshot: string
flags:
@@ -1939,9 +1952,9 @@ Page:
items:
type: object
properties:
- startOffset: number
- endOffset: number
- count: number
+ startOffset: int
+ endOffset: int
+ count: int
startCSSCoverage:
internal: true
@@ -1963,8 +1976,8 @@ Page:
items:
type: object
properties:
- start: number
- end: number
+ start: int
+ end: int
bringToFront:
title: Bring to front
@@ -2005,8 +2018,8 @@ Page:
viewportSize:
type: object?
properties:
- width: number
- height: number
+ width: int
+ height: int
fileChooser:
parameters:
@@ -2023,7 +2036,7 @@ Page:
locatorHandlerTriggered:
parameters:
- uid: number
+ uid: int
route:
parameters:
@@ -2110,7 +2123,7 @@ Frame:
title: Aria snapshot
parameters:
selector: string
- timeout: number
+ timeout: float
returns:
snapshot: string
flags:
@@ -2121,7 +2134,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2133,7 +2146,7 @@ Frame:
strict: boolean?
force: boolean?
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2158,15 +2171,15 @@ Frame:
- Meta
- Shift
position: Point?
- delay: number?
+ delay: float?
button:
type: enum?
literals:
- left
- right
- middle
- clickCount: number?
- timeout: number
+ clickCount: int?
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2186,7 +2199,7 @@ Frame:
source: string
target: string
force: boolean?
- timeout: number
+ timeout: float
trial: boolean?
sourcePosition: Point?
targetPosition: Point?
@@ -2213,14 +2226,14 @@ Frame:
- Meta
- Shift
position: Point?
- delay: number?
+ delay: float?
button:
type: enum?
literals:
- left
- right
- middle
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2234,7 +2247,7 @@ Frame:
strict: boolean?
type: string
eventInit: SerializedArgument
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2268,7 +2281,7 @@ Frame:
strict: boolean?
value: string
force: boolean?
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2279,7 +2292,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2307,7 +2320,7 @@ Frame:
selector: string
strict: boolean?
name: string
- timeout: number
+ timeout: float
returns:
value: string?
flags:
@@ -2317,7 +2330,7 @@ Frame:
title: Navigate to "{url}"
parameters:
url: string
- timeout: number
+ timeout: float
waitUntil: LifecycleEvent?
referer: string?
returns:
@@ -2343,7 +2356,7 @@ Frame:
- Meta
- Shift
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2355,7 +2368,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: string
flags:
@@ -2366,7 +2379,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: string
flags:
@@ -2377,7 +2390,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: string
flags:
@@ -2388,7 +2401,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: boolean
flags:
@@ -2399,7 +2412,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: boolean
flags:
@@ -2410,7 +2423,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: boolean
flags:
@@ -2443,7 +2456,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: boolean
flags:
@@ -2455,9 +2468,9 @@ Frame:
selector: string
strict: boolean?
key: string
- delay: number?
+ delay: float?
noWaitAfter: boolean?
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2489,7 +2502,7 @@ Frame:
parameters:
selector: string
returns:
- value: number
+ value: int
flags:
snapshot: true
@@ -2509,9 +2522,9 @@ Frame:
valueOrLabel: string?
value: string?
label: string?
- index: number?
+ index: int?
force: boolean?
- timeout: number
+ timeout: float
returns:
values:
type: array
@@ -2525,7 +2538,7 @@ Frame:
title: Set content
parameters:
html: string
- timeout: number
+ timeout: float
waitUntil: LifecycleEvent?
flags:
snapshot: true
@@ -2552,7 +2565,7 @@ Frame:
streams:
type: array?
items: WritableStream
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2575,7 +2588,7 @@ Frame:
- Meta
- Shift
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2587,7 +2600,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
returns:
value: string?
flags:
@@ -2604,8 +2617,8 @@ Frame:
selector: string
strict: boolean?
text: string
- delay: number?
- timeout: number
+ delay: float?
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2618,7 +2631,7 @@ Frame:
strict: boolean?
force: boolean?
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2628,7 +2641,7 @@ Frame:
waitForTimeout:
title: Wait for timeout
parameters:
- waitTimeout: number
+ waitTimeout: float
flags:
snapshot: true
@@ -2638,9 +2651,9 @@ Frame:
expression: string
isFunction: boolean?
arg: SerializedArgument
- timeout: number
+ timeout: float
# When present, polls on interval. Otherwise, polls on raf.
- pollingInterval: number?
+ pollingInterval: float?
returns:
handle: JSHandle
flags:
@@ -2651,7 +2664,7 @@ Frame:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
state:
type: enum?
literals:
@@ -2674,11 +2687,11 @@ Frame:
expectedText:
type: array?
items: ExpectedTextValue
- expectedNumber: number?
+ expectedNumber: float?
expectedValue: SerializedArgument?
useInnerText: boolean?
isNot: boolean
- timeout: number
+ timeout: float
returns:
matches: boolean
received: SerializedValue?
@@ -2846,7 +2859,7 @@ ElementHandle:
parameters:
force: boolean?
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2869,15 +2882,15 @@ ElementHandle:
- Meta
- Shift
position: Point?
- delay: number?
+ delay: float?
button:
type: enum?
literals:
- left
- right
- middle
- clickCount: number?
- timeout: number
+ clickCount: int?
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2906,14 +2919,14 @@ ElementHandle:
- Meta
- Shift
position: Point?
- delay: number?
+ delay: float?
button:
type: enum?
literals:
- left
- right
- middle
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -2934,7 +2947,7 @@ ElementHandle:
parameters:
value: string
force: boolean?
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -2968,7 +2981,7 @@ ElementHandle:
- Meta
- Shift
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -3047,8 +3060,8 @@ ElementHandle:
title: Press "{key}"
parameters:
key: string
- delay: number?
- timeout: number
+ delay: float?
+ timeout: float
noWaitAfter: boolean?
flags:
slowMo: true
@@ -3079,13 +3092,13 @@ ElementHandle:
screenshot:
title: Screenshot
parameters:
- timeout: number
+ timeout: float
type:
type: enum?
literals:
- png
- jpeg
- quality: number?
+ quality: int?
$mixin: CommonScreenshotOptions
returns:
binary: binary
@@ -3095,7 +3108,7 @@ ElementHandle:
scrollIntoViewIfNeeded:
title: Scroll into view
parameters:
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -3114,9 +3127,9 @@ ElementHandle:
valueOrLabel: string?
value: string?
label: string?
- index: number?
+ index: int?
force: boolean?
- timeout: number
+ timeout: float
returns:
values:
type: array
@@ -3130,7 +3143,7 @@ ElementHandle:
title: Select text
parameters:
force: boolean?
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -3155,7 +3168,7 @@ ElementHandle:
streams:
type: array?
items: WritableStream
- timeout: number
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -3176,7 +3189,7 @@ ElementHandle:
- Meta
- Shift
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -3194,8 +3207,8 @@ ElementHandle:
title: Type
parameters:
text: string
- delay: number?
- timeout: number
+ delay: float?
+ timeout: float
flags:
slowMo: true
snapshot: true
@@ -3206,7 +3219,7 @@ ElementHandle:
parameters:
force: boolean?
position: Point?
- timeout: number
+ timeout: float
trial: boolean?
flags:
slowMo: true
@@ -3225,7 +3238,7 @@ ElementHandle:
- enabled
- disabled
- editable
- timeout: number
+ timeout: float
flags:
snapshot: true
@@ -3234,7 +3247,7 @@ ElementHandle:
parameters:
selector: string
strict: boolean?
- timeout: number
+ timeout: float
state:
type: enum?
literals:
@@ -3311,7 +3324,7 @@ Route:
internal: true
parameters:
# default is 200
- status: number?
+ status: int?
headers:
type: array?
items: NameValue
@@ -3349,14 +3362,14 @@ WebSocketRoute:
closePage:
internal: true
parameters:
- code: number?
+ code: int?
reason: string?
wasClean: boolean
closeServer:
internal: true
parameters:
- code: number?
+ code: int?
reason: string?
wasClean: boolean
@@ -3374,13 +3387,13 @@ WebSocketRoute:
closePage:
parameters:
- code: number?
+ code: int?
reason: string?
wasClean: boolean
closeServer:
parameters:
- code: number?
+ code: int?
reason: string?
wasClean: boolean
@@ -3388,14 +3401,14 @@ WebSocketRoute:
ResourceTiming:
type: object
properties:
- startTime: number
- domainLookupStart: number
- domainLookupEnd: number
- connectStart: number
- secureConnectionStart: number
- connectEnd: number
- requestStart: number
- responseStart: number
+ startTime: float
+ domainLookupStart: float
+ domainLookupEnd: float
+ connectStart: float
+ secureConnectionStart: float
+ connectEnd: float
+ requestStart: float
+ responseStart: float
Response:
type: interface
@@ -3403,7 +3416,7 @@ Response:
initializer:
request: Request
url: string
- status: number
+ status: int
statusText: string
headers:
type: array
@@ -3448,23 +3461,23 @@ SecurityDetails:
issuer: string?
protocol: string?
subjectName: string?
- validFrom: number?
- validTo: number?
+ validFrom: float?
+ validTo: float?
RequestSizes:
type: object
properties:
- requestBodySize: number
- requestHeadersSize: number
- responseBodySize: number
- responseHeadersSize: number
+ requestBodySize: int
+ requestHeadersSize: int
+ responseBodySize: int
+ responseHeadersSize: int
RemoteAddr:
type: object
properties:
ipAddress: string
- port: number
+ port: int
WebSocket:
@@ -3480,12 +3493,12 @@ WebSocket:
frameSent:
parameters:
- opcode: number
+ opcode: int
data: string
frameReceived:
parameters:
- opcode: number
+ opcode: int
data: string
socketError:
@@ -3568,8 +3581,8 @@ Tracing:
type: object?
properties:
file: string
- line: number?
- column: number?
+ line: int?
+ column: int?
tracingGroupEnd:
title: Group end
@@ -3646,7 +3659,7 @@ Stream:
read:
internal: true
parameters:
- size: number?
+ size: int?
returns:
binary: binary
@@ -3708,7 +3721,7 @@ Electron:
env:
type: array?
items: NameValue
- timeout: number
+ timeout: float
acceptDownloads:
type: enum?
literals:
@@ -3729,9 +3742,9 @@ Electron:
geolocation:
type: object?
properties:
- longitude: number
- latitude: number
- accuracy: number?
+ longitude: float
+ latitude: float
+ accuracy: float?
httpCredentials:
type: object?
properties:
@@ -3748,8 +3761,8 @@ Electron:
size:
type: object?
properties:
- width: number
- height: number
+ width: int
+ height: int
strictSelectors: boolean?
timezoneId: string?
tracesDir: string?
@@ -3821,7 +3834,7 @@ Android:
internal: true
parameters:
host: string?
- port: number?
+ port: int?
omitDriverInstall: boolean?
returns:
devices:
@@ -3864,29 +3877,29 @@ AndroidDevice:
type: enum?
literals:
- gone
- timeout: number
+ timeout: float
fill:
title: Fill "{text}"
parameters:
androidSelector: AndroidSelector
text: string
- timeout: number
+ timeout: float
tap:
title: Tap
parameters:
androidSelector: AndroidSelector
- duration: number?
- timeout: number
+ duration: float?
+ timeout: float
drag:
title: Drag
parameters:
androidSelector: AndroidSelector
dest: Point
- speed: number?
- timeout: number
+ speed: float?
+ timeout: float
fling:
title: Fling
@@ -3899,30 +3912,30 @@ AndroidDevice:
- down
- left
- right
- speed: number?
- timeout: number
+ speed: float?
+ timeout: float
longTap:
title: Long tap
parameters:
androidSelector: AndroidSelector
- timeout: number
+ timeout: float
pinchClose:
title: Pinch close
parameters:
androidSelector: AndroidSelector
- percent: number
- speed: number?
- timeout: number
+ percent: float
+ speed: float?
+ timeout: float
pinchOpen:
title: Pinch open
parameters:
androidSelector: AndroidSelector
- percent: number
- speed: number?
- timeout: number
+ percent: float
+ speed: float?
+ timeout: float
scroll:
title: Scroll
@@ -3935,9 +3948,9 @@ AndroidDevice:
- down
- left
- right
- percent: number
- speed: number?
- timeout: number
+ percent: float
+ speed: float?
+ timeout: float
swipe:
title: Swipe
@@ -3950,9 +3963,9 @@ AndroidDevice:
- down
- left
- right
- percent: number
- speed: number?
- timeout: number
+ percent: float
+ speed: float?
+ timeout: float
info:
internal: true
@@ -3987,14 +4000,14 @@ AndroidDevice:
segments:
type: array
items: Point
- steps: number
+ steps: int
inputDrag:
title: Drag
parameters:
from: Point
to: Point
- steps: number
+ steps: int
launchBrowser:
title: Launch browser
@@ -4042,7 +4055,7 @@ AndroidDevice:
parameters:
file: binary
path: string
- mode: number?
+ mode: int?
connectToWebView:
internal: true
@@ -4069,7 +4082,7 @@ AndroidDevice:
AndroidWebView:
type: object
properties:
- pid: number
+ pid: int
pkg: string
socketName: string
@@ -4081,7 +4094,7 @@ AndroidSelector:
checked: boolean?
clazz: string?
clickable: boolean?
- depth: number?
+ depth: int?
desc: string?
enabled: boolean?
focusable: boolean?
@@ -4094,7 +4107,7 @@ AndroidSelector:
type: object?
properties:
androidSelector: AndroidSelector
- maxDepth: number?
+ maxDepth: int?
longClickable: boolean?
pkg: string?
res: string?
diff --git a/tests/library/browsercontext-storage-state.spec.ts b/tests/library/browsercontext-storage-state.spec.ts
index 4f4fca6cee201..8c11a086958f7 100644
--- a/tests/library/browsercontext-storage-state.spec.ts
+++ b/tests/library/browsercontext-storage-state.spec.ts
@@ -500,3 +500,74 @@ it('should support empty indexedDB', { annotation: { type: 'issue', description:
const context = await contextFactory({ storageState });
expect(await context.storageState({ indexedDB: true })).toEqual(storageState);
});
+
+it('should cleanup existing and set new storage state', async ({ contextFactory }, testInfo) => {
+ const context = await contextFactory();
+ const page = await context.newPage();
+ await page.route('**/*', route => {
+ route.fulfill({ body: '' }).catch(() => {});
+ });
+ await page.goto('https://www.example.com');
+ await page.evaluate(async () => {
+ localStorage['name1'] = 'value1';
+ document.cookie = 'username=John Doe';
+ return document.cookie;
+ });
+
+ const state = await context.storageState();
+ expect(state).toEqual({
+ cookies: [
+ expect.objectContaining({
+ domain: 'www.example.com',
+ name: 'username',
+ value: 'John Doe',
+ }),
+ ],
+ origins: [
+ {
+ origin: 'https://www.example.com',
+ localStorage: [{
+ name: 'name1',
+ value: 'value1',
+ }],
+ },
+ ],
+ });
+
+ await context.setStorageState({
+ cookies: [
+ {
+ domain: 'www.example.com',
+ name: 'foo',
+ value: 'bar',
+ path: '/',
+ expires: -1,
+ httpOnly: false,
+ secure: false,
+ sameSite: 'Lax',
+ },
+ ],
+ origins: [
+ {
+ origin: 'https://www.another.com',
+ localStorage: [{
+ name: 'name2',
+ value: 'value2',
+ }],
+ },
+ ],
+ });
+
+ expect(context.pages()).toHaveLength(1);
+ await expect(page).toHaveURL('https://www.example.com/');
+
+ await page.goto('https://www.another.com');
+ expect(await page.evaluate(() => document.cookie)).toBe('');
+ expect(await page.evaluate(() => window.localStorage['name1'])).toBe(undefined);
+ expect(await page.evaluate(() => window.localStorage['name2'])).toBe('value2');
+
+ await page.goto('https://www.example.com');
+ expect(await page.evaluate(() => document.cookie)).toBe('foo=bar');
+ expect(await page.evaluate(() => window.localStorage['name1'])).toBe(undefined);
+ expect(await page.evaluate(() => window.localStorage['name2'])).toBe(undefined);
+});
diff --git a/tests/library/chromium/tracing.spec.ts b/tests/library/chromium/tracing.spec.ts
index f61072fa32a08..f933ebbe2ce06 100644
--- a/tests/library/chromium/tracing.spec.ts
+++ b/tests/library/chromium/tracing.spec.ts
@@ -100,6 +100,7 @@ it('should support a buffer without a path', async ({ browser, server }) => {
const page = await browser.newPage();
await browser.startTracing(page, { screenshots: true });
await page.goto(server.PREFIX + '/grid.html');
+ await rafraf(page);
const trace = await browser.stopTracing();
expect(trace.toString()).toContain('screenshot');
await page.close();
diff --git a/tests/library/geolocation.spec.ts b/tests/library/geolocation.spec.ts
index 30ea11781d99c..525e5cd3092ce 100644
--- a/tests/library/geolocation.spec.ts
+++ b/tests/library/geolocation.spec.ts
@@ -85,7 +85,7 @@ it('should throw with missing latitude', async ({ contextFactory }) => {
} catch (e) {
error = e;
}
- expect(error.message).toContain('geolocation.latitude: expected number, got undefined');
+ expect(error.message).toContain('geolocation.latitude: expected float, got undefined');
});
it('should not modify passed default options object', async ({ browser }) => {
@@ -106,7 +106,7 @@ it('should throw with missing longitude in default options', async ({ browser })
} catch (e) {
error = e;
}
- expect(error.message).toContain('geolocation.longitude: expected number, got undefined');
+ expect(error.message).toContain('geolocation.longitude: expected float, got undefined');
});
it('should use context options', async ({ browser, server }) => {
diff --git a/tests/page/page-select-option.spec.ts b/tests/page/page-select-option.spec.ts
index 0355b4592bbd8..8b6afbd640d61 100644
--- a/tests/page/page-select-option.spec.ts
+++ b/tests/page/page-select-option.spec.ts
@@ -222,7 +222,7 @@ it('should throw if passed wrong types', async ({ page, server }) => {
} catch (e) {
error = e;
}
- expect(error.message).toContain('options[0].index: expected number, got string');
+ expect(error.message).toContain('options[0].index: expected integer, got string');
});
// @see https://github.com/GoogleChrome/puppeteer/issues/3327
it('should work when re-defining top-level Event class', async ({ page, server }) => {
diff --git a/utils/generate_channels.js b/utils/generate_channels.js
index febc92fb40c3c..77ae55d234909 100755
--- a/utils/generate_channels.js
+++ b/utils/generate_channels.js
@@ -41,8 +41,12 @@ function inlineType(type, indent, wrapEnums = false) {
return { ts: 'Binary', scheme: 'tBinary', optional };
if (type === 'json')
return { ts: 'any', scheme: 'tAny', optional };
- if (['string', 'boolean', 'number', 'undefined'].includes(type))
+ if (['string', 'boolean', 'undefined'].includes(type))
return { ts: type, scheme: `t${titleCase(type)}`, optional };
+ if (type === 'number')
+ throw new Error('Use "int" or "float" instead of "number" in protocol.yml');
+ if (type === 'int' || type === 'float')
+ return { ts: 'number', scheme: `t${titleCase(type)}`, optional };
if (channels.has(type)) {
let derived = derivedClasses.get(type) || [];
derived = [...derived, type];
@@ -153,7 +157,7 @@ const validator_ts = [
// This file is generated by ${path.basename(__filename)}, do not edit manually.
-import { scheme, tOptional, tObject, tBoolean, tNumber, tString, tAny, tEnum, tArray, tBinary, tChannel, tType } from './validatorPrimitives';
+import { scheme, tOptional, tObject, tBoolean, tInt, tFloat, tString, tAny, tEnum, tArray, tBinary, tChannel, tType } from './validatorPrimitives';
export type { Validator, ValidatorContext } from './validatorPrimitives';
export { ValidationError, findValidator, maybeFindValidator, createMetadataValidator } from './validatorPrimitives';
`];