From ba95543130c3b6e6d04eb90d5b3295899a0efebf Mon Sep 17 00:00:00 2001
From: Playwright Service <89237858+playwrightmachine@users.noreply.github.com>
Date: Thu, 2 Jun 2022 10:44:23 -0700
Subject: [PATCH] feat(roll): roll to ToT Playwright (02-06-22) (#583)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
---
dotnet/docs/api/class-route.mdx | 1 +
dotnet/docs/test-assertions.mdx | 4 +-
java/docs/test-assertions.mdx | 4 +-
nodejs/docs/test-assertions.mdx | 4 +-
nodejs/docs/testing-library.mdx | 256 ++++++++++++++++++++++++++++++++
python/docs/test-assertions.mdx | 8 +-
6 files changed, 272 insertions(+), 5 deletions(-)
create mode 100644 nodejs/docs/testing-library.mdx
diff --git a/dotnet/docs/api/class-route.mdx b/dotnet/docs/api/class-route.mdx
index 22bacc0615b45..4a2a05a259823 100644
--- a/dotnet/docs/api/class-route.mdx
+++ b/dotnet/docs/api/class-route.mdx
@@ -61,6 +61,7 @@ await page.RouteAsync("**/*", route =>
- `ContentType` <[string]?> If set, equals to setting `Content-Type` response header.#
- `Headers` <[IDictionary]?<[string], [string]>> Response headers. Header values will be converted to a string.#
- `Path` <[string]?> File path to respond with. The content type will be inferred from file extension. If `path` is a relative path, then it is resolved relative to the current working directory.#
+ - `Response` <[APIResponse]?> [APIResponse] to fulfill route's request with. Individual fields of the response (such as headers) can be overridden using fulfill options.#
- `Status` <[int]?> Response status code, defaults to `200`.#
- returns: <[void]>#
diff --git a/dotnet/docs/test-assertions.mdx b/dotnet/docs/test-assertions.mdx
index 2848afb7b8feb..cd9aaa61f9156 100644
--- a/dotnet/docs/test-assertions.mdx
+++ b/dotnet/docs/test-assertions.mdx
@@ -163,6 +163,7 @@ await Expect(locator).ToBeVisibleAsync();
## Expect(Locator).ToContainTextAsync(expected, options) {#locator-assertions-to-contain-text}
- `expected` <[string]|[Regex]|[IEnumerable]<[string]>|[IEnumerable]<[Regex]>> Expected substring or RegExp or a list of those.#
- `options` <`LocatorAssertionsToContainTextOptions?`>
+ - `IgnoreCase` <[bool]?> Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular expression flag if specified.#
- `Timeout` <[double]?> Time to retry the assertion for.#
- `UseInnerText` <[bool]?> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[void]>#
@@ -273,6 +274,7 @@ await Expect(locator).ToHaveJSPropertyAsync("loaded", true);
## Expect(Locator).ToHaveTextAsync(expected, options) {#locator-assertions-to-have-text}
- `expected` <[string]|[Regex]|[IEnumerable]<[string]>|[IEnumerable]<[Regex]>> Expected substring or RegExp or a list of those.#
- `options` <`LocatorAssertionsToHaveTextOptions?`>
+ - `IgnoreCase` <[bool]?> Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular expression flag if specified.#
- `Timeout` <[double]?> Time to retry the assertion for.#
- `UseInnerText` <[bool]?> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[void]>#
@@ -293,7 +295,7 @@ await Expect(locator).toHaveTextAsync(new string[]{ "Text 1", "Text 2", "Text 3"
```
## Expect(Locator).ToHaveValueAsync(value, options) {#locator-assertions-to-have-value}
-- `value` <[string]|[Regex]> Expected value.#
+- `value` <[string]|[Regex]|[IEnumerable]<[string]|[Regex]>> Expected value. A list of expected values can be used if the Locator is a `select` element with the `multiple` attribute.#
- `options` <`LocatorAssertionsToHaveValueOptions?`>
- `Timeout` <[double]?> Time to retry the assertion for.#
- returns: <[void]>#
diff --git a/java/docs/test-assertions.mdx b/java/docs/test-assertions.mdx
index 245650767f2fe..e224733992d9d 100644
--- a/java/docs/test-assertions.mdx
+++ b/java/docs/test-assertions.mdx
@@ -152,6 +152,7 @@ assertThat(page.locator(".my-element")).isVisible();
## assertThat(locator).containsText(expected[, options]) {#locator-assertions-to-contain-text}
- `expected` <[String]|[Pattern]|[String][]|[Pattern][]> Expected substring or RegExp or a list of those.#
- `options` <`LocatorAssertions.ContainsTextOptions`>
+ - `setIgnoreCase` <[boolean]> Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular expression flag if specified.#
- `setTimeout` <[double]> Time to retry the assertion for.#
- `setUseInnerText` <[boolean]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[void]>#
@@ -252,6 +253,7 @@ assertThat(page.locator("input")).hasJSProperty("loaded", true);
## assertThat(locator).hasText(expected[, options]) {#locator-assertions-to-have-text}
- `expected` <[String]|[Pattern]|[String][]|[Pattern][]> Expected substring or RegExp or a list of those.#
- `options` <`LocatorAssertions.HasTextOptions`>
+ - `setIgnoreCase` <[boolean]> Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular expression flag if specified.#
- `setTimeout` <[double]> Time to retry the assertion for.#
- `setUseInnerText` <[boolean]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[void]>#
@@ -270,7 +272,7 @@ assertThat(page.locator("list > .component")).hasText(new String[] {"Text 1", "T
```
## assertThat(locator).hasValue(value[, options]) {#locator-assertions-to-have-value}
-- `value` <[String]|[Pattern]> Expected value.#
+- `value` <[String]|[Pattern]|[List]<[String]|[Pattern]>> Expected value. A list of expected values can be used if the Locator is a `select` element with the `multiple` attribute.#
- `options` <`LocatorAssertions.HasValueOptions`>
- `setTimeout` <[double]> Time to retry the assertion for.#
- returns: <[void]>#
diff --git a/nodejs/docs/test-assertions.mdx b/nodejs/docs/test-assertions.mdx
index a016a24fe12e4..06edbfeded3d1 100644
--- a/nodejs/docs/test-assertions.mdx
+++ b/nodejs/docs/test-assertions.mdx
@@ -270,6 +270,7 @@ await expect(locator).toBeVisible();
## expect(locator).toContainText(expected[, options]) {#locator-assertions-to-contain-text}
- `expected` <[string]|[RegExp]|[Array]<[string]|[RegExp]>> Expected substring or RegExp or a list of those.#
- `options?` <[Object]>
+ - `ignoreCase?` <[boolean]> Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular expression flag if specified.#
- `timeout?` <[number]> Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`.#
- `useInnerText?` <[boolean]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[Promise]<[void]>>#
@@ -433,6 +434,7 @@ await expect(locator).toHaveScreenshot();
## expect(locator).toHaveText(expected[, options]) {#locator-assertions-to-have-text}
- `expected` <[string]|[RegExp]|[Array]<[string]|[RegExp]>> Expected substring or RegExp or a list of those.#
- `options?` <[Object]>
+ - `ignoreCase?` <[boolean]> Whether to perform case-insensitive match. `ignoreCase` option takes precedence over the corresponding regular expression flag if specified.#
- `timeout?` <[number]> Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`.#
- `useInnerText?` <[boolean]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[Promise]<[void]>>#
@@ -453,7 +455,7 @@ await expect(locator).toHaveText(['Text 1', 'Text 2', 'Text 3']);
```
## expect(locator).toHaveValue(value[, options]) {#locator-assertions-to-have-value}
-- `value` <[string]|[RegExp]> Expected value.#
+- `value` <[string]|[RegExp]|[Array]<[string]|[RegExp]>> Expected value. A list of expected values can be used if the Locator is a `select` element with the `multiple` attribute.#
- `options?` <[Object]>
- `timeout?` <[number]> Time to retry the assertion for. Defaults to `timeout` in `TestConfig.expect`.#
- returns: <[Promise]<[void]>>#
diff --git a/nodejs/docs/testing-library.mdx b/nodejs/docs/testing-library.mdx
new file mode 100644
index 0000000000000..54c660dafc339
--- /dev/null
+++ b/nodejs/docs/testing-library.mdx
@@ -0,0 +1,256 @@
+---
+id: testing-library
+title: "Migrating from Testing Library"
+---
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+- [Migration principles](#migration-principles)
+- [Cheat Sheet](#cheat-sheet)
+- [Example](#example)
+- [Migrating queries](#migrating-queries)
+- [Replacing `waitFor`](#replacing-waitfor)
+- [Replacing `within`](#replacing-within)
+- [Playwright Test Super Powers](#playwright-test-super-powers)
+- [Further Reading](#further-reading)
+
+## Migration principles
+
+This guide describes migration to Playwright's [Experimental Component Testing](./test-components) from [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro/), [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/), [Vue Testing Library](https://testing-library.com/docs/vue-testing-library/intro) and [Svelte Testing Library](https://testing-library.com/docs/svelte-testing-library/intro).
+
+:::note
+If you use DOM Testing Library in the browser (for example, you bundle end-to-end tests with webpack), you can switch directly to Playwright Test. Examples below are focused on component tests, but for end-to-end test you just need to replace `await mount` with `await page.goto('http://localhost:3000/')` to open the page under test.
+:::
+
+## Cheat Sheet
+
+| Testing Library | Playwright |
+|---------------------------------------------------------|-----------------------------------------------|
+| [screen](https://testing-library.com/docs/queries/about#screen) | [page](./api/class-page) and [component](./api/class-locator) |
+| [queries](https://testing-library.com/docs/queries/about) | [locators](./locators) |
+| [async helpers](https://testing-library.com/docs/dom-testing-library/api-async) | [assertions](./test-assertions) |
+| [user events](https://testing-library.com/docs/user-event/intro) | [actions](./api/class-locator) |
+| `await user.click(screen.getByText('Click me'))` | `await component.locator('text=Click me').click()` |
+| `await user.click(await screen.findByText('Click me'))` | `await component.locator('text=Click me').click()` |
+| `await user.type(screen.getByLabelText('Password'), 'secret')` | `await component.locator('text=Password').fill('secret')` |
+| `expect(screen.getByLabelText('Password')).toHaveValue('secret')` | `await expect(component.locator('text=Password')).toHaveValue('secret')` |
+| `screen.findByText('...')` | `component.locator('text=...')` |
+| `screen.getByTestId('...')` | `component.locator('data-testid=...')` |
+| `screen.queryByPlaceholderText('...')` | `component.locator('[placeholder="..."]')` |
+| `screen.getAllByRole('button', { pressed: true })` | `component.locator('role=button[pressed]')` |
+
+## Example
+
+Testing Library:
+
+```js
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+
+test('should sign in', async () => {
+ // Setup the page.
+ const user = userEvent.setup();
+ render();
+
+ // Perform actions.
+ await user.type(screen.getByLabelText('Username'), 'John');
+ await user.type(screen.getByLabelText('Password'), 'secret');
+ await user.click(screen.getByText('Sign in'));
+
+ // Verify signed in state by waiting until "Welcome" message appears.
+ await screen.findByText('Welcome, John');
+});
+```
+
+Line-by-line migration to Playwright Test:
+
+```js
+const { test, expect } = require('@playwright/experimental-ct-react'); // 1
+
+test('should sign in', async ({ page, mount }) => { // 2
+ // Setup the page.
+ const component = await mount(); // 3
+
+ // Perform actions.
+ await component.locator('text=Username').fill('John'); // 4
+ await component.locator('text=Password').fill('secret');
+ await component.locator('text=Sign in').click();
+
+ // Verify signed in state by waiting until "Welcome" message appears.
+ await expect(component.locator('text=Welcome, John')).toBeVisible(); // 5
+});
+```
+
+Migration highlights (see inline comments in the Playwright Test code snippet):
+1. Import everything from `@playwright/experimental-ct-react` (or -vue, -svelte) for component tests, or from `@playwright/test` for end-to-end tests.
+1. Test function is given a `page` that is isolated from other tests, and `mount` that renders a component in this page. These are two of the [useful fixtures](./api/class-fixtures) in Playwright Test.
+1. Replace `render` with `mount` that returns a [component locator](./locators).
+1. Use locators created with [locator.locator(selector[, options])](./api/class-locator.mdx#locator-locator) or [page.locator(selector[, options])](./api/class-page.mdx#page-locator) to perform most of the actions.
+1. Use [assertions](./test-assertions) to verify the state.
+
+## Migrating queries
+
+All queries like `getBy...`, `findBy...`, `queryBy...` and their multi-element counterparts are replaced with `page.locator('...')`. Locators always auto-wait and retry when needed, so you don't have to worry about choosing the right method. When you want to do a [list operation](./locators#lists), e.g. assert a list of texts, Playwright automatically performs multi-element opertations.
+1. `getByRole`: use [role selector](./selectors#role-selector) `component.locator('role=button[name="Sign up"]')`.
+1. `getByText`: use `component.locator('text=some value')` and other variations of the [text selector](./selectors#text-selector).
+1. `getByTestId`: use [test id selectors](./selectors#id-data-testid-data-test-id-data-test-selectors), for example `component.locator('data-testid=some value')`.
+1. `getByPlaceholderText`: use css alternative `component.locator('[placeholder="some value"]')`.
+1. `getByAltText`: use css alternative `component.locator('[alt="some value"]')` or [role selector](./selectors#role-selector) `component.locator('role=img[name="some value"]')`.
+1. `getByTitle`: use css alternative `component.locator('[title="some value"]')`
+
+## Replacing `waitFor`
+
+Playwright includes [assertions](./test-assertions) that automatically wait for the condition, so you don't usually need an explicit `waitFor`/`waitForElementToBeRemoved` call.
+
+```js
+// Testing Library
+await waitFor(() => {
+ expect(getByText('the lion king')).toBeInTheDocument()
+})
+await waitForElementToBeRemoved(() => queryByText('the mummy'))
+
+// Playwright
+await expect(page.locator('text=the lion king')).toBeVisible()
+await expect(page.locator('text=the mummy')).toBeHidden()
+```
+
+When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#polling) instead.
+
+```js
+await expect.poll(async () => {
+ const response = await page.request.get('https://api.example.com');
+ return response.status();
+}).toBe(200);
+```
+
+## Replacing `within`
+
+You can create a locator inside another locator with [locator.locator(selector[, options])](./api/class-locator.mdx#locator-locator) method.
+
+```js
+// Testing Library
+const messages = document.getElementById('messages')
+const helloMessage = within(messages).getByText('hello')
+
+// Playwright
+const messages = component.locator('id=messages')
+const helloMessage = messages.locator('text=hello')
+```
+
+## Playwright Test Super Powers
+
+Once you're on Playwright Test, you get a lot!
+- Full zero-configuration TypeScript support
+- Run tests across **all web engines** (Chrome, Firefox, Safari) on **any popular operating system** (Windows, macOS, Ubuntu)
+- Full support for multiple origins, [(i)frames](./api/class-frame), [tabs and contexts](./pages)
+- Run tests in isolation in parallel across multiple browsers
+- Built-in test artifact collection: [video recording](./test-configuration#record-video), [screenshots](./test-configuration#automatic-screenshots) and [playwright traces](./test-configuration#record-test-trace)
+
+Also you get all these ✨ awesome tools ✨ that come bundled with Playwright Test:
+- [Playwright Inspector](./inspector)
+- [Playwright Test Code generation](./auth#code-generation)
+- [Playwright Tracing](./trace-viewer) for post-mortem debugging
+
+## Further Reading
+
+Learn more about Playwright Test runner:
+- [Getting Started](./intro)
+- [Experimental Component Testing](./test-components)
+- [Locators](./api/class-locator)
+- [Selectors](./selectors)
+- [Assertions](./test-assertions)
+- [Auto-waiting](./actionability)
+
+[Accessibility]: ./api/class-accessibility.mdx "Accessibility"
+[Android]: ./api/class-android.mdx "Android"
+[AndroidDevice]: ./api/class-androiddevice.mdx "AndroidDevice"
+[AndroidInput]: ./api/class-androidinput.mdx "AndroidInput"
+[AndroidSocket]: ./api/class-androidsocket.mdx "AndroidSocket"
+[AndroidWebView]: ./api/class-androidwebview.mdx "AndroidWebView"
+[APIRequest]: ./api/class-apirequest.mdx "APIRequest"
+[APIRequestContext]: ./api/class-apirequestcontext.mdx "APIRequestContext"
+[APIResponse]: ./api/class-apiresponse.mdx "APIResponse"
+[APIResponseAssertions]: ./test-assertions.mdx "APIResponseAssertions"
+[Browser]: ./api/class-browser.mdx "Browser"
+[BrowserContext]: ./api/class-browsercontext.mdx "BrowserContext"
+[BrowserServer]: ./api/class-browserserver.mdx "BrowserServer"
+[BrowserType]: ./api/class-browsertype.mdx "BrowserType"
+[CDPSession]: ./api/class-cdpsession.mdx "CDPSession"
+[ConsoleMessage]: ./api/class-consolemessage.mdx "ConsoleMessage"
+[Coverage]: ./api/class-coverage.mdx "Coverage"
+[Dialog]: ./api/class-dialog.mdx "Dialog"
+[Download]: ./api/class-download.mdx "Download"
+[Electron]: ./api/class-electron.mdx "Electron"
+[ElectronApplication]: ./api/class-electronapplication.mdx "ElectronApplication"
+[ElementHandle]: ./api/class-elementhandle.mdx "ElementHandle"
+[FileChooser]: ./api/class-filechooser.mdx "FileChooser"
+[Frame]: ./api/class-frame.mdx "Frame"
+[FrameLocator]: ./api/class-framelocator.mdx "FrameLocator"
+[JSHandle]: ./api/class-jshandle.mdx "JSHandle"
+[Keyboard]: ./api/class-keyboard.mdx "Keyboard"
+[Locator]: ./api/class-locator.mdx "Locator"
+[LocatorAssertions]: ./test-assertions.mdx "LocatorAssertions"
+[Logger]: ./api/class-logger.mdx "Logger"
+[Mouse]: ./api/class-mouse.mdx "Mouse"
+[Page]: ./api/class-page.mdx "Page"
+[PageAssertions]: ./test-assertions.mdx "PageAssertions"
+[Playwright]: ./api/class-playwright.mdx "Playwright"
+[PlaywrightAssertions]: ./test-assertions.mdx "PlaywrightAssertions"
+[Request]: ./api/class-request.mdx "Request"
+[Response]: ./api/class-response.mdx "Response"
+[Route]: ./api/class-route.mdx "Route"
+[ScreenshotAssertions]: ./test-assertions.mdx "ScreenshotAssertions"
+[Selectors]: ./api/class-selectors.mdx "Selectors"
+[TimeoutError]: ./api/class-timeouterror.mdx "TimeoutError"
+[Touchscreen]: ./api/class-touchscreen.mdx "Touchscreen"
+[Tracing]: ./api/class-tracing.mdx "Tracing"
+[Video]: ./api/class-video.mdx "Video"
+[WebSocket]: ./api/class-websocket.mdx "WebSocket"
+[Worker]: ./api/class-worker.mdx "Worker"
+[Fixtures]: ./api/class-fixtures.mdx "Fixtures"
+[Test]: ./api/class-test.mdx "Test"
+[TestConfig]: ./api/class-testconfig.mdx "TestConfig"
+[TestError]: ./api/class-testerror.mdx "TestError"
+[TestInfo]: ./api/class-testinfo.mdx "TestInfo"
+[TestOptions]: ./api/class-testoptions.mdx "TestOptions"
+[TestProject]: ./api/class-testproject.mdx "TestProject"
+[WorkerInfo]: ./api/class-workerinfo.mdx "WorkerInfo"
+[Location]: ./api/class-location.mdx "Location"
+[Reporter]: ./api/class-reporter.mdx "Reporter"
+[Suite]: ./api/class-suite.mdx "Suite"
+[TestCase]: ./api/class-testcase.mdx "TestCase"
+[TestResult]: ./api/class-testresult.mdx "TestResult"
+[TestStep]: ./api/class-teststep.mdx "TestStep"
+[Element]: https://developer.mozilla.org/en-US/docs/Web/API/element "Element"
+[EvaluationArgument]: ./evaluating.mdx#evaluation-argument "EvaluationArgument"
+[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise"
+[iterator]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols "Iterator"
+[origin]: https://developer.mozilla.org/en-US/docs/Glossary/Origin "Origin"
+[selector]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors "selector"
+[Serializable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description "Serializable"
+[UIEvent.detail]: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail "UIEvent.detail"
+[UnixTime]: https://en.wikipedia.org/wiki/Unix_time "Unix Time"
+[xpath]: https://developer.mozilla.org/en-US/docs/Web/XPath "xpath"
+
+[Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array "Array"
+[boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type "Boolean"
+[Buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer "Buffer"
+[ChildProcess]: https://nodejs.org/api/child_process.html "ChildProcess"
+[Error]: https://nodejs.org/api/errors.html#errors_class_error "Error"
+[EventEmitter]: https://nodejs.org/api/events.html#events_class_eventemitter "EventEmitter"
+[function]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function "Function"
+[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map "Map"
+[null]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null "null"
+[number]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type "Number"
+[Object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object "Object"
+[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise"
+[Readable]: https://nodejs.org/api/stream.html#stream_class_stream_readable "Readable"
+[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp "RegExp"
+[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type "string"
+[void]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined "void"
+[URL]: https://nodejs.org/api/url.html "URL"
+
+[all available image tags]: https://mcr.microsoft.com/v2/playwright/tags/list "all available image tags"
+[Docker Hub]: https://hub.docker.com/_/microsoft-playwright "Docker Hub"
+[Dockerfile.focal]: https://github.com/microsoft/playwright/blob/master/utils/docker/Dockerfile.focal "Dockerfile.focal"
diff --git a/python/docs/test-assertions.mdx b/python/docs/test-assertions.mdx
index 7c2e004d11a44..08dfe4e11b9de 100644
--- a/python/docs/test-assertions.mdx
+++ b/python/docs/test-assertions.mdx
@@ -137,6 +137,7 @@ The opposite of [expect(locator).to_be_visible(**kwargs)](./test-assertions.mdx#
## expect(locator).not_to_contain_text(expected, **kwargs) {#locator-assertions-not-to-contain-text}
- `expected` <[str]|[Pattern]|[List]\[[str]|[Pattern]\]> Expected substring or RegExp or a list of those.#
+- `ignore_case` <[bool]> Whether to perform case-insensitive match. `ignore_case` option takes precedence over the corresponding regular expression flag if specified.#
- `timeout` <[float]> Time to retry the assertion for.#
- `use_inner_text` <[bool]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[NoneType]>#
@@ -190,6 +191,7 @@ The opposite of [expect(locator).to_have_js_property(name, value, **kwargs)](./t
## expect(locator).not_to_have_text(expected, **kwargs) {#locator-assertions-not-to-have-text}
- `expected` <[str]|[Pattern]|[List]\[[str]|[Pattern]\]> Expected substring or RegExp or a list of those.#
+- `ignore_case` <[bool]> Whether to perform case-insensitive match. `ignore_case` option takes precedence over the corresponding regular expression flag if specified.#
- `timeout` <[float]> Time to retry the assertion for.#
- `use_inner_text` <[bool]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[NoneType]>#
@@ -197,7 +199,7 @@ The opposite of [expect(locator).to_have_js_property(name, value, **kwargs)](./t
The opposite of [expect(locator).to_have_text(expected, **kwargs)](./test-assertions.mdx#locator-assertions-to-have-text).
## expect(locator).not_to_have_value(value, **kwargs) {#locator-assertions-not-to-have-value}
-- `value` <[str]|[Pattern]> Expected value.#
+- `value` <[str]|[Pattern]|[List]\[[str]|[Pattern]\]> Expected value. A list of expected values can be used if the Locator is a `select` element with the `multiple` attribute.#
- `timeout` <[float]> Time to retry the assertion for.#
- returns: <[NoneType]>#
@@ -494,6 +496,7 @@ await expect(locator).to_be_visible()
## expect(locator).to_contain_text(expected, **kwargs) {#locator-assertions-to-contain-text}
- `expected` <[str]|[Pattern]|[List]\[[str]|[Pattern]\]> Expected substring or RegExp or a list of those.#
+- `ignore_case` <[bool]> Whether to perform case-insensitive match. `ignore_case` option takes precedence over the corresponding regular expression flag if specified.#
- `timeout` <[float]> Time to retry the assertion for.#
- `use_inner_text` <[bool]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[NoneType]>#
@@ -827,6 +830,7 @@ await expect(locator).to_have_js_property("loaded", True)
## expect(locator).to_have_text(expected, **kwargs) {#locator-assertions-to-have-text}
- `expected` <[str]|[Pattern]|[List]\[[str]|[Pattern]\]> Expected substring or RegExp or a list of those.#
+- `ignore_case` <[bool]> Whether to perform case-insensitive match. `ignore_case` option takes precedence over the corresponding regular expression flag if specified.#
- `timeout` <[float]> Time to retry the assertion for.#
- `use_inner_text` <[bool]> Whether to use `element.innerText` instead of `element.textContent` when retrieving DOM node text.#
- returns: <[NoneType]>#
@@ -900,7 +904,7 @@ await expect(locator).to_have_text(["Text 1", "Text 2", "Text 3"])
## expect(locator).to_have_value(value, **kwargs) {#locator-assertions-to-have-value}
-- `value` <[str]|[Pattern]> Expected value.#
+- `value` <[str]|[Pattern]|[List]\[[str]|[Pattern]\]> Expected value. A list of expected values can be used if the Locator is a `select` element with the `multiple` attribute.#
- `timeout` <[float]> Time to retry the assertion for.#
- returns: <[NoneType]>#