Compare commits
16 commits
main
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a32d04f00e | ||
|
|
8b3ba3f34e | ||
|
|
d93029f32f | ||
|
|
0c6217a85f | ||
|
|
f96b487030 | ||
|
|
937424fb59 | ||
|
|
3d2ffd0fe9 | ||
|
|
dba1319300 | ||
|
|
90f959a11c | ||
|
|
13e6e48a2b | ||
|
|
8762407038 | ||
|
|
f9145b1a7e | ||
|
|
2c17b1f0d3 | ||
|
|
d5943def35 | ||
|
|
73fdd2505d | ||
|
|
13f4531da4 |
|
|
@ -1,6 +1,6 @@
|
||||||
# 🎭 Playwright
|
# 🎭 Playwright
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop --> [](https://aka.ms/playwright/discord)
|
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop --> [](https://aka.ms/playwright/discord)
|
||||||
|
|
||||||
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
|
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
|
||||||
|
|
||||||
| | Linux | macOS | Windows |
|
| | Linux | macOS | Windows |
|
||||||
| :--- | :---: | :---: | :---: |
|
| :--- | :---: | :---: | :---: |
|
||||||
| Chromium <!-- GEN:chromium-version -->129.0.6668.22<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Chromium <!-- GEN:chromium-version -->129.0.6668.29<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| WebKit <!-- GEN:webkit-version -->18.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| WebKit <!-- GEN:webkit-version -->18.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| Firefox <!-- GEN:firefox-version -->130.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Firefox <!-- GEN:firefox-version -->130.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.delete.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.delete.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.delete.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.delete.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.delete.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.delete.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -150,6 +150,9 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.delete.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.delete.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.delete.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.delete.headers = %%-js-python-csharp-fetch-option-headers-%%
|
### option: APIRequestContext.delete.headers = %%-js-python-csharp-fetch-option-headers-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
|
@ -303,7 +306,7 @@ Target URL or Request to get all parameters from.
|
||||||
### option: APIRequestContext.fetch.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.fetch.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.fetch.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.fetch.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.fetch.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.fetch.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -312,6 +315,9 @@ Target URL or Request to get all parameters from.
|
||||||
### option: APIRequestContext.fetch.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.fetch.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.fetch.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.fetch.method
|
### option: APIRequestContext.fetch.method
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
* langs: js, python, csharp
|
* langs: js, python, csharp
|
||||||
|
|
@ -418,7 +424,7 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query
|
||||||
### option: APIRequestContext.get.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.get.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.get.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.get.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.get.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.get.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -427,6 +433,9 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query
|
||||||
### option: APIRequestContext.get.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.get.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.get.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.get.headers = %%-js-python-csharp-fetch-option-headers-%%
|
### option: APIRequestContext.get.headers = %%-js-python-csharp-fetch-option-headers-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
|
@ -477,7 +486,7 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.head.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.head.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.head.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.head.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.head.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.head.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -486,6 +495,9 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.head.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.head.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.head.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.head.headers = %%-js-python-csharp-fetch-option-headers-%%
|
### option: APIRequestContext.head.headers = %%-js-python-csharp-fetch-option-headers-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
|
@ -536,7 +548,7 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.patch.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.patch.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.patch.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.patch.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.patch.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.patch.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -545,6 +557,9 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.patch.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.patch.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.patch.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.patch.headers = %%-js-python-csharp-fetch-option-headers-%%
|
### option: APIRequestContext.patch.headers = %%-js-python-csharp-fetch-option-headers-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
|
@ -716,7 +731,7 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar
|
||||||
### option: APIRequestContext.post.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.post.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.post.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.post.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.post.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.post.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -725,6 +740,9 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar
|
||||||
### option: APIRequestContext.post.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.post.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.post.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.post.headers = %%-js-python-csharp-fetch-option-headers-%%
|
### option: APIRequestContext.post.headers = %%-js-python-csharp-fetch-option-headers-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
|
@ -775,7 +793,7 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.put.params = %%-js-fetch-option-params-%%
|
### option: APIRequestContext.put.params = %%-js-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### param: APIRequestContext.put.params = %%-java-csharp-fetch-params-%%
|
### param: APIRequestContext.put.params = %%-java-fetch-params-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: APIRequestContext.put.params = %%-python-fetch-option-params-%%
|
### option: APIRequestContext.put.params = %%-python-fetch-option-params-%%
|
||||||
|
|
@ -784,6 +802,9 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.put.params = %%-csharp-fetch-option-params-%%
|
### option: APIRequestContext.put.params = %%-csharp-fetch-option-params-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.put.paramsString = %%-csharp-fetch-option-paramsString-%%
|
||||||
|
* since: v1.47
|
||||||
|
|
||||||
### option: APIRequestContext.put.headers = %%-js-python-csharp-fetch-option-headers-%%
|
### option: APIRequestContext.put.headers = %%-js-python-csharp-fetch-option-headers-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,7 @@ Query parameters to be sent with the URL.
|
||||||
|
|
||||||
## python-fetch-option-params
|
## python-fetch-option-params
|
||||||
* langs: python
|
* langs: python
|
||||||
- `params` <[Object]<[string], [string]|[float]|[boolean]>>
|
- `params` <[Object]<[string], [string]|[float]|[boolean]>|[string]>
|
||||||
|
|
||||||
Query parameters to be sent with the URL.
|
Query parameters to be sent with the URL.
|
||||||
|
|
||||||
|
|
@ -374,7 +374,13 @@ Query parameters to be sent with the URL.
|
||||||
|
|
||||||
Query parameters to be sent with the URL.
|
Query parameters to be sent with the URL.
|
||||||
|
|
||||||
## java-csharp-fetch-params
|
## csharp-fetch-option-paramsString
|
||||||
|
* langs: csharp
|
||||||
|
- `paramsString` <[string]>
|
||||||
|
|
||||||
|
Query parameters to be sent with the URL.
|
||||||
|
|
||||||
|
## java-fetch-params
|
||||||
* langs: java
|
* langs: java
|
||||||
- `options` ?<[RequestOptions]>
|
- `options` ?<[RequestOptions]>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,26 @@ toc_max_heading_level: 2
|
||||||
|
|
||||||
### Network Tab improvements
|
### Network Tab improvements
|
||||||
|
|
||||||
The Network tab in the trace viewer now allows searching and filtering by asset type:
|
The Network tab in the trace viewer has several nice improvements:
|
||||||
|
|
||||||
|
- filtering by asset type and URL
|
||||||
|
- better display of query string parameters
|
||||||
|
- preview of font assets
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
And for fonts, it now shows a nice preview:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
- The `mcr.microsoft.com/playwright-dotnet:v1.47.0` now serves a Playwright image based on Ubuntu 24.04 Noble.
|
- The `mcr.microsoft.com/playwright/dotnet:v1.47.0` now serves a Playwright image based on Ubuntu 24.04 Noble.
|
||||||
To use the 22.04 jammy-based image, please use `mcr.microsoft.com/playwright-dotnet:v1.47.0-jammy` instead.
|
To use the 22.04 jammy-based image, please use `mcr.microsoft.com/playwright/dotnet:v1.47.0-jammy` instead.
|
||||||
|
- The `:latest`/`:focal`/`:jammy` tag for Playwright Docker images is no longer being published. Pin to a specific version for better stability and reproducibility.
|
||||||
- TLS client certificates can now be passed from memory by passing [`option: cert`] and [`option: key`] as byte arrays instead of file paths.
|
- TLS client certificates can now be passed from memory by passing [`option: cert`] and [`option: key`] as byte arrays instead of file paths.
|
||||||
- [`option: noWaitAfter`] in [`method: Locator.selectOption`] was deprecated.
|
- [`option: noWaitAfter`] in [`method: Locator.selectOption`] was deprecated.
|
||||||
- We've seen reports of WebGL in Webkit misbehaving on GitHub Actions `macos-13`. We recommend upgrading GitHub Actions to `macos-14`.
|
- We've seen reports of WebGL in Webkit misbehaving on GitHub Actions `macos-13`. We recommend upgrading GitHub Actions to `macos-14`.
|
||||||
|
|
||||||
### Browser Versions
|
### Browser Versions
|
||||||
|
|
||||||
- Chromium 129.0.6668.22
|
- Chromium 129.0.6668.29
|
||||||
- Mozilla Firefox 130.0
|
- Mozilla Firefox 130.0
|
||||||
- WebKit 18.0
|
- WebKit 18.0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,26 @@ toc_max_heading_level: 2
|
||||||
|
|
||||||
### Network Tab improvements
|
### Network Tab improvements
|
||||||
|
|
||||||
The Network tab in the trace viewer now allows searching and filtering by asset type:
|
The Network tab in the trace viewer has several nice improvements:
|
||||||
|
|
||||||
|
- filtering by asset type and URL
|
||||||
|
- better display of query string parameters
|
||||||
|
- preview of font assets
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
And for fonts, it now shows a nice preview:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
- The `mcr.microsoft.com/playwright-java:v1.47.0` now serves a Playwright image based on Ubuntu 24.04 Noble.
|
- The `mcr.microsoft.com/playwright/java:v1.47.0` now serves a Playwright image based on Ubuntu 24.04 Noble.
|
||||||
To use the 22.02 jammy-based image, please use `mcr.microsoft.com/playwright-java:v1.47.0-jammy` instead.
|
To use the 22.02 jammy-based image, please use `mcr.microsoft.com/playwright/java:v1.47.0-jammy` instead.
|
||||||
|
- The `:latest`/`:focal`/`:jammy` tag for Playwright Docker images is no longer being published. Pin to a specific version for better stability and reproducibility.
|
||||||
- TLS client certificates can now be passed from memory by passing [`option: cert`] and [`option: key`] as byte arrays instead of file paths.
|
- TLS client certificates can now be passed from memory by passing [`option: cert`] and [`option: key`] as byte arrays instead of file paths.
|
||||||
- [`option: noWaitAfter`] in [`method: Locator.selectOption`] was deprecated.
|
- [`option: noWaitAfter`] in [`method: Locator.selectOption`] was deprecated.
|
||||||
- We've seen reports of WebGL in Webkit misbehaving on GitHub Actions `macos-13`. We recommend upgrading GitHub Actions to `macos-14`.
|
- We've seen reports of WebGL in Webkit misbehaving on GitHub Actions `macos-13`. We recommend upgrading GitHub Actions to `macos-14`.
|
||||||
|
|
||||||
### Browser Versions
|
### Browser Versions
|
||||||
|
|
||||||
- Chromium 129.0.6668.22
|
- Chromium 129.0.6668.29
|
||||||
- Mozilla Firefox 130.0
|
- Mozilla Firefox 130.0
|
||||||
- WebKit 18.0
|
- WebKit 18.0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,14 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
|
||||||
|
|
||||||
### Network Tab improvements
|
### Network Tab improvements
|
||||||
|
|
||||||
The Network tab in the UI mode and trace viewer now allows searching and filtering by asset type:
|
The Network tab in the UI mode and trace viewer has several nice improvements:
|
||||||
|
|
||||||
|
- filtering by asset type and URL
|
||||||
|
- better display of query string parameters
|
||||||
|
- preview of font assets
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
And for fonts, it now shows a nice preview:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
### `--tsconfig` CLI option
|
### `--tsconfig` CLI option
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ test('query params', async ({ request }) => {
|
||||||
|
|
||||||
### Browser Versions
|
### Browser Versions
|
||||||
|
|
||||||
- Chromium 129.0.6668.22
|
- Chromium 129.0.6668.29
|
||||||
- Mozilla Firefox 130.0
|
- Mozilla Firefox 130.0
|
||||||
- WebKit 18.0
|
- WebKit 18.0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,26 @@ toc_max_heading_level: 2
|
||||||
|
|
||||||
### Network Tab improvements
|
### Network Tab improvements
|
||||||
|
|
||||||
The Network tab in the trace viewer now allows searching and filtering by asset type:
|
The Network tab in the trace viewer has several nice improvements:
|
||||||
|
|
||||||
|
- filtering by asset type and URL
|
||||||
|
- better display of query string parameters
|
||||||
|
- preview of font assets
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
And for fonts, it now shows a nice preview:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### Miscellaneous
|
### Miscellaneous
|
||||||
|
|
||||||
- The `mcr.microsoft.com/playwright-python:v1.47.0` now serves a Playwright image based on Ubuntu 24.04 Noble.
|
- The `mcr.microsoft.com/playwright/python:v1.47.0` now serves a Playwright image based on Ubuntu 24.04 Noble.
|
||||||
To use the 22.04 jammy-based image, please use `mcr.microsoft.com/playwright-python:v1.47.0-jammy` instead.
|
To use the 22.04 jammy-based image, please use `mcr.microsoft.com/playwright/python:v1.47.0-jammy` instead.
|
||||||
|
- The `:latest`/`:focal`/`:jammy` tag for Playwright Docker images is no longer being published. Pin to a specific version for better stability and reproducibility.
|
||||||
- TLS client certificates can now be passed from memory by passing [`option: cert`] and [`option: key`] as bytes instead of file paths.
|
- TLS client certificates can now be passed from memory by passing [`option: cert`] and [`option: key`] as bytes instead of file paths.
|
||||||
- [`option: noWaitAfter`] in [`method: Locator.selectOption`] was deprecated.
|
- [`option: noWaitAfter`] in [`method: Locator.selectOption`] was deprecated.
|
||||||
- We've seen reports of WebGL in Webkit misbehaving on GitHub Actions `macos-13`. We recommend upgrading GitHub Actions to `macos-14`.
|
- We've seen reports of WebGL in Webkit misbehaving on GitHub Actions `macos-13`. We recommend upgrading GitHub Actions to `macos-14`.
|
||||||
|
|
||||||
### Browser Versions
|
### Browser Versions
|
||||||
|
|
||||||
- Chromium 129.0.6668.22
|
- Chromium 129.0.6668.29
|
||||||
- Mozilla Firefox 130.0
|
- Mozilla Firefox 130.0
|
||||||
- WebKit 18.0
|
- WebKit 18.0
|
||||||
|
|
||||||
|
|
|
||||||
68
package-lock.json
generated
68
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
@ -7912,10 +7912,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright": {
|
"packages/playwright": {
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -7929,11 +7929,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-chromium": {
|
"packages/playwright-browser-chromium": {
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
|
|
@ -7941,11 +7941,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-firefox": {
|
"packages/playwright-browser-firefox": {
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
|
|
@ -7953,22 +7953,22 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-webkit": {
|
"packages/playwright-browser-webkit": {
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-chromium": {
|
"packages/playwright-chromium": {
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -7978,7 +7978,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-core": {
|
"packages/playwright-core": {
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
|
|
@ -7989,11 +7989,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-core": {
|
"packages/playwright-ct-core": {
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.47.0-next",
|
"playwright": "1.47.2",
|
||||||
"playwright-core": "1.47.0-next",
|
"playwright-core": "1.47.2",
|
||||||
"vite": "^5.2.8"
|
"vite": "^5.2.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -8002,10 +8002,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react": {
|
"packages/playwright-ct-react": {
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8017,10 +8017,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react17": {
|
"packages/playwright-ct-react17": {
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8032,10 +8032,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-solid": {
|
"packages/playwright-ct-solid": {
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8050,10 +8050,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-svelte": {
|
"packages/playwright-ct-svelte": {
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8068,10 +8068,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue": {
|
"packages/playwright-ct-vue": {
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8083,10 +8083,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue2": {
|
"packages/playwright-ct-vue2": {
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8135,11 +8135,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-firefox": {
|
"packages/playwright-firefox": {
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8150,10 +8150,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-test": {
|
"packages/playwright-test": {
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.47.0-next"
|
"playwright": "1.47.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8163,11 +8163,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-webkit": {
|
"packages/playwright-webkit": {
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright package that automatically installs Chromium",
|
"description": "Playwright package that automatically installs Chromium",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright package that automatically installs Firefox",
|
"description": "Playwright package that automatically installs Firefox",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright package that automatically installs WebKit",
|
"description": "Playwright package that automatically installs WebKit",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -27,6 +27,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-chromium",
|
"name": "playwright-chromium",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate Chromium",
|
"description": "A high-level API to automate Chromium",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
"browsers": [
|
"browsers": [
|
||||||
{
|
{
|
||||||
"name": "chromium",
|
"name": "chromium",
|
||||||
"revision": "1133",
|
"revision": "1134",
|
||||||
"installByDefault": true,
|
"installByDefault": true,
|
||||||
"browserVersion": "129.0.6668.22"
|
"browserVersion": "129.0.6668.29"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chromium-tip-of-tree",
|
"name": "chromium-tip-of-tree",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-core",
|
"name": "playwright-core",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
|
|
@ -690,16 +690,15 @@ class FrameSession {
|
||||||
if (!frame || this._eventBelongsToStaleFrame(frame._id))
|
if (!frame || this._eventBelongsToStaleFrame(frame._id))
|
||||||
return;
|
return;
|
||||||
const delegate = new CRExecutionContext(this._client, contextPayload);
|
const delegate = new CRExecutionContext(this._client, contextPayload);
|
||||||
let worldName: types.World;
|
let worldName: types.World|null = null;
|
||||||
if (contextPayload.auxData && !!contextPayload.auxData.isDefault)
|
if (contextPayload.auxData && !!contextPayload.auxData.isDefault)
|
||||||
worldName = 'main';
|
worldName = 'main';
|
||||||
else if (contextPayload.name === UTILITY_WORLD_NAME)
|
else if (contextPayload.name === UTILITY_WORLD_NAME)
|
||||||
worldName = 'utility';
|
worldName = 'utility';
|
||||||
else
|
|
||||||
return;
|
|
||||||
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
||||||
(context as any)[contextDelegateSymbol] = delegate;
|
(context as any)[contextDelegateSymbol] = delegate;
|
||||||
frame._contextCreated(worldName, context);
|
if (worldName)
|
||||||
|
frame._contextCreated(worldName, context);
|
||||||
this._contextIdToContext.set(contextPayload.id, context);
|
this._contextIdToContext.set(contextPayload.id, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
|
||||||
return formatter.format();
|
return formatter.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.ContentFrame()`);
|
const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.ContentFrame`);
|
||||||
const subject = `${pageAlias}${locators.join('')}`;
|
const subject = `${pageAlias}${locators.join('')}`;
|
||||||
const signals = toSignalMap(action);
|
const signals = toSignalMap(action);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {
|
||||||
return formatter.format();
|
return formatter.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.content_frame()`);
|
const locators = actionInContext.frame.framePath.map(selector => `.${this._asLocator(selector)}.content_frame`);
|
||||||
const subject = `${pageAlias}${locators.join('')}`;
|
const subject = `${pageAlias}${locators.join('')}`;
|
||||||
const signals = toSignalMap(action);
|
const signals = toSignalMap(action);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"Galaxy S5": {
|
"Galaxy S5": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -121,7 +121,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S5 landscape": {
|
"Galaxy S5 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -132,7 +132,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S8": {
|
"Galaxy S8": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 740
|
"height": 740
|
||||||
|
|
@ -143,7 +143,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S8 landscape": {
|
"Galaxy S8 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 740,
|
"width": 740,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -154,7 +154,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S9+": {
|
"Galaxy S9+": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 320,
|
"width": 320,
|
||||||
"height": 658
|
"height": 658
|
||||||
|
|
@ -165,7 +165,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy S9+ landscape": {
|
"Galaxy S9+ landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 658,
|
"width": 658,
|
||||||
"height": 320
|
"height": 320
|
||||||
|
|
@ -176,7 +176,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy Tab S4": {
|
"Galaxy Tab S4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 712,
|
"width": 712,
|
||||||
"height": 1138
|
"height": 1138
|
||||||
|
|
@ -187,7 +187,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Galaxy Tab S4 landscape": {
|
"Galaxy Tab S4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 1138,
|
"width": 1138,
|
||||||
"height": 712
|
"height": 712
|
||||||
|
|
@ -1098,7 +1098,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"LG Optimus L70": {
|
"LG Optimus L70": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 384,
|
"width": 384,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1109,7 +1109,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"LG Optimus L70 landscape": {
|
"LG Optimus L70 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 384
|
"height": 384
|
||||||
|
|
@ -1120,7 +1120,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 550": {
|
"Microsoft Lumia 550": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1131,7 +1131,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 550 landscape": {
|
"Microsoft Lumia 550 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1142,7 +1142,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 950": {
|
"Microsoft Lumia 950": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1153,7 +1153,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Microsoft Lumia 950 landscape": {
|
"Microsoft Lumia 950 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36 Edge/14.14263",
|
"userAgent": "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36 Edge/14.14263",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1164,7 +1164,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 10": {
|
"Nexus 10": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 800,
|
"width": 800,
|
||||||
"height": 1280
|
"height": 1280
|
||||||
|
|
@ -1175,7 +1175,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 10 landscape": {
|
"Nexus 10 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 1280,
|
"width": 1280,
|
||||||
"height": 800
|
"height": 800
|
||||||
|
|
@ -1186,7 +1186,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 4": {
|
"Nexus 4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 384,
|
"width": 384,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1197,7 +1197,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 4 landscape": {
|
"Nexus 4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 384
|
"height": 384
|
||||||
|
|
@ -1208,7 +1208,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5": {
|
"Nexus 5": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1219,7 +1219,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5 landscape": {
|
"Nexus 5 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1230,7 +1230,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5X": {
|
"Nexus 5X": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 732
|
"height": 732
|
||||||
|
|
@ -1241,7 +1241,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 5X landscape": {
|
"Nexus 5X landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 732,
|
"width": 732,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1252,7 +1252,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6": {
|
"Nexus 6": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 732
|
"height": 732
|
||||||
|
|
@ -1263,7 +1263,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6 landscape": {
|
"Nexus 6 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 732,
|
"width": 732,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1274,7 +1274,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6P": {
|
"Nexus 6P": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 732
|
"height": 732
|
||||||
|
|
@ -1285,7 +1285,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 6P landscape": {
|
"Nexus 6P landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 732,
|
"width": 732,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1296,7 +1296,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 7": {
|
"Nexus 7": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 600,
|
"width": 600,
|
||||||
"height": 960
|
"height": 960
|
||||||
|
|
@ -1307,7 +1307,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Nexus 7 landscape": {
|
"Nexus 7 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 960,
|
"width": 960,
|
||||||
"height": 600
|
"height": 600
|
||||||
|
|
@ -1362,7 +1362,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"Pixel 2": {
|
"Pixel 2": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 411,
|
"width": 411,
|
||||||
"height": 731
|
"height": 731
|
||||||
|
|
@ -1373,7 +1373,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 2 landscape": {
|
"Pixel 2 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 731,
|
"width": 731,
|
||||||
"height": 411
|
"height": 411
|
||||||
|
|
@ -1384,7 +1384,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 2 XL": {
|
"Pixel 2 XL": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 411,
|
"width": 411,
|
||||||
"height": 823
|
"height": 823
|
||||||
|
|
@ -1395,7 +1395,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 2 XL landscape": {
|
"Pixel 2 XL landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 823,
|
"width": 823,
|
||||||
"height": 411
|
"height": 411
|
||||||
|
|
@ -1406,7 +1406,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 3": {
|
"Pixel 3": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 393,
|
"width": 393,
|
||||||
"height": 786
|
"height": 786
|
||||||
|
|
@ -1417,7 +1417,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 3 landscape": {
|
"Pixel 3 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 786,
|
"width": 786,
|
||||||
"height": 393
|
"height": 393
|
||||||
|
|
@ -1428,7 +1428,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4": {
|
"Pixel 4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 353,
|
"width": 353,
|
||||||
"height": 745
|
"height": 745
|
||||||
|
|
@ -1439,7 +1439,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4 landscape": {
|
"Pixel 4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 745,
|
"width": 745,
|
||||||
"height": 353
|
"height": 353
|
||||||
|
|
@ -1450,7 +1450,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4a (5G)": {
|
"Pixel 4a (5G)": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 892
|
"height": 892
|
||||||
|
|
@ -1465,7 +1465,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 4a (5G) landscape": {
|
"Pixel 4a (5G) landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"height": 892,
|
"height": 892,
|
||||||
"width": 412
|
"width": 412
|
||||||
|
|
@ -1480,7 +1480,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 5": {
|
"Pixel 5": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 393,
|
"width": 393,
|
||||||
"height": 851
|
"height": 851
|
||||||
|
|
@ -1495,7 +1495,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 5 landscape": {
|
"Pixel 5 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 851,
|
"width": 851,
|
||||||
"height": 393
|
"height": 393
|
||||||
|
|
@ -1510,7 +1510,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 7": {
|
"Pixel 7": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 412,
|
"width": 412,
|
||||||
"height": 915
|
"height": 915
|
||||||
|
|
@ -1525,7 +1525,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Pixel 7 landscape": {
|
"Pixel 7 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 915,
|
"width": 915,
|
||||||
"height": 412
|
"height": 412
|
||||||
|
|
@ -1540,7 +1540,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Moto G4": {
|
"Moto G4": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 360,
|
"width": 360,
|
||||||
"height": 640
|
"height": 640
|
||||||
|
|
@ -1551,7 +1551,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Moto G4 landscape": {
|
"Moto G4 landscape": {
|
||||||
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Mobile Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Mobile Safari/537.36",
|
||||||
"viewport": {
|
"viewport": {
|
||||||
"width": 640,
|
"width": 640,
|
||||||
"height": 360
|
"height": 360
|
||||||
|
|
@ -1562,7 +1562,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Chrome HiDPI": {
|
"Desktop Chrome HiDPI": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1792,
|
"width": 1792,
|
||||||
"height": 1120
|
"height": 1120
|
||||||
|
|
@ -1577,7 +1577,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Edge HiDPI": {
|
"Desktop Edge HiDPI": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36 Edg/129.0.6668.22",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36 Edg/129.0.6668.29",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1792,
|
"width": 1792,
|
||||||
"height": 1120
|
"height": 1120
|
||||||
|
|
@ -1622,7 +1622,7 @@
|
||||||
"defaultBrowserType": "webkit"
|
"defaultBrowserType": "webkit"
|
||||||
},
|
},
|
||||||
"Desktop Chrome": {
|
"Desktop Chrome": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1920,
|
"width": 1920,
|
||||||
"height": 1080
|
"height": 1080
|
||||||
|
|
@ -1637,7 +1637,7 @@
|
||||||
"defaultBrowserType": "chromium"
|
"defaultBrowserType": "chromium"
|
||||||
},
|
},
|
||||||
"Desktop Edge": {
|
"Desktop Edge": {
|
||||||
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.22 Safari/537.36 Edg/129.0.6668.22",
|
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.29 Safari/537.36 Edg/129.0.6668.29",
|
||||||
"screen": {
|
"screen": {
|
||||||
"width": 1920,
|
"width": 1920,
|
||||||
"height": 1080
|
"height": 1080
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,9 @@ export function isNonRecoverableDOMError(error: Error) {
|
||||||
export class FrameExecutionContext extends js.ExecutionContext {
|
export class FrameExecutionContext extends js.ExecutionContext {
|
||||||
readonly frame: frames.Frame;
|
readonly frame: frames.Frame;
|
||||||
private _injectedScriptPromise?: Promise<js.JSHandle>;
|
private _injectedScriptPromise?: Promise<js.JSHandle>;
|
||||||
readonly world: types.World;
|
readonly world: types.World | null;
|
||||||
|
|
||||||
constructor(delegate: js.ExecutionContextDelegate, frame: frames.Frame, world: types.World) {
|
constructor(delegate: js.ExecutionContextDelegate, frame: frames.Frame, world: types.World|null) {
|
||||||
super(frame, delegate, world || 'content-script');
|
super(frame, delegate, world || 'content-script');
|
||||||
this.frame = frame;
|
this.frame = frame;
|
||||||
this.world = world;
|
this.world = world;
|
||||||
|
|
|
||||||
|
|
@ -163,16 +163,15 @@ export class FFPage implements PageDelegate {
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return;
|
return;
|
||||||
const delegate = new FFExecutionContext(this._session, executionContextId);
|
const delegate = new FFExecutionContext(this._session, executionContextId);
|
||||||
let worldName: types.World;
|
let worldName: types.World|null = null;
|
||||||
if (auxData.name === UTILITY_WORLD_NAME)
|
if (auxData.name === UTILITY_WORLD_NAME)
|
||||||
worldName = 'utility';
|
worldName = 'utility';
|
||||||
else if (!auxData.name)
|
else if (!auxData.name)
|
||||||
worldName = 'main';
|
worldName = 'main';
|
||||||
else
|
|
||||||
return;
|
|
||||||
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
||||||
(context as any)[contextDelegateSymbol] = delegate;
|
(context as any)[contextDelegateSymbol] = delegate;
|
||||||
frame._contextCreated(worldName, context);
|
if (worldName)
|
||||||
|
frame._contextCreated(worldName, context);
|
||||||
this._contextIdToContext.set(executionContextId, context);
|
this._contextIdToContext.set(executionContextId, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,6 @@ const BIN_PATH = path.join(__dirname, '..', '..', '..', 'bin');
|
||||||
|
|
||||||
const PLAYWRIGHT_CDN_MIRRORS = [
|
const PLAYWRIGHT_CDN_MIRRORS = [
|
||||||
'https://playwright.azureedge.net',
|
'https://playwright.azureedge.net',
|
||||||
'https://playwright-akamai.azureedge.net',
|
|
||||||
'https://playwright-verizon.azureedge.net',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (process.env.PW_TEST_CDN_THAT_SHOULD_WORK) {
|
if (process.env.PW_TEST_CDN_THAT_SHOULD_WORK) {
|
||||||
|
|
|
||||||
|
|
@ -502,16 +502,15 @@ export class WKPage implements PageDelegate {
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return;
|
return;
|
||||||
const delegate = new WKExecutionContext(this._session, contextPayload.id);
|
const delegate = new WKExecutionContext(this._session, contextPayload.id);
|
||||||
let worldName: types.World;
|
let worldName: types.World|null = null;
|
||||||
if (contextPayload.type === 'normal')
|
if (contextPayload.type === 'normal')
|
||||||
worldName = 'main';
|
worldName = 'main';
|
||||||
else if (contextPayload.type === 'user' && contextPayload.name === UTILITY_WORLD_NAME)
|
else if (contextPayload.type === 'user' && contextPayload.name === UTILITY_WORLD_NAME)
|
||||||
worldName = 'utility';
|
worldName = 'utility';
|
||||||
else
|
|
||||||
return;
|
|
||||||
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
||||||
(context as any)[contextDelegateSymbol] = delegate;
|
(context as any)[contextDelegateSymbol] = delegate;
|
||||||
frame._contextCreated(worldName, context);
|
if (worldName)
|
||||||
|
frame._contextCreated(worldName, context);
|
||||||
this._contextIdToContext.set(contextPayload.id, context);
|
this._contextIdToContext.set(contextPayload.id, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing Helpers",
|
"description": "Playwright Component Testing Helpers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next",
|
"playwright-core": "1.47.2",
|
||||||
"vite": "^5.2.8",
|
"vite": "^5.2.8",
|
||||||
"playwright": "1.47.0-next"
|
"playwright": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ function vitePlugin(registerSource: string, templateDir: string, buildInfo: Buil
|
||||||
|
|
||||||
async writeBundle(this: PluginContext) {
|
async writeBundle(this: PluginContext) {
|
||||||
for (const importInfo of importInfos.values()) {
|
for (const importInfo of importInfos.values()) {
|
||||||
const importPath = resolveHook(importInfo.filename, importInfo.importSource, true);
|
const importPath = resolveHook(importInfo.filename, importInfo.importSource);
|
||||||
if (!importPath)
|
if (!importPath)
|
||||||
continue;
|
continue;
|
||||||
const deps = new Set<string>();
|
const deps = new Set<string>();
|
||||||
|
|
|
||||||
|
|
@ -147,13 +147,13 @@ export async function populateComponentsFromTests(componentRegistry: ComponentRe
|
||||||
for (const importInfo of importList)
|
for (const importInfo of importList)
|
||||||
componentRegistry.set(importInfo.id, importInfo);
|
componentRegistry.set(importInfo.id, importInfo);
|
||||||
if (componentsByImportingFile)
|
if (componentsByImportingFile)
|
||||||
componentsByImportingFile.set(file, importList.map(i => resolveHook(i.filename, i.importSource, true)).filter(Boolean) as string[]);
|
componentsByImportingFile.set(file, importList.map(i => resolveHook(i.filename, i.importSource)).filter(Boolean) as string[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hasJSComponents(components: ImportInfo[]): boolean {
|
export function hasJSComponents(components: ImportInfo[]): boolean {
|
||||||
for (const component of components) {
|
for (const component of components) {
|
||||||
const importPath = resolveHook(component.filename, component.importSource, true);
|
const importPath = resolveHook(component.filename, component.importSource);
|
||||||
const extname = importPath ? path.extname(importPath) : '';
|
const extname = importPath ? path.extname(importPath) : '';
|
||||||
if (extname === '.js' || (importPath && !extname && fs.existsSync(importPath + '.js')))
|
if (extname === '.js' || (importPath && !extname && fs.existsSync(importPath + '.js')))
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -183,7 +183,7 @@ export function transformIndexFile(id: string, content: string, templateDir: str
|
||||||
lines.push(registerSource);
|
lines.push(registerSource);
|
||||||
|
|
||||||
for (const value of importInfos.values()) {
|
for (const value of importInfos.values()) {
|
||||||
const importPath = resolveHook(value.filename, value.importSource, true) || value.importSource;
|
const importPath = resolveHook(value.filename, value.importSource) || value.importSource;
|
||||||
lines.push(`const ${value.id} = () => import('${importPath?.replaceAll(path.sep, '/')}').then((mod) => mod.${value.remoteName || 'default'});`);
|
lines.push(`const ${value.id} = () => import('${importPath?.replaceAll(path.sep, '/')}').then((mod) => mod.${value.remoteName || 'default'});`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing for React",
|
"description": "Playwright Component Testing for React",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing for React",
|
"description": "Playwright Component Testing for React",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing for Solid",
|
"description": "Playwright Component Testing for Solid",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing for Svelte",
|
"description": "Playwright Component Testing for Svelte",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing for Vue",
|
"description": "Playwright Component Testing for Vue",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "Playwright Component Testing for Vue2",
|
"description": "Playwright Component Testing for Vue2",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
"./package.json": "./package.json"
|
"./package.json": "./package.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.47.0-next",
|
"@playwright/experimental-ct-core": "1.47.2",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-firefox",
|
"name": "playwright-firefox",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate Firefox",
|
"description": "A high-level API to automate Firefox",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
},
|
},
|
||||||
"scripts": {},
|
"scripts": {},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.47.0-next"
|
"playwright": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-webkit",
|
"name": "playwright-webkit",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate WebKit",
|
"description": "A high-level API to automate WebKit",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -30,6 +30,6 @@
|
||||||
"install": "node install.js"
|
"install": "node install.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "playwright",
|
"name": "playwright",
|
||||||
"version": "1.47.0-next",
|
"version": "1.47.2",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.47.0-next"
|
"playwright-core": "1.47.2"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"fsevents": "2.3.2"
|
"fsevents": "2.3.2"
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import { fileIsModule } from '../util';
|
||||||
async function resolve(specifier: string, context: { parentURL?: string }, defaultResolve: Function) {
|
async function resolve(specifier: string, context: { parentURL?: string }, defaultResolve: Function) {
|
||||||
if (context.parentURL && context.parentURL.startsWith('file://')) {
|
if (context.parentURL && context.parentURL.startsWith('file://')) {
|
||||||
const filename = url.fileURLToPath(context.parentURL);
|
const filename = url.fileURLToPath(context.parentURL);
|
||||||
const resolved = resolveHook(filename, specifier, true);
|
const resolved = resolveHook(filename, specifier);
|
||||||
if (resolved !== undefined)
|
if (resolved !== undefined)
|
||||||
specifier = url.pathToFileURL(resolved).toString();
|
specifier = url.pathToFileURL(resolved).toString();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import type { LoadedTsConfig } from '../third_party/tsconfig-loader';
|
||||||
import { tsConfigLoader } from '../third_party/tsconfig-loader';
|
import { tsConfigLoader } from '../third_party/tsconfig-loader';
|
||||||
import Module from 'module';
|
import Module from 'module';
|
||||||
import type { BabelPlugin, BabelTransformFunction } from './babelBundle';
|
import type { BabelPlugin, BabelTransformFunction } from './babelBundle';
|
||||||
import { createFileMatcher, fileIsModule, resolveImportSpecifierExtension } from '../util';
|
import { createFileMatcher, fileIsModule, resolveImportSpecifierAfterMapping } from '../util';
|
||||||
import type { Matcher } from '../util';
|
import type { Matcher } from '../util';
|
||||||
import { getFromCompilationCache, currentFileDepsCollector, belongsToNodeModules, installSourceMapSupport } from './compilationCache';
|
import { getFromCompilationCache, currentFileDepsCollector, belongsToNodeModules, installSourceMapSupport } from './compilationCache';
|
||||||
|
|
||||||
|
|
@ -92,20 +92,19 @@ function loadAndValidateTsconfigsForFile(file: string): ParsedTsConfigData[] {
|
||||||
const pathSeparator = process.platform === 'win32' ? ';' : ':';
|
const pathSeparator = process.platform === 'win32' ? ';' : ':';
|
||||||
const builtins = new Set(Module.builtinModules);
|
const builtins = new Set(Module.builtinModules);
|
||||||
|
|
||||||
export function resolveHook(filename: string, specifier: string, isESM: boolean): string | undefined {
|
export function resolveHook(filename: string, specifier: string): string | undefined {
|
||||||
if (specifier.startsWith('node:') || builtins.has(specifier))
|
if (specifier.startsWith('node:') || builtins.has(specifier))
|
||||||
return;
|
return;
|
||||||
if (!shouldTransform(filename))
|
if (!shouldTransform(filename))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isRelativeSpecifier(specifier))
|
if (isRelativeSpecifier(specifier))
|
||||||
return resolveImportSpecifierExtension(path.resolve(path.dirname(filename), specifier), false, isESM);
|
return resolveImportSpecifierAfterMapping(path.resolve(path.dirname(filename), specifier), false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TypeScript discourages path-mapping into node_modules
|
* TypeScript discourages path-mapping into node_modules:
|
||||||
* (https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages).
|
* https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages
|
||||||
* It seems like TypeScript tries path-mapping first, but does not look at the `package.json` or `index.js` files in ESM.
|
* However, if path-mapping doesn't yield a result, TypeScript falls back to the default resolution through node_modules.
|
||||||
* If path-mapping doesn't yield a result, TypeScript falls back to the default resolution (typically node_modules).
|
|
||||||
*/
|
*/
|
||||||
const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
|
const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
|
||||||
const tsconfigs = loadAndValidateTsconfigsForFile(filename);
|
const tsconfigs = loadAndValidateTsconfigsForFile(filename);
|
||||||
|
|
@ -148,7 +147,7 @@ export function resolveHook(filename: string, specifier: string, isESM: boolean)
|
||||||
if (value.includes('*'))
|
if (value.includes('*'))
|
||||||
candidate = candidate.replace('*', matchedPartOfSpecifier);
|
candidate = candidate.replace('*', matchedPartOfSpecifier);
|
||||||
candidate = path.resolve(tsconfig.pathsBase!, candidate);
|
candidate = path.resolve(tsconfig.pathsBase!, candidate);
|
||||||
const existing = resolveImportSpecifierExtension(candidate, true, isESM);
|
const existing = resolveImportSpecifierAfterMapping(candidate, true);
|
||||||
if (existing) {
|
if (existing) {
|
||||||
longestPrefixLength = keyPrefix.length;
|
longestPrefixLength = keyPrefix.length;
|
||||||
pathMatchedByLongestPrefix = existing;
|
pathMatchedByLongestPrefix = existing;
|
||||||
|
|
@ -162,7 +161,7 @@ export function resolveHook(filename: string, specifier: string, isESM: boolean)
|
||||||
if (path.isAbsolute(specifier)) {
|
if (path.isAbsolute(specifier)) {
|
||||||
// Handle absolute file paths like `import '/path/to/file'`
|
// Handle absolute file paths like `import '/path/to/file'`
|
||||||
// Do not handle module imports like `import 'fs'`
|
// Do not handle module imports like `import 'fs'`
|
||||||
return resolveImportSpecifierExtension(specifier, false, isESM);
|
return resolveImportSpecifierAfterMapping(specifier, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,7 +243,7 @@ function installTransformIfNeeded() {
|
||||||
const originalResolveFilename = (Module as any)._resolveFilename;
|
const originalResolveFilename = (Module as any)._resolveFilename;
|
||||||
function resolveFilename(this: any, specifier: string, parent: Module, ...rest: any[]) {
|
function resolveFilename(this: any, specifier: string, parent: Module, ...rest: any[]) {
|
||||||
if (parent) {
|
if (parent) {
|
||||||
const resolved = resolveHook(parent.filename, specifier, false);
|
const resolved = resolveHook(parent.filename, specifier);
|
||||||
if (resolved !== undefined)
|
if (resolved !== undefined)
|
||||||
specifier = resolved;
|
specifier = resolved;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -295,8 +295,23 @@ function folderIsModule(folder: string): boolean {
|
||||||
return require(packageJsonPath).type === 'module';
|
return require(packageJsonPath).type === 'module';
|
||||||
}
|
}
|
||||||
|
|
||||||
// This follows the --moduleResolution=bundler strategy from tsc.
|
const packageJsonMainFieldCache = new Map<string, string | undefined>();
|
||||||
// https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#moduleresolution-bundler
|
|
||||||
|
function getMainFieldFromPackageJson(packageJsonPath: string) {
|
||||||
|
if (!packageJsonMainFieldCache.has(packageJsonPath)) {
|
||||||
|
let mainField: string | undefined;
|
||||||
|
try {
|
||||||
|
mainField = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).main;
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
packageJsonMainFieldCache.set(packageJsonPath, mainField);
|
||||||
|
}
|
||||||
|
return packageJsonMainFieldCache.get(packageJsonPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method performs "file extension subsitution" to find the ts, js or similar source file
|
||||||
|
// based on the import specifier, which might or might not have an extension. See TypeScript docs:
|
||||||
|
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#file-extension-substitution.
|
||||||
const kExtLookups = new Map([
|
const kExtLookups = new Map([
|
||||||
['.js', ['.jsx', '.ts', '.tsx']],
|
['.js', ['.jsx', '.ts', '.tsx']],
|
||||||
['.jsx', ['.tsx']],
|
['.jsx', ['.tsx']],
|
||||||
|
|
@ -304,7 +319,7 @@ const kExtLookups = new Map([
|
||||||
['.mjs', ['.mts']],
|
['.mjs', ['.mts']],
|
||||||
['', ['.js', '.ts', '.jsx', '.tsx', '.cjs', '.mjs', '.cts', '.mts']],
|
['', ['.js', '.ts', '.jsx', '.tsx', '.cjs', '.mjs', '.cts', '.mts']],
|
||||||
]);
|
]);
|
||||||
export function resolveImportSpecifierExtension(resolved: string, isPathMapping: boolean, isESM: boolean): string | undefined {
|
function resolveImportSpecifierExtension(resolved: string): string | undefined {
|
||||||
if (fileExists(resolved))
|
if (fileExists(resolved))
|
||||||
return resolved;
|
return resolved;
|
||||||
|
|
||||||
|
|
@ -318,26 +333,47 @@ export function resolveImportSpecifierExtension(resolved: string, isPathMapping:
|
||||||
}
|
}
|
||||||
break; // Do not try '' when a more specific extension like '.jsx' matched.
|
break; // Do not try '' when a more specific extension like '.jsx' matched.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// After TypeScript path mapping, here's how directories with a `package.json` are resolved:
|
// This method resolves directory imports and performs "file extension subsitution".
|
||||||
// - `package.json#exports` is not respected
|
// It is intended to be called after the path mapping resolution.
|
||||||
// - `package.json#main` is respected only in CJS mode
|
//
|
||||||
// - `index.js` default is respected only in CJS mode
|
// Directory imports follow the --moduleResolution=bundler strategy from tsc.
|
||||||
//
|
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution
|
||||||
// More info:
|
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#bundler
|
||||||
// - https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages
|
//
|
||||||
// - https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution
|
// See also Node.js "folder as module" behavior:
|
||||||
// - https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules
|
// https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules.
|
||||||
|
export function resolveImportSpecifierAfterMapping(resolved: string, afterPathMapping: boolean): string | undefined {
|
||||||
|
const resolvedFile = resolveImportSpecifierExtension(resolved);
|
||||||
|
if (resolvedFile)
|
||||||
|
return resolvedFile;
|
||||||
|
|
||||||
const shouldNotResolveDirectory = isPathMapping && isESM;
|
if (dirExists(resolved)) {
|
||||||
|
const packageJsonPath = path.join(resolved, 'package.json');
|
||||||
|
|
||||||
|
if (afterPathMapping) {
|
||||||
|
// Most notably, the module resolution algorithm is not performed after the path mapping.
|
||||||
|
// This means no node_modules lookup or package.json#exports.
|
||||||
|
//
|
||||||
|
// Only the "folder as module" Node.js behavior is respected:
|
||||||
|
// - consult `package.json#main`;
|
||||||
|
// - look for `index.js` or similar.
|
||||||
|
const mainField = getMainFieldFromPackageJson(packageJsonPath);
|
||||||
|
const mainFieldResolved = mainField ? resolveImportSpecifierExtension(path.resolve(resolved, mainField)) : undefined;
|
||||||
|
return mainFieldResolved || resolveImportSpecifierExtension(path.join(resolved, 'index'));
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldNotResolveDirectory && dirExists(resolved)) {
|
|
||||||
// If we import a package, let Node.js figure out the correct import based on package.json.
|
// If we import a package, let Node.js figure out the correct import based on package.json.
|
||||||
if (fileExists(path.join(resolved, 'package.json')))
|
// This also covers the "main" field for "folder as module".
|
||||||
|
if (fileExists(packageJsonPath))
|
||||||
return resolved;
|
return resolved;
|
||||||
|
|
||||||
|
// Implement the "folder as module" Node.js behavior.
|
||||||
|
// Note that we do not delegate to Node.js, because we support this for ESM as well,
|
||||||
|
// following the TypeScript "bundler" mode.
|
||||||
const dirImport = path.join(resolved, 'index');
|
const dirImport = path.join(resolved, 'index');
|
||||||
return resolveImportSpecifierExtension(dirImport, isPathMapping, isESM);
|
return resolveImportSpecifierExtension(dirImport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ export class TimeoutManager {
|
||||||
|
|
||||||
setIgnoreTimeouts() {
|
setIgnoreTimeouts() {
|
||||||
this._ignoreTimeouts = true;
|
this._ignoreTimeouts = true;
|
||||||
|
if (this._running)
|
||||||
|
this._updateTimeout(this._running);
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt() {
|
interrupt() {
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ function monotonicTimeDeltaBetweenLibraryAndRunner(nonPrimaryContexts: ContextEn
|
||||||
for (const action of context.actions) {
|
for (const action of context.actions) {
|
||||||
if (!action.startTime)
|
if (!action.startTime)
|
||||||
continue;
|
continue;
|
||||||
const key = matchByStepId ? action.stepId! : `${action.apiName}@${(action as any).wallTime}`;
|
const key = matchByStepId ? action.callId! : `${action.apiName}@${(action as any).wallTime}`;
|
||||||
const libraryAction = libraryActions.get(key);
|
const libraryAction = libraryActions.get(key);
|
||||||
if (libraryAction)
|
if (libraryAction)
|
||||||
return action.startTime - libraryAction.startTime;
|
return action.startTime - libraryAction.startTime;
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
.network-request-details-tab {
|
.network-request-details-tab {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
|
|
||||||
5
tests/assets/extension-with-logging/background.js
Normal file
5
tests/assets/extension-with-logging/background.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
console.log("Service worker script loaded");
|
||||||
|
|
||||||
|
chrome.runtime.onInstalled.addListener(() => {
|
||||||
|
console.log("Extension installed");
|
||||||
|
});
|
||||||
1
tests/assets/extension-with-logging/content.js
Normal file
1
tests/assets/extension-with-logging/content.js
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
console.log("Test console log from a third-party execution context");
|
||||||
17
tests/assets/extension-with-logging/manifest.json
Normal file
17
tests/assets/extension-with-logging/manifest.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "Console Log Extension",
|
||||||
|
"version": "1.0",
|
||||||
|
"background": {
|
||||||
|
"service_worker": "background.js"
|
||||||
|
},
|
||||||
|
"permissions": [
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": ["<all_urls>"],
|
||||||
|
"js": ["content.js"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
tests/assets/trace-remote-time-diff.zip
Normal file
BIN
tests/assets/trace-remote-time-diff.zip
Normal file
Binary file not shown.
|
|
@ -20,8 +20,6 @@ import type { AddressInfo } from 'net';
|
||||||
|
|
||||||
const CDNS = [
|
const CDNS = [
|
||||||
'https://playwright.azureedge.net',
|
'https://playwright.azureedge.net',
|
||||||
'https://playwright-akamai.azureedge.net',
|
|
||||||
'https://playwright-verizon.azureedge.net',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const DL_STAT_BLOCK = /^.*from url: (.*)$\n^.*to location: (.*)$\n^.*response status code: (.*)$\n^.*total bytes: (\d+)$\n^.*download complete, size: (\d+)$\n^.*SUCCESS downloading (\w+) .*$/gm;
|
const DL_STAT_BLOCK = /^.*from url: (.*)$\n^.*to location: (.*)$\n^.*response status code: (.*)$\n^.*total bytes: (\d+)$\n^.*download complete, size: (\d+)$\n^.*SUCCESS downloading (\w+) .*$/gm;
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,27 @@ it('should support request/response events when using backgroundPage()', async (
|
||||||
await context.close();
|
await context.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should report console messages from content script', {
|
||||||
|
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32762' }
|
||||||
|
}, async ({ browserType, createUserDataDir, asset, server }) => {
|
||||||
|
const userDataDir = await createUserDataDir();
|
||||||
|
const extensionPath = asset('extension-with-logging');
|
||||||
|
const extensionOptions = {
|
||||||
|
headless: false,
|
||||||
|
args: [
|
||||||
|
`--disable-extensions-except=${extensionPath}`,
|
||||||
|
`--load-extension=${extensionPath}`,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const context = await browserType.launchPersistentContext(userDataDir, extensionOptions);
|
||||||
|
const page = await context.newPage();
|
||||||
|
const consolePromise = page.waitForEvent('console', e => e.text().includes('Test console log from a third-party execution context'));
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
const message = await consolePromise;
|
||||||
|
expect(message.text()).toContain('Test console log from a third-party execution context');
|
||||||
|
await context.close();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not create pages automatically', async ({ browserType }) => {
|
it('should not create pages automatically', async ({ browserType }) => {
|
||||||
const browser = await browserType.launch();
|
const browser = await browserType.launch();
|
||||||
const browserSession = await browser.newBrowserCDPSession();
|
const browserSession = await browser.newBrowserCDPSession();
|
||||||
|
|
|
||||||
|
|
@ -127,13 +127,13 @@ await page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).Nth(1).ClickAsy
|
||||||
page.locator("#frame1").contentFrame().getByText("Hello1").click();`);
|
page.locator("#frame1").contentFrame().getByText("Hello1").click();`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(`
|
expect.soft(sources.get('Python')!.text).toContain(`
|
||||||
page.locator("#frame1").content_frame().get_by_text("Hello1").click()`);
|
page.locator("#frame1").content_frame.get_by_text("Hello1").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(`
|
expect.soft(sources.get('Python Async')!.text).toContain(`
|
||||||
await page.locator("#frame1").content_frame().get_by_text("Hello1").click()`);
|
await page.locator("#frame1").content_frame.get_by_text("Hello1").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(`
|
expect.soft(sources.get('C#')!.text).toContain(`
|
||||||
await page.Locator("#frame1").ContentFrame().GetByText("Hello1").ClickAsync();`);
|
await page.Locator("#frame1").ContentFrame.GetByText("Hello1").ClickAsync();`);
|
||||||
|
|
||||||
|
|
||||||
[sources] = await Promise.all([
|
[sources] = await Promise.all([
|
||||||
|
|
@ -148,13 +148,13 @@ await page.Locator("#frame1").ContentFrame().GetByText("Hello1").ClickAsync();`)
|
||||||
page.locator("#frame1").contentFrame().locator("iframe").contentFrame().getByText("Hello2").click();`);
|
page.locator("#frame1").contentFrame().locator("iframe").contentFrame().getByText("Hello2").click();`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(`
|
expect.soft(sources.get('Python')!.text).toContain(`
|
||||||
page.locator("#frame1").content_frame().locator("iframe").content_frame().get_by_text("Hello2").click()`);
|
page.locator("#frame1").content_frame.locator("iframe").content_frame.get_by_text("Hello2").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(`
|
expect.soft(sources.get('Python Async')!.text).toContain(`
|
||||||
await page.locator("#frame1").content_frame().locator("iframe").content_frame().get_by_text("Hello2").click()`);
|
await page.locator("#frame1").content_frame.locator("iframe").content_frame.get_by_text("Hello2").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(`
|
expect.soft(sources.get('C#')!.text).toContain(`
|
||||||
await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().GetByText("Hello2").ClickAsync();`);
|
await page.Locator("#frame1").ContentFrame.Locator("iframe").ContentFrame.GetByText("Hello2").ClickAsync();`);
|
||||||
|
|
||||||
|
|
||||||
[sources] = await Promise.all([
|
[sources] = await Promise.all([
|
||||||
|
|
@ -169,13 +169,13 @@ await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Ge
|
||||||
page.locator("#frame1").contentFrame().locator("iframe").contentFrame().locator("iframe[name=\\"one\\"]").contentFrame().getByText("HelloNameOne").click();`);
|
page.locator("#frame1").contentFrame().locator("iframe").contentFrame().locator("iframe[name=\\"one\\"]").contentFrame().getByText("HelloNameOne").click();`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(`
|
expect.soft(sources.get('Python')!.text).toContain(`
|
||||||
page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe[name=\\"one\\"]").content_frame().get_by_text("HelloNameOne").click()`);
|
page.locator("#frame1").content_frame.locator("iframe").content_frame.locator("iframe[name=\\"one\\"]").content_frame.get_by_text("HelloNameOne").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(`
|
expect.soft(sources.get('Python Async')!.text).toContain(`
|
||||||
await page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe[name=\\"one\\"]").content_frame().get_by_text("HelloNameOne").click()`);
|
await page.locator("#frame1").content_frame.locator("iframe").content_frame.locator("iframe[name=\\"one\\"]").content_frame.get_by_text("HelloNameOne").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(`
|
expect.soft(sources.get('C#')!.text).toContain(`
|
||||||
await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Locator("iframe[name=\\"one\\"]").ContentFrame().GetByText("HelloNameOne").ClickAsync();`);
|
await page.Locator("#frame1").ContentFrame.Locator("iframe").ContentFrame.Locator("iframe[name=\\"one\\"]").ContentFrame.GetByText("HelloNameOne").ClickAsync();`);
|
||||||
|
|
||||||
[sources] = await Promise.all([
|
[sources] = await Promise.all([
|
||||||
recorder.waitForOutput('JavaScript', 'HelloNameAnonymous'),
|
recorder.waitForOutput('JavaScript', 'HelloNameAnonymous'),
|
||||||
|
|
@ -189,13 +189,13 @@ await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Lo
|
||||||
page.locator("#frame1").contentFrame().locator("iframe").contentFrame().locator("iframe").nth(2).contentFrame().getByText("HelloNameAnonymous").click();`);
|
page.locator("#frame1").contentFrame().locator("iframe").contentFrame().locator("iframe").nth(2).contentFrame().getByText("HelloNameAnonymous").click();`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(`
|
expect.soft(sources.get('Python')!.text).toContain(`
|
||||||
page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe").nth(2).content_frame().get_by_text("HelloNameAnonymous").click()`);
|
page.locator("#frame1").content_frame.locator("iframe").content_frame.locator("iframe").nth(2).content_frame.get_by_text("HelloNameAnonymous").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(`
|
expect.soft(sources.get('Python Async')!.text).toContain(`
|
||||||
await page.locator("#frame1").content_frame().locator("iframe").content_frame().locator("iframe").nth(2).content_frame().get_by_text("HelloNameAnonymous").click()`);
|
await page.locator("#frame1").content_frame.locator("iframe").content_frame.locator("iframe").nth(2).content_frame.get_by_text("HelloNameAnonymous").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(`
|
expect.soft(sources.get('C#')!.text).toContain(`
|
||||||
await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Locator("iframe").Nth(2).ContentFrame().GetByText("HelloNameAnonymous").ClickAsync();`);
|
await page.Locator("#frame1").ContentFrame.Locator("iframe").ContentFrame.Locator("iframe").Nth(2).ContentFrame.GetByText("HelloNameAnonymous").ClickAsync();`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should generate frame locators with special characters in name attribute', async ({ page, openRecorder, server }) => {
|
test('should generate frame locators with special characters in name attribute', async ({ page, openRecorder, server }) => {
|
||||||
|
|
@ -217,13 +217,13 @@ await page.Locator("#frame1").ContentFrame().Locator("iframe").ContentFrame().Lo
|
||||||
page.locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Click me")).click()`);
|
page.locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Click me")).click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(`
|
expect.soft(sources.get('Python')!.text).toContain(`
|
||||||
page.locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").content_frame().get_by_role("button", name="Click me").click()`);
|
page.locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").content_frame.get_by_role("button", name="Click me").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(`
|
expect.soft(sources.get('Python Async')!.text).toContain(`
|
||||||
await page.locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").content_frame().get_by_role("button", name="Click me").click()`);
|
await page.locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").content_frame.get_by_role("button", name="Click me").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(`
|
expect.soft(sources.get('C#')!.text).toContain(`
|
||||||
await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`);
|
await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should generate frame locators with title attribute', async ({ page, openRecorder, server }) => {
|
test('should generate frame locators with title attribute', async ({ page, openRecorder, server }) => {
|
||||||
|
|
@ -246,15 +246,15 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(
|
expect.soft(sources.get('Python')!.text).toContain(
|
||||||
`page.locator(\"iframe[title=\\\"hello world\\\"]\").content_frame().get_by_role(\"button\", name=\"Click me\").click()`
|
`page.locator(\"iframe[title=\\\"hello world\\\"]\").content_frame.get_by_role(\"button\", name=\"Click me\").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(
|
expect.soft(sources.get('Python Async')!.text).toContain(
|
||||||
`await page.locator("iframe[title=\\\"hello world\\\"]").content_frame().get_by_role("button", name="Click me").click()`
|
`await page.locator("iframe[title=\\\"hello world\\\"]").content_frame.get_by_role("button", name="Click me").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(
|
expect.soft(sources.get('C#')!.text).toContain(
|
||||||
`await page.Locator("iframe[title=\\\"hello world\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
`await page.Locator("iframe[title=\\\"hello world\\\"]").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -278,15 +278,15 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(
|
expect.soft(sources.get('Python')!.text).toContain(
|
||||||
`page.locator(\"iframe[name=\\\"hello world\\\"]\").content_frame().get_by_role(\"button\", name=\"Click me\").click()`
|
`page.locator(\"iframe[name=\\\"hello world\\\"]\").content_frame.get_by_role(\"button\", name=\"Click me\").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(
|
expect.soft(sources.get('Python Async')!.text).toContain(
|
||||||
`await page.locator("iframe[name=\\\"hello world\\\"]").content_frame().get_by_role("button", name="Click me").click()`
|
`await page.locator("iframe[name=\\\"hello world\\\"]").content_frame.get_by_role("button", name="Click me").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(
|
expect.soft(sources.get('C#')!.text).toContain(
|
||||||
`await page.Locator("iframe[name=\\\"hello world\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
`await page.Locator("iframe[name=\\\"hello world\\\"]").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -310,15 +310,15 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(
|
expect.soft(sources.get('Python')!.text).toContain(
|
||||||
`page.locator(\"#hello-world\").content_frame().get_by_role(\"button\", name=\"Click me\").click()`
|
`page.locator(\"#hello-world\").content_frame.get_by_role(\"button\", name=\"Click me\").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(
|
expect.soft(sources.get('Python Async')!.text).toContain(
|
||||||
`await page.locator("#hello-world").content_frame().get_by_role("button", name="Click me").click()`
|
`await page.locator("#hello-world").content_frame.get_by_role("button", name="Click me").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(
|
expect.soft(sources.get('C#')!.text).toContain(
|
||||||
`await page.Locator("#hello-world").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
`await page.Locator("#hello-world").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -342,15 +342,15 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(
|
expect.soft(sources.get('Python')!.text).toContain(
|
||||||
`page.locator(\"[data-testid=\\\"my-testid\\\"]\").content_frame().get_by_role(\"button\", name=\"Click me\").click()`
|
`page.locator(\"[data-testid=\\\"my-testid\\\"]\").content_frame.get_by_role(\"button\", name=\"Click me\").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(
|
expect.soft(sources.get('Python Async')!.text).toContain(
|
||||||
`await page.locator("[data-testid=\\\"my-testid\\\"]").content_frame().get_by_role("button", name="Click me").click()`
|
`await page.locator("[data-testid=\\\"my-testid\\\"]").content_frame.get_by_role("button", name="Click me").click()`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(
|
expect.soft(sources.get('C#')!.text).toContain(
|
||||||
`await page.Locator("[data-testid=\\\"my-testid\\\"]").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
`await page.Locator("[data-testid=\\\"my-testid\\\"]").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Click me" }).ClickAsync();`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -371,13 +371,13 @@ await page.Locator("iframe[name=\\"foo\\\\<bar\\\\'\\\\\\"\\\\\`\\\\>\\"]").Cont
|
||||||
page.locator("#frame1").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Submit")).click();`);
|
page.locator("#frame1").contentFrame().getByRole(AriaRole.BUTTON, new FrameLocator.GetByRoleOptions().setName("Submit")).click();`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python')!.text).toContain(`
|
expect.soft(sources.get('Python')!.text).toContain(`
|
||||||
page.locator("#frame1").content_frame().get_by_role("button", name="Submit").click()`);
|
page.locator("#frame1").content_frame.get_by_role("button", name="Submit").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('Python Async')!.text).toContain(`
|
expect.soft(sources.get('Python Async')!.text).toContain(`
|
||||||
await page.locator("#frame1").content_frame().get_by_role("button", name="Submit").click()`);
|
await page.locator("#frame1").content_frame.get_by_role("button", name="Submit").click()`);
|
||||||
|
|
||||||
expect.soft(sources.get('C#')!.text).toContain(`
|
expect.soft(sources.get('C#')!.text).toContain(`
|
||||||
await page.Locator("#frame1").ContentFrame().GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`);
|
await page.Locator("#frame1").ContentFrame.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();`);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should generate getByTestId', async ({ page, openRecorder }) => {
|
test('should generate getByTestId', async ({ page, openRecorder }) => {
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,12 @@ test('should complain about newer version of trace in old viewer', async ({ show
|
||||||
await expect(traceViewer.page.getByText('The trace was created by a newer version of Playwright and is not supported by this version of the viewer.')).toBeVisible();
|
await expect(traceViewer.page.getByText('The trace was created by a newer version of Playwright and is not supported by this version of the viewer.')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should properly synchronize local and remote time', async ({ showTraceViewer, asset }, testInfo) => {
|
||||||
|
const traceViewer = await showTraceViewer([asset('trace-remote-time-diff.zip')]);
|
||||||
|
// The total duration should be sub 10s, rather than 16h.
|
||||||
|
await expect(traceViewer.page.locator('.timeline-time').last()).toHaveText('8.5s');
|
||||||
|
});
|
||||||
|
|
||||||
test('should contain action info', async ({ showTraceViewer }) => {
|
test('should contain action info', async ({ showTraceViewer }) => {
|
||||||
const traceViewer = await showTraceViewer([traceFile]);
|
const traceViewer = await showTraceViewer([traceFile]);
|
||||||
await traceViewer.selectAction('locator.click');
|
await traceViewer.selectAction('locator.click');
|
||||||
|
|
|
||||||
|
|
@ -872,3 +872,25 @@ test('should allow dynamic import in evaluate', async ({ runInlineTest, server }
|
||||||
expect(result.exitCode).toBe(0);
|
expect(result.exitCode).toBe(0);
|
||||||
expect(result.passed).toBe(1);
|
expect(result.passed).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('page.pause() should disable test timeout', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'a.test.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
|
test('test', async ({ page }) => {
|
||||||
|
test.setTimeout(2000);
|
||||||
|
|
||||||
|
await Promise.race([
|
||||||
|
page.pause(),
|
||||||
|
new Promise(f => setTimeout(f, 3000)),
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log('success!');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
}, { headed: true });
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.output).toContain('success!');
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -569,116 +569,6 @@ test('should resolve paths relative to the originating config when extending and
|
||||||
expect(result.exitCode).toBe(0);
|
expect(result.exitCode).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should import packages with non-index main script through path resolver', async ({ runInlineTest }) => {
|
|
||||||
const result = await runInlineTest({
|
|
||||||
'app/pkg/main.ts': `
|
|
||||||
export const foo = 42;
|
|
||||||
`,
|
|
||||||
'app/pkg/package.json': `
|
|
||||||
{ "main": "main.ts" }
|
|
||||||
`,
|
|
||||||
'package.json': `
|
|
||||||
{ "name": "example-project" }
|
|
||||||
`,
|
|
||||||
'playwright.config.ts': `
|
|
||||||
export default {};
|
|
||||||
`,
|
|
||||||
'tsconfig.json': `{
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"app/*": ["app/*"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}`,
|
|
||||||
'example.spec.ts': `
|
|
||||||
import { foo } from 'app/pkg';
|
|
||||||
import { test, expect } from '@playwright/test';
|
|
||||||
test('test', ({}) => {
|
|
||||||
console.log('foo=' + foo);
|
|
||||||
});
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.exitCode).toBe(0);
|
|
||||||
expect(result.passed).toBe(1);
|
|
||||||
expect(result.output).not.toContain(`find module`);
|
|
||||||
expect(result.output).toContain(`foo=42`);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should not honor `package.json#main` field in ESM mode', async ({ runInlineTest }) => {
|
|
||||||
const result = await runInlineTest({
|
|
||||||
'app/pkg/main.ts': `
|
|
||||||
export const foo = 42;
|
|
||||||
`,
|
|
||||||
'app/pkg/package.json': `
|
|
||||||
{ "main": "main.ts" }
|
|
||||||
`,
|
|
||||||
'package.json': `
|
|
||||||
{ "name": "example-project", "type": "module" }
|
|
||||||
`,
|
|
||||||
'playwright.config.ts': `
|
|
||||||
export default {};
|
|
||||||
`,
|
|
||||||
'tsconfig.json': `{
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"app/*": ["app/*"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}`,
|
|
||||||
'example.spec.ts': `
|
|
||||||
import { foo } from 'app/pkg';
|
|
||||||
import { test, expect } from '@playwright/test';
|
|
||||||
test('test', ({}) => {
|
|
||||||
console.log('foo=' + foo);
|
|
||||||
});
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.exitCode).toBe(1);
|
|
||||||
expect(result.output).toContain(`Cannot find package 'app'`);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('does not honor `exports` field after type mapping', async ({ runInlineTest }) => {
|
|
||||||
const result = await runInlineTest({
|
|
||||||
'app/pkg/main.ts': `
|
|
||||||
export const filename = 'main.ts';
|
|
||||||
`,
|
|
||||||
'app/pkg/index.js': `
|
|
||||||
export const filename = 'index.js';
|
|
||||||
`,
|
|
||||||
'app/pkg/package.json': JSON.stringify({
|
|
||||||
exports: { '.': { require: './main.ts' } }
|
|
||||||
}),
|
|
||||||
'package.json': JSON.stringify({
|
|
||||||
name: 'example-project'
|
|
||||||
}),
|
|
||||||
'playwright.config.ts': `
|
|
||||||
export default {};
|
|
||||||
`,
|
|
||||||
'tsconfig.json': JSON.stringify({
|
|
||||||
compilerOptions: {
|
|
||||||
baseUrl: '.',
|
|
||||||
paths: {
|
|
||||||
'app/*': ['app/*'],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
'example.spec.ts': `
|
|
||||||
import { filename } from 'app/pkg';
|
|
||||||
import { test, expect } from '@playwright/test';
|
|
||||||
test('test', ({}) => {
|
|
||||||
console.log('filename=' + filename);
|
|
||||||
});
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.output).toContain('filename=index.js');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should respect tsconfig project references', async ({ runInlineTest }) => {
|
test('should respect tsconfig project references', async ({ runInlineTest }) => {
|
||||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29256' });
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/29256' });
|
||||||
|
|
||||||
|
|
@ -767,64 +657,425 @@ test('should respect --tsconfig option', async ({ runInlineTest }) => {
|
||||||
expect(result.output).not.toContain(`Could not`);
|
expect(result.output).not.toContain(`Could not`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.describe('directory imports', () => {
|
||||||
|
test('should resolve index.js without path mapping in CJS', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'foo-pkg/index.js': `
|
||||||
|
exports.foo = 'bar';
|
||||||
|
`,
|
||||||
|
'foo-pkg/index.d.ts': `
|
||||||
|
export const foo: 'bar';
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import { foo } from './foo-pkg';
|
||||||
|
test('pass', async () => {
|
||||||
|
const bar: 'bar' = foo;
|
||||||
|
expect(bar).toBe('bar');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
test('should resolve index.js in CJS after path mapping', async ({ runInlineTest }) => {
|
const result = await runInlineTest(files);
|
||||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' });
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
|
||||||
const result = await runInlineTest({
|
const tscResult = await runTSC(files);
|
||||||
'@acme/lib/index.js': `
|
expect(tscResult.exitCode).toBe(0);
|
||||||
exports.greet = () => console.log('hello playwright');
|
|
||||||
`,
|
|
||||||
'@acme/lib/index.d.ts': `
|
|
||||||
export const greet: () => void;
|
|
||||||
`,
|
|
||||||
'tests/hello.test.ts': `
|
|
||||||
import { greet } from '@acme/lib';
|
|
||||||
import { test } from '@playwright/test';
|
|
||||||
test('hello', async ({}) => {
|
|
||||||
greet();
|
|
||||||
});
|
|
||||||
`,
|
|
||||||
'tests/tsconfig.json': JSON.stringify({
|
|
||||||
compilerOptions: {
|
|
||||||
'paths': {
|
|
||||||
'@acme/*': ['../@acme/*'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.exitCode).toBe(0);
|
test('should resolve index.js without path mapping in ESM', async ({ runInlineTest, runTSC }) => {
|
||||||
expect(result.passed).toBe(1);
|
const files = {
|
||||||
});
|
'foo-pkg/index.js': `
|
||||||
|
export const foo = 'bar';
|
||||||
|
`,
|
||||||
|
'foo-pkg/index.d.ts': `
|
||||||
|
export const foo: 'bar';
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "type": "module" }
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import { foo } from './foo-pkg';
|
||||||
|
test('pass', async () => {
|
||||||
|
const bar: 'bar' = foo;
|
||||||
|
expect(bar).toBe('bar');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
test('should not resolve index.js in ESM after path mapping', async ({ runInlineTest }) => {
|
const result = await runInlineTest(files);
|
||||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' });
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
|
||||||
const result = await runInlineTest({
|
const tscResult = await runTSC(files);
|
||||||
'@acme/lib/index.js': `
|
expect(tscResult.exitCode).toBe(0);
|
||||||
export const greet = () => console.log('hello playwright');
|
|
||||||
`,
|
|
||||||
'@acme/lib/index.d.ts': `
|
|
||||||
export const greet: () => void;
|
|
||||||
`,
|
|
||||||
'tests/hello.test.ts': `
|
|
||||||
import { greet } from '@acme/lib';
|
|
||||||
import { test } from '@playwright/test';
|
|
||||||
test('hello', async ({}) => {
|
|
||||||
greet();
|
|
||||||
});
|
|
||||||
`,
|
|
||||||
'tests/tsconfig.json': JSON.stringify({
|
|
||||||
compilerOptions: {
|
|
||||||
'paths': {
|
|
||||||
'@acme/*': ['../@acme/*'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
'package.json': JSON.stringify({ type: 'module' }),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.exitCode).toBe(1);
|
test('should resolve index.js after path mapping in CJS', async ({ runInlineTest, runTSC }) => {
|
||||||
expect(result.output).toContain(`Cannot find package '@acme/lib'`);
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' });
|
||||||
|
|
||||||
|
const files = {
|
||||||
|
'@acme/lib/index.js': `
|
||||||
|
exports.greet = () => 2;
|
||||||
|
`,
|
||||||
|
'@acme/lib/index.d.ts': `
|
||||||
|
export const greet: () => number;
|
||||||
|
`,
|
||||||
|
'tests/hello.test.ts': `
|
||||||
|
import { greet } from '@acme/lib';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('hello', async ({}) => {
|
||||||
|
const foo: number = greet();
|
||||||
|
expect(foo).toBe(2);
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@acme/*": ["./@acme/*"]
|
||||||
|
},
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should resolve index.js after path mapping in ESM', async ({ runInlineTest, runTSC }) => {
|
||||||
|
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31811' });
|
||||||
|
|
||||||
|
const files = {
|
||||||
|
'@acme/lib/index.js': `
|
||||||
|
export const greet = () => 2;
|
||||||
|
`,
|
||||||
|
'@acme/lib/index.d.ts': `
|
||||||
|
export const greet: () => number;
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "type": "module" }
|
||||||
|
`,
|
||||||
|
'tests/hello.test.ts': `
|
||||||
|
import { greet } from '@acme/lib';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('hello', async ({}) => {
|
||||||
|
const foo: number = greet();
|
||||||
|
expect(foo).toBe(2);
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@acme/*": ["./@acme/*"]
|
||||||
|
},
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should respect package.json#main after path mapping in CJS', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'app/pkg/main.ts': `
|
||||||
|
export const foo = 42;
|
||||||
|
`,
|
||||||
|
'app/pkg/package.json': `
|
||||||
|
{ "main": "main.ts" }
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "name": "example-project" }
|
||||||
|
`,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
export default {};
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"app/*": ["app/*"]
|
||||||
|
},
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
'example.spec.ts': `
|
||||||
|
import { foo } from 'app/pkg';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('test', ({}) => {
|
||||||
|
const bar: number = foo;
|
||||||
|
expect(bar).toBe(42);
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.output).not.toContain(`find module`);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should respect package.json#main after path mapping in ESM', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'app/pkg/main.ts': `
|
||||||
|
export const foo = 42;
|
||||||
|
`,
|
||||||
|
'app/pkg/package.json': `
|
||||||
|
{ "main": "main.ts", "type": "module" }
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "name": "example-project", "type": "module" }
|
||||||
|
`,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
export default {};
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"app/*": ["app/*"]
|
||||||
|
},
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
'example.spec.ts': `
|
||||||
|
import { foo } from 'app/pkg';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('test', ({}) => {
|
||||||
|
const bar: number = foo;
|
||||||
|
expect(bar).toBe(42);
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should respect package.json#exports without path mapping in CJS', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'node_modules/foo-pkg/package.json': `
|
||||||
|
{ "name": "foo-pkg", "exports": { ".": "./foo.js" } }
|
||||||
|
`,
|
||||||
|
'node_modules/foo-pkg/foo.js': `
|
||||||
|
exports.foo = 'bar';
|
||||||
|
`,
|
||||||
|
'node_modules/foo-pkg/foo.d.ts': `
|
||||||
|
export const foo: 'bar';
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "name": "test-project" }
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import { foo } from 'foo-pkg';
|
||||||
|
test('pass', async () => {
|
||||||
|
const bar: 'bar' = foo;
|
||||||
|
expect(bar).toBe('bar');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should respect package.json#exports without path mapping in ESM', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'node_modules/foo-pkg/package.json': `
|
||||||
|
{ "name": "foo-pkg", "type": "module", "exports": { "default": "./foo.js" } }
|
||||||
|
`,
|
||||||
|
'node_modules/foo-pkg/foo.js': `
|
||||||
|
export const foo = 'bar';
|
||||||
|
`,
|
||||||
|
'node_modules/foo-pkg/foo.d.ts': `
|
||||||
|
export const foo: 'bar';
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "name": "test-project", "type": "module" }
|
||||||
|
`,
|
||||||
|
'a.test.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
import { foo } from 'foo-pkg';
|
||||||
|
test('pass', async () => {
|
||||||
|
const bar: 'bar' = foo;
|
||||||
|
expect(bar).toBe('bar');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not respect package.json#exports after type mapping in CJS', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'app/pkg/main.ts': `
|
||||||
|
export const filename: 'main.ts' = 'main.ts';
|
||||||
|
`,
|
||||||
|
'app/pkg/index.js': `
|
||||||
|
export const filename = 'index.js';
|
||||||
|
`,
|
||||||
|
'app/pkg/index.d.ts': `
|
||||||
|
export const filename: 'index.js';
|
||||||
|
`,
|
||||||
|
'app/pkg/package.json': `
|
||||||
|
{ "exports": { ".": "./main.ts" } }
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "name": "example-project" }
|
||||||
|
`,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
export default {};
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"app/*": ["app/*"]
|
||||||
|
},
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
'example.spec.ts': `
|
||||||
|
import { filename } from 'app/pkg';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('test', ({}) => {
|
||||||
|
const foo: 'index.js' = filename;
|
||||||
|
expect(foo).toBe('index.js');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not respect package.json#exports after type mapping in ESM', async ({ runInlineTest, runTSC }) => {
|
||||||
|
const files = {
|
||||||
|
'app/pkg/main.ts': `
|
||||||
|
export const filename: 'main.ts' = 'main.ts';
|
||||||
|
`,
|
||||||
|
'app/pkg/index.js': `
|
||||||
|
export const filename = 'index.js';
|
||||||
|
`,
|
||||||
|
'app/pkg/index.d.ts': `
|
||||||
|
export const filename: 'index.js';
|
||||||
|
`,
|
||||||
|
'app/pkg/package.json': `
|
||||||
|
{ "exports": { ".": "./main.ts" }, "type": "module" }
|
||||||
|
`,
|
||||||
|
'package.json': `
|
||||||
|
{ "name": "example-project", "type": "module" }
|
||||||
|
`,
|
||||||
|
'playwright.config.ts': `
|
||||||
|
export default {};
|
||||||
|
`,
|
||||||
|
'tsconfig.json': `
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"app/*": ["app/*"]
|
||||||
|
},
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"module": "preserve",
|
||||||
|
"noEmit": true,
|
||||||
|
"noImplicitAny": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
'example.spec.ts': `
|
||||||
|
import { filename } from 'app/pkg';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('test', ({}) => {
|
||||||
|
const foo: 'index.js' = filename;
|
||||||
|
expect(foo).toBe('index.js');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await runInlineTest(files);
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
|
||||||
|
const tscResult = await runTSC(files);
|
||||||
|
expect(tscResult.exitCode).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue