Merge branch 'main' into lbo-relative-hosting
Signed-off-by: Lukas Bockstaller <lukas.bockstaller@everest-erp.com>
This commit is contained in:
commit
966d4661ab
|
|
@ -7,8 +7,6 @@ test/assets/modernizr.js
|
||||||
/packages/playwright-core/types/*
|
/packages/playwright-core/types/*
|
||||||
/packages/playwright-ct-core/src/generated/*
|
/packages/playwright-ct-core/src/generated/*
|
||||||
/index.d.ts
|
/index.d.ts
|
||||||
utils/generate_types/overrides.d.ts
|
|
||||||
utils/generate_types/test/test.ts
|
|
||||||
node_modules/
|
node_modules/
|
||||||
browser_patches/*/checkout/
|
browser_patches/*/checkout/
|
||||||
browser_patches/chromium/output/
|
browser_patches/chromium/output/
|
||||||
|
|
|
||||||
4
.github/actions/download-artifact/action.yml
vendored
4
.github/actions/download-artifact/action.yml
vendored
|
|
@ -4,12 +4,10 @@ inputs:
|
||||||
namePrefix:
|
namePrefix:
|
||||||
description: 'Name prefix of the artifacts to download'
|
description: 'Name prefix of the artifacts to download'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
|
||||||
default: 'blob-report'
|
default: 'blob-report'
|
||||||
path:
|
path:
|
||||||
description: 'Directory with downloaded artifacts'
|
description: 'Directory with downloaded artifacts'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
|
||||||
default: '.'
|
default: '.'
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
|
|
@ -36,7 +34,7 @@ runs:
|
||||||
artifact_id: artifact.id,
|
artifact_id: artifact.id,
|
||||||
archive_format: 'zip'
|
archive_format: 'zip'
|
||||||
});
|
});
|
||||||
console.log('downloaded artifact', result);
|
console.log(`Downloaded ${artifact.name}.zip (${result.data.byteLength} bytes)`);
|
||||||
fs.writeFileSync(`${{ inputs.path }}/artifacts/${artifact.name}.zip`, Buffer.from(result.data));
|
fs.writeFileSync(`${{ inputs.path }}/artifacts/${artifact.name}.zip`, Buffer.from(result.data));
|
||||||
}
|
}
|
||||||
- name: Unzip artifacts
|
- name: Unzip artifacts
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
name: 'Download blob report from Azure'
|
|
||||||
description: 'Download blob report from Azure blob storage'
|
|
||||||
inputs:
|
|
||||||
blob_prefix:
|
|
||||||
description: 'Name of the Azure blob storage directory containing blob report'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
output_dir:
|
|
||||||
description: 'Output directory where downloaded blobs will be stored'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
default: 'blob-report'
|
|
||||||
connection_string:
|
|
||||||
description: 'Azure connection string'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: Download Blob Reports from Azure Blob Storage
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
OUTPUT_DIR='${{ inputs.output_dir }}'
|
|
||||||
mkdir -p $OUTPUT_DIR
|
|
||||||
LIST=$(az storage blob list -c '$web' --prefix ${{ inputs.blob_prefix }} --connection-string "${{ inputs.connection_string }}")
|
|
||||||
for name in $(echo $LIST | jq --raw-output '.[].name | select(test("report-.*\\.zip$"))');
|
|
||||||
do
|
|
||||||
az storage blob download -c '$web' --name $name -f $OUTPUT_DIR/$(basename $name) --connection-string "${{ inputs.connection_string }}"
|
|
||||||
done
|
|
||||||
87
.github/actions/run-test/action.yml
vendored
Normal file
87
.github/actions/run-test/action.yml
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
name: 'Run browser tests'
|
||||||
|
description: 'Run browser tests'
|
||||||
|
inputs:
|
||||||
|
command:
|
||||||
|
description: 'Command to run tests'
|
||||||
|
required: true
|
||||||
|
node-version:
|
||||||
|
description: 'Node.js version to use'
|
||||||
|
required: false
|
||||||
|
default: '18'
|
||||||
|
browsers-to-install:
|
||||||
|
description: 'Browser to install. Default is all browsers.'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
bot-name:
|
||||||
|
description: 'Bot name'
|
||||||
|
required: true
|
||||||
|
shell:
|
||||||
|
description: 'Shell to use'
|
||||||
|
required: false
|
||||||
|
default: 'bash'
|
||||||
|
flakiness-client-id:
|
||||||
|
description: 'Azure Flakiness Dashboard Client ID'
|
||||||
|
required: false
|
||||||
|
flakiness-tenant-id:
|
||||||
|
description: 'Azure Flakiness Dashboard Tenant ID'
|
||||||
|
required: false
|
||||||
|
flakiness-subscription-id:
|
||||||
|
description: 'Azure Flakiness Dashboard Subscription ID'
|
||||||
|
required: false
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ inputs.node-version }}
|
||||||
|
# https://github.com/actions/runner-images/issues/9330
|
||||||
|
- name: Allow microphone access to all apps (macOS 14)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [[ "$(uname)" == "Darwin" && "$(sw_vers -productVersion | cut -d. -f1)" == "14" ]]; then
|
||||||
|
echo "Allowing microphone access to all apps"
|
||||||
|
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
|
||||||
|
fi
|
||||||
|
- run: npm ci
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
DEBUG: pw:install
|
||||||
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
|
||||||
|
- run: npm run build
|
||||||
|
shell: bash
|
||||||
|
- run: npx playwright install --with-deps ${{ inputs.browsers-to-install }}
|
||||||
|
shell: bash
|
||||||
|
- name: Run tests
|
||||||
|
if: inputs.shell == 'bash'
|
||||||
|
run: |
|
||||||
|
if [[ "$(uname)" == "Linux" ]]; then
|
||||||
|
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- ${{ inputs.command }}
|
||||||
|
else
|
||||||
|
${{ inputs.command }}
|
||||||
|
fi
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
PWTEST_BOT_NAME: ${{ inputs.bot-name }}
|
||||||
|
- name: Run tests
|
||||||
|
if: inputs.shell != 'bash'
|
||||||
|
run: ${{ inputs.command }}
|
||||||
|
shell: ${{ inputs.shell }}
|
||||||
|
env:
|
||||||
|
PWTEST_BOT_NAME: ${{ inputs.bot-name }}
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: ${{ !cancelled() && github.event_name == 'push' && github.repository == 'microsoft/playwright' }}
|
||||||
|
with:
|
||||||
|
client-id: ${{ inputs.flakiness-client-id }}
|
||||||
|
tenant-id: ${{ inputs.flakiness-tenant-id }}
|
||||||
|
subscription-id: ${{ inputs.flakiness-subscription-id }}
|
||||||
|
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
shell: bash
|
||||||
|
- name: Upload blob report
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
uses: ./.github/actions/upload-blob-report
|
||||||
|
with:
|
||||||
|
report_dir: blob-report
|
||||||
|
job_name: ${{ inputs.bot-name }}
|
||||||
11
.github/actions/upload-blob-report/action.yml
vendored
11
.github/actions/upload-blob-report/action.yml
vendored
|
|
@ -4,29 +4,30 @@ inputs:
|
||||||
report_dir:
|
report_dir:
|
||||||
description: 'Directory containing blob report'
|
description: 'Directory containing blob report'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
|
||||||
default: 'test-results/blob-report'
|
default: 'test-results/blob-report'
|
||||||
job_name:
|
job_name:
|
||||||
description: 'Unique job name'
|
description: 'Unique job name'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
|
||||||
default: ''
|
default: ''
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
|
- name: Integrity check
|
||||||
|
shell: bash
|
||||||
|
run: find "${{ inputs.report_dir }}" -name "*.zip" -exec unzip -t {} \;
|
||||||
- name: Upload blob report to GitHub
|
- name: Upload blob report to GitHub
|
||||||
if: always() && github.event_name == 'pull_request'
|
if: ${{ !cancelled() && github.event_name == 'pull_request' }}
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: blob-report-${{ inputs.job_name }}
|
name: blob-report-${{ inputs.job_name }}
|
||||||
path: ${{ inputs.report_dir }}/**
|
path: ${{ inputs.report_dir }}/**
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
- name: Write triggering pull request number in a file
|
- name: Write triggering pull request number in a file
|
||||||
if: always() && github.event_name == 'pull_request'
|
if: ${{ !cancelled() && github.event_name == 'pull_request' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: echo '${{ github.event.number }}' > pull_request_number.txt;
|
run: echo '${{ github.event.number }}' > pull_request_number.txt;
|
||||||
- name: Upload artifact with the pull request number
|
- name: Upload artifact with the pull request number
|
||||||
if: always() && github.event_name == 'pull_request'
|
if: ${{ !cancelled() && github.event_name == 'pull_request' }}
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: pull-request-${{ inputs.job_name }}
|
name: pull-request-${{ inputs.job_name }}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "playwright-chromium",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A high-level API to automate web browsers",
|
|
||||||
"repository": "github:Microsoft/playwright",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "playwright-core",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A high-level API to automate web browsers",
|
|
||||||
"repository": "github:Microsoft/playwright",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "playwright-firefox",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A high-level API to automate web browsers",
|
|
||||||
"repository": "github:Microsoft/playwright",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@playwright/test",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A high-level API to automate web browsers",
|
|
||||||
"repository": "github:Microsoft/playwright",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "playwright-webkit",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A high-level API to automate web browsers",
|
|
||||||
"repository": "github:Microsoft/playwright",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "playwright",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "A high-level API to automate web browsers",
|
|
||||||
"repository": "github:Microsoft/playwright",
|
|
||||||
"license": "Apache-2.0"
|
|
||||||
}
|
|
||||||
15
.github/workflows/create_test_report.yml
vendored
15
.github/workflows/create_test_report.yml
vendored
|
|
@ -9,6 +9,8 @@ jobs:
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
checks: write
|
checks: write
|
||||||
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
if: ${{ github.event.workflow_run.event == 'pull_request' }}
|
if: ${{ github.event.workflow_run.event == 'pull_request' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -16,7 +18,6 @@ jobs:
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
env:
|
env:
|
||||||
DEBUG: pw:install
|
DEBUG: pw:install
|
||||||
|
|
@ -35,16 +36,20 @@ jobs:
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: --max-old-space-size=4096
|
NODE_OPTIONS: --max-old-space-size=4096
|
||||||
|
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_BLOB_REPORTS_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_BLOB_REPORTS_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_BLOB_REPORTS_SUBSCRIPTION_ID }}
|
||||||
|
|
||||||
- name: Upload HTML report to Azure
|
- name: Upload HTML report to Azure
|
||||||
run: |
|
run: |
|
||||||
REPORT_DIR='run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}'
|
REPORT_DIR='run-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}-${{ github.sha }}'
|
||||||
azcopy cp --recursive "./playwright-report/*" "https://mspwblobreport.blob.core.windows.net/\$web/$REPORT_DIR"
|
azcopy cp --recursive "./playwright-report/*" "https://mspwblobreport.blob.core.windows.net/\$web/$REPORT_DIR"
|
||||||
echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/index.html"
|
echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/index.html"
|
||||||
env:
|
env:
|
||||||
AZCOPY_AUTO_LOGIN_TYPE: SPN
|
AZCOPY_AUTO_LOGIN_TYPE: AZCLI
|
||||||
AZCOPY_SPA_APPLICATION_ID: '${{ secrets.AZCOPY_SPA_APPLICATION_ID }}'
|
|
||||||
AZCOPY_SPA_CLIENT_SECRET: '${{ secrets.AZCOPY_SPA_CLIENT_SECRET }}'
|
|
||||||
AZCOPY_TENANT_ID: '${{ secrets.AZCOPY_TENANT_ID }}'
|
|
||||||
|
|
||||||
- name: Read pull request number
|
- name: Read pull request number
|
||||||
uses: ./.github/actions/download-artifact
|
uses: ./.github/actions/download-artifact
|
||||||
|
|
|
||||||
13
.github/workflows/publish_canary.yml
vendored
13
.github/workflows/publish_canary.yml
vendored
|
|
@ -17,8 +17,9 @@ jobs:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.repository == 'microsoft/playwright'
|
if: github.repository == 'microsoft/playwright'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
id-token: write
|
contents: read # This is required for actions/checkout to succeed
|
||||||
|
environment: allow-publish-driver-to-cdn # This is required for OIDC login (azure/login)
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|
@ -49,11 +50,15 @@ jobs:
|
||||||
utils/publish_all_packages.sh --beta
|
utils/publish_all_packages.sh --beta
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_PW_CDN_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_PW_CDN_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_PW_CDN_SUBSCRIPTION_ID }}
|
||||||
- name: build & publish driver
|
- name: build & publish driver
|
||||||
env:
|
env:
|
||||||
AZ_UPLOAD_FOLDER: driver/next
|
AZ_UPLOAD_FOLDER: driver/next
|
||||||
AZ_ACCOUNT_KEY: ${{ secrets.AZ_ACCOUNT_KEY }}
|
|
||||||
AZ_ACCOUNT_NAME: ${{ secrets.AZ_ACCOUNT_NAME }}
|
|
||||||
run: |
|
run: |
|
||||||
utils/build/build-playwright-driver.sh
|
utils/build/build-playwright-driver.sh
|
||||||
utils/build/upload-playwright-driver.sh
|
utils/build/upload-playwright-driver.sh
|
||||||
|
|
|
||||||
17
.github/workflows/publish_release_docker.yml
vendored
17
.github/workflows/publish_release_docker.yml
vendored
|
|
@ -18,18 +18,17 @@ jobs:
|
||||||
publish-docker-release:
|
publish-docker-release:
|
||||||
name: "publish to DockerHub"
|
name: "publish to DockerHub"
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
permissions:
|
||||||
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
if: github.repository == 'microsoft/playwright'
|
if: github.repository == 'microsoft/playwright'
|
||||||
|
environment: allow-publishing-docker-to-acr
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
- uses: azure/docker-login@v1
|
|
||||||
with:
|
|
||||||
login-server: playwright.azurecr.io
|
|
||||||
username: playwright
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
- name: Set up Docker QEMU for arm64 docker builds
|
- name: Set up Docker QEMU for arm64 docker builds
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
with:
|
||||||
|
|
@ -37,6 +36,14 @@ jobs:
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npx playwright install-deps
|
- run: npx playwright install-deps
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_DOCKER_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_DOCKER_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_DOCKER_SUBSCRIPTION_ID }}
|
||||||
|
- name: Login to ACR via OIDC
|
||||||
|
run: az acr login --name playwright
|
||||||
- run: ./utils/docker/publish_docker.sh stable
|
- run: ./utils/docker/publish_docker.sh stable
|
||||||
if: (github.event_name != 'workflow_dispatch' && !github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release == 'true')
|
if: (github.event_name != 'workflow_dispatch' && !github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release == 'true')
|
||||||
- run: ./utils/docker/publish_docker.sh canary
|
- run: ./utils/docker/publish_docker.sh canary
|
||||||
|
|
|
||||||
12
.github/workflows/publish_release_driver.yml
vendored
12
.github/workflows/publish_release_driver.yml
vendored
|
|
@ -12,6 +12,10 @@ jobs:
|
||||||
name: "publish playwright driver to CDN"
|
name: "publish playwright driver to CDN"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.repository == 'microsoft/playwright'
|
if: github.repository == 'microsoft/playwright'
|
||||||
|
permissions:
|
||||||
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
|
environment: allow-publish-driver-to-cdn # This is required for OIDC login (azure/login)
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|
@ -22,8 +26,12 @@ jobs:
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npx playwright install-deps
|
- run: npx playwright install-deps
|
||||||
- run: utils/build/build-playwright-driver.sh
|
- run: utils/build/build-playwright-driver.sh
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_PW_CDN_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_PW_CDN_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_PW_CDN_SUBSCRIPTION_ID }}
|
||||||
- run: utils/build/upload-playwright-driver.sh
|
- run: utils/build/upload-playwright-driver.sh
|
||||||
env:
|
env:
|
||||||
AZ_UPLOAD_FOLDER: driver
|
AZ_UPLOAD_FOLDER: driver
|
||||||
AZ_ACCOUNT_KEY: ${{ secrets.AZ_ACCOUNT_KEY }}
|
|
||||||
AZ_ACCOUNT_NAME: ${{ secrets.AZ_ACCOUNT_NAME }}
|
|
||||||
|
|
|
||||||
4
.github/workflows/publish_release_npm.yml
vendored
4
.github/workflows/publish_release_npm.yml
vendored
|
|
@ -25,10 +25,10 @@ jobs:
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npx playwright install-deps
|
- run: npx playwright install-deps
|
||||||
- run: utils/publish_all_packages.sh --release-candidate
|
- run: utils/publish_all_packages.sh --release-candidate
|
||||||
if: "github.event.release.prerelease"
|
if: ${{ github.event.release.prerelease }}
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
- run: utils/publish_all_packages.sh --release
|
- run: utils/publish_all_packages.sh --release
|
||||||
if: "!github.event.release.prerelease"
|
if: ${{ !github.event.release.prerelease }}
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
|
||||||
2
.github/workflows/roll_driver_nodejs.yml
vendored
2
.github/workflows/roll_driver_nodejs.yml
vendored
|
|
@ -9,6 +9,8 @@ jobs:
|
||||||
name: Trigger Roll
|
name: Trigger Roll
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
if: github.repository == 'microsoft/playwright'
|
if: github.repository == 'microsoft/playwright'
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|
|
||||||
4
.github/workflows/tests_components.yml
vendored
4
.github/workflows/tests_components.yml
vendored
|
|
@ -26,10 +26,10 @@ jobs:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
node-version: [18]
|
node-version: [18]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
|
||||||
node-version: 16
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
- os: ubuntu-latest
|
||||||
|
node-version: 22
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
|
||||||
16
.github/workflows/tests_electron.yml
vendored
16
.github/workflows/tests_electron.yml
vendored
|
|
@ -17,15 +17,18 @@ on:
|
||||||
env:
|
env:
|
||||||
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
||||||
FORCE_COLOR: 1
|
FORCE_COLOR: 1
|
||||||
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test_electron:
|
test_electron:
|
||||||
name: ${{ matrix.os }}
|
name: ${{ matrix.os }}
|
||||||
|
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
permissions:
|
||||||
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -41,8 +44,13 @@ jobs:
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest'
|
||||||
- run: npm run etest
|
- run: npm run etest
|
||||||
if: matrix.os != 'ubuntu-latest'
|
if: matrix.os != 'ubuntu-latest'
|
||||||
- run: node tests/config/checkCoverage.js electron
|
- name: Azure Login
|
||||||
if: always() && matrix.os == 'ubuntu-latest'
|
uses: azure/login@v2
|
||||||
|
if: ${{ !cancelled() && github.event_name == 'push' && github.repository == 'microsoft/playwright' }}
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
151
.github/workflows/tests_primary.yml
vendored
151
.github/workflows/tests_primary.yml
vendored
|
|
@ -22,12 +22,12 @@ concurrency:
|
||||||
env:
|
env:
|
||||||
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
||||||
FORCE_COLOR: 1
|
FORCE_COLOR: 1
|
||||||
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
|
|
||||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test_linux:
|
test_linux:
|
||||||
name: ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }})
|
name: ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }})
|
||||||
|
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -35,74 +35,55 @@ jobs:
|
||||||
os: [ubuntu-22.04]
|
os: [ubuntu-22.04]
|
||||||
node-version: [18]
|
node-version: [18]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-22.04
|
|
||||||
node-version: 16
|
|
||||||
browser: chromium
|
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
node-version: 20
|
node-version: 20
|
||||||
browser: chromium
|
browser: chromium
|
||||||
|
- os: ubuntu-22.04
|
||||||
|
node-version: 22
|
||||||
|
browser: chromium
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
permissions:
|
||||||
PWTEST_BOT_NAME: "${{ matrix.browser }}-${{ matrix.os }}-node${{ matrix.node-version }}"
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: ./.github/actions/run-test
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- run: npm ci
|
browsers-to-install: ${{ matrix.browser }} chromium
|
||||||
env:
|
command: npm run test -- --project=${{ matrix.browser }}-*
|
||||||
DEBUG: pw:install
|
bot-name: "${{ matrix.browser }}-${{ matrix.os }}-node${{ matrix.node-version }}"
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
- run: npm run build
|
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
- run: npx playwright install --with-deps ${{ matrix.browser }} chromium
|
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=${{ matrix.browser }}-*
|
|
||||||
- run: node tests/config/checkCoverage.js ${{ matrix.browser }}
|
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
|
||||||
if: always()
|
|
||||||
shell: bash
|
|
||||||
- name: Upload blob report
|
|
||||||
if: always()
|
|
||||||
uses: ./.github/actions/upload-blob-report
|
|
||||||
with:
|
|
||||||
report_dir: blob-report
|
|
||||||
job_name: ${{ env.PWTEST_BOT_NAME }}
|
|
||||||
|
|
||||||
test_linux_chromium_tot:
|
test_linux_chromium_tot:
|
||||||
name: ${{ matrix.os }} (chromium tip-of-tree)
|
name: ${{ matrix.os }} (chromium tip-of-tree)
|
||||||
|
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-20.04]
|
os: [ubuntu-20.04]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
permissions:
|
||||||
PWTEST_BOT_NAME: "${{ matrix.os }}-chromium-tip-of-tree"
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: ./.github/actions/run-test
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
browsers-to-install: chromium-tip-of-tree
|
||||||
- run: npm ci
|
command: npm run test -- --project=chromium-*
|
||||||
env:
|
bot-name: "${{ matrix.os }}-chromium-tip-of-tree"
|
||||||
DEBUG: pw:install
|
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
- run: npm run build
|
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
- run: npx playwright install --with-deps chromium-tip-of-tree
|
|
||||||
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=chromium-*
|
|
||||||
env:
|
env:
|
||||||
PWTEST_CHANNEL: chromium-tip-of-tree
|
PWTEST_CHANNEL: chromium-tip-of-tree
|
||||||
PWTEST_BOT_NAME: "${{ matrix.os }}-chromium-tip-of-tree"
|
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
|
||||||
if: always()
|
|
||||||
shell: bash
|
|
||||||
- name: Upload blob report
|
|
||||||
if: always()
|
|
||||||
uses: ./.github/actions/upload-blob-report
|
|
||||||
with:
|
|
||||||
report_dir: blob-report
|
|
||||||
job_name: ${{ env.PWTEST_BOT_NAME }}
|
|
||||||
|
|
||||||
test_test_runner:
|
test_test_runner:
|
||||||
name: Test Runner
|
name: Test Runner
|
||||||
|
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -112,47 +93,37 @@ jobs:
|
||||||
shardTotal: [2]
|
shardTotal: [2]
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
node-version: 16
|
node-version: 20
|
||||||
shardIndex: 1
|
shardIndex: 1
|
||||||
shardTotal: 2
|
shardTotal: 2
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
node-version: 16
|
node-version: 20
|
||||||
shardIndex: 2
|
shardIndex: 2
|
||||||
shardTotal: 2
|
shardTotal: 2
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
node-version: 20
|
node-version: 22
|
||||||
shardIndex: 1
|
shardIndex: 1
|
||||||
shardTotal: 2
|
shardTotal: 2
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
node-version: 20
|
node-version: 22
|
||||||
shardIndex: 2
|
shardIndex: 2
|
||||||
shardTotal: 2
|
shardTotal: 2
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
env:
|
permissions:
|
||||||
PWTEST_BOT_NAME: "${{ matrix.os }}-node${{ matrix.node-version }}-${{ matrix.shardIndex }}"
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: ./.github/actions/run-test
|
||||||
with:
|
with:
|
||||||
node-version: ${{matrix.node-version}}
|
node-version: ${{matrix.node-version}}
|
||||||
- run: npm ci
|
command: npm run ttest -- --shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
||||||
|
bot-name: "${{ matrix.os }}-node${{ matrix.node-version }}-${{ matrix.shardIndex }}"
|
||||||
|
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
|
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
|
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
env:
|
env:
|
||||||
DEBUG: pw:install
|
PWTEST_CHANNEL: firefox-beta
|
||||||
- run: npm run build
|
|
||||||
- run: npx playwright install --with-deps
|
|
||||||
- run: npm run ttest -- --shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
|
||||||
if: matrix.os != 'ubuntu-latest'
|
|
||||||
- run: xvfb-run npm run ttest -- --shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
|
||||||
if: matrix.os == 'ubuntu-latest'
|
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
|
||||||
if: always()
|
|
||||||
shell: bash
|
|
||||||
- name: Upload blob report
|
|
||||||
if: always()
|
|
||||||
uses: ./.github/actions/upload-blob-report
|
|
||||||
with:
|
|
||||||
report_dir: blob-report
|
|
||||||
job_name: ${{ env.PWTEST_BOT_NAME }}
|
|
||||||
|
|
||||||
test_web_components:
|
test_web_components:
|
||||||
name: Web Components
|
name: Web Components
|
||||||
|
|
@ -172,18 +143,18 @@ jobs:
|
||||||
env:
|
env:
|
||||||
PWTEST_BOT_NAME: "web-components-html-reporter"
|
PWTEST_BOT_NAME: "web-components-html-reporter"
|
||||||
- name: Upload blob report
|
- name: Upload blob report
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/upload-blob-report
|
uses: ./.github/actions/upload-blob-report
|
||||||
with:
|
with:
|
||||||
report_dir: packages/html-reporter/blob-report
|
report_dir: packages/html-reporter/blob-report
|
||||||
job_name: "web-components-html-reporter"
|
job_name: "web-components-html-reporter"
|
||||||
|
|
||||||
- run: npm run test-web
|
- run: npm run test-web
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
env:
|
env:
|
||||||
PWTEST_BOT_NAME: "web-components-web"
|
PWTEST_BOT_NAME: "web-components-web"
|
||||||
- name: Upload blob report
|
- name: Upload blob report
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/upload-blob-report
|
uses: ./.github/actions/upload-blob-report
|
||||||
with:
|
with:
|
||||||
report_dir: packages/web/blob-report
|
report_dir: packages/web/blob-report
|
||||||
|
|
@ -219,7 +190,7 @@ jobs:
|
||||||
run: npm run test -- --workers=1
|
run: npm run test -- --workers=1
|
||||||
working-directory: ./playwright-vscode
|
working-directory: ./playwright-vscode
|
||||||
- name: Upload blob report
|
- name: Upload blob report
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
uses: ./.github/actions/upload-blob-report
|
uses: ./.github/actions/upload-blob-report
|
||||||
with:
|
with:
|
||||||
report_dir: playwright-vscode/blob-report
|
report_dir: playwright-vscode/blob-report
|
||||||
|
|
@ -227,6 +198,7 @@ jobs:
|
||||||
|
|
||||||
test_package_installations:
|
test_package_installations:
|
||||||
name: "Installation Test ${{ matrix.os }}"
|
name: "Installation Test ${{ matrix.os }}"
|
||||||
|
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -236,30 +208,19 @@ jobs:
|
||||||
- windows-latest
|
- windows-latest
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
env:
|
permissions:
|
||||||
PWTEST_BOT_NAME: "package-installations-${{ matrix.os }}"
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
- run: npm ci
|
|
||||||
env:
|
|
||||||
DEBUG: pw:install
|
|
||||||
- run: npm run build
|
|
||||||
- run: npx playwright install --with-deps
|
|
||||||
- run: npm install -g yarn@1
|
- run: npm install -g yarn@1
|
||||||
- run: npm install -g pnpm@8
|
- run: npm install -g pnpm@8
|
||||||
- run: npm run itest
|
- uses: ./.github/actions/run-test
|
||||||
if: matrix.os != 'ubuntu-latest'
|
|
||||||
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run itest
|
|
||||||
if: matrix.os == 'ubuntu-latest'
|
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
|
||||||
if: always()
|
|
||||||
shell: bash
|
|
||||||
- name: Upload blob report
|
|
||||||
if: always()
|
|
||||||
uses: ./.github/actions/upload-blob-report
|
|
||||||
with:
|
with:
|
||||||
report_dir: blob-report
|
command: npm run itest
|
||||||
job_name: ${{ env.PWTEST_BOT_NAME }}
|
bot-name: "package-installations-${{ matrix.os }}"
|
||||||
|
# TODO: figure out why itest fails with 'bash' on Windows.
|
||||||
|
shell: ${{ matrix.os == 'windows-latest' && 'pwsh' || 'bash' }}
|
||||||
|
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
|
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
|
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
|
|
|
||||||
795
.github/workflows/tests_secondary.yml
vendored
795
.github/workflows/tests_secondary.yml
vendored
File diff suppressed because it is too large
Load diff
4
.github/workflows/tests_service.yml
vendored
4
.github/workflows/tests_service.yml
vendored
|
|
@ -33,7 +33,7 @@ jobs:
|
||||||
PLAYWRIGHT_SERVICE_OS: ${{ matrix.service-os }}
|
PLAYWRIGHT_SERVICE_OS: ${{ matrix.service-os }}
|
||||||
PLAYWRIGHT_SERVICE_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }}
|
PLAYWRIGHT_SERVICE_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }}
|
||||||
- name: Upload blob report to GitHub
|
- name: Upload blob report to GitHub
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: all-blob-reports
|
name: all-blob-reports
|
||||||
|
|
@ -43,7 +43,7 @@ jobs:
|
||||||
merge_reports:
|
merge_reports:
|
||||||
name: "Merge reports"
|
name: "Merge reports"
|
||||||
needs: [test]
|
needs: [test]
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
|
||||||
24
.github/workflows/tests_stress.yml
vendored
24
.github/workflows/tests_stress.yml
vendored
|
|
@ -30,29 +30,27 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 20
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: npx playwright install --with-deps
|
- run: npx playwright install --with-deps
|
||||||
- run: npx playwright install firefox-asan
|
|
||||||
if: matrix.os != 'windows-latest'
|
|
||||||
- run: npm run stest contexts -- --project=chromium
|
- run: npm run stest contexts -- --project=chromium
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest browsers -- --project=chromium
|
- run: npm run stest browsers -- --project=chromium
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest frames -- --project=chromium
|
- run: npm run stest frames -- --project=chromium
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest contexts -- --project=webkit
|
- run: npm run stest contexts -- --project=webkit
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest browsers -- --project=webkit
|
- run: npm run stest browsers -- --project=webkit
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest frames -- --project=webkit
|
- run: npm run stest frames -- --project=webkit
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest contexts -- --project=firefox
|
- run: npm run stest contexts -- --project=firefox
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest browsers -- --project=firefox
|
- run: npm run stest browsers -- --project=firefox
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest frames -- --project=firefox
|
- run: npm run stest frames -- --project=firefox
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
- run: npm run stest heap -- --project=chromium
|
- run: npm run stest heap -- --project=chromium
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
|
|
|
||||||
14
.github/workflows/tests_video.yml
vendored
14
.github/workflows/tests_video.yml
vendored
|
|
@ -9,17 +9,20 @@ on:
|
||||||
env:
|
env:
|
||||||
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
||||||
FORCE_COLOR: 1
|
FORCE_COLOR: 1
|
||||||
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
|
|
||||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
video_linux:
|
video_linux:
|
||||||
name: "Video Linux"
|
name: "Video Linux"
|
||||||
|
environment: allow-uploading-flakiness-results
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
browser: [chromium, firefox, webkit]
|
browser: [chromium, firefox, webkit]
|
||||||
os: [ubuntu-20.04, ubuntu-22.04]
|
os: [ubuntu-20.04, ubuntu-22.04]
|
||||||
|
permissions:
|
||||||
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -35,6 +38,13 @@ jobs:
|
||||||
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=${{ matrix.browser }}-*
|
- run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=${{ matrix.browser }}-*
|
||||||
env:
|
env:
|
||||||
PWTEST_VIDEO: 1
|
PWTEST_VIDEO: 1
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: ${{ !cancelled() && github.event_name == 'push' && github.repository == 'microsoft/playwright' }}
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
20
.github/workflows/tests_webview2.yml
vendored
20
.github/workflows/tests_webview2.yml
vendored
|
|
@ -17,13 +17,16 @@ on:
|
||||||
env:
|
env:
|
||||||
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
# Force terminal colors. @see https://www.npmjs.com/package/colors
|
||||||
FORCE_COLOR: 1
|
FORCE_COLOR: 1
|
||||||
FLAKINESS_CONNECTION_STRING: ${{ secrets.FLAKINESS_CONNECTION_STRING }}
|
|
||||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test_webview2:
|
test_webview2:
|
||||||
name: WebView2
|
name: WebView2
|
||||||
|
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
|
permissions:
|
||||||
|
id-token: write # This is required for OIDC login (azure/login) to succeed
|
||||||
|
contents: read # This is required for actions/checkout to succeed
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|
@ -38,7 +41,20 @@ jobs:
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: dotnet build
|
- run: dotnet build
|
||||||
working-directory: tests/webview2/webview2-app/
|
working-directory: tests/webview2/webview2-app/
|
||||||
|
- name: Update to Evergreen WebView2 Runtime
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
# See here: https://developer.microsoft.com/en-us/microsoft-edge/webview2/
|
||||||
|
Invoke-WebRequest -Uri 'https://go.microsoft.com/fwlink/p/?LinkId=2124703' -OutFile 'setup.exe'
|
||||||
|
Start-Process -FilePath setup.exe -Verb RunAs -Wait
|
||||||
- run: npm run webview2test
|
- run: npm run webview2test
|
||||||
|
- name: Azure Login
|
||||||
|
uses: azure/login@v2
|
||||||
|
if: ${{ !cancelled() && github.event_name == 'push' && github.repository == 'microsoft/playwright' }}
|
||||||
|
with:
|
||||||
|
client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
|
||||||
|
tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
|
||||||
|
subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
|
||||||
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,6 +7,7 @@ node_modules/
|
||||||
*.swp
|
*.swp
|
||||||
*.pyc
|
*.pyc
|
||||||
.vscode
|
.vscode
|
||||||
|
.mono
|
||||||
.idea
|
.idea
|
||||||
yarn.lock
|
yarn.lock
|
||||||
/packages/playwright-core/src/generated
|
/packages/playwright-core/src/generated
|
||||||
|
|
|
||||||
|
|
@ -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://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 -->
|
||||||
|
|
||||||
## [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,9 +8,9 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
|
||||||
|
|
||||||
| | Linux | macOS | Windows |
|
| | Linux | macOS | Windows |
|
||||||
| :--- | :---: | :---: | :---: |
|
| :--- | :---: | :---: | :---: |
|
||||||
| Chromium <!-- GEN:chromium-version -->123.0.6312.22<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Chromium <!-- GEN:chromium-version -->125.0.6422.26<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
| Firefox <!-- GEN:firefox-version -->123.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
| Firefox <!-- GEN:firefox-version -->125.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||||
|
|
||||||
Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
|
Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
REMOTE_URL="https://github.com/mozilla/gecko-dev"
|
REMOTE_URL="https://github.com/mozilla/gecko-dev"
|
||||||
BASE_BRANCH="release"
|
BASE_BRANCH="release"
|
||||||
BASE_REVISION="a32b8662993085139ac91212a297123b632fc1c0"
|
BASE_REVISION="f8704c84a751716bad093b9bdc482db53fe5b3ea"
|
||||||
|
|
|
||||||
|
|
@ -553,7 +553,11 @@ class NetworkRequest {
|
||||||
|
|
||||||
_sendOnRequestFinished() {
|
_sendOnRequestFinished() {
|
||||||
const pageNetwork = this._pageNetwork;
|
const pageNetwork = this._pageNetwork;
|
||||||
if (pageNetwork) {
|
// Undefined |responseEndTime| means there has been no response yet.
|
||||||
|
// This happens when request interception API is used to redirect
|
||||||
|
// the request to a different URL.
|
||||||
|
// In this case, we should not emit "requestFinished" event.
|
||||||
|
if (pageNetwork && this.httpChannel.responseEndTime !== undefined) {
|
||||||
let protocolVersion = undefined;
|
let protocolVersion = undefined;
|
||||||
try {
|
try {
|
||||||
protocolVersion = this.httpChannel.protocolVersion;
|
protocolVersion = this.httpChannel.protocolVersion;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ const ALL_PERMISSIONS = [
|
||||||
'desktop-notification',
|
'desktop-notification',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let globalTabAndWindowActivationChain = Promise.resolve();
|
||||||
|
|
||||||
class DownloadInterceptor {
|
class DownloadInterceptor {
|
||||||
constructor(registry) {
|
constructor(registry) {
|
||||||
this._registry = registry
|
this._registry = registry
|
||||||
|
|
@ -384,7 +386,7 @@ class PageTarget {
|
||||||
const tabBrowser = ownerWindow.gBrowser;
|
const tabBrowser = ownerWindow.gBrowser;
|
||||||
// Serialize all tab-switching commands per tabbed browser
|
// Serialize all tab-switching commands per tabbed browser
|
||||||
// to disallow concurrent tab switching.
|
// to disallow concurrent tab switching.
|
||||||
const result = (tabBrowser.__serializedChain ?? Promise.resolve()).then(async () => {
|
const result = globalTabAndWindowActivationChain.then(async () => {
|
||||||
this._window.focus();
|
this._window.focus();
|
||||||
if (tabBrowser.selectedTab !== this._tab) {
|
if (tabBrowser.selectedTab !== this._tab) {
|
||||||
const promise = helper.awaitEvent(ownerWindow, 'TabSwitchDone');
|
const promise = helper.awaitEvent(ownerWindow, 'TabSwitchDone');
|
||||||
|
|
@ -399,7 +401,7 @@ class PageTarget {
|
||||||
notificationsPopup?.style.removeProperty('pointer-events');
|
notificationsPopup?.style.removeProperty('pointer-events');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tabBrowser.__serializedChain = result.catch(error => { /* swallow errors to keep chain running */ });
|
globalTabAndWindowActivationChain = result.catch(error => { /* swallow errors to keep chain running */ });
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ class PageAgent {
|
||||||
|
|
||||||
const docShell = frameTree.mainFrame().docShell();
|
const docShell = frameTree.mainFrame().docShell();
|
||||||
this._docShell = docShell;
|
this._docShell = docShell;
|
||||||
this._initialDPPX = docShell.contentViewer.overrideDPPX;
|
|
||||||
|
|
||||||
// Dispatch frameAttached events for all initial frames
|
// Dispatch frameAttached events for all initial frames
|
||||||
for (const frame of this._frameTree.frames()) {
|
for (const frame of this._frameTree.frames()) {
|
||||||
|
|
@ -383,6 +382,12 @@ class PageAgent {
|
||||||
throw new Error('Object is not input!');
|
throw new Error('Object is not input!');
|
||||||
const nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
|
const nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
|
||||||
unsafeObject.mozSetFileArray(nsFiles);
|
unsafeObject.mozSetFileArray(nsFiles);
|
||||||
|
const events = [
|
||||||
|
new (frame.domWindow().Event)('input', { bubbles: true, cancelable: true, composed: true }),
|
||||||
|
new (frame.domWindow().Event)('change', { bubbles: true, cancelable: true, composed: true }),
|
||||||
|
];
|
||||||
|
for (const event of events)
|
||||||
|
unsafeObject.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getContentQuads({objectId, frameId}) {
|
_getContentQuads({objectId, frameId}) {
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,10 @@ index b40e0fceb567c0d217adf284e13f434e49cc8467..2c4e6d5fbf8da40954ad6a5b15e41249
|
||||||
DWORD creationFlags = CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT;
|
DWORD creationFlags = CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT;
|
||||||
|
|
||||||
diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn
|
diff --git a/browser/installer/allowed-dupes.mn b/browser/installer/allowed-dupes.mn
|
||||||
index 24a6f228c617c034ccc4926c238aa15e32c964f6..38c4ed9936f5033abe7a4ac7997aea2d92747733 100644
|
index f6d425f36a965f03ac82dbe3ab6cde06f12751ac..d60999ab2658b1e1e5f07a8aee530451c44f2957 100644
|
||||||
--- a/browser/installer/allowed-dupes.mn
|
--- a/browser/installer/allowed-dupes.mn
|
||||||
+++ b/browser/installer/allowed-dupes.mn
|
+++ b/browser/installer/allowed-dupes.mn
|
||||||
@@ -71,6 +71,12 @@ browser/features/webcompat@mozilla.org/shims/empty-shim.txt
|
@@ -73,6 +73,12 @@ browser/features/webcompat@mozilla.org/shims/empty-shim.txt
|
||||||
removed-files
|
removed-files
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -106,10 +106,10 @@ index 24a6f228c617c034ccc4926c238aa15e32c964f6..38c4ed9936f5033abe7a4ac7997aea2d
|
||||||
browser/chrome/browser/search-extensions/amazon/favicon.ico
|
browser/chrome/browser/search-extensions/amazon/favicon.ico
|
||||||
browser/chrome/browser/search-extensions/amazondotcn/favicon.ico
|
browser/chrome/browser/search-extensions/amazondotcn/favicon.ico
|
||||||
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
|
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
|
||||||
index b3213b8c4498b0467d7863d53c5fc4240e4609be..5ca6b68c6c7aaebd41a81999974f69810876f82b 100644
|
index 4068c0c165fcebd0a72f4d780bc0cbd680fe7a9c..fec7f8505d22485fa6ad4193d59387f493bd1ef8 100644
|
||||||
--- a/browser/installer/package-manifest.in
|
--- a/browser/installer/package-manifest.in
|
||||||
+++ b/browser/installer/package-manifest.in
|
+++ b/browser/installer/package-manifest.in
|
||||||
@@ -195,6 +195,9 @@
|
@@ -197,6 +197,9 @@
|
||||||
@RESPATH@/chrome/remote.manifest
|
@RESPATH@/chrome/remote.manifest
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -167,7 +167,7 @@ index 4236ec2921bd57c58cfffdf1cdcf509d76fca3db..23d0cb1f06bb8c7a1cac8fcec94a99fb
|
||||||
const transportProvider = {
|
const transportProvider = {
|
||||||
setListener(upgradeListener) {
|
setListener(upgradeListener) {
|
||||||
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp
|
diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp
|
||||||
index 211f83a476caa08281b3a0158da42cb08b01a374..47d78411e67d3f9b67c48ff10379e117b8631ab6 100644
|
index 0ef5e02d2ae365b4e7b30fd49771e547c030bcfc..0787518696fc90bba3dce8c1e1c00387c3e7a6c9 100644
|
||||||
--- a/docshell/base/BrowsingContext.cpp
|
--- a/docshell/base/BrowsingContext.cpp
|
||||||
+++ b/docshell/base/BrowsingContext.cpp
|
+++ b/docshell/base/BrowsingContext.cpp
|
||||||
@@ -114,6 +114,20 @@ struct ParamTraits<mozilla::dom::PrefersColorSchemeOverride>
|
@@ -114,6 +114,20 @@ struct ParamTraits<mozilla::dom::PrefersColorSchemeOverride>
|
||||||
|
|
@ -191,7 +191,7 @@ index 211f83a476caa08281b3a0158da42cb08b01a374..47d78411e67d3f9b67c48ff10379e117
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::dom::ExplicitActiveStatus>
|
struct ParamTraits<mozilla::dom::ExplicitActiveStatus>
|
||||||
: public ContiguousEnumSerializer<
|
: public ContiguousEnumSerializer<
|
||||||
@@ -2781,6 +2795,40 @@ void BrowsingContext::DidSet(FieldIndex<IDX_PrefersColorSchemeOverride>,
|
@@ -2793,6 +2807,40 @@ void BrowsingContext::DidSet(FieldIndex<IDX_PrefersColorSchemeOverride>,
|
||||||
PresContextAffectingFieldChanged();
|
PresContextAffectingFieldChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +233,7 @@ index 211f83a476caa08281b3a0158da42cb08b01a374..47d78411e67d3f9b67c48ff10379e117
|
||||||
nsString&& aOldValue) {
|
nsString&& aOldValue) {
|
||||||
MOZ_ASSERT(IsTop());
|
MOZ_ASSERT(IsTop());
|
||||||
diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h
|
diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h
|
||||||
index 84532563e1db1941abca5afa74a7d68473d391ef..84d6f605d5f70d11b355ba76b0f5af868864ac18 100644
|
index 7554128cf49ce929c973aeddf5f50ede01829c28..81ae7ec9523b944654c048af6a9f6844799eb4f3 100644
|
||||||
--- a/docshell/base/BrowsingContext.h
|
--- a/docshell/base/BrowsingContext.h
|
||||||
+++ b/docshell/base/BrowsingContext.h
|
+++ b/docshell/base/BrowsingContext.h
|
||||||
@@ -200,10 +200,10 @@ struct EmbedderColorSchemes {
|
@@ -200,10 +200,10 @@ struct EmbedderColorSchemes {
|
||||||
|
|
@ -260,7 +260,7 @@ index 84532563e1db1941abca5afa74a7d68473d391ef..84d6f605d5f70d11b355ba76b0f5af86
|
||||||
/* The number of entries added to the session history because of this \
|
/* The number of entries added to the session history because of this \
|
||||||
* browsing context. */ \
|
* browsing context. */ \
|
||||||
FIELD(HistoryEntryCount, uint32_t) \
|
FIELD(HistoryEntryCount, uint32_t) \
|
||||||
@@ -923,6 +927,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
@@ -933,6 +937,14 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
||||||
return GetPrefersColorSchemeOverride();
|
return GetPrefersColorSchemeOverride();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,7 +275,7 @@ index 84532563e1db1941abca5afa74a7d68473d391ef..84d6f605d5f70d11b355ba76b0f5af86
|
||||||
bool IsInBFCache() const;
|
bool IsInBFCache() const;
|
||||||
|
|
||||||
bool AllowJavascript() const { return GetAllowJavascript(); }
|
bool AllowJavascript() const { return GetAllowJavascript(); }
|
||||||
@@ -1087,6 +1099,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
@@ -1097,6 +1109,23 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
||||||
void WalkPresContexts(Callback&&);
|
void WalkPresContexts(Callback&&);
|
||||||
void PresContextAffectingFieldChanged();
|
void PresContextAffectingFieldChanged();
|
||||||
|
|
||||||
|
|
@ -300,7 +300,7 @@ index 84532563e1db1941abca5afa74a7d68473d391ef..84d6f605d5f70d11b355ba76b0f5af86
|
||||||
|
|
||||||
bool CanSet(FieldIndex<IDX_SuspendMediaWhenInactive>, bool, ContentParent*) {
|
bool CanSet(FieldIndex<IDX_SuspendMediaWhenInactive>, bool, ContentParent*) {
|
||||||
diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp
|
diff --git a/docshell/base/CanonicalBrowsingContext.cpp b/docshell/base/CanonicalBrowsingContext.cpp
|
||||||
index 044df3a801ed55e08347464397821261bb6761c0..8aa8e4844e4ba5364cbb0547c5397ce695798861 100644
|
index d5f85b1e571a7840425164a3c7715e8c70ed5c8b..5ba7484b1e7f817b2bb21dd6b5b35c6ffe2c1ca5 100644
|
||||||
--- a/docshell/base/CanonicalBrowsingContext.cpp
|
--- a/docshell/base/CanonicalBrowsingContext.cpp
|
||||||
+++ b/docshell/base/CanonicalBrowsingContext.cpp
|
+++ b/docshell/base/CanonicalBrowsingContext.cpp
|
||||||
@@ -1466,6 +1466,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI,
|
@@ -1466,6 +1466,12 @@ void CanonicalBrowsingContext::LoadURI(nsIURI* aURI,
|
||||||
|
|
@ -317,7 +317,7 @@ index 044df3a801ed55e08347464397821261bb6761c0..8aa8e4844e4ba5364cbb0547c5397ce6
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
|
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
|
||||||
index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e8aa888bf 100644
|
index 0b8212fbf3f81ef6264f17fc8e84f91cde39c0f7..99d43d662978c0418231b8ea55d670f81b5618d7 100644
|
||||||
--- a/docshell/base/nsDocShell.cpp
|
--- a/docshell/base/nsDocShell.cpp
|
||||||
+++ b/docshell/base/nsDocShell.cpp
|
+++ b/docshell/base/nsDocShell.cpp
|
||||||
@@ -15,6 +15,12 @@
|
@@ -15,6 +15,12 @@
|
||||||
|
|
@ -350,7 +350,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
#include "mozilla/net/DocumentChannelChild.h"
|
#include "mozilla/net/DocumentChannelChild.h"
|
||||||
#include "mozilla/net/ParentChannelWrapper.h"
|
#include "mozilla/net/ParentChannelWrapper.h"
|
||||||
@@ -111,6 +119,7 @@
|
@@ -111,6 +119,7 @@
|
||||||
#include "nsIDocShellTreeOwner.h"
|
#include "nsIDocumentViewer.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "nsHTMLDocument.h"
|
#include "nsHTMLDocument.h"
|
||||||
+#include "mozilla/dom/Element.h"
|
+#include "mozilla/dom/Element.h"
|
||||||
|
|
@ -379,7 +379,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
mAllowAuth(mItemType == typeContent),
|
mAllowAuth(mItemType == typeContent),
|
||||||
mAllowKeywordFixup(false),
|
mAllowKeywordFixup(false),
|
||||||
mDisableMetaRefreshWhenInactive(false),
|
mDisableMetaRefreshWhenInactive(false),
|
||||||
@@ -3147,6 +3164,214 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
|
@@ -3115,6 +3132,214 @@ nsDocShell::GetMessageManager(ContentFrameMessageManager** aMessageManager) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -594,7 +594,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDocShell::GetIsNavigating(bool* aOut) {
|
nsDocShell::GetIsNavigating(bool* aOut) {
|
||||||
*aOut = mIsNavigating;
|
*aOut = mIsNavigating;
|
||||||
@@ -4835,7 +5060,7 @@ nsDocShell::GetVisibility(bool* aVisibility) {
|
@@ -4803,7 +5028,7 @@ nsDocShell::GetVisibility(bool* aVisibility) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsDocShell::ActivenessMaybeChanged() {
|
void nsDocShell::ActivenessMaybeChanged() {
|
||||||
|
|
@ -603,7 +603,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
if (RefPtr<PresShell> presShell = GetPresShell()) {
|
if (RefPtr<PresShell> presShell = GetPresShell()) {
|
||||||
presShell->ActivenessMaybeChanged();
|
presShell->ActivenessMaybeChanged();
|
||||||
}
|
}
|
||||||
@@ -6753,6 +6978,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
|
@@ -6722,6 +6947,10 @@ bool nsDocShell::CanSavePresentation(uint32_t aLoadType,
|
||||||
return false; // no entry to save into
|
return false; // no entry to save into
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -613,8 +613,8 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
+
|
+
|
||||||
MOZ_ASSERT(!mozilla::SessionHistoryInParent(),
|
MOZ_ASSERT(!mozilla::SessionHistoryInParent(),
|
||||||
"mOSHE cannot be non-null with SHIP");
|
"mOSHE cannot be non-null with SHIP");
|
||||||
nsCOMPtr<nsIContentViewer> viewer = mOSHE->GetContentViewer();
|
nsCOMPtr<nsIDocumentViewer> viewer = mOSHE->GetDocumentViewer();
|
||||||
@@ -8536,6 +8765,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
|
@@ -8454,6 +8683,12 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState) {
|
||||||
true, // aForceNoOpener
|
true, // aForceNoOpener
|
||||||
getter_AddRefs(newBC));
|
getter_AddRefs(newBC));
|
||||||
MOZ_ASSERT(!newBC);
|
MOZ_ASSERT(!newBC);
|
||||||
|
|
@ -627,7 +627,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9611,6 +9846,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
|
@@ -9566,6 +9801,16 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
|
||||||
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
|
nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
|
||||||
|
|
||||||
nsCOMPtr<nsIRequest> req;
|
nsCOMPtr<nsIRequest> req;
|
||||||
|
|
@ -644,7 +644,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
|
rv = DoURILoad(aLoadState, aCacheKey, getter_AddRefs(req));
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
@@ -12768,6 +13013,9 @@ class OnLinkClickEvent : public Runnable {
|
@@ -12714,6 +12959,9 @@ class OnLinkClickEvent : public Runnable {
|
||||||
mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
|
mHandler->OnLinkClickSync(mContent, mLoadState, mNoOpenerImplied,
|
||||||
mTriggeringPrincipal);
|
mTriggeringPrincipal);
|
||||||
}
|
}
|
||||||
|
|
@ -654,7 +654,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12852,6 +13100,8 @@ nsresult nsDocShell::OnLinkClick(
|
@@ -12798,6 +13046,8 @@ nsresult nsDocShell::OnLinkClick(
|
||||||
nsCOMPtr<nsIRunnable> ev =
|
nsCOMPtr<nsIRunnable> ev =
|
||||||
new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
|
new OnLinkClickEvent(this, aContent, loadState, noOpenerImplied,
|
||||||
aIsTrusted, aTriggeringPrincipal);
|
aIsTrusted, aTriggeringPrincipal);
|
||||||
|
|
@ -664,7 +664,7 @@ index f4d8843e2df614b0037d2bfa47f02e328c7dff6c..596208d570d6625fa6b99fd75e7a037e
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
|
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
|
||||||
index 237cf8dc1a54ed8d0523272aaaebfd6f10f9213f..73c096a2850850921aff97037457cde598ffef2a 100644
|
index 9f2d9a17dc0d54be4bd09f8e04da6e85f987fe34..8ff6e67fedef0bf73297c4cfed569b8f2ced36d9 100644
|
||||||
--- a/docshell/base/nsDocShell.h
|
--- a/docshell/base/nsDocShell.h
|
||||||
+++ b/docshell/base/nsDocShell.h
|
+++ b/docshell/base/nsDocShell.h
|
||||||
@@ -15,6 +15,7 @@
|
@@ -15,6 +15,7 @@
|
||||||
|
|
@ -683,7 +683,7 @@ index 237cf8dc1a54ed8d0523272aaaebfd6f10f9213f..73c096a2850850921aff97037457cde5
|
||||||
class nsGlobalWindowOuter;
|
class nsGlobalWindowOuter;
|
||||||
|
|
||||||
class FramingChecker;
|
class FramingChecker;
|
||||||
@@ -408,6 +410,15 @@ class nsDocShell final : public nsDocLoader,
|
@@ -401,6 +403,15 @@ class nsDocShell final : public nsDocLoader,
|
||||||
void SetWillChangeProcess() { mWillChangeProcess = true; }
|
void SetWillChangeProcess() { mWillChangeProcess = true; }
|
||||||
bool WillChangeProcess() { return mWillChangeProcess; }
|
bool WillChangeProcess() { return mWillChangeProcess; }
|
||||||
|
|
||||||
|
|
@ -698,8 +698,8 @@ index 237cf8dc1a54ed8d0523272aaaebfd6f10f9213f..73c096a2850850921aff97037457cde5
|
||||||
+
|
+
|
||||||
// Create a content viewer within this nsDocShell for the given
|
// Create a content viewer within this nsDocShell for the given
|
||||||
// `WindowGlobalChild` actor.
|
// `WindowGlobalChild` actor.
|
||||||
nsresult CreateContentViewerForActor(
|
nsresult CreateDocumentViewerForActor(
|
||||||
@@ -1010,6 +1021,8 @@ class nsDocShell final : public nsDocLoader,
|
@@ -1003,6 +1014,8 @@ class nsDocShell final : public nsDocLoader,
|
||||||
|
|
||||||
bool CSSErrorReportingEnabled() const { return mCSSErrorReportingEnabled; }
|
bool CSSErrorReportingEnabled() const { return mCSSErrorReportingEnabled; }
|
||||||
|
|
||||||
|
|
@ -708,7 +708,7 @@ index 237cf8dc1a54ed8d0523272aaaebfd6f10f9213f..73c096a2850850921aff97037457cde5
|
||||||
// Handles retrieval of subframe session history for nsDocShell::LoadURI. If a
|
// Handles retrieval of subframe session history for nsDocShell::LoadURI. If a
|
||||||
// load is requested in a subframe of the current DocShell, the subframe
|
// load is requested in a subframe of the current DocShell, the subframe
|
||||||
// loadType may need to reflect the loadType of the parent document, or in
|
// loadType may need to reflect the loadType of the parent document, or in
|
||||||
@@ -1300,6 +1313,16 @@ class nsDocShell final : public nsDocLoader,
|
@@ -1294,6 +1307,16 @@ class nsDocShell final : public nsDocLoader,
|
||||||
bool mAllowDNSPrefetch : 1;
|
bool mAllowDNSPrefetch : 1;
|
||||||
bool mAllowWindowControl : 1;
|
bool mAllowWindowControl : 1;
|
||||||
bool mCSSErrorReportingEnabled : 1;
|
bool mCSSErrorReportingEnabled : 1;
|
||||||
|
|
@ -726,18 +726,18 @@ index 237cf8dc1a54ed8d0523272aaaebfd6f10f9213f..73c096a2850850921aff97037457cde5
|
||||||
bool mAllowKeywordFixup : 1;
|
bool mAllowKeywordFixup : 1;
|
||||||
bool mDisableMetaRefreshWhenInactive : 1;
|
bool mDisableMetaRefreshWhenInactive : 1;
|
||||||
diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
|
diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
|
||||||
index a3ee2c3944018c64c93c02c5658c527ec5f9d2cb..272e5147568b95bf313ac7a940619382a0c42763 100644
|
index 9e79b6831a74c6de7c6a6c56d9a024d29c1c704b..db5cd5586b74ec65d788480f9c5fca93eb562c21 100644
|
||||||
--- a/docshell/base/nsIDocShell.idl
|
--- a/docshell/base/nsIDocShell.idl
|
||||||
+++ b/docshell/base/nsIDocShell.idl
|
+++ b/docshell/base/nsIDocShell.idl
|
||||||
@@ -44,6 +44,7 @@ interface nsIURI;
|
@@ -44,6 +44,7 @@ interface nsIURI;
|
||||||
interface nsIChannel;
|
interface nsIChannel;
|
||||||
interface nsIContentViewer;
|
|
||||||
interface nsIContentSecurityPolicy;
|
interface nsIContentSecurityPolicy;
|
||||||
|
interface nsIDocumentViewer;
|
||||||
+interface nsIDOMGeoPosition;
|
+interface nsIDOMGeoPosition;
|
||||||
interface nsIEditor;
|
interface nsIEditor;
|
||||||
interface nsIEditingSession;
|
interface nsIEditingSession;
|
||||||
interface nsIInputStream;
|
interface nsIInputStream;
|
||||||
@@ -760,6 +761,36 @@ interface nsIDocShell : nsIDocShellTreeItem
|
@@ -767,6 +768,36 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||||
*/
|
*/
|
||||||
void synchronizeLayoutHistoryState();
|
void synchronizeLayoutHistoryState();
|
||||||
|
|
||||||
|
|
@ -775,10 +775,10 @@ index a3ee2c3944018c64c93c02c5658c527ec5f9d2cb..272e5147568b95bf313ac7a940619382
|
||||||
* This attempts to save any applicable layout history state (like
|
* This attempts to save any applicable layout history state (like
|
||||||
* scroll position) in the nsISHEntry. This is normally done
|
* scroll position) in the nsISHEntry. This is normally done
|
||||||
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
|
diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp
|
||||||
index ff78b31699fe28e60915703b7642a72d540f6f99..dd8f4dd0283e3d0ce1b5ae8745312fcb64126c75 100644
|
index 0a2f5be08d0dcad40cd11f4b064a1287b8141e2f..a845203c6aaea8384e8835cbe005669767a1b196 100644
|
||||||
--- a/dom/base/Document.cpp
|
--- a/dom/base/Document.cpp
|
||||||
+++ b/dom/base/Document.cpp
|
+++ b/dom/base/Document.cpp
|
||||||
@@ -3682,6 +3682,9 @@ void Document::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages) {
|
@@ -3705,6 +3705,9 @@ void Document::SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::ApplySettingsFromCSP(bool aSpeculative) {
|
void Document::ApplySettingsFromCSP(bool aSpeculative) {
|
||||||
|
|
@ -788,7 +788,7 @@ index ff78b31699fe28e60915703b7642a72d540f6f99..dd8f4dd0283e3d0ce1b5ae8745312fcb
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
if (!aSpeculative) {
|
if (!aSpeculative) {
|
||||||
// 1) apply settings from regular CSP
|
// 1) apply settings from regular CSP
|
||||||
@@ -3739,6 +3742,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
@@ -3762,6 +3765,11 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
||||||
MOZ_ASSERT(!mScriptGlobalObject,
|
MOZ_ASSERT(!mScriptGlobalObject,
|
||||||
"CSP must be initialized before mScriptGlobalObject is set!");
|
"CSP must be initialized before mScriptGlobalObject is set!");
|
||||||
|
|
||||||
|
|
@ -800,7 +800,7 @@ index ff78b31699fe28e60915703b7642a72d540f6f99..dd8f4dd0283e3d0ce1b5ae8745312fcb
|
||||||
// If this is a data document - no need to set CSP.
|
// If this is a data document - no need to set CSP.
|
||||||
if (mLoadedAsData) {
|
if (mLoadedAsData) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@@ -4534,6 +4542,10 @@ bool Document::HasFocus(ErrorResult& rv) const {
|
@@ -4557,6 +4565,10 @@ bool Document::HasFocus(ErrorResult& rv) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -811,7 +811,7 @@ index ff78b31699fe28e60915703b7642a72d540f6f99..dd8f4dd0283e3d0ce1b5ae8745312fcb
|
||||||
if (!fm->IsInActiveWindow(bc)) {
|
if (!fm->IsInActiveWindow(bc)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -18736,6 +18748,68 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const {
|
@@ -18878,6 +18890,68 @@ ColorScheme Document::PreferredColorScheme(IgnoreRFP aIgnoreRFP) const {
|
||||||
return PreferenceSheet::PrefsFor(*this).mColorScheme;
|
return PreferenceSheet::PrefsFor(*this).mColorScheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -881,10 +881,10 @@ index ff78b31699fe28e60915703b7642a72d540f6f99..dd8f4dd0283e3d0ce1b5ae8745312fcb
|
||||||
if (!sLoadingForegroundTopLevelContentDocument) {
|
if (!sLoadingForegroundTopLevelContentDocument) {
|
||||||
return false;
|
return false;
|
||||||
diff --git a/dom/base/Document.h b/dom/base/Document.h
|
diff --git a/dom/base/Document.h b/dom/base/Document.h
|
||||||
index 55e4f71d5b33cca55454ac0d4e16d4a96137a616..8ad7117047ee6d0b5de2538cd086d60ae9837594 100644
|
index 3f8032594868b8aa1c8bec2d25b789518170eb0e..5017b426369378b892a224a88410f18e743da45f 100644
|
||||||
--- a/dom/base/Document.h
|
--- a/dom/base/Document.h
|
||||||
+++ b/dom/base/Document.h
|
+++ b/dom/base/Document.h
|
||||||
@@ -4030,6 +4030,9 @@ class Document : public nsINode,
|
@@ -4051,6 +4051,9 @@ class Document : public nsINode,
|
||||||
// color-scheme meta tag.
|
// color-scheme meta tag.
|
||||||
ColorScheme DefaultColorScheme() const;
|
ColorScheme DefaultColorScheme() const;
|
||||||
|
|
||||||
|
|
@ -895,10 +895,10 @@ index 55e4f71d5b33cca55454ac0d4e16d4a96137a616..8ad7117047ee6d0b5de2538cd086d60a
|
||||||
|
|
||||||
static bool AutomaticStorageAccessPermissionCanBeGranted(
|
static bool AutomaticStorageAccessPermissionCanBeGranted(
|
||||||
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
|
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
|
||||||
index 7e54ac18ad9a646e981e7bc356e75de273c75845..1e673db0fd8adc9a4096a826184425e939d5e926 100644
|
index d4b04f809228fecc3e2dbf33dac42151ffc24b11..39dfddff7404e878cd9fcc8f3b9bb734ab72d743 100644
|
||||||
--- a/dom/base/Navigator.cpp
|
--- a/dom/base/Navigator.cpp
|
||||||
+++ b/dom/base/Navigator.cpp
|
+++ b/dom/base/Navigator.cpp
|
||||||
@@ -331,14 +331,18 @@ void Navigator::GetAppName(nsAString& aAppName) const {
|
@@ -335,14 +335,18 @@ void Navigator::GetAppName(nsAString& aAppName) const {
|
||||||
* for more detail.
|
* for more detail.
|
||||||
*/
|
*/
|
||||||
/* static */
|
/* static */
|
||||||
|
|
@ -919,7 +919,7 @@ index 7e54ac18ad9a646e981e7bc356e75de273c75845..1e673db0fd8adc9a4096a826184425e9
|
||||||
|
|
||||||
// Split values on commas.
|
// Split values on commas.
|
||||||
for (nsDependentSubstring lang :
|
for (nsDependentSubstring lang :
|
||||||
@@ -390,7 +394,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) {
|
@@ -394,7 +398,13 @@ void Navigator::GetLanguage(nsAString& aLanguage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
|
void Navigator::GetLanguages(nsTArray<nsString>& aLanguages) {
|
||||||
|
|
@ -935,10 +935,10 @@ index 7e54ac18ad9a646e981e7bc356e75de273c75845..1e673db0fd8adc9a4096a826184425e9
|
||||||
// The returned value is cached by the binding code. The window listens to the
|
// The returned value is cached by the binding code. The window listens to the
|
||||||
// accept languages change and will clear the cache when needed. It has to
|
// accept languages change and will clear the cache when needed. It has to
|
||||||
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
|
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
|
||||||
index 851b681570e35ba86341f56912684bc8ec7001f3..2fd4d6fd9deafaa42604428dc17798142ce77e19 100644
|
index 998328cfc6f36fd579e4fe26629a92a1ceefa9fa..c73e48d8dfe5a66fb9eb7f6bf49527f88cabc884 100644
|
||||||
--- a/dom/base/Navigator.h
|
--- a/dom/base/Navigator.h
|
||||||
+++ b/dom/base/Navigator.h
|
+++ b/dom/base/Navigator.h
|
||||||
@@ -214,7 +214,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
@@ -216,7 +216,7 @@ class Navigator final : public nsISupports, public nsWrapperCache {
|
||||||
|
|
||||||
StorageManager* Storage();
|
StorageManager* Storage();
|
||||||
|
|
||||||
|
|
@ -948,10 +948,10 @@ index 851b681570e35ba86341f56912684bc8ec7001f3..2fd4d6fd9deafaa42604428dc1779814
|
||||||
dom::MediaCapabilities* MediaCapabilities();
|
dom::MediaCapabilities* MediaCapabilities();
|
||||||
dom::MediaSession* MediaSession();
|
dom::MediaSession* MediaSession();
|
||||||
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
|
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
|
||||||
index a5fee753ce551826e5b974ca01aff1f541754f6b..f1a80d1bb25175c12345acbc27b82d96793e061d 100644
|
index 6d3a9f8937a7b37bf82a18362d7ee525e4e267f4..c598acdcda9d47cdd193011e8faa916988872a18 100644
|
||||||
--- a/dom/base/nsContentUtils.cpp
|
--- a/dom/base/nsContentUtils.cpp
|
||||||
+++ b/dom/base/nsContentUtils.cpp
|
+++ b/dom/base/nsContentUtils.cpp
|
||||||
@@ -8598,7 +8598,8 @@ nsresult nsContentUtils::SendMouseEvent(
|
@@ -8697,7 +8697,8 @@ nsresult nsContentUtils::SendMouseEvent(
|
||||||
bool aIgnoreRootScrollFrame, float aPressure,
|
bool aIgnoreRootScrollFrame, float aPressure,
|
||||||
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
|
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
|
||||||
PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized,
|
PreventDefaultResult* aPreventDefault, bool aIsDOMEventSynthesized,
|
||||||
|
|
@ -961,7 +961,7 @@ index a5fee753ce551826e5b974ca01aff1f541754f6b..f1a80d1bb25175c12345acbc27b82d96
|
||||||
nsPoint offset;
|
nsPoint offset;
|
||||||
nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
|
nsCOMPtr<nsIWidget> widget = GetWidget(aPresShell, &offset);
|
||||||
if (!widget) return NS_ERROR_FAILURE;
|
if (!widget) return NS_ERROR_FAILURE;
|
||||||
@@ -8606,6 +8607,7 @@ nsresult nsContentUtils::SendMouseEvent(
|
@@ -8705,6 +8706,7 @@ nsresult nsContentUtils::SendMouseEvent(
|
||||||
EventMessage msg;
|
EventMessage msg;
|
||||||
Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
|
Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
|
||||||
bool contextMenuKey = false;
|
bool contextMenuKey = false;
|
||||||
|
|
@ -969,7 +969,7 @@ index a5fee753ce551826e5b974ca01aff1f541754f6b..f1a80d1bb25175c12345acbc27b82d96
|
||||||
if (aType.EqualsLiteral("mousedown")) {
|
if (aType.EqualsLiteral("mousedown")) {
|
||||||
msg = eMouseDown;
|
msg = eMouseDown;
|
||||||
} else if (aType.EqualsLiteral("mouseup")) {
|
} else if (aType.EqualsLiteral("mouseup")) {
|
||||||
@@ -8630,6 +8632,12 @@ nsresult nsContentUtils::SendMouseEvent(
|
@@ -8729,6 +8731,12 @@ nsresult nsContentUtils::SendMouseEvent(
|
||||||
msg = eMouseHitTest;
|
msg = eMouseHitTest;
|
||||||
} else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
|
} else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
|
||||||
msg = eMouseExploreByTouch;
|
msg = eMouseExploreByTouch;
|
||||||
|
|
@ -982,7 +982,7 @@ index a5fee753ce551826e5b974ca01aff1f541754f6b..f1a80d1bb25175c12345acbc27b82d96
|
||||||
} else {
|
} else {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -8638,12 +8646,21 @@ nsresult nsContentUtils::SendMouseEvent(
|
@@ -8737,12 +8745,21 @@ nsresult nsContentUtils::SendMouseEvent(
|
||||||
aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
|
aInputSourceArg = MouseEvent_Binding::MOZ_SOURCE_MOUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1006,7 +1006,7 @@ index a5fee753ce551826e5b974ca01aff1f541754f6b..f1a80d1bb25175c12345acbc27b82d96
|
||||||
event.pointerId = aIdentifier;
|
event.pointerId = aIdentifier;
|
||||||
event.mModifiers = GetWidgetModifiers(aModifiers);
|
event.mModifiers = GetWidgetModifiers(aModifiers);
|
||||||
event.mButton = aButton;
|
event.mButton = aButton;
|
||||||
@@ -8654,8 +8671,10 @@ nsresult nsContentUtils::SendMouseEvent(
|
@@ -8753,8 +8770,10 @@ nsresult nsContentUtils::SendMouseEvent(
|
||||||
event.mPressure = aPressure;
|
event.mPressure = aPressure;
|
||||||
event.mInputSource = aInputSourceArg;
|
event.mInputSource = aInputSourceArg;
|
||||||
event.mClickCount = aClickCount;
|
event.mClickCount = aClickCount;
|
||||||
|
|
@ -1018,10 +1018,10 @@ index a5fee753ce551826e5b974ca01aff1f541754f6b..f1a80d1bb25175c12345acbc27b82d96
|
||||||
nsPresContext* presContext = aPresShell->GetPresContext();
|
nsPresContext* presContext = aPresShell->GetPresContext();
|
||||||
if (!presContext) return NS_ERROR_FAILURE;
|
if (!presContext) return NS_ERROR_FAILURE;
|
||||||
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
|
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
|
||||||
index 36c1a4f4eeba0fa75d79715f79de0d705719e5c5..6ad5426612ef37d7326bafd771a4c2d6d9142cb5 100644
|
index db68b67c5a3e60ac214231ac82fd9f652a697858..529b49b2c6c5f693747d847bca85e93415b9159c 100644
|
||||||
--- a/dom/base/nsContentUtils.h
|
--- a/dom/base/nsContentUtils.h
|
||||||
+++ b/dom/base/nsContentUtils.h
|
+++ b/dom/base/nsContentUtils.h
|
||||||
@@ -2963,7 +2963,8 @@ class nsContentUtils {
|
@@ -2958,7 +2958,8 @@ class nsContentUtils {
|
||||||
int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure,
|
int32_t aModifiers, bool aIgnoreRootScrollFrame, float aPressure,
|
||||||
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
|
unsigned short aInputSourceArg, uint32_t aIdentifier, bool aToWindow,
|
||||||
mozilla::PreventDefaultResult* aPreventDefault,
|
mozilla::PreventDefaultResult* aPreventDefault,
|
||||||
|
|
@ -1032,10 +1032,10 @@ index 36c1a4f4eeba0fa75d79715f79de0d705719e5c5..6ad5426612ef37d7326bafd771a4c2d6
|
||||||
static void FirePageShowEventForFrameLoaderSwap(
|
static void FirePageShowEventForFrameLoaderSwap(
|
||||||
nsIDocShellTreeItem* aItem,
|
nsIDocShellTreeItem* aItem,
|
||||||
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
|
diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp
|
||||||
index e6762018cce8e4c8691703ed15ea29e709f31cf2..4d0b679c4700e8fe18408a186b7e4d512a71dc30 100644
|
index 6c547a9fd8604ac7fd7b965be473bc4120b2fdf7..c9aa1951da7af70913f77c76bb7c68ba144adaeb 100644
|
||||||
--- a/dom/base/nsDOMWindowUtils.cpp
|
--- a/dom/base/nsDOMWindowUtils.cpp
|
||||||
+++ b/dom/base/nsDOMWindowUtils.cpp
|
+++ b/dom/base/nsDOMWindowUtils.cpp
|
||||||
@@ -684,6 +684,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) {
|
@@ -685,6 +685,26 @@ nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1062,7 +1062,7 @@ index e6762018cce8e4c8691703ed15ea29e709f31cf2..4d0b679c4700e8fe18408a186b7e4d51
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDOMWindowUtils::SendMouseEvent(
|
nsDOMWindowUtils::SendMouseEvent(
|
||||||
const nsAString& aType, float aX, float aY, int32_t aButton,
|
const nsAString& aType, float aX, float aY, int32_t aButton,
|
||||||
@@ -698,7 +718,7 @@ nsDOMWindowUtils::SendMouseEvent(
|
@@ -699,7 +719,7 @@ nsDOMWindowUtils::SendMouseEvent(
|
||||||
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false,
|
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false,
|
||||||
aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
|
aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
|
||||||
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
|
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
|
||||||
|
|
@ -1071,7 +1071,7 @@ index e6762018cce8e4c8691703ed15ea29e709f31cf2..4d0b679c4700e8fe18408a186b7e4d51
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@@ -716,7 +736,7 @@ nsDOMWindowUtils::SendMouseEventToWindow(
|
@@ -717,7 +737,7 @@ nsDOMWindowUtils::SendMouseEventToWindow(
|
||||||
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true,
|
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true,
|
||||||
nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
|
nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true,
|
||||||
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
|
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false,
|
||||||
|
|
@ -1080,7 +1080,7 @@ index e6762018cce8e4c8691703ed15ea29e709f31cf2..4d0b679c4700e8fe18408a186b7e4d51
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@@ -725,13 +745,13 @@ nsDOMWindowUtils::SendMouseEventCommon(
|
@@ -726,13 +746,13 @@ nsDOMWindowUtils::SendMouseEventCommon(
|
||||||
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
|
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
|
||||||
float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId,
|
float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId,
|
||||||
bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized,
|
bool aToWindow, bool* aPreventDefault, bool aIsDOMEventSynthesized,
|
||||||
|
|
@ -1110,7 +1110,7 @@ index 63968c9b7a4e418e4c0de6e7a75fa215a36a9105..decf3ea3833ccdffd49a7aded2d600f9
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult SendTouchEventCommon(
|
nsresult SendTouchEventCommon(
|
||||||
diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
|
diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
|
||||||
index 0d9e4df42f7efcbb0068bc162dfbb17003cd3802..55c0e9e8cfa434c5b8c7dbd27651bf94d5b9a2d1 100644
|
index 60f45157cdfceb7ebf4f9a1681d0e59dc1822360..964d7cc1b847cd8ef21cef29be4fdc11168b18d8 100644
|
||||||
--- a/dom/base/nsFocusManager.cpp
|
--- a/dom/base/nsFocusManager.cpp
|
||||||
+++ b/dom/base/nsFocusManager.cpp
|
+++ b/dom/base/nsFocusManager.cpp
|
||||||
@@ -1673,6 +1673,10 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
@@ -1673,6 +1673,10 @@ Maybe<uint64_t> nsFocusManager::SetFocusInner(Element* aNewContent,
|
||||||
|
|
@ -1136,10 +1136,10 @@ index 0d9e4df42f7efcbb0068bc162dfbb17003cd3802..55c0e9e8cfa434c5b8c7dbd27651bf94
|
||||||
// care of lowering the present active window. This happens in
|
// care of lowering the present active window. This happens in
|
||||||
// a separate runnable to avoid touching multiple windows in
|
// a separate runnable to avoid touching multiple windows in
|
||||||
diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp
|
diff --git a/dom/base/nsGlobalWindowOuter.cpp b/dom/base/nsGlobalWindowOuter.cpp
|
||||||
index 97d967175822e4f62079c21152f96e5540dbb98f..c5bf0d155649e6715aa3af6ca29c237b1dab6ead 100644
|
index a10808b95d5f7c81942d2a513f63a72c7821061e..027b9a3c87811b794816bddb90ff67bc271f7faa 100644
|
||||||
--- a/dom/base/nsGlobalWindowOuter.cpp
|
--- a/dom/base/nsGlobalWindowOuter.cpp
|
||||||
+++ b/dom/base/nsGlobalWindowOuter.cpp
|
+++ b/dom/base/nsGlobalWindowOuter.cpp
|
||||||
@@ -2509,10 +2509,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
|
@@ -2510,10 +2510,16 @@ nsresult nsGlobalWindowOuter::SetNewDocument(Document* aDocument,
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (!isContentAboutBlankInChromeDocshell) {
|
if (!isContentAboutBlankInChromeDocshell) {
|
||||||
|
|
@ -1160,7 +1160,7 @@ index 97d967175822e4f62079c21152f96e5540dbb98f..c5bf0d155649e6715aa3af6ca29c237b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2632,6 +2638,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() {
|
@@ -2633,6 +2639,19 @@ void nsGlobalWindowOuter::DispatchDOMWindowCreated() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1193,10 +1193,10 @@ index 8337a7353fb8e97372f0b57bd0fd867506a9129f..e7dedd6d26125e481e1145337a0be6ab
|
||||||
// Outer windows only.
|
// Outer windows only.
|
||||||
virtual void EnsureSizeAndPositionUpToDate() override;
|
virtual void EnsureSizeAndPositionUpToDate() override;
|
||||||
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
|
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
|
||||||
index 369bb41fe459c8ef4c10c61c1530f52d51b3f6de..15ef3c6824cc70e756777612f0fd148e5678c795 100644
|
index 11ca350f483458ba11f0ee170ce38e9785e8c70f..6bb310f6e96239388b4c92bd7bdf2d698fac8139 100644
|
||||||
--- a/dom/base/nsINode.cpp
|
--- a/dom/base/nsINode.cpp
|
||||||
+++ b/dom/base/nsINode.cpp
|
+++ b/dom/base/nsINode.cpp
|
||||||
@@ -1359,6 +1359,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions,
|
@@ -1362,6 +1362,61 @@ void nsINode::GetBoxQuadsFromWindowOrigin(const BoxQuadOptions& aOptions,
|
||||||
mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv);
|
mozilla::GetBoxQuadsFromWindowOrigin(this, aOptions, aResult, aRv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1259,10 +1259,10 @@ index 369bb41fe459c8ef4c10c61c1530f52d51b3f6de..15ef3c6824cc70e756777612f0fd148e
|
||||||
DOMQuad& aQuad, const GeometryNode& aFrom,
|
DOMQuad& aQuad, const GeometryNode& aFrom,
|
||||||
const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
|
const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
|
||||||
diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h
|
diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h
|
||||||
index 807deebaad78f531c59d18aac2c2833e38d13946..3754b573ef119854e2c41b51b0dd0a43d7c53315 100644
|
index 0ba44cb08ffffde3bf9616e7e3b1fb33317181b6..b698e309e7bf658739b3a69a1d68f657a6c84e6e 100644
|
||||||
--- a/dom/base/nsINode.h
|
--- a/dom/base/nsINode.h
|
||||||
+++ b/dom/base/nsINode.h
|
+++ b/dom/base/nsINode.h
|
||||||
@@ -2229,6 +2229,10 @@ class nsINode : public mozilla::dom::EventTarget {
|
@@ -2235,6 +2235,10 @@ class nsINode : public mozilla::dom::EventTarget {
|
||||||
nsTArray<RefPtr<DOMQuad>>& aResult,
|
nsTArray<RefPtr<DOMQuad>>& aResult,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
|
@ -1274,7 +1274,7 @@ index 807deebaad78f531c59d18aac2c2833e38d13946..3754b573ef119854e2c41b51b0dd0a43
|
||||||
DOMQuad& aQuad, const TextOrElementOrDocument& aFrom,
|
DOMQuad& aQuad, const TextOrElementOrDocument& aFrom,
|
||||||
const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
|
const ConvertCoordinateOptions& aOptions, CallerType aCallerType,
|
||||||
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
|
diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp
|
||||||
index bb280d9a15aed8b7d82a93214e82222e9b5a14ae..d64cd52877c1643148ce5912eec26bd1569acdac 100644
|
index cf8037cd580013efe5eb578c43f45c0d21946c6a..583460796fdef633e8075013597f7c315ce4ab06 100644
|
||||||
--- a/dom/base/nsJSUtils.cpp
|
--- a/dom/base/nsJSUtils.cpp
|
||||||
+++ b/dom/base/nsJSUtils.cpp
|
+++ b/dom/base/nsJSUtils.cpp
|
||||||
@@ -177,6 +177,11 @@ bool nsJSUtils::GetScopeChainForElement(
|
@@ -177,6 +177,11 @@ bool nsJSUtils::GetScopeChainForElement(
|
||||||
|
|
@ -1290,7 +1290,7 @@ index bb280d9a15aed8b7d82a93214e82222e9b5a14ae..d64cd52877c1643148ce5912eec26bd1
|
||||||
void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
|
void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
|
||||||
|
|
||||||
diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
|
diff --git a/dom/base/nsJSUtils.h b/dom/base/nsJSUtils.h
|
||||||
index 36e906061588aab50dee129cc46dd2e4d3e153f8..c3591f98d4df19b166fc5c99332e559b1d499049 100644
|
index cceb725d393d5e5f83c8f87491089c3fa1d57cc3..e906a7fb7c3fd72554613f640dcc272e6984d929 100644
|
||||||
--- a/dom/base/nsJSUtils.h
|
--- a/dom/base/nsJSUtils.h
|
||||||
+++ b/dom/base/nsJSUtils.h
|
+++ b/dom/base/nsJSUtils.h
|
||||||
@@ -79,6 +79,7 @@ class nsJSUtils {
|
@@ -79,6 +79,7 @@ class nsJSUtils {
|
||||||
|
|
@ -1302,7 +1302,7 @@ index 36e906061588aab50dee129cc46dd2e4d3e153f8..c3591f98d4df19b166fc5c99332e559b
|
||||||
|
|
||||||
static bool DumpEnabled();
|
static bool DumpEnabled();
|
||||||
diff --git a/dom/chrome-webidl/BrowsingContext.webidl b/dom/chrome-webidl/BrowsingContext.webidl
|
diff --git a/dom/chrome-webidl/BrowsingContext.webidl b/dom/chrome-webidl/BrowsingContext.webidl
|
||||||
index 2e8abd50793dd1392a876e53e99ad806a256f755..695b9e8ffff846d663b645e3ca6fc83a39f6f126 100644
|
index 8600a844634eed78e0b8470eaf11144f8ebd230b..853a4c98b78092181ad15542ae48cd41e9c49a82 100644
|
||||||
--- a/dom/chrome-webidl/BrowsingContext.webidl
|
--- a/dom/chrome-webidl/BrowsingContext.webidl
|
||||||
+++ b/dom/chrome-webidl/BrowsingContext.webidl
|
+++ b/dom/chrome-webidl/BrowsingContext.webidl
|
||||||
@@ -53,6 +53,24 @@ enum PrefersColorSchemeOverride {
|
@@ -53,6 +53,24 @@ enum PrefersColorSchemeOverride {
|
||||||
|
|
@ -1443,7 +1443,7 @@ index 7e1af00d05fbafa2d828e2c7e4dcc5c82d115f5b..e85af9718d064e4d2865bc944e9d4ba1
|
||||||
~Geolocation();
|
~Geolocation();
|
||||||
|
|
||||||
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
|
diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
|
||||||
index 09d57823aa37f596ac04261025862975f414bd7c..8cee0ae86ae1ed3aeda879cbf55f381a772dfa8b 100644
|
index ae2c4af82c3827a521a79f8879a6f941ea68feca..92ea48eba6fb575ea1415d8713b49707b895561b 100644
|
||||||
--- a/dom/html/HTMLInputElement.cpp
|
--- a/dom/html/HTMLInputElement.cpp
|
||||||
+++ b/dom/html/HTMLInputElement.cpp
|
+++ b/dom/html/HTMLInputElement.cpp
|
||||||
@@ -58,6 +58,7 @@
|
@@ -58,6 +58,7 @@
|
||||||
|
|
@ -1454,7 +1454,7 @@ index 09d57823aa37f596ac04261025862975f414bd7c..8cee0ae86ae1ed3aeda879cbf55f381a
|
||||||
#include "nsIFormControlFrame.h"
|
#include "nsIFormControlFrame.h"
|
||||||
#include "nsITextControlFrame.h"
|
#include "nsITextControlFrame.h"
|
||||||
#include "nsIFrame.h"
|
#include "nsIFrame.h"
|
||||||
@@ -783,6 +784,12 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) {
|
@@ -784,6 +785,12 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1468,7 +1468,7 @@ index 09d57823aa37f596ac04261025862975f414bd7c..8cee0ae86ae1ed3aeda879cbf55f381a
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
|
diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl
|
||||||
index 4170a79023a2503831d080a6e65d5e143f34f241..3af08d6ea5f1cfbdc373774764a0c45fe3aa0e27 100644
|
index 564b24e3f89e0ce6e683902a7fc4e1c3a6f5faac..e4264b251e580bb13aa2941b26227541c74d3371 100644
|
||||||
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
|
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
|
||||||
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
|
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
|
||||||
@@ -373,6 +373,26 @@ interface nsIDOMWindowUtils : nsISupports {
|
@@ -373,6 +373,26 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||||
|
|
@ -1499,10 +1499,10 @@ index 4170a79023a2503831d080a6e65d5e143f34f241..3af08d6ea5f1cfbdc373774764a0c45f
|
||||||
* touchstart, touchend, touchmove, and touchcancel
|
* touchstart, touchend, touchmove, and touchcancel
|
||||||
*
|
*
|
||||||
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
|
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
|
||||||
index 2e69547612aa1ef91d726ee54475a5f8e638e214..2b7aae36d1b4b7a7a7a7a6117104d3455e1768e3 100644
|
index 830ad8579a39d262a1fd2c86479f2ddc77c01ae2..b840b68c9b5545fc974e1dafacac2e74372f4e41 100644
|
||||||
--- a/dom/ipc/BrowserChild.cpp
|
--- a/dom/ipc/BrowserChild.cpp
|
||||||
+++ b/dom/ipc/BrowserChild.cpp
|
+++ b/dom/ipc/BrowserChild.cpp
|
||||||
@@ -1647,6 +1647,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
@@ -1651,6 +1651,21 @@ void BrowserChild::HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
||||||
if (postLayerization) {
|
if (postLayerization) {
|
||||||
postLayerization->Register();
|
postLayerization->Register();
|
||||||
}
|
}
|
||||||
|
|
@ -1539,7 +1539,7 @@ index 5aa445d2e0a6169e57c44569974d557b3baf7064..671f71979b407f0ca17c66f13805e851
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.cc b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.cc b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
||||||
index 532605b813d4e4a7693e6c82f6792075ef2565de..d225ffaf3439739d989b21f858c1763942beee9e 100644
|
index a966ff06d4a52e2ff70ce71df3a6a607a67e3eda..eb6bb16413df43217ddd85048c02d41d15e8431f 100644
|
||||||
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
||||||
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.cc
|
||||||
@@ -135,11 +135,12 @@ int32_t ScreenDeviceInfoImpl::GetOrientation(const char* aDeviceUniqueIdUTF8,
|
@@ -135,11 +135,12 @@ int32_t ScreenDeviceInfoImpl::GetOrientation(const char* aDeviceUniqueIdUTF8,
|
||||||
|
|
@ -1644,7 +1644,7 @@ index 532605b813d4e4a7693e6c82f6792075ef2565de..d225ffaf3439739d989b21f858c17639
|
||||||
frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel;
|
frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel;
|
||||||
|
|
||||||
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.h b/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
diff --git a/dom/media/systemservices/video_engine/desktop_capture_impl.h b/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
||||||
index 64eadb140131ea807db8b55431630523342a88ce..371e093fef6e225302da6aaf6e1ede05b93efd74 100644
|
index 7292f6c8a70298d4bf103080804843fa9bba1d15..7a50fee0d2fcaad475302d010892800a6e3c4e75 100644
|
||||||
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
--- a/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
||||||
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
+++ b/dom/media/systemservices/video_engine/desktop_capture_impl.h
|
||||||
@@ -24,6 +24,7 @@
|
@@ -24,6 +24,7 @@
|
||||||
|
|
@ -1677,7 +1677,7 @@ index 64eadb140131ea807db8b55431630523342a88ce..371e093fef6e225302da6aaf6e1ede05
|
||||||
// simulate deviceInfo interface for video engine, bridge screen/application and
|
// simulate deviceInfo interface for video engine, bridge screen/application and
|
||||||
// real screen/application device info
|
// real screen/application device info
|
||||||
|
|
||||||
@@ -155,13 +171,13 @@ class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
|
@@ -158,13 +174,13 @@ class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
|
||||||
// As with video, DesktopCaptureImpl is a proxy for screen sharing
|
// As with video, DesktopCaptureImpl is a proxy for screen sharing
|
||||||
// and follows the video pipeline design
|
// and follows the video pipeline design
|
||||||
class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
||||||
|
|
@ -1694,7 +1694,7 @@ index 64eadb140131ea807db8b55431630523342a88ce..371e093fef6e225302da6aaf6e1ede05
|
||||||
|
|
||||||
[[nodiscard]] static std::shared_ptr<VideoCaptureModule::DeviceInfo>
|
[[nodiscard]] static std::shared_ptr<VideoCaptureModule::DeviceInfo>
|
||||||
CreateDeviceInfo(const int32_t aId,
|
CreateDeviceInfo(const int32_t aId,
|
||||||
@@ -175,6 +191,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
@@ -178,6 +194,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
||||||
void DeRegisterCaptureDataCallback(
|
void DeRegisterCaptureDataCallback(
|
||||||
rtc::VideoSinkInterface<VideoFrame>* aCallback) override;
|
rtc::VideoSinkInterface<VideoFrame>* aCallback) override;
|
||||||
int32_t StopCaptureIfAllClientsClose() override;
|
int32_t StopCaptureIfAllClientsClose() override;
|
||||||
|
|
@ -1703,7 +1703,7 @@ index 64eadb140131ea807db8b55431630523342a88ce..371e093fef6e225302da6aaf6e1ede05
|
||||||
|
|
||||||
int32_t SetCaptureRotation(VideoRotation aRotation) override;
|
int32_t SetCaptureRotation(VideoRotation aRotation) override;
|
||||||
bool SetApplyRotation(bool aEnable) override;
|
bool SetApplyRotation(bool aEnable) override;
|
||||||
@@ -197,7 +215,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
@@ -200,7 +218,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DesktopCaptureImpl(const int32_t aId, const char* aUniqueId,
|
DesktopCaptureImpl(const int32_t aId, const char* aUniqueId,
|
||||||
|
|
@ -1713,7 +1713,7 @@ index 64eadb140131ea807db8b55431630523342a88ce..371e093fef6e225302da6aaf6e1ede05
|
||||||
virtual ~DesktopCaptureImpl();
|
virtual ~DesktopCaptureImpl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -205,6 +224,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
@@ -208,6 +227,9 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
||||||
static constexpr uint32_t kMaxDesktopCaptureCpuUsage = 50;
|
static constexpr uint32_t kMaxDesktopCaptureCpuUsage = 50;
|
||||||
void InitOnThread(std::unique_ptr<DesktopCapturer> aCapturer, int aFramerate);
|
void InitOnThread(std::unique_ptr<DesktopCapturer> aCapturer, int aFramerate);
|
||||||
void ShutdownOnThread();
|
void ShutdownOnThread();
|
||||||
|
|
@ -1723,7 +1723,7 @@ index 64eadb140131ea807db8b55431630523342a88ce..371e093fef6e225302da6aaf6e1ede05
|
||||||
// DesktopCapturer::Callback interface.
|
// DesktopCapturer::Callback interface.
|
||||||
void OnCaptureResult(DesktopCapturer::Result aResult,
|
void OnCaptureResult(DesktopCapturer::Result aResult,
|
||||||
std::unique_ptr<DesktopFrame> aFrame) override;
|
std::unique_ptr<DesktopFrame> aFrame) override;
|
||||||
@@ -212,6 +234,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
@@ -215,6 +237,8 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
|
||||||
// Notifies all mCallbacks of OnFrame(). mCaptureThread only.
|
// Notifies all mCallbacks of OnFrame(). mCaptureThread only.
|
||||||
void NotifyOnFrame(const VideoFrame& aFrame);
|
void NotifyOnFrame(const VideoFrame& aFrame);
|
||||||
|
|
||||||
|
|
@ -1777,7 +1777,7 @@ index 3b39538e51840cd9b1685b2efd2ff2e9ec83608a..c7bf4f2d53b58bbacb22b3ebebf6f3fc
|
||||||
|
|
||||||
return aGlobalOrNull;
|
return aGlobalOrNull;
|
||||||
diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp
|
diff --git a/dom/security/nsCSPUtils.cpp b/dom/security/nsCSPUtils.cpp
|
||||||
index d1bd1d060d749de3ac16bd6e9fd3383383e4dd9a..e6262c210accf12c3d071d42031b432b2a6332b5 100644
|
index 50730b691b06409f47cb9172570866a7bb519abc..e5ae4f31b8f93f17943c24108a82c6370470e9f2 100644
|
||||||
--- a/dom/security/nsCSPUtils.cpp
|
--- a/dom/security/nsCSPUtils.cpp
|
||||||
+++ b/dom/security/nsCSPUtils.cpp
|
+++ b/dom/security/nsCSPUtils.cpp
|
||||||
@@ -22,6 +22,7 @@
|
@@ -22,6 +22,7 @@
|
||||||
|
|
@ -1824,7 +1824,7 @@ index 2f71b284ee5f7e11f117c447834b48355784448c..2640bd57123c2b03bf4b06a2419cd020
|
||||||
* returned quads are further translated relative to the window
|
* returned quads are further translated relative to the window
|
||||||
* origin -- which is not the layout origin. Further translation
|
* origin -- which is not the layout origin. Further translation
|
||||||
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
|
diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp
|
||||||
index 4fc3db17b202f768cadc7fa3921badc4374a9f7a..be58abf2b7906e7307dd8f106f5f8bd2206793bc 100644
|
index bcfbe33925afb97e68305394fb38e42481682540..47bc46f34a93991f112292c851c539a6bc97778f 100644
|
||||||
--- a/dom/workers/RuntimeService.cpp
|
--- a/dom/workers/RuntimeService.cpp
|
||||||
+++ b/dom/workers/RuntimeService.cpp
|
+++ b/dom/workers/RuntimeService.cpp
|
||||||
@@ -985,7 +985,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) {
|
@@ -985,7 +985,7 @@ void PrefLanguagesChanged(const char* /* aPrefName */, void* /* aClosure */) {
|
||||||
|
|
@ -1902,7 +1902,7 @@ index d10dabb5c5ff8e17851edf2bd2efc08e74584d8e..53c4070c5fde43b27fb8fbfdcf4c23d8
|
||||||
|
|
||||||
bool IsWorkerGlobal(JSObject* global);
|
bool IsWorkerGlobal(JSObject* global);
|
||||||
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
|
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
|
||||||
index ed8a07bcdc25f77a93079c8b9f113c59b9befaf9..2f09a961603f28a658f2d29321a389b7623482b9 100644
|
index acef06ba3abb006932f26f8a96fd73028f015150..940210c603d906ae0469d826b81ba8f537e7fef5 100644
|
||||||
--- a/dom/workers/WorkerPrivate.cpp
|
--- a/dom/workers/WorkerPrivate.cpp
|
||||||
+++ b/dom/workers/WorkerPrivate.cpp
|
+++ b/dom/workers/WorkerPrivate.cpp
|
||||||
@@ -679,6 +679,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable {
|
@@ -679,6 +679,18 @@ class UpdateContextOptionsRunnable final : public WorkerControlRunnable {
|
||||||
|
|
@ -1924,7 +1924,7 @@ index ed8a07bcdc25f77a93079c8b9f113c59b9befaf9..2f09a961603f28a658f2d29321a389b7
|
||||||
class UpdateLanguagesRunnable final : public WorkerRunnable {
|
class UpdateLanguagesRunnable final : public WorkerRunnable {
|
||||||
nsTArray<nsString> mLanguages;
|
nsTArray<nsString> mLanguages;
|
||||||
|
|
||||||
@@ -1949,6 +1961,16 @@ void WorkerPrivate::UpdateContextOptions(
|
@@ -1977,6 +1989,16 @@ void WorkerPrivate::UpdateContextOptions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1941,7 +1941,7 @@ index ed8a07bcdc25f77a93079c8b9f113c59b9befaf9..2f09a961603f28a658f2d29321a389b7
|
||||||
void WorkerPrivate::UpdateLanguages(const nsTArray<nsString>& aLanguages) {
|
void WorkerPrivate::UpdateLanguages(const nsTArray<nsString>& aLanguages) {
|
||||||
AssertIsOnParentThread();
|
AssertIsOnParentThread();
|
||||||
|
|
||||||
@@ -5450,6 +5472,15 @@ void WorkerPrivate::UpdateContextOptionsInternal(
|
@@ -5480,6 +5502,15 @@ void WorkerPrivate::UpdateContextOptionsInternal(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1958,7 +1958,7 @@ index ed8a07bcdc25f77a93079c8b9f113c59b9befaf9..2f09a961603f28a658f2d29321a389b7
|
||||||
const nsTArray<nsString>& aLanguages) {
|
const nsTArray<nsString>& aLanguages) {
|
||||||
WorkerGlobalScope* globalScope = GlobalScope();
|
WorkerGlobalScope* globalScope = GlobalScope();
|
||||||
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
|
diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h
|
||||||
index a134d4846f9ad0f273f61fe2c2daa10af7b3c7a6..38bb391cb542a560f93a0c302a1d942aad8135a6 100644
|
index a670d009759d101cf9574cde3c2481b8aa2737f6..ac87b7f27dfcc060adb52387b146c45eed996fa7 100644
|
||||||
--- a/dom/workers/WorkerPrivate.h
|
--- a/dom/workers/WorkerPrivate.h
|
||||||
+++ b/dom/workers/WorkerPrivate.h
|
+++ b/dom/workers/WorkerPrivate.h
|
||||||
@@ -417,6 +417,8 @@ class WorkerPrivate final
|
@@ -417,6 +417,8 @@ class WorkerPrivate final
|
||||||
|
|
@ -2019,10 +2019,10 @@ index 9d0423ef13958d5c443cc3531269603c4801c338..f0c4ba7c528d2be466e0f7669a1e37e8
|
||||||
* Set the default time zone.
|
* Set the default time zone.
|
||||||
*/
|
*/
|
||||||
diff --git a/js/public/Date.h b/js/public/Date.h
|
diff --git a/js/public/Date.h b/js/public/Date.h
|
||||||
index 422ea0b2c0daafd4447d0d83500ea73545c99b76..7f03adc302112e0de3d842d7ce6bc0909b50f76a 100644
|
index 523e84c8c93f4221701f90f2e8ee146ec8e1adbd..98d5b1176e5378431b859a2dbd4d4e778d236e78 100644
|
||||||
--- a/js/public/Date.h
|
--- a/js/public/Date.h
|
||||||
+++ b/js/public/Date.h
|
+++ b/js/public/Date.h
|
||||||
@@ -54,6 +54,8 @@ namespace JS {
|
@@ -55,6 +55,8 @@ namespace JS {
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API void ResetTimeZone();
|
extern JS_PUBLIC_API void ResetTimeZone();
|
||||||
|
|
||||||
|
|
@ -2032,10 +2032,10 @@ index 422ea0b2c0daafd4447d0d83500ea73545c99b76..7f03adc302112e0de3d842d7ce6bc090
|
||||||
inline ClippedTime TimeClip(double time);
|
inline ClippedTime TimeClip(double time);
|
||||||
|
|
||||||
diff --git a/js/src/debugger/Object.cpp b/js/src/debugger/Object.cpp
|
diff --git a/js/src/debugger/Object.cpp b/js/src/debugger/Object.cpp
|
||||||
index 2cb72597fdf2a10fdc53bf03d6cc98d9bc16af58..b3ce8a99c37fc8c503206ea2b47b7e000fc4bf3b 100644
|
index c5a4f1f6dcf95922b5c8506d6bd24ad4fd2f1efc..a79bb0ad42d1bbd0434cda27c118cdd099013ab2 100644
|
||||||
--- a/js/src/debugger/Object.cpp
|
--- a/js/src/debugger/Object.cpp
|
||||||
+++ b/js/src/debugger/Object.cpp
|
+++ b/js/src/debugger/Object.cpp
|
||||||
@@ -2446,7 +2446,11 @@ Maybe<Completion> DebuggerObject::call(JSContext* cx,
|
@@ -2450,7 +2450,11 @@ Maybe<Completion> DebuggerObject::call(JSContext* cx,
|
||||||
invokeArgs[i].set(args2[i]);
|
invokeArgs[i].set(args2[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2202,10 +2202,10 @@ index dac899f7558b26d6848da8b98ed8a93555c8751a..2a07d67fa1c2840b25085566e84dc3b2
|
||||||
// No boxes to return
|
// No boxes to return
|
||||||
return;
|
return;
|
||||||
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
|
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
|
||||||
index 6e27e39f432d678376cec3bfd8491e5f20ebd893..a69211527a0a2411b6ef4a69de0183428114139d 100644
|
index 4afd2b10dfdab527b63f17919c52a559b3ac3de6..787283c004d9baa7227f00c338e0322dca88f949 100644
|
||||||
--- a/layout/base/PresShell.cpp
|
--- a/layout/base/PresShell.cpp
|
||||||
+++ b/layout/base/PresShell.cpp
|
+++ b/layout/base/PresShell.cpp
|
||||||
@@ -10906,7 +10906,9 @@ bool PresShell::ComputeActiveness() const {
|
@@ -10963,7 +10963,9 @@ bool PresShell::ComputeActiveness() const {
|
||||||
if (!browserChild->IsVisible()) {
|
if (!browserChild->IsVisible()) {
|
||||||
MOZ_LOG(gLog, LogLevel::Debug,
|
MOZ_LOG(gLog, LogLevel::Debug,
|
||||||
(" > BrowserChild %p is not visible", browserChild));
|
(" > BrowserChild %p is not visible", browserChild));
|
||||||
|
|
@ -2217,10 +2217,10 @@ index 6e27e39f432d678376cec3bfd8491e5f20ebd893..a69211527a0a2411b6ef4a69de018342
|
||||||
|
|
||||||
// If the browser is visible but just due to be preserving layers
|
// If the browser is visible but just due to be preserving layers
|
||||||
diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h
|
diff --git a/layout/style/GeckoBindings.h b/layout/style/GeckoBindings.h
|
||||||
index 327b3d587844c0ad81f5b9c2c622bf52315380bf..d5eefde23dfa3d5666f04af90b7dda1ffa38f6bd 100644
|
index 7bb839ae18835d128dc9285b7f9dc5b5e06335af..09e3979d07447522ace740daf2b818a6c551ceba 100644
|
||||||
--- a/layout/style/GeckoBindings.h
|
--- a/layout/style/GeckoBindings.h
|
||||||
+++ b/layout/style/GeckoBindings.h
|
+++ b/layout/style/GeckoBindings.h
|
||||||
@@ -632,6 +632,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*);
|
@@ -625,6 +625,7 @@ float Gecko_MediaFeatures_GetResolution(const mozilla::dom::Document*);
|
||||||
bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*);
|
bool Gecko_MediaFeatures_PrefersReducedMotion(const mozilla::dom::Document*);
|
||||||
bool Gecko_MediaFeatures_PrefersReducedTransparency(
|
bool Gecko_MediaFeatures_PrefersReducedTransparency(
|
||||||
const mozilla::dom::Document*);
|
const mozilla::dom::Document*);
|
||||||
|
|
@ -2229,10 +2229,10 @@ index 327b3d587844c0ad81f5b9c2c622bf52315380bf..d5eefde23dfa3d5666f04af90b7dda1f
|
||||||
const mozilla::dom::Document*);
|
const mozilla::dom::Document*);
|
||||||
mozilla::StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
|
mozilla::StylePrefersColorScheme Gecko_MediaFeatures_PrefersColorScheme(
|
||||||
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
|
diff --git a/layout/style/nsMediaFeatures.cpp b/layout/style/nsMediaFeatures.cpp
|
||||||
index f10c779512c8d6a778ccd2fe98f069745a58adab..8534639ff3c256820846c6e014185783bb317efe 100644
|
index c99eecb4867c623b8ccc6e6fb42986d71f795cc0..d127837d7e069818daaeb73ef42497226ff95e26 100644
|
||||||
--- a/layout/style/nsMediaFeatures.cpp
|
--- a/layout/style/nsMediaFeatures.cpp
|
||||||
+++ b/layout/style/nsMediaFeatures.cpp
|
+++ b/layout/style/nsMediaFeatures.cpp
|
||||||
@@ -261,11 +261,11 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) {
|
@@ -257,11 +257,11 @@ bool Gecko_MediaFeatures_MatchesPlatform(StylePlatform aPlatform) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Gecko_MediaFeatures_PrefersReducedMotion(const Document* aDocument) {
|
bool Gecko_MediaFeatures_PrefersReducedMotion(const Document* aDocument) {
|
||||||
|
|
@ -2250,10 +2250,10 @@ index f10c779512c8d6a778ccd2fe98f069745a58adab..8534639ff3c256820846c6e014185783
|
||||||
|
|
||||||
bool Gecko_MediaFeatures_PrefersReducedTransparency(const Document* aDocument) {
|
bool Gecko_MediaFeatures_PrefersReducedTransparency(const Document* aDocument) {
|
||||||
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
|
diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp
|
||||||
index 7e8b75f0156b059c19c9a2322087c2d79d28f961..d8899ca4ec66a1d1cafba5cb09205fa3b7d41384 100644
|
index b15f24fffd7ea5a8a00319451fa7ebf9df32ec05..0279f6626f2ac938b0456d370fd956f2a23a036b 100644
|
||||||
--- a/netwerk/base/LoadInfo.cpp
|
--- a/netwerk/base/LoadInfo.cpp
|
||||||
+++ b/netwerk/base/LoadInfo.cpp
|
+++ b/netwerk/base/LoadInfo.cpp
|
||||||
@@ -647,7 +647,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
|
@@ -653,7 +653,8 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
|
||||||
mInterceptionInfo(rhs.mInterceptionInfo),
|
mInterceptionInfo(rhs.mInterceptionInfo),
|
||||||
mHasInjectedCookieForCookieBannerHandling(
|
mHasInjectedCookieForCookieBannerHandling(
|
||||||
rhs.mHasInjectedCookieForCookieBannerHandling),
|
rhs.mHasInjectedCookieForCookieBannerHandling),
|
||||||
|
|
@ -2263,7 +2263,7 @@ index 7e8b75f0156b059c19c9a2322087c2d79d28f961..d8899ca4ec66a1d1cafba5cb09205fa3
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadInfo::LoadInfo(
|
LoadInfo::LoadInfo(
|
||||||
@@ -2363,4 +2364,16 @@ LoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) {
|
@@ -2369,4 +2370,16 @@ LoadInfo::SetWasSchemelessInput(bool aWasSchemelessInput) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2314,10 +2314,10 @@ index 920e7623a7f912296fc23361f66ab35a30c35f1e..dfea0d0f7a72da9699615d7ff778e429
|
||||||
} // namespace net
|
} // namespace net
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
|
diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl
|
||||||
index ccceadc42ce12bec8e9878124904f0ba3914a030..56ec55af399e7b831558ca5d2a71513d9c919839 100644
|
index ddfcb223e6126c943b58e9d198f0e2fa767c3de1..4280b836c55e5778ad4c94226ea537facb19c436 100644
|
||||||
--- a/netwerk/base/nsILoadInfo.idl
|
--- a/netwerk/base/nsILoadInfo.idl
|
||||||
+++ b/netwerk/base/nsILoadInfo.idl
|
+++ b/netwerk/base/nsILoadInfo.idl
|
||||||
@@ -1531,4 +1531,6 @@ interface nsILoadInfo : nsISupports
|
@@ -1532,4 +1532,6 @@ interface nsILoadInfo : nsISupports
|
||||||
* Whether the load has gone through the URL bar, where the fixup had to add * the protocol scheme.
|
* Whether the load has gone through the URL bar, where the fixup had to add * the protocol scheme.
|
||||||
*/
|
*/
|
||||||
[infallible] attribute boolean wasSchemelessInput;
|
[infallible] attribute boolean wasSchemelessInput;
|
||||||
|
|
@ -2325,7 +2325,7 @@ index ccceadc42ce12bec8e9878124904f0ba3914a030..56ec55af399e7b831558ca5d2a71513d
|
||||||
+ [infallible] attribute unsigned long long jugglerLoadIdentifier;
|
+ [infallible] attribute unsigned long long jugglerLoadIdentifier;
|
||||||
};
|
};
|
||||||
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
|
diff --git a/netwerk/base/nsINetworkInterceptController.idl b/netwerk/base/nsINetworkInterceptController.idl
|
||||||
index d72dc570dc82ff9d576942b9e7c23d8a74d68049..a5fcddc4b0e53a862e5a77120b4ccff8a27cfbab 100644
|
index 155daa5cd52c4e93e1cc4559875868f4faf2c37e..02e8a2614a27a4cc9e1de760d4c48617eba25d4d 100644
|
||||||
--- a/netwerk/base/nsINetworkInterceptController.idl
|
--- a/netwerk/base/nsINetworkInterceptController.idl
|
||||||
+++ b/netwerk/base/nsINetworkInterceptController.idl
|
+++ b/netwerk/base/nsINetworkInterceptController.idl
|
||||||
@@ -59,6 +59,7 @@ interface nsIInterceptedChannel : nsISupports
|
@@ -59,6 +59,7 @@ interface nsIInterceptedChannel : nsISupports
|
||||||
|
|
@ -2337,7 +2337,7 @@ index d72dc570dc82ff9d576942b9e7c23d8a74d68049..a5fcddc4b0e53a862e5a77120b4ccff8
|
||||||
/**
|
/**
|
||||||
* Set the status and reason for the forthcoming synthesized response.
|
* Set the status and reason for the forthcoming synthesized response.
|
||||||
diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp
|
diff --git a/netwerk/ipc/DocumentLoadListener.cpp b/netwerk/ipc/DocumentLoadListener.cpp
|
||||||
index 995560e4818c69f89959e36164fa9eba39925037..3d92280cfd73c5b09926151aac36857775f48e30 100644
|
index ca1f59e8847bd399fcf3018ede95d318265c374c..d114f0bcaddedc3553780ff7b97e395e28aff91e 100644
|
||||||
--- a/netwerk/ipc/DocumentLoadListener.cpp
|
--- a/netwerk/ipc/DocumentLoadListener.cpp
|
||||||
+++ b/netwerk/ipc/DocumentLoadListener.cpp
|
+++ b/netwerk/ipc/DocumentLoadListener.cpp
|
||||||
@@ -167,6 +167,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext,
|
@@ -167,6 +167,7 @@ static auto CreateDocumentLoadInfo(CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
|
@ -2349,7 +2349,7 @@ index 995560e4818c69f89959e36164fa9eba39925037..3d92280cfd73c5b09926151aac368577
|
||||||
return loadInfo.forget();
|
return loadInfo.forget();
|
||||||
}
|
}
|
||||||
diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
diff --git a/netwerk/protocol/http/InterceptedHttpChannel.cpp b/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
||||||
index 4bee70faf21db77daf381f40a562840470f788f4..93986ccb252bca67f2a0b291c915d523f5dad9eb 100644
|
index c58fbc96391f8dcb585bd00b5ae8cba9088abd82..c121c891b61c9d60df770020c4ad09521d2bbfe6 100644
|
||||||
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
||||||
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
|
||||||
@@ -727,6 +727,14 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor)
|
@@ -727,6 +727,14 @@ NS_IMPL_ISUPPORTS(ResetInterceptionHeaderVisitor, nsIHttpHeaderVisitor)
|
||||||
|
|
@ -2367,7 +2367,7 @@ index 4bee70faf21db77daf381f40a562840470f788f4..93986ccb252bca67f2a0b291c915d523
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
InterceptedHttpChannel::ResetInterception(bool aBypass) {
|
InterceptedHttpChannel::ResetInterception(bool aBypass) {
|
||||||
INTERCEPTED_LOG(("InterceptedHttpChannel::ResetInterception [%p] bypass: %s",
|
INTERCEPTED_LOG(("InterceptedHttpChannel::ResetInterception [%p] bypass: %s",
|
||||||
@@ -1070,11 +1078,18 @@ InterceptedHttpChannel::OnStartRequest(nsIRequest* aRequest) {
|
@@ -1140,11 +1148,18 @@ InterceptedHttpChannel::OnStartRequest(nsIRequest* aRequest) {
|
||||||
GetCallback(mProgressSink);
|
GetCallback(mProgressSink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2387,10 +2387,10 @@ index 4bee70faf21db77daf381f40a562840470f788f4..93986ccb252bca67f2a0b291c915d523
|
||||||
if (mPump && mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
|
if (mPump && mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
|
||||||
mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
|
mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
|
||||||
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
|
diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp
|
||||||
index 125728fa73180bbe57bfc1f53379ec637f108eb7..5fd60bebebbfa0f2de99cb14762cf0d52dbdb0cb 100644
|
index 3cb38dcf28a5cb3a8e70c336c8b1c822be59268f..4d9ae3ab666d4ba7b42730d50367720870f0183f 100644
|
||||||
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
|
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
|
||||||
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
|
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
|
||||||
@@ -1376,6 +1376,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta(
|
@@ -1381,6 +1381,10 @@ void nsHtml5TreeOpExecutor::UpdateReferrerInfoFromMeta(
|
||||||
void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
|
void nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP) {
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
|
@ -2475,7 +2475,7 @@ index 6dfd07d6b676a99993408921de8dea9d561f201d..e3c6794363cd6336effbeac83a179f37
|
||||||
readonly attribute boolean securityCheckDisabled;
|
readonly attribute boolean securityCheckDisabled;
|
||||||
};
|
};
|
||||||
diff --git a/services/settings/Utils.sys.mjs b/services/settings/Utils.sys.mjs
|
diff --git a/services/settings/Utils.sys.mjs b/services/settings/Utils.sys.mjs
|
||||||
index 73c83e526be1a3a252f995d0718e3975d50bffa7..4b05141c8ab8b084d977341127f36ea6d226aa9a 100644
|
index 73c83e526be1a3a252f995d0718e3975d50bffa7..db5977c54221e19e107a8325a0834302c2e84546 100644
|
||||||
--- a/services/settings/Utils.sys.mjs
|
--- a/services/settings/Utils.sys.mjs
|
||||||
+++ b/services/settings/Utils.sys.mjs
|
+++ b/services/settings/Utils.sys.mjs
|
||||||
@@ -95,7 +95,7 @@ function _isUndefined(value) {
|
@@ -95,7 +95,7 @@ function _isUndefined(value) {
|
||||||
|
|
@ -2487,8 +2487,18 @@ index 73c83e526be1a3a252f995d0718e3975d50bffa7..4b05141c8ab8b084d977341127f36ea6
|
||||||
? lazy.gServerURL
|
? lazy.gServerURL
|
||||||
: AppConstants.REMOTE_SETTINGS_SERVER_URL;
|
: AppConstants.REMOTE_SETTINGS_SERVER_URL;
|
||||||
},
|
},
|
||||||
|
@@ -108,6 +108,9 @@ export var Utils = {
|
||||||
|
log,
|
||||||
|
|
||||||
|
get shouldSkipRemoteActivityDueToTests() {
|
||||||
|
+ // Playwright does not set Cu.isInAutomation, hence we just return true
|
||||||
|
+ // here in order to disable the remote activity.
|
||||||
|
+ return true;
|
||||||
|
return (
|
||||||
|
(lazy.isRunningTests || Cu.isInAutomation) &&
|
||||||
|
this.SERVER_URL == "data:,#remote-settings-dummy/v1"
|
||||||
diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs
|
diff --git a/servo/components/style/gecko/media_features.rs b/servo/components/style/gecko/media_features.rs
|
||||||
index 014248a26f7b070850edf1d7db0990fd8ef26a10..9846ae282d959c406f15052791aae3ec9351326f 100644
|
index c9ad30b28b069a122cf01c5e97b83dc68ef022ff..f32dbcfe26fe2f6b8a0d066d6dfd208f1afc510d 100644
|
||||||
--- a/servo/components/style/gecko/media_features.rs
|
--- a/servo/components/style/gecko/media_features.rs
|
||||||
+++ b/servo/components/style/gecko/media_features.rs
|
+++ b/servo/components/style/gecko/media_features.rs
|
||||||
@@ -293,10 +293,15 @@ pub enum ForcedColors {
|
@@ -293,10 +293,15 @@ pub enum ForcedColors {
|
||||||
|
|
@ -2511,21 +2521,21 @@ index 014248a26f7b070850edf1d7db0990fd8ef26a10..9846ae282d959c406f15052791aae3ec
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl
|
diff --git a/toolkit/components/browser/nsIWebBrowserChrome.idl b/toolkit/components/browser/nsIWebBrowserChrome.idl
|
||||||
index 54de3abab5757dd706e3d909ccef6a0bed5deacc..f5c5480cd052ede0c76e5eec733dbb9283389045 100644
|
index 517c87a285dd93220cb2654d6ba7bb05c66cdeb7..e3010421d8dbe5ed5ed72feedb9f15805b32503e 100644
|
||||||
--- a/toolkit/components/browser/nsIWebBrowserChrome.idl
|
--- a/toolkit/components/browser/nsIWebBrowserChrome.idl
|
||||||
+++ b/toolkit/components/browser/nsIWebBrowserChrome.idl
|
+++ b/toolkit/components/browser/nsIWebBrowserChrome.idl
|
||||||
@@ -71,6 +71,9 @@ interface nsIWebBrowserChrome : nsISupports
|
@@ -74,6 +74,9 @@ interface nsIWebBrowserChrome : nsISupports
|
||||||
// Whether this window should use out-of-process cross-origin subframes.
|
// Whether this window should use out-of-process cross-origin subframes.
|
||||||
const unsigned long CHROME_FISSION_WINDOW = 0x00200000;
|
const unsigned long CHROME_FISSION_WINDOW = 1 << 21;
|
||||||
|
|
||||||
+ // Whether this window has "width" or "height" defined in features
|
+ // Whether this window has "width" or "height" defined in features
|
||||||
+ const unsigned long JUGGLER_WINDOW_EXPLICIT_SIZE = 0x00400000;
|
+ const unsigned long JUGGLER_WINDOW_EXPLICIT_SIZE = 0x00400000;
|
||||||
+
|
+
|
||||||
// Prevents new window animations on MacOS and Windows. Currently
|
// Prevents new window animations on MacOS and Windows. Currently
|
||||||
// ignored for Linux.
|
// ignored for Linux.
|
||||||
const unsigned long CHROME_SUPPRESS_ANIMATION = 0x01000000;
|
const unsigned long CHROME_SUPPRESS_ANIMATION = 1 << 24;
|
||||||
diff --git a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
diff --git a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
||||||
index 61eda006f090e391b3c0f209e9400920f480c115..8fea8caf17913a2736884caca8f6087f1fb48d15 100644
|
index 15fa2193c6116b5bd0cf2ee608eb5971f3d24370..aa92eb63b8f907e0df9ef8df60fd076aa3d6a472 100644
|
||||||
--- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
--- a/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
||||||
+++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
+++ b/toolkit/components/enterprisepolicies/EnterprisePoliciesParent.sys.mjs
|
||||||
@@ -108,6 +108,12 @@ EnterprisePoliciesManager.prototype = {
|
@@ -108,6 +108,12 @@ EnterprisePoliciesManager.prototype = {
|
||||||
|
|
@ -2570,10 +2580,10 @@ index 654903fadb709be976b72f36f155e23bc0622152..815b3dc24c9fda6b1db6c4666ac68904
|
||||||
int32_t aMaxSelfProgress,
|
int32_t aMaxSelfProgress,
|
||||||
int32_t aCurTotalProgress,
|
int32_t aCurTotalProgress,
|
||||||
diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
||||||
index 144924a7a6b3d11c0de3992d1e1f99a04f7611b4..b7646200f7843d42ef3fb1919e5a1d3057eaf14c 100644
|
index 209af157a35cf9c4586424421ee19b3f680796b6..1feb61e2f18e9a13631addc935f00da07739291e 100644
|
||||||
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
||||||
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
|
||||||
@@ -1880,7 +1880,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent(
|
@@ -1853,7 +1853,11 @@ uint32_t nsWindowWatcher::CalculateChromeFlagsForContent(
|
||||||
|
|
||||||
// Open a minimal popup.
|
// Open a minimal popup.
|
||||||
*aIsPopupRequested = true;
|
*aIsPopupRequested = true;
|
||||||
|
|
@ -2587,7 +2597,7 @@ index 144924a7a6b3d11c0de3992d1e1f99a04f7611b4..b7646200f7843d42ef3fb1919e5a1d30
|
||||||
|
|
||||||
/**
|
/**
|
||||||
diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs
|
diff --git a/toolkit/mozapps/update/UpdateService.sys.mjs b/toolkit/mozapps/update/UpdateService.sys.mjs
|
||||||
index fcb142e5d74ab40515fd6e3b7848a661771d459c..592d4b759958283b1c53c52a648f35f97110705b 100644
|
index 290344c58bf488b4aa955c2c58bdaa11048e2f48..2d419b90e6c5a910d3038380cd6c819eb8b0c768 100644
|
||||||
--- a/toolkit/mozapps/update/UpdateService.sys.mjs
|
--- a/toolkit/mozapps/update/UpdateService.sys.mjs
|
||||||
+++ b/toolkit/mozapps/update/UpdateService.sys.mjs
|
+++ b/toolkit/mozapps/update/UpdateService.sys.mjs
|
||||||
@@ -3853,6 +3853,8 @@ UpdateService.prototype = {
|
@@ -3853,6 +3853,8 @@ UpdateService.prototype = {
|
||||||
|
|
@ -2600,15 +2610,15 @@ index fcb142e5d74ab40515fd6e3b7848a661771d459c..592d4b759958283b1c53c52a648f35f9
|
||||||
(Cu.isInAutomation ||
|
(Cu.isInAutomation ||
|
||||||
lazy.Marionette.running ||
|
lazy.Marionette.running ||
|
||||||
diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
|
diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
|
||||||
index 2e3721e8a5807936c02cce6c21240df3b4c92c97..ecd1ca11d96c14ba6db4b09d4d9c10ef757e690b 100644
|
index f554b692f7e874dd21be1ef783e899ba602ee7f3..dd6c94f8723ca227611c8390d9dcd4f292939703 100644
|
||||||
--- a/toolkit/toolkit.mozbuild
|
--- a/toolkit/toolkit.mozbuild
|
||||||
+++ b/toolkit/toolkit.mozbuild
|
+++ b/toolkit/toolkit.mozbuild
|
||||||
@@ -155,6 +155,7 @@ if CONFIG['ENABLE_WEBDRIVER']:
|
@@ -155,6 +155,7 @@ if CONFIG["ENABLE_WEBDRIVER"]:
|
||||||
'/remote',
|
"/remote",
|
||||||
'/testing/firefox-ui',
|
"/testing/firefox-ui",
|
||||||
'/testing/marionette',
|
"/testing/marionette",
|
||||||
+ '/juggler',
|
+ "/juggler",
|
||||||
'/toolkit/components/telemetry/tests/marionette',
|
"/toolkit/components/telemetry/tests/marionette",
|
||||||
]
|
]
|
||||||
|
|
||||||
diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp
|
diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp
|
||||||
|
|
@ -2647,23 +2657,22 @@ index 7eb9e1104682d4eb47060654f43a1efa8b2a6bb2..a8315d6decf654b5302bea5beeea3414
|
||||||
// Only run this code if LauncherProcessWin.h was included beforehand, thus
|
// Only run this code if LauncherProcessWin.h was included beforehand, thus
|
||||||
// signalling that the hosting process should support launcher mode.
|
// signalling that the hosting process should support launcher mode.
|
||||||
diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp
|
diff --git a/uriloader/base/nsDocLoader.cpp b/uriloader/base/nsDocLoader.cpp
|
||||||
index d54be4a4d7697851cc5279a39a49b06c745b7630..abb455116db3011dc7f84df86631da5eb7030700 100644
|
index fe72a2715da8846146377e719559c16e6ef1f7ff..a5959143bac8f62ee359fa3883a844f3fe541685 100644
|
||||||
--- a/uriloader/base/nsDocLoader.cpp
|
--- a/uriloader/base/nsDocLoader.cpp
|
||||||
+++ b/uriloader/base/nsDocLoader.cpp
|
+++ b/uriloader/base/nsDocLoader.cpp
|
||||||
@@ -828,6 +828,13 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout,
|
@@ -813,6 +813,12 @@ void nsDocLoader::DocLoaderIsEmpty(bool aFlushLayout,
|
||||||
("DocLoader:%p: Firing load event for document.open\n",
|
("DocLoader:%p: Firing load event for document.open\n",
|
||||||
this));
|
this));
|
||||||
|
|
||||||
+ nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
+ nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||||
+ if (os) {
|
+ if (os) {
|
||||||
+ nsIPrincipal* principal = doc->NodePrincipal();
|
+ nsIPrincipal* principal = doc->NodePrincipal();
|
||||||
+ if (!principal->IsSystemPrincipal())
|
+ if (!principal->IsSystemPrincipal())
|
||||||
+ os->NotifyObservers(ToSupports(doc), "juggler-document-open-loaded", nullptr);
|
+ os->NotifyObservers(ToSupports(doc), "juggler-document-open-loaded", nullptr);
|
||||||
+ }
|
+ }
|
||||||
+
|
// This is a very cut-down version of
|
||||||
// This is a very cut-down version of
|
// nsDocumentViewer::LoadComplete that doesn't do various things
|
||||||
// nsDocumentViewer::LoadComplete that doesn't do various things
|
// that are not relevant here because this wasn't an actual
|
||||||
// that are not relevant here because this wasn't an actual
|
|
||||||
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
|
diff --git a/uriloader/exthandler/nsExternalHelperAppService.cpp b/uriloader/exthandler/nsExternalHelperAppService.cpp
|
||||||
index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295ea050b878 100644
|
index 4573e28470c5112f5ac2c5dd53e7a9d1ceedb943..b53b86d8e39f1de4b0d0f1a8d5d7295ea050b878 100644
|
||||||
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
|
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
|
||||||
|
|
@ -2877,7 +2886,7 @@ index 1c25e9d9a101233f71e92288a0f93125b81ac1c5..22cf67b0f6e3ddd2b3ed725a314ba6a9
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
diff --git a/widget/MouseEvents.h b/widget/MouseEvents.h
|
diff --git a/widget/MouseEvents.h b/widget/MouseEvents.h
|
||||||
index 7ad7d82cd68810d9557adaa31ad5c7cb80bfb079..7a3d0116ce924e1e26a1cc6976abe11ed6f4a62c 100644
|
index ea714704df53af78a55065ce7626798e0e674a23..a108e0459aeac9789adac7d7ec166abf94646454 100644
|
||||||
--- a/widget/MouseEvents.h
|
--- a/widget/MouseEvents.h
|
||||||
+++ b/widget/MouseEvents.h
|
+++ b/widget/MouseEvents.h
|
||||||
@@ -258,6 +258,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase,
|
@@ -258,6 +258,7 @@ class WidgetMouseEvent : public WidgetMouseEventBase,
|
||||||
|
|
@ -2926,7 +2935,7 @@ diff --git a/widget/cocoa/NativeKeyBindings.mm b/widget/cocoa/NativeKeyBindings.
|
||||||
index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce8050630a1aa 100644
|
index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce8050630a1aa 100644
|
||||||
--- a/widget/cocoa/NativeKeyBindings.mm
|
--- a/widget/cocoa/NativeKeyBindings.mm
|
||||||
+++ b/widget/cocoa/NativeKeyBindings.mm
|
+++ b/widget/cocoa/NativeKeyBindings.mm
|
||||||
@@ -528,6 +528,13 @@
|
@@ -528,6 +528,13 @@ void NativeKeyBindings::GetEditCommandsForTests(
|
||||||
break;
|
break;
|
||||||
case KEY_NAME_INDEX_ArrowLeft:
|
case KEY_NAME_INDEX_ArrowLeft:
|
||||||
if (aEvent.IsAlt()) {
|
if (aEvent.IsAlt()) {
|
||||||
|
|
@ -2940,7 +2949,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
|
if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
|
||||||
@@ -550,6 +557,13 @@
|
@@ -550,6 +557,13 @@ void NativeKeyBindings::GetEditCommandsForTests(
|
||||||
break;
|
break;
|
||||||
case KEY_NAME_INDEX_ArrowRight:
|
case KEY_NAME_INDEX_ArrowRight:
|
||||||
if (aEvent.IsAlt()) {
|
if (aEvent.IsAlt()) {
|
||||||
|
|
@ -2954,7 +2963,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
|
if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
|
||||||
@@ -572,6 +586,10 @@
|
@@ -572,6 +586,10 @@ void NativeKeyBindings::GetEditCommandsForTests(
|
||||||
break;
|
break;
|
||||||
case KEY_NAME_INDEX_ArrowUp:
|
case KEY_NAME_INDEX_ArrowUp:
|
||||||
if (aEvent.IsControl()) {
|
if (aEvent.IsControl()) {
|
||||||
|
|
@ -2965,7 +2974,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (aEvent.IsMeta()) {
|
if (aEvent.IsMeta()) {
|
||||||
@@ -582,7 +600,7 @@
|
@@ -582,7 +600,7 @@ void NativeKeyBindings::GetEditCommandsForTests(
|
||||||
!aEvent.IsShift()
|
!aEvent.IsShift()
|
||||||
? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:))
|
? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:))
|
||||||
: ToObjcSelectorPtr(
|
: ToObjcSelectorPtr(
|
||||||
|
|
@ -2974,7 +2983,7 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805
|
||||||
aCommands);
|
aCommands);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -609,6 +627,10 @@
|
@@ -609,6 +627,10 @@ void NativeKeyBindings::GetEditCommandsForTests(
|
||||||
break;
|
break;
|
||||||
case KEY_NAME_INDEX_ArrowDown:
|
case KEY_NAME_INDEX_ArrowDown:
|
||||||
if (aEvent.IsControl()) {
|
if (aEvent.IsControl()) {
|
||||||
|
|
@ -2985,31 +2994,6 @@ index e4bdf715e2fb899e97a5bfeb2e147127460d6047..3554f919480278b7353617481c7ce805
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (aEvent.IsMeta()) {
|
if (aEvent.IsMeta()) {
|
||||||
diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm
|
|
||||||
index f3a760476290953df2179fa44bd68dd171d291ab..6cd3f8178d260904905372c1afc7ecbcc568fbc8 100644
|
|
||||||
--- a/widget/cocoa/nsCocoaUtils.mm
|
|
||||||
+++ b/widget/cocoa/nsCocoaUtils.mm
|
|
||||||
@@ -267,14 +267,17 @@ static float MenuBarScreenHeight() {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
- nsCOMPtr<nsIWidget> hiddenWindowWidget;
|
|
||||||
+ nsCOMPtr<nsIWidget> mainWindowWidget;
|
|
||||||
if (NS_FAILED(baseHiddenWindow->GetMainWidget(
|
|
||||||
- getter_AddRefs(hiddenWindowWidget)))) {
|
|
||||||
+ getter_AddRefs(mainWindowWidget)))) {
|
|
||||||
NS_WARNING("Couldn't get nsIWidget from hidden window (nsIBaseWindow)");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
- return hiddenWindowWidget;
|
|
||||||
+ // In the case of headless mode, it's a HeadlessWidget while the callee expects a nsCocoaWindow
|
|
||||||
+ if (gfxPlatform::IsHeadless())
|
|
||||||
+ return nullptr;
|
|
||||||
+ return mainWindowWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL nsCocoaUtils::WasLaunchedAtLogin() {
|
|
||||||
diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp
|
diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp
|
||||||
index bb4ee9175e66dc40de1871a7f91368fe309494a3..747625e3869882300bfbc18b184db5151dd90c1a 100644
|
index bb4ee9175e66dc40de1871a7f91368fe309494a3..747625e3869882300bfbc18b184db5151dd90c1a 100644
|
||||||
--- a/widget/headless/HeadlessCompositorWidget.cpp
|
--- a/widget/headless/HeadlessCompositorWidget.cpp
|
||||||
|
|
@ -3202,7 +3186,7 @@ index 9856991ef32f25f51942f8cd664a09bec2192c70..948947a421179e91c51005aeb83ed0d1
|
||||||
~HeadlessWidget();
|
~HeadlessWidget();
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h
|
diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h
|
||||||
index a3d7aaf1b6c651fedbab7875c1a38647103d08ed..ac3b09e50216524cce90d96b013007f7b07472da 100644
|
index 8ba46829357fc4acc47bf20842fd869902efa000..a1b5b2c5230d90981bd563d4df2d2bf1c2e05cef 100644
|
||||||
--- a/widget/nsGUIEventIPC.h
|
--- a/widget/nsGUIEventIPC.h
|
||||||
+++ b/widget/nsGUIEventIPC.h
|
+++ b/widget/nsGUIEventIPC.h
|
||||||
@@ -234,6 +234,7 @@ struct ParamTraits<mozilla::WidgetMouseEvent> {
|
@@ -234,6 +234,7 @@ struct ParamTraits<mozilla::WidgetMouseEvent> {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ pref("datareporting.policy.dataSubmissionPolicyBypassNotification", true);
|
||||||
// Force pdfs into downloads.
|
// Force pdfs into downloads.
|
||||||
pref("pdfjs.disabled", true);
|
pref("pdfjs.disabled", true);
|
||||||
|
|
||||||
|
// This preference breaks our authentication flow.
|
||||||
|
pref("network.auth.use_redirect_for_retries", false);
|
||||||
|
|
||||||
// Disable cross-process iframes, but not cross-process navigations.
|
// Disable cross-process iframes, but not cross-process navigations.
|
||||||
pref("fission.webContentIsolationStrategy", 0);
|
pref("fission.webContentIsolationStrategy", 0);
|
||||||
|
|
||||||
|
|
@ -109,9 +112,20 @@ pref("prompts.contentPromptSubDialog", false);
|
||||||
// Do not use system colors - they are affected by themes.
|
// Do not use system colors - they are affected by themes.
|
||||||
pref("ui.use_standins_for_native_colors", true);
|
pref("ui.use_standins_for_native_colors", true);
|
||||||
|
|
||||||
|
// Turn off the Push service.
|
||||||
pref("dom.push.serverURL", "");
|
pref("dom.push.serverURL", "");
|
||||||
// This setting breaks settings loading.
|
// Prevent Remote Settings (firefox.settings.services.mozilla.com) to issue non local connections.
|
||||||
pref("services.settings.server", "");
|
pref("services.settings.server", "");
|
||||||
|
// Prevent location.services.mozilla.com to issue non local connections.
|
||||||
|
pref("browser.region.network.url", "");
|
||||||
|
pref("browser.pocket.enabled", false);
|
||||||
|
pref("browser.newtabpage.activity-stream.feeds.topsites", false);
|
||||||
|
// Disable sponsored tiles from "Mozilla Tiles Service"
|
||||||
|
pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false);
|
||||||
|
// required to prevent non-local access to push.services.mozilla.com
|
||||||
|
pref("dom.push.connection.enabled", false);
|
||||||
|
// Prevent contile.services.mozilla.com to issue non local connections.
|
||||||
|
pref("browser.topsites.contile.enabled", false);
|
||||||
pref("browser.safebrowsing.provider.mozilla.updateURL", "");
|
pref("browser.safebrowsing.provider.mozilla.updateURL", "");
|
||||||
pref("browser.library.activity-stream.enabled", false);
|
pref("browser.library.activity-stream.enabled", false);
|
||||||
pref("browser.search.geoSpecificDefaults", false);
|
pref("browser.search.geoSpecificDefaults", false);
|
||||||
|
|
@ -308,3 +322,6 @@ pref("devtools.toolbox.host", "window");
|
||||||
|
|
||||||
// Disable auto translations
|
// Disable auto translations
|
||||||
pref("browser.translations.enable", false);
|
pref("browser.translations.enable", false);
|
||||||
|
|
||||||
|
// Disable spell check
|
||||||
|
pref("layout.spellcheckDefault", 0);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
REMOTE_URL="https://github.com/WebKit/WebKit.git"
|
REMOTE_URL="https://github.com/WebKit/WebKit.git"
|
||||||
BASE_BRANCH="main"
|
BASE_BRANCH="main"
|
||||||
BASE_REVISION="3db3a794a844d2c7e4cda8fc6a7588f8e62ee85a"
|
BASE_REVISION="e225c278f4c06f451ea92cc68b12986dd2a99979"
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -14,7 +14,7 @@ A few examples of problems this can catch include:
|
||||||
|
|
||||||
The following examples rely on the [`@axe-core/playwright`](https://npmjs.org/@axe-core/playwright) package which adds support for running the [axe accessibility testing engine](https://www.deque.com/axe/) as part of your Playwright tests.
|
The following examples rely on the [`@axe-core/playwright`](https://npmjs.org/@axe-core/playwright) package which adds support for running the [axe accessibility testing engine](https://www.deque.com/axe/) as part of your Playwright tests.
|
||||||
|
|
||||||
:::note Disclaimer
|
:::note[Disclaimer]
|
||||||
Automated accessibility tests can detect some common accessibility problems such as missing or invalid properties. But many accessibility problems can only be discovered through manual testing. We recommend using a combination of automated testing, manual accessibility assessments, and inclusive user testing.
|
Automated accessibility tests can detect some common accessibility problems such as missing or invalid properties. But many accessibility problems can only be discovered through manual testing. We recommend using a combination of automated testing, manual accessibility assessments, and inclusive user testing.
|
||||||
|
|
||||||
For manual assessments, we recommend [Accessibility Insights for Web](https://accessibilityinsights.io/docs/web/overview/?referrer=playwright-accessibility-testing-js), a free and open source dev tool that walks you through assessing a website for [WCAG 2.1 AA](https://www.w3.org/WAI/WCAG21/quickref/?currentsidebar=%23col_customize&levels=aaa) coverage.
|
For manual assessments, we recommend [Accessibility Insights for Web](https://accessibilityinsights.io/docs/web/overview/?referrer=playwright-accessibility-testing-js), a free and open source dev tool that walks you through assessing a website for [WCAG 2.1 AA](https://www.w3.org/WAI/WCAG21/quickref/?currentsidebar=%23col_customize&levels=aaa) coverage.
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,10 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.delete.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.delete.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.17
|
* since: v1.17
|
||||||
|
|
||||||
### option: APIRequestContext.delete.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.delete.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.17
|
||||||
|
|
||||||
|
### option: APIRequestContext.delete.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.17
|
* since: v1.17
|
||||||
|
|
||||||
### option: APIRequestContext.delete.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.delete.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
@ -187,10 +190,12 @@ All responses returned by [`method: APIRequestContext.get`] and similar methods
|
||||||
- returns: <[APIResponse]>
|
- returns: <[APIResponse]>
|
||||||
|
|
||||||
Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and update
|
Sends HTTP(S) request and returns its response. The method will populate request cookies from the context and update
|
||||||
context cookies from the response. The method will automatically follow redirects. JSON objects can be passed directly to the request.
|
context cookies from the response. The method will automatically follow redirects.
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
|
JSON objects can be passed directly to the request:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await request.fetch('https://example.com/api/createBook', {
|
await request.fetch('https://example.com/api/createBook', {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
|
@ -224,28 +229,17 @@ var data = new Dictionary<string, object>() {
|
||||||
await Request.FetchAsync("https://example.com/api/createBook", new() { Method = "post", DataObject = data });
|
await Request.FetchAsync("https://example.com/api/createBook", new() { Method = "post", DataObject = data });
|
||||||
```
|
```
|
||||||
|
|
||||||
The common way to send file(s) in the body of a request is to encode it as form fields with `multipart/form-data` encoding. You can achieve that with Playwright API like this:
|
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use [FormData] to construct request body and pass it to the request as [`option: multipart`] parameter:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Open file as a stream and pass it to the request:
|
const form = new FormData();
|
||||||
const stream = fs.createReadStream('team.csv');
|
form.set('name', 'John');
|
||||||
await request.fetch('https://example.com/api/uploadTeamList', {
|
form.append('name', 'Doe');
|
||||||
method: 'post',
|
// Send two file fields with the same name.
|
||||||
multipart: {
|
form.append('file', new File(['console.log(2024);'], 'f1.js', { type: 'text/javascript' }));
|
||||||
fileField: stream
|
form.append('file', new File(['hello'], 'f2.txt', { type: 'text/plain' }));
|
||||||
}
|
await request.fetch('https://example.com/api/uploadForm', {
|
||||||
});
|
multipart: form
|
||||||
|
|
||||||
// Or you can pass the file content directly as an object:
|
|
||||||
await request.fetch('https://example.com/api/uploadScript', {
|
|
||||||
method: 'post',
|
|
||||||
multipart: {
|
|
||||||
fileField: {
|
|
||||||
name: 'f.js',
|
|
||||||
mimeType: 'text/javascript',
|
|
||||||
buffer: Buffer.from('console.log(2022);')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -259,15 +253,14 @@ APIResponse response = request.fetch("https://example.com/api/uploadTeamList",
|
||||||
// Or you can pass the file content directly as FilePayload object:
|
// Or you can pass the file content directly as FilePayload object:
|
||||||
FilePayload filePayload = new FilePayload("f.js", "text/javascript",
|
FilePayload filePayload = new FilePayload("f.js", "text/javascript",
|
||||||
"console.log(2022);".getBytes(StandardCharsets.UTF_8));
|
"console.log(2022);".getBytes(StandardCharsets.UTF_8));
|
||||||
APIResponse response = request.fetch("https://example.com/api/uploadTeamList",
|
APIResponse response = request.fetch("https://example.com/api/uploadScript",
|
||||||
RequestOptions.create().setMethod("post").setMultipart(
|
RequestOptions.create().setMethod("post").setMultipart(
|
||||||
FormData.create().set("fileField", filePayload)));
|
FormData.create().set("fileField", filePayload)));
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
api_request_context.fetch(
|
api_request_context.fetch(
|
||||||
"https://example.com/api/uploadScrip'",
|
"https://example.com/api/uploadScript", method="post",
|
||||||
method="post",
|
|
||||||
multipart={
|
multipart={
|
||||||
"fileField": {
|
"fileField": {
|
||||||
"name": "f.js",
|
"name": "f.js",
|
||||||
|
|
@ -324,7 +317,10 @@ If set changes the fetch method (e.g. [PUT](https://developer.mozilla.org/en-US/
|
||||||
### option: APIRequestContext.fetch.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.fetch.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.fetch.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.fetch.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.fetch.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.fetch.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.fetch.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
@ -410,7 +406,10 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query
|
||||||
### option: APIRequestContext.get.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.get.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.26
|
* since: v1.26
|
||||||
|
|
||||||
### option: APIRequestContext.get.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.get.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.26
|
||||||
|
|
||||||
|
### option: APIRequestContext.get.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.26
|
* since: v1.26
|
||||||
|
|
||||||
### option: APIRequestContext.get.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.get.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
@ -460,7 +459,10 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.head.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.head.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.26
|
* since: v1.26
|
||||||
|
|
||||||
### option: APIRequestContext.head.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.head.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.26
|
||||||
|
|
||||||
|
### option: APIRequestContext.head.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.26
|
* since: v1.26
|
||||||
|
|
||||||
### option: APIRequestContext.head.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.head.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
@ -510,7 +512,10 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.patch.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.patch.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.patch.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.patch.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.patch.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.patch.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.patch.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
@ -566,7 +571,7 @@ api_request_context.post("https://example.com/api/createBook", data=data)
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var data = new Dictionary<string, object>() {
|
var data = new Dictionary<string, object>() {
|
||||||
{ "firstNam", "John" },
|
{ "firstName", "John" },
|
||||||
{ "lastName", "Doe" }
|
{ "lastName", "Doe" }
|
||||||
};
|
};
|
||||||
await request.PostAsync("https://example.com/api/createBook", new() { DataObject = data });
|
await request.PostAsync("https://example.com/api/createBook", new() { DataObject = data });
|
||||||
|
|
@ -604,26 +609,17 @@ formData.Set("body", "John Doe");
|
||||||
await request.PostAsync("https://example.com/api/findBook", new() { Form = formData });
|
await request.PostAsync("https://example.com/api/findBook", new() { Form = formData });
|
||||||
```
|
```
|
||||||
|
|
||||||
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. You can achieve that with Playwright API like this:
|
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use [FormData] to construct request body and pass it to the request as `multipart` parameter:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Open file as a stream and pass it to the request:
|
const form = new FormData();
|
||||||
const stream = fs.createReadStream('team.csv');
|
form.set('name', 'John');
|
||||||
await request.post('https://example.com/api/uploadTeamList', {
|
form.append('name', 'Doe');
|
||||||
multipart: {
|
// Send two file fields with the same name.
|
||||||
fileField: stream
|
form.append('file', new File(['console.log(2024);'], 'f1.js', { type: 'text/javascript' }));
|
||||||
}
|
form.append('file', new File(['hello'], 'f2.txt', { type: 'text/plain' }));
|
||||||
});
|
await request.post('https://example.com/api/uploadForm', {
|
||||||
|
multipart: form
|
||||||
// Or you can pass the file content directly as an object:
|
|
||||||
await request.post('https://example.com/api/uploadScript', {
|
|
||||||
multipart: {
|
|
||||||
fileField: {
|
|
||||||
name: 'f.js',
|
|
||||||
mimeType: 'text/javascript',
|
|
||||||
buffer: Buffer.from('console.log(2022);')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -635,16 +631,16 @@ APIResponse response = request.post("https://example.com/api/uploadTeamList",
|
||||||
FormData.create().set("fileField", file)));
|
FormData.create().set("fileField", file)));
|
||||||
|
|
||||||
// Or you can pass the file content directly as FilePayload object:
|
// Or you can pass the file content directly as FilePayload object:
|
||||||
FilePayload filePayload = new FilePayload("f.js", "text/javascript",
|
FilePayload filePayload1 = new FilePayload("f1.js", "text/javascript",
|
||||||
"console.log(2022);".getBytes(StandardCharsets.UTF_8));
|
"console.log(2022);".getBytes(StandardCharsets.UTF_8));
|
||||||
APIResponse response = request.post("https://example.com/api/uploadTeamList",
|
APIResponse response = request.post("https://example.com/api/uploadScript",
|
||||||
RequestOptions.create().setMultipart(
|
RequestOptions.create().setMultipart(
|
||||||
FormData.create().set("fileField", filePayload)));
|
FormData.create().set("fileField", filePayload)));
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
api_request_context.post(
|
api_request_context.post(
|
||||||
"https://example.com/api/uploadScrip'",
|
"https://example.com/api/uploadScript'",
|
||||||
multipart={
|
multipart={
|
||||||
"fileField": {
|
"fileField": {
|
||||||
"name": "f.js",
|
"name": "f.js",
|
||||||
|
|
@ -690,7 +686,10 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar
|
||||||
### option: APIRequestContext.post.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.post.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.post.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.post.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.post.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.post.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.post.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
@ -740,7 +739,10 @@ context cookies from the response. The method will automatically follow redirect
|
||||||
### option: APIRequestContext.put.form = %%-csharp-fetch-option-form-%%
|
### option: APIRequestContext.put.form = %%-csharp-fetch-option-form-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.put.multipart = %%-js-python-fetch-option-multipart-%%
|
### option: APIRequestContext.put.multipart = %%-js-fetch-option-multipart-%%
|
||||||
|
* since: v1.16
|
||||||
|
|
||||||
|
### option: APIRequestContext.put.multipart = %%-python-fetch-option-multipart-%%
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
|
|
||||||
### option: APIRequestContext.put.multipart = %%-csharp-fetch-option-multipart-%%
|
### option: APIRequestContext.put.multipart = %%-csharp-fetch-option-multipart-%%
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ await context.CloseAsync();
|
||||||
|
|
||||||
## event: BrowserContext.backgroundPage
|
## event: BrowserContext.backgroundPage
|
||||||
* since: v1.11
|
* since: v1.11
|
||||||
* langs: js, python
|
|
||||||
- argument: <[Page]>
|
- argument: <[Page]>
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
|
|
@ -73,6 +72,12 @@ Only works with Chromium browser's persistent context.
|
||||||
|
|
||||||
Emitted when new background page is created in the context.
|
Emitted when new background page is created in the context.
|
||||||
|
|
||||||
|
```java
|
||||||
|
context.onBackgroundPage(backgroundPage -> {
|
||||||
|
System.out.println(backgroundPage.url());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const backgroundPage = await context.waitForEvent('backgroundpage');
|
const backgroundPage = await context.waitForEvent('backgroundpage');
|
||||||
```
|
```
|
||||||
|
|
@ -85,6 +90,14 @@ background_page = await context.wait_for_event("backgroundpage")
|
||||||
background_page = context.wait_for_event("backgroundpage")
|
background_page = context.wait_for_event("backgroundpage")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
context.BackgroundPage += (_, backgroundPage) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine(backgroundPage.Url);
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## event: BrowserContext.close
|
## event: BrowserContext.close
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
- argument: <[BrowserContext]>
|
- argument: <[BrowserContext]>
|
||||||
|
|
@ -205,7 +218,7 @@ also fire for popup pages. See also [`event: Page.popup`] to receive events abou
|
||||||
|
|
||||||
The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
|
The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
|
||||||
popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is
|
popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is
|
||||||
done and its response has started loading in the popup.
|
done and its response has started loading in the popup. If you would like to route/listen to this network request, use [`method: BrowserContext.route`] and [`event: BrowserContext.request`] respectively instead of similar methods on the [Page].
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const newPagePromise = context.waitForEvent('page');
|
const newPagePromise = context.waitForEvent('page');
|
||||||
|
|
@ -441,7 +454,6 @@ Script to be evaluated in all pages in the browser context. Optional.
|
||||||
|
|
||||||
## method: BrowserContext.backgroundPages
|
## method: BrowserContext.backgroundPages
|
||||||
* since: v1.11
|
* since: v1.11
|
||||||
* langs: js, python
|
|
||||||
- returns: <[Array]<[Page]>>
|
- returns: <[Array]<[Page]>>
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
|
|
@ -459,7 +471,71 @@ Returns the browser instance of the context. If it was launched as a persistent
|
||||||
## async method: BrowserContext.clearCookies
|
## async method: BrowserContext.clearCookies
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
|
|
||||||
Clears context cookies.
|
Removes cookies from context. Accepts optional filter.
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```js
|
||||||
|
await context.clearCookies();
|
||||||
|
await context.clearCookies({ name: 'session-id' });
|
||||||
|
await context.clearCookies({ domain: 'my-origin.com' });
|
||||||
|
await context.clearCookies({ domain: /.*my-origin\.com/ });
|
||||||
|
await context.clearCookies({ path: '/api/v1' });
|
||||||
|
await context.clearCookies({ name: 'session-id', domain: 'my-origin.com' });
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```java
|
||||||
|
context.clearCookies();
|
||||||
|
context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("session-id"));
|
||||||
|
context.clearCookies(new BrowserContext.ClearCookiesOptions().setDomain("my-origin.com"));
|
||||||
|
context.clearCookies(new BrowserContext.ClearCookiesOptions().setPath("/api/v1"));
|
||||||
|
context.clearCookies(new BrowserContext.ClearCookiesOptions()
|
||||||
|
.setName("session-id")
|
||||||
|
.setDomain("my-origin.com"));
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
await context.clear_cookies()
|
||||||
|
await context.clear_cookies(name="session-id")
|
||||||
|
await context.clear_cookies(domain="my-origin.com")
|
||||||
|
await context.clear_cookies(path="/api/v1")
|
||||||
|
await context.clear_cookies(name="session-id", domain="my-origin.com")
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
context.clear_cookies()
|
||||||
|
context.clear_cookies(name="session-id")
|
||||||
|
context.clear_cookies(domain="my-origin.com")
|
||||||
|
context.clear_cookies(path="/api/v1")
|
||||||
|
context.clear_cookies(name="session-id", domain="my-origin.com")
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await context.ClearCookiesAsync();
|
||||||
|
await context.ClearCookiesAsync(new() { Name = "session-id" });
|
||||||
|
await context.ClearCookiesAsync(new() { Domain = "my-origin.com" });
|
||||||
|
await context.ClearCookiesAsync(new() { Path = "/api/v1" });
|
||||||
|
await context.ClearCookiesAsync(new() { Name = "session-id", Domain = "my-origin.com" });
|
||||||
|
```
|
||||||
|
|
||||||
|
### option: BrowserContext.clearCookies.name
|
||||||
|
* since: v1.43
|
||||||
|
- `name` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Only removes cookies with the given name.
|
||||||
|
|
||||||
|
### option: BrowserContext.clearCookies.domain
|
||||||
|
* since: v1.43
|
||||||
|
- `domain` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Only removes cookies with the given domain.
|
||||||
|
|
||||||
|
### option: BrowserContext.clearCookies.path
|
||||||
|
* since: v1.43
|
||||||
|
- `path` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Only removes cookies with the given path.
|
||||||
|
|
||||||
## async method: BrowserContext.clearPermissions
|
## async method: BrowserContext.clearPermissions
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
|
|
@ -1013,27 +1089,6 @@ Creates a new page in the browser context.
|
||||||
|
|
||||||
Returns all open pages in the context.
|
Returns all open pages in the context.
|
||||||
|
|
||||||
## async method: BrowserContext.removeCookies
|
|
||||||
* since: v1.43
|
|
||||||
|
|
||||||
Removes cookies from context. At least one of the removal criteria should be provided.
|
|
||||||
|
|
||||||
**Usage**
|
|
||||||
|
|
||||||
```js
|
|
||||||
await browserContext.removeCookies({ name: 'session-id' });
|
|
||||||
await browserContext.removeCookies({ domain: 'my-origin.com' });
|
|
||||||
await browserContext.removeCookies({ path: '/api/v1' });
|
|
||||||
await browserContext.removeCookies({ name: 'session-id', domain: 'my-origin.com' });
|
|
||||||
```
|
|
||||||
|
|
||||||
### param: BrowserContext.removeCookies.filter
|
|
||||||
* since: v1.43
|
|
||||||
- `filter` <[Object]>
|
|
||||||
- `name` ?<[string]>
|
|
||||||
- `domain` ?<[string]>
|
|
||||||
- `path` ?<[string]>
|
|
||||||
|
|
||||||
## property: BrowserContext.request
|
## property: BrowserContext.request
|
||||||
* since: v1.16
|
* since: v1.16
|
||||||
* langs:
|
* langs:
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ client.on("Animation.animationCreated", lambda: print("animation created!"))
|
||||||
response = await client.send("Animation.getPlaybackRate")
|
response = await client.send("Animation.getPlaybackRate")
|
||||||
print("playback rate is " + str(response["playbackRate"]))
|
print("playback rate is " + str(response["playbackRate"]))
|
||||||
await client.send("Animation.setPlaybackRate", {
|
await client.send("Animation.setPlaybackRate", {
|
||||||
playbackRate: response["playbackRate"] / 2
|
"playbackRate": response["playbackRate"] / 2
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ client.on("Animation.animationCreated", lambda: print("animation created!"))
|
||||||
response = client.send("Animation.getPlaybackRate")
|
response = client.send("Animation.getPlaybackRate")
|
||||||
print("playback rate is " + str(response["playbackRate"]))
|
print("playback rate is " + str(response["playbackRate"]))
|
||||||
client.send("Animation.setPlaybackRate", {
|
client.send("Animation.setPlaybackRate", {
|
||||||
playbackRate: response["playbackRate"] / 2
|
"playbackRate": response["playbackRate"] / 2
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
```csharp
|
```csharp
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
ElementHandle represents an in-page DOM element. ElementHandles can be created with the [`method: Page.querySelector`] method.
|
ElementHandle represents an in-page DOM element. ElementHandles can be created with the [`method: Page.querySelector`] method.
|
||||||
|
|
||||||
:::caution Discouraged
|
:::warning[Discouraged]
|
||||||
The use of ElementHandle is discouraged, use [Locator] objects and web-first assertions instead.
|
The use of ElementHandle is discouraged, use [Locator] objects and web-first assertions instead.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -692,7 +692,7 @@ generate the text for. A superset of the [`param: key`] values can be found
|
||||||
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
||||||
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
||||||
|
|
||||||
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
||||||
|
|
||||||
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@
|
||||||
Error is raised whenever certain operations are terminated abnormally, e.g.
|
Error is raised whenever certain operations are terminated abnormally, e.g.
|
||||||
browser closes while [`method: Page.evaluate`] is running. All Playwright exceptions
|
browser closes while [`method: Page.evaluate`] is running. All Playwright exceptions
|
||||||
inherit from this class.
|
inherit from this class.
|
||||||
- [error.message](./class-error.md#errormessage)
|
|
||||||
- [error.name](./class-error.md#errorname)
|
|
||||||
- [error.stack](./class-error.md#errorstack)
|
|
||||||
|
|
||||||
## property: Error.message
|
## property: Error.message
|
||||||
* since: v1.11
|
* since: v1.11
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,77 @@ FormData form = FormData.create()
|
||||||
page.request().post("http://localhost/submit", RequestOptions.create().setForm(form));
|
page.request().post("http://localhost/submit", RequestOptions.create().setForm(form));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## method: FormData.append
|
||||||
|
* since: v1.44
|
||||||
|
- returns: <[FormData]>
|
||||||
|
|
||||||
|
Appends a new value onto an existing key inside a FormData object, or adds the key if it
|
||||||
|
does not already exist. File values can be passed either as `Path` or as `FilePayload`.
|
||||||
|
Multiple fields with the same name can be added.
|
||||||
|
|
||||||
|
The difference between [`method: FormData.set`] and [`method: FormData.append`] is that if the specified key already exists,
|
||||||
|
[`method: FormData.set`] will overwrite all existing values with the new one, whereas [`method: FormData.append`] will append
|
||||||
|
the new value onto the end of the existing set of values.
|
||||||
|
|
||||||
|
```java
|
||||||
|
import com.microsoft.playwright.options.FormData;
|
||||||
|
...
|
||||||
|
FormData form = FormData.create()
|
||||||
|
// Only name and value are set.
|
||||||
|
.append("firstName", "John")
|
||||||
|
// Name and value are set, filename and Content-Type are inferred from the file path.
|
||||||
|
.append("attachment", Paths.get("pic.jpg"))
|
||||||
|
// Name, value, filename and Content-Type are set.
|
||||||
|
.append("attachment", new FilePayload("table.csv", "text/csv", Files.readAllBytes(Paths.get("my-tble.csv"))));
|
||||||
|
page.request().post("http://localhost/submit", RequestOptions.create().setForm(form));
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var multipart = Context.APIRequest.CreateFormData();
|
||||||
|
// Only name and value are set.
|
||||||
|
multipart.Append("firstName", "John");
|
||||||
|
// Name, value, filename and Content-Type are set.
|
||||||
|
multipart.Append("attachment", new FilePayload()
|
||||||
|
{
|
||||||
|
Name = "pic.jpg",
|
||||||
|
MimeType = "image/jpeg",
|
||||||
|
Buffer = File.ReadAllBytes("john.jpg")
|
||||||
|
});
|
||||||
|
// Name, value, filename and Content-Type are set.
|
||||||
|
multipart.Append("attachment", new FilePayload()
|
||||||
|
{
|
||||||
|
Name = "table.csv",
|
||||||
|
MimeType = "text/csv",
|
||||||
|
Buffer = File.ReadAllBytes("my-tble.csv")
|
||||||
|
});
|
||||||
|
await Page.APIRequest.PostAsync("https://localhost/submit", new() { Multipart = multipart });
|
||||||
|
```
|
||||||
|
|
||||||
|
### param: FormData.append.name
|
||||||
|
* since: v1.44
|
||||||
|
- `name` <[string]>
|
||||||
|
|
||||||
|
Field name.
|
||||||
|
|
||||||
|
### param: FormData.append.value
|
||||||
|
* since: v1.44
|
||||||
|
- `value` <[string]|[boolean]|[int]|[Path]|[Object]>
|
||||||
|
- `name` <[string]> File name
|
||||||
|
- `mimeType` <[string]> File type
|
||||||
|
- `buffer` <[Buffer]> File content
|
||||||
|
|
||||||
|
Field value.
|
||||||
|
|
||||||
|
### param: FormData.append.value
|
||||||
|
* since: v1.44
|
||||||
|
* langs: csharp
|
||||||
|
- `value` <[string]|[boolean]|[int]|[Object]>
|
||||||
|
- `name` <[string]> File name
|
||||||
|
- `mimeType` <[string]> File type
|
||||||
|
- `buffer` <[Buffer]> File content
|
||||||
|
|
||||||
|
Field value.
|
||||||
|
|
||||||
## method: FormData.create
|
## method: FormData.create
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
* langs: java
|
* langs: java
|
||||||
|
|
@ -36,7 +107,7 @@ FormData form = FormData.create()
|
||||||
// Name and value are set, filename and Content-Type are inferred from the file path.
|
// Name and value are set, filename and Content-Type are inferred from the file path.
|
||||||
.set("profilePicture1", Paths.get("john.jpg"))
|
.set("profilePicture1", Paths.get("john.jpg"))
|
||||||
// Name, value, filename and Content-Type are set.
|
// Name, value, filename and Content-Type are set.
|
||||||
.set("profilePicture2", new FilePayload("john.jpg", "image/jpeg", Files.readAllBytes(Paths.get("john.jpg"))));
|
.set("profilePicture2", new FilePayload("john.jpg", "image/jpeg", Files.readAllBytes(Paths.get("john.jpg"))))
|
||||||
.set("age", 30);
|
.set("age", 30);
|
||||||
page.request().post("http://localhost/submit", RequestOptions.create().setForm(form));
|
page.request().post("http://localhost/submit", RequestOptions.create().setForm(form));
|
||||||
```
|
```
|
||||||
|
|
@ -52,6 +123,7 @@ multipart.Set("profilePicture", new FilePayload()
|
||||||
MimeType = "image/jpeg",
|
MimeType = "image/jpeg",
|
||||||
Buffer = File.ReadAllBytes("john.jpg")
|
Buffer = File.ReadAllBytes("john.jpg")
|
||||||
});
|
});
|
||||||
|
multipart.Set("age", 30);
|
||||||
await Page.APIRequest.PostAsync("https://localhost/submit", new() { Multipart = multipart });
|
await Page.APIRequest.PostAsync("https://localhost/submit", new() { Multipart = multipart });
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1030,7 +1030,8 @@ Attribute name to get the value for.
|
||||||
|
|
||||||
%%-template-locator-get-by-role-%%
|
%%-template-locator-get-by-role-%%
|
||||||
|
|
||||||
### param: Frame.getByRole.role = %%-locator-get-by-role-role-%%
|
### param: Frame.getByRole.role = %%-get-by-role-to-have-role-role-%%
|
||||||
|
* since: v1.27
|
||||||
|
|
||||||
### option: Frame.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
### option: Frame.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
||||||
* since: v1.27
|
* since: v1.27
|
||||||
|
|
@ -1393,7 +1394,8 @@ generate the text for. A superset of the [`param: key`] values can be found
|
||||||
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
||||||
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
||||||
|
|
||||||
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
||||||
|
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
||||||
|
|
||||||
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
||||||
|
|
||||||
|
|
@ -1970,6 +1972,10 @@ Waits for the required load state to be reached.
|
||||||
This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
|
This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
|
||||||
when this method is called. If current document has already reached the required state, resolves immediately.
|
when this method is called. If current document has already reached the required state, resolves immediately.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Most of the time, this method is not needed because Playwright [auto-waits before every action](../actionability.md).
|
||||||
|
:::
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
|
||||||
|
|
@ -74,27 +74,12 @@ await page.FrameLocator(".result-frame").First.getByRole(AriaRole.Button).ClickA
|
||||||
|
|
||||||
**Converting Locator to FrameLocator**
|
**Converting Locator to FrameLocator**
|
||||||
|
|
||||||
If you have a [Locator] object pointing to an `iframe` it can be converted to [FrameLocator] using [`:scope`](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) CSS selector:
|
If you have a [Locator] object pointing to an `iframe` it can be converted to [FrameLocator] using [`method: Locator.contentFrame`].
|
||||||
|
|
||||||
```js
|
**Converting FrameLocator to Locator**
|
||||||
const frameLocator = locator.frameLocator(':scope');
|
|
||||||
```
|
|
||||||
|
|
||||||
```java
|
If you have a [FrameLocator] object it can be converted to [Locator] pointing to the same `iframe` using [`method: FrameLocator.owner`].
|
||||||
Locator frameLocator = locator.frameLocator(':scope');
|
|
||||||
```
|
|
||||||
|
|
||||||
```python async
|
|
||||||
frameLocator = locator.frame_locator(":scope")
|
|
||||||
```
|
|
||||||
|
|
||||||
```python sync
|
|
||||||
frameLocator = locator.frame_locator(":scope")
|
|
||||||
```
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var frameLocator = locator.FrameLocator(":scope");
|
|
||||||
```
|
|
||||||
|
|
||||||
## method: FrameLocator.first
|
## method: FrameLocator.first
|
||||||
* since: v1.17
|
* since: v1.17
|
||||||
|
|
@ -148,7 +133,8 @@ in that iframe.
|
||||||
|
|
||||||
%%-template-locator-get-by-role-%%
|
%%-template-locator-get-by-role-%%
|
||||||
|
|
||||||
### param: FrameLocator.getByRole.role = %%-locator-get-by-role-role-%%
|
### param: FrameLocator.getByRole.role = %%-get-by-role-to-have-role-role-%%
|
||||||
|
* since: v1.27
|
||||||
|
|
||||||
### option: FrameLocator.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
### option: FrameLocator.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
||||||
* since: v1.27
|
* since: v1.27
|
||||||
|
|
@ -217,3 +203,51 @@ Returns locator to the n-th matching frame. It's zero based, `nth(0)` selects th
|
||||||
### param: FrameLocator.nth.index
|
### param: FrameLocator.nth.index
|
||||||
* since: v1.17
|
* since: v1.17
|
||||||
- `index` <[int]>
|
- `index` <[int]>
|
||||||
|
|
||||||
|
## method: FrameLocator.owner
|
||||||
|
* since: v1.43
|
||||||
|
- returns: <[Locator]>
|
||||||
|
|
||||||
|
Returns a [Locator] object pointing to the same `iframe` as this frame locator.
|
||||||
|
|
||||||
|
Useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
|
||||||
|
|
||||||
|
For a reverse operation, use [`method: Locator.contentFrame`].
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const frameLocator = page.frameLocator('iframe[name="embedded"]');
|
||||||
|
// ...
|
||||||
|
const locator = frameLocator.owner();
|
||||||
|
await expect(locator).toBeVisible();
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
FrameLocator frameLocator = page.frameLocator("iframe[name=\"embedded\"]");
|
||||||
|
// ...
|
||||||
|
Locator locator = frameLocator.owner();
|
||||||
|
assertThat(locator).isVisible();
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
frame_locator = page.frame_locator("iframe[name=\"embedded\"]")
|
||||||
|
# ...
|
||||||
|
locator = frame_locator.owner
|
||||||
|
await expect(locator).to_be_visible()
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
frame_locator = page.frame_locator("iframe[name=\"embedded\"]")
|
||||||
|
# ...
|
||||||
|
locator = frame_locator.owner
|
||||||
|
expect(locator).to_be_visible()
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var frameLocator = Page.FrameLocator("iframe[name=\"embedded\"]");
|
||||||
|
// ...
|
||||||
|
var locator = frameLocator.Owner;
|
||||||
|
await Expect(locator).ToBeVisibleAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,8 @@ generate the text for. A superset of the [`param: key`] values can be found
|
||||||
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
||||||
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
||||||
|
|
||||||
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
||||||
|
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
||||||
|
|
||||||
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
||||||
|
|
||||||
|
|
@ -227,7 +228,8 @@ generate the text for. A superset of the [`param: key`] values can be found
|
||||||
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
||||||
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
||||||
|
|
||||||
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
||||||
|
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
||||||
|
|
||||||
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ foreach (var li in await page.GetByRole("listitem").AllAsync())
|
||||||
|
|
||||||
Returns an array of `node.innerText` values for all matching nodes.
|
Returns an array of `node.innerText` values for all matching nodes.
|
||||||
|
|
||||||
:::caution Asserting text
|
:::warning[Asserting text]
|
||||||
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ var texts = await page.GetByRole(AriaRole.Link).AllInnerTextsAsync();
|
||||||
|
|
||||||
Returns an array of `node.textContent` values for all matching nodes.
|
Returns an array of `node.textContent` values for all matching nodes.
|
||||||
|
|
||||||
:::caution Asserting text
|
:::warning[Asserting text]
|
||||||
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -443,7 +443,7 @@ await page.Locator("canvas").ClickAsync(new() {
|
||||||
|
|
||||||
Returns the number of elements matching the locator.
|
Returns the number of elements matching the locator.
|
||||||
|
|
||||||
:::caution Asserting count
|
:::warning[Asserting count]
|
||||||
If you need to assert the number of elements on the page, prefer [`method: LocatorAssertions.toHaveCount`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert the number of elements on the page, prefer [`method: LocatorAssertions.toHaveCount`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -747,6 +747,53 @@ Resolves given locator to the first matching DOM element. If there are no matchi
|
||||||
|
|
||||||
Resolves given locator to all matching DOM elements. If there are no matching elements, returns an empty list.
|
Resolves given locator to all matching DOM elements. If there are no matching elements, returns an empty list.
|
||||||
|
|
||||||
|
## method: Locator.contentFrame
|
||||||
|
* since: v1.43
|
||||||
|
- returns: <[FrameLocator]>
|
||||||
|
|
||||||
|
Returns a [FrameLocator] object pointing to the same `iframe` as this locator.
|
||||||
|
|
||||||
|
Useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
|
||||||
|
|
||||||
|
For a reverse operation, use [`method: FrameLocator.owner`].
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const locator = page.locator('iframe[name="embedded"]');
|
||||||
|
// ...
|
||||||
|
const frameLocator = locator.contentFrame();
|
||||||
|
await frameLocator.getByRole('button').click();
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
Locator locator = page.locator("iframe[name=\"embedded\"]");
|
||||||
|
// ...
|
||||||
|
FrameLocator frameLocator = locator.contentFrame();
|
||||||
|
frameLocator.getByRole(AriaRole.BUTTON).click();
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
locator = page.locator("iframe[name=\"embedded\"]")
|
||||||
|
# ...
|
||||||
|
frame_locator = locator.content_frame
|
||||||
|
await frame_locator.get_by_role("button").click()
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
locator = page.locator("iframe[name=\"embedded\"]")
|
||||||
|
# ...
|
||||||
|
frame_locator = locator.content_frame
|
||||||
|
frame_locator.get_by_role("button").click()
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var locator = Page.Locator("iframe[name=\"embedded\"]");
|
||||||
|
// ...
|
||||||
|
var frameLocator = locator.ContentFrame;
|
||||||
|
await frameLocator.GetByRole(AriaRole.Button).ClickAsync();
|
||||||
|
```
|
||||||
|
|
||||||
## async method: Locator.evaluate
|
## async method: Locator.evaluate
|
||||||
* since: v1.14
|
* since: v1.14
|
||||||
- returns: <[Serializable]>
|
- returns: <[Serializable]>
|
||||||
|
|
@ -1074,7 +1121,7 @@ await locator.ClickAsync();
|
||||||
|
|
||||||
Returns the matching element's attribute value.
|
Returns the matching element's attribute value.
|
||||||
|
|
||||||
:::caution Asserting attributes
|
:::warning[Asserting attributes]
|
||||||
If you need to assert an element's attribute, prefer [`method: LocatorAssertions.toHaveAttribute`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert an element's attribute, prefer [`method: LocatorAssertions.toHaveAttribute`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1126,7 +1173,8 @@ Attribute name to get the value for.
|
||||||
|
|
||||||
%%-template-locator-get-by-role-%%
|
%%-template-locator-get-by-role-%%
|
||||||
|
|
||||||
### param: Locator.getByRole.role = %%-locator-get-by-role-role-%%
|
### param: Locator.getByRole.role = %%-get-by-role-to-have-role-role-%%
|
||||||
|
* since: v1.27
|
||||||
|
|
||||||
### option: Locator.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
### option: Locator.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
||||||
* since: v1.27
|
* since: v1.27
|
||||||
|
|
@ -1246,7 +1294,7 @@ Returns the [`element.innerHTML`](https://developer.mozilla.org/en-US/docs/Web/A
|
||||||
|
|
||||||
Returns the [`element.innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText).
|
Returns the [`element.innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText).
|
||||||
|
|
||||||
:::caution Asserting text
|
:::warning[Asserting text]
|
||||||
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1262,7 +1310,7 @@ If you need to assert text on the page, prefer [`method: LocatorAssertions.toHav
|
||||||
|
|
||||||
Returns the value for the matching `<input>` or `<textarea>` or `<select>` element.
|
Returns the value for the matching `<input>` or `<textarea>` or `<select>` element.
|
||||||
|
|
||||||
:::caution Asserting value
|
:::warning[Asserting value]
|
||||||
If you need to assert input value, prefer [`method: LocatorAssertions.toHaveValue`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert input value, prefer [`method: LocatorAssertions.toHaveValue`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1304,7 +1352,7 @@ Throws elements that are not an input, textarea or a select. However, if the ele
|
||||||
|
|
||||||
Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
|
Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
|
||||||
|
|
||||||
:::caution Asserting checked state
|
:::warning[Asserting checked state]
|
||||||
If you need to assert that checkbox is checked, prefer [`method: LocatorAssertions.toBeChecked`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert that checkbox is checked, prefer [`method: LocatorAssertions.toBeChecked`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1342,7 +1390,7 @@ var isChecked = await page.GetByRole(AriaRole.Checkbox).IsCheckedAsync();
|
||||||
|
|
||||||
Returns whether the element is disabled, the opposite of [enabled](../actionability.md#enabled).
|
Returns whether the element is disabled, the opposite of [enabled](../actionability.md#enabled).
|
||||||
|
|
||||||
:::caution Asserting disabled state
|
:::warning[Asserting disabled state]
|
||||||
If you need to assert that an element is disabled, prefer [`method: LocatorAssertions.toBeDisabled`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert that an element is disabled, prefer [`method: LocatorAssertions.toBeDisabled`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1380,7 +1428,7 @@ Boolean disabled = await page.GetByRole(AriaRole.Button).IsDisabledAsync();
|
||||||
|
|
||||||
Returns whether the element is [editable](../actionability.md#editable).
|
Returns whether the element is [editable](../actionability.md#editable).
|
||||||
|
|
||||||
:::caution Asserting editable state
|
:::warning[Asserting editable state]
|
||||||
If you need to assert that an element is editable, prefer [`method: LocatorAssertions.toBeEditable`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert that an element is editable, prefer [`method: LocatorAssertions.toBeEditable`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1418,7 +1466,7 @@ Boolean editable = await page.GetByRole(AriaRole.Textbox).IsEditableAsync();
|
||||||
|
|
||||||
Returns whether the element is [enabled](../actionability.md#enabled).
|
Returns whether the element is [enabled](../actionability.md#enabled).
|
||||||
|
|
||||||
:::caution Asserting enabled state
|
:::warning[Asserting enabled state]
|
||||||
If you need to assert that an element is enabled, prefer [`method: LocatorAssertions.toBeEnabled`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert that an element is enabled, prefer [`method: LocatorAssertions.toBeEnabled`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1456,7 +1504,7 @@ Boolean enabled = await page.GetByRole(AriaRole.Button).IsEnabledAsync();
|
||||||
|
|
||||||
Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible).
|
Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible).
|
||||||
|
|
||||||
:::caution Asserting visibility
|
:::warning[Asserting visibility]
|
||||||
If you need to assert that element is hidden, prefer [`method: LocatorAssertions.toBeHidden`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert that element is hidden, prefer [`method: LocatorAssertions.toBeHidden`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1493,7 +1541,7 @@ Boolean hidden = await page.GetByRole(AriaRole.Button).IsHiddenAsync();
|
||||||
|
|
||||||
Returns whether the element is [visible](../actionability.md#visible).
|
Returns whether the element is [visible](../actionability.md#visible).
|
||||||
|
|
||||||
:::caution Asserting visibility
|
:::warning[Asserting visibility]
|
||||||
If you need to assert that element is visible, prefer [`method: LocatorAssertions.toBeVisible`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert that element is visible, prefer [`method: LocatorAssertions.toBeVisible`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -1713,7 +1761,8 @@ generate the text for. A superset of the [`param: key`] values can be found
|
||||||
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
||||||
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
||||||
|
|
||||||
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
||||||
|
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
||||||
|
|
||||||
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
||||||
|
|
||||||
|
|
@ -2277,7 +2326,7 @@ When all steps combined have not finished during the specified [`option: timeout
|
||||||
|
|
||||||
Returns the [`node.textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent).
|
Returns the [`node.textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent).
|
||||||
|
|
||||||
:::caution Asserting text
|
:::warning[Asserting text]
|
||||||
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,11 +211,8 @@ The opposite of [`method: LocatorAssertions.toContainText`].
|
||||||
|
|
||||||
Expected substring or RegExp or a list of those.
|
Expected substring or RegExp or a list of those.
|
||||||
|
|
||||||
### option: LocatorAssertions.NotToContainText.ignoreCase
|
### option: LocatorAssertions.NotToContainText.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
* since: v1.23
|
* since: v1.23
|
||||||
- `ignoreCase` <[boolean]>
|
|
||||||
|
|
||||||
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
|
||||||
|
|
||||||
### option: LocatorAssertions.NotToContainText.useInnerText
|
### option: LocatorAssertions.NotToContainText.useInnerText
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
@ -226,6 +223,45 @@ Whether to use `element.innerText` instead of `element.textContent` when retriev
|
||||||
### option: LocatorAssertions.NotToContainText.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.NotToContainText.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
|
|
||||||
|
## async method: LocatorAssertions.NotToHaveAccessibleDescription
|
||||||
|
* since: v1.44
|
||||||
|
* langs: python
|
||||||
|
|
||||||
|
The opposite of [`method: LocatorAssertions.toHaveAccessibleDescription`].
|
||||||
|
|
||||||
|
### param: LocatorAssertions.NotToHaveAccessibleDescription.name
|
||||||
|
* since: v1.44
|
||||||
|
- `name` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Expected accessible name.
|
||||||
|
|
||||||
|
### option: LocatorAssertions.NotToHaveAccessibleDescription.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.NotToHaveAccessibleDescription.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
|
||||||
|
## async method: LocatorAssertions.NotToHaveAccessibleName
|
||||||
|
* since: v1.44
|
||||||
|
* langs: python
|
||||||
|
|
||||||
|
The opposite of [`method: LocatorAssertions.toHaveAccessibleName`].
|
||||||
|
|
||||||
|
### param: LocatorAssertions.NotToHaveAccessibleName.name
|
||||||
|
* since: v1.44
|
||||||
|
- `name` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Expected accessible name.
|
||||||
|
|
||||||
|
### option: LocatorAssertions.NotToHaveAccessibleName.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.NotToHaveAccessibleName.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
|
||||||
## async method: LocatorAssertions.NotToHaveAttribute
|
## async method: LocatorAssertions.NotToHaveAttribute
|
||||||
* since: v1.20
|
* since: v1.20
|
||||||
* langs: python
|
* langs: python
|
||||||
|
|
@ -244,11 +280,8 @@ Attribute name.
|
||||||
|
|
||||||
Expected attribute value.
|
Expected attribute value.
|
||||||
|
|
||||||
### option: LocatorAssertions.NotToHaveAttribute.ignoreCase
|
### option: LocatorAssertions.NotToHaveAttribute.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
* since: v1.40
|
* since: v1.40
|
||||||
- `ignoreCase` <[boolean]>
|
|
||||||
|
|
||||||
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
|
||||||
|
|
||||||
### option: LocatorAssertions.NotToHaveAttribute.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.NotToHaveAttribute.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
@ -340,6 +373,23 @@ Property value.
|
||||||
### option: LocatorAssertions.NotToHaveJSProperty.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.NotToHaveJSProperty.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
|
|
||||||
|
## async method: LocatorAssertions.NotToHaveRole
|
||||||
|
* since: v1.44
|
||||||
|
* langs: python
|
||||||
|
|
||||||
|
The opposite of [`method: LocatorAssertions.toHaveRole`].
|
||||||
|
|
||||||
|
### param: LocatorAssertions.NotToHaveRole.name
|
||||||
|
* since: v1.44
|
||||||
|
- `name` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Expected accessible name.
|
||||||
|
|
||||||
|
### option: LocatorAssertions.NotToHaveRole.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
|
||||||
## async method: LocatorAssertions.NotToHaveText
|
## async method: LocatorAssertions.NotToHaveText
|
||||||
* since: v1.20
|
* since: v1.20
|
||||||
* langs: python
|
* langs: python
|
||||||
|
|
@ -352,11 +402,8 @@ The opposite of [`method: LocatorAssertions.toHaveText`].
|
||||||
|
|
||||||
Expected string or RegExp or a list of those.
|
Expected string or RegExp or a list of those.
|
||||||
|
|
||||||
### option: LocatorAssertions.NotToHaveText.ignoreCase
|
### option: LocatorAssertions.NotToHaveText.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
* since: v1.23
|
* since: v1.23
|
||||||
- `ignoreCase` <[boolean]>
|
|
||||||
|
|
||||||
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
|
||||||
|
|
||||||
### option: LocatorAssertions.NotToHaveText.useInnerText
|
### option: LocatorAssertions.NotToHaveText.useInnerText
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
@ -1089,11 +1136,8 @@ Expected substring or RegExp or a list of those.
|
||||||
|
|
||||||
Expected substring or RegExp or a list of those.
|
Expected substring or RegExp or a list of those.
|
||||||
|
|
||||||
### option: LocatorAssertions.toContainText.ignoreCase
|
### option: LocatorAssertions.toContainText.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
* since: v1.23
|
* since: v1.23
|
||||||
- `ignoreCase` <[boolean]>
|
|
||||||
|
|
||||||
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
|
||||||
|
|
||||||
### option: LocatorAssertions.toContainText.useInnerText
|
### option: LocatorAssertions.toContainText.useInnerText
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
@ -1107,6 +1151,107 @@ Whether to use `element.innerText` instead of `element.textContent` when retriev
|
||||||
### option: LocatorAssertions.toContainText.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.toContainText.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
|
|
||||||
|
## async method: LocatorAssertions.toHaveAccessibleDescription
|
||||||
|
* since: v1.44
|
||||||
|
* langs:
|
||||||
|
- alias-java: hasAccessibleDescription
|
||||||
|
|
||||||
|
Ensures the [Locator] points to an element with a given [accessible description](https://w3c.github.io/accname/#dfn-accessible-description).
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const locator = page.getByTestId('save-button');
|
||||||
|
await expect(locator).toHaveAccessibleDescription('Save results to disk');
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
Locator locator = page.getByTestId("save-button");
|
||||||
|
assertThat(locator).hasAccessibleDescription("Save results to disk");
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
locator = page.get_by_test_id("save-button")
|
||||||
|
await expect(locator).to_have_accessible_description("Save results to disk")
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
locator = page.get_by_test_id("save-button")
|
||||||
|
expect(locator).to_have_accessible_description("Save results to disk")
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var locator = Page.GetByTestId("save-button");
|
||||||
|
await Expect(locator).toHaveAccessibleDescriptionAsync("Save results to disk");
|
||||||
|
```
|
||||||
|
|
||||||
|
### param: LocatorAssertions.toHaveAccessibleDescription.description
|
||||||
|
* since: v1.44
|
||||||
|
- `description` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Expected accessible description.
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveAccessibleDescription.timeout = %%-js-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveAccessibleDescription.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveAccessibleDescription.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
|
||||||
|
## async method: LocatorAssertions.toHaveAccessibleName
|
||||||
|
* since: v1.44
|
||||||
|
* langs:
|
||||||
|
- alias-java: hasAccessibleName
|
||||||
|
|
||||||
|
Ensures the [Locator] points to an element with a given [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const locator = page.getByTestId('save-button');
|
||||||
|
await expect(locator).toHaveAccessibleName('Save to disk');
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
Locator locator = page.getByTestId("save-button");
|
||||||
|
assertThat(locator).hasAccessibleName("Save to disk");
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
locator = page.get_by_test_id("save-button")
|
||||||
|
await expect(locator).to_have_accessible_name("Save to disk")
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
locator = page.get_by_test_id("save-button")
|
||||||
|
expect(locator).to_have_accessible_name("Save to disk")
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var locator = Page.GetByTestId("save-button");
|
||||||
|
await Expect(locator).toHaveAccessibleNameAsync("Save to disk");
|
||||||
|
```
|
||||||
|
|
||||||
|
### param: LocatorAssertions.toHaveAccessibleName.name
|
||||||
|
* since: v1.44
|
||||||
|
- `name` <[string]|[RegExp]>
|
||||||
|
|
||||||
|
Expected accessible name.
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveAccessibleName.timeout = %%-js-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveAccessibleName.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveAccessibleName.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
|
||||||
## async method: LocatorAssertions.toHaveAttribute
|
## async method: LocatorAssertions.toHaveAttribute
|
||||||
* since: v1.20
|
* since: v1.20
|
||||||
* langs:
|
* langs:
|
||||||
|
|
@ -1162,11 +1307,8 @@ Expected attribute value.
|
||||||
### option: LocatorAssertions.toHaveAttribute.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.toHaveAttribute.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
### option: LocatorAssertions.toHaveAttribute.ignoreCase
|
### option: LocatorAssertions.toHaveAttribute.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
* since: v1.40
|
* since: v1.40
|
||||||
- `ignoreCase` <[boolean]>
|
|
||||||
|
|
||||||
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
|
||||||
|
|
||||||
## async method: LocatorAssertions.toHaveAttribute#2
|
## async method: LocatorAssertions.toHaveAttribute#2
|
||||||
* since: v1.39
|
* since: v1.39
|
||||||
|
|
@ -1504,6 +1646,53 @@ Property value.
|
||||||
### option: LocatorAssertions.toHaveJSProperty.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: LocatorAssertions.toHaveJSProperty.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
|
|
||||||
|
## async method: LocatorAssertions.toHaveRole
|
||||||
|
* since: v1.44
|
||||||
|
* langs:
|
||||||
|
- alias-java: hasRole
|
||||||
|
|
||||||
|
Ensures the [Locator] points to an element with a given [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles).
|
||||||
|
|
||||||
|
Note that role is matched as a string, disregarding the ARIA role hierarchy. For example, asserting a superclass role `"checkbox"` on an element with a subclass role `"switch"` will fail.
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const locator = page.getByTestId('save-button');
|
||||||
|
await expect(locator).toHaveRole('button');
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
Locator locator = page.getByTestId("save-button");
|
||||||
|
assertThat(locator).hasRole(AriaRole.BUTTON);
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
locator = page.get_by_test_id("save-button")
|
||||||
|
await expect(locator).to_have_role("button")
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
locator = page.get_by_test_id("save-button")
|
||||||
|
expect(locator).to_have_role("button")
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var locator = Page.GetByTestId("save-button");
|
||||||
|
await Expect(locator).ToHaveRoleAsync(AriaRole.Button);
|
||||||
|
```
|
||||||
|
|
||||||
|
### param: LocatorAssertions.toHaveRole.role = %%-get-by-role-to-have-role-role-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveRole.timeout = %%-js-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
### option: LocatorAssertions.toHaveRole.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
|
||||||
## async method: LocatorAssertions.toHaveScreenshot#1
|
## async method: LocatorAssertions.toHaveScreenshot#1
|
||||||
* since: v1.23
|
* since: v1.23
|
||||||
* langs: js
|
* langs: js
|
||||||
|
|
@ -1769,11 +1958,8 @@ Expected string or RegExp or a list of those.
|
||||||
|
|
||||||
Expected string or RegExp or a list of those.
|
Expected string or RegExp or a list of those.
|
||||||
|
|
||||||
### option: LocatorAssertions.toHaveText.ignoreCase
|
### option: LocatorAssertions.toHaveText.ignoreCase = %%-assertions-ignore-case-%%
|
||||||
* since: v1.23
|
* since: v1.23
|
||||||
- `ignoreCase` <[boolean]>
|
|
||||||
|
|
||||||
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
|
||||||
|
|
||||||
### option: LocatorAssertions.toHaveText.useInnerText
|
### option: LocatorAssertions.toHaveText.useInnerText
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
|
||||||
(async () => {
|
(async () => {
|
||||||
const browser = await chromium.launch({
|
const browser = await chromium.launch({
|
||||||
logger: {
|
logger: {
|
||||||
isEnabled: (name, severity) => name === 'browser',
|
isEnabled: (name, severity) => name === 'api',
|
||||||
log: (name, severity, message, args) => console.log(`${name} ${message}`)
|
log: (name, severity, message, args) => console.log(`${name} ${message}`)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -290,9 +290,7 @@ Emitted when a JavaScript dialog appears, such as `alert`, `prompt`, `confirm` o
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
page.on('dialog', dialog => {
|
page.on('dialog', dialog => dialog.accept());
|
||||||
dialog.accept();
|
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
@ -448,7 +446,7 @@ Emitted when the page opens a new tab or window. This event is emitted in additi
|
||||||
|
|
||||||
The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
|
The earliest moment that page is available is when it has navigated to the initial url. For example, when opening a
|
||||||
popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is
|
popup with `window.open('http://example.com')`, this event will fire when the network request to "http://example.com" is
|
||||||
done and its response has started loading in the popup.
|
done and its response has started loading in the popup. If you would like to route/listen to this network request, use [`method: BrowserContext.route`] and [`event: BrowserContext.request`] respectively instead of similar methods on the [Page].
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Start waiting for popup before clicking. Note no await.
|
// Start waiting for popup before clicking. Note no await.
|
||||||
|
|
@ -2342,7 +2340,8 @@ Attribute name to get the value for.
|
||||||
|
|
||||||
%%-template-locator-get-by-role-%%
|
%%-template-locator-get-by-role-%%
|
||||||
|
|
||||||
### param: Page.getByRole.role = %%-locator-get-by-role-role-%%
|
### param: Page.getByRole.role = %%-get-by-role-to-have-role-role-%%
|
||||||
|
* since: v1.27
|
||||||
|
|
||||||
### option: Page.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
### option: Page.getByRole.-inline- = %%-locator-get-by-role-option-list-v1.27-%%
|
||||||
* since: v1.27
|
* since: v1.27
|
||||||
|
|
@ -3014,7 +3013,8 @@ generate the text for. A superset of the [`param: key`] values can be found
|
||||||
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
||||||
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
||||||
|
|
||||||
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
|
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
||||||
|
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
||||||
|
|
||||||
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
Holding down `Shift` will type the text that corresponds to the [`param: key`] in the upper case.
|
||||||
|
|
||||||
|
|
@ -3146,17 +3146,14 @@ return value resolves to `[]`.
|
||||||
## async method: Page.addLocatorHandler
|
## async method: Page.addLocatorHandler
|
||||||
* since: v1.42
|
* since: v1.42
|
||||||
|
|
||||||
:::warning Experimental
|
|
||||||
This method is experimental and its behavior may change in the upcoming releases.
|
|
||||||
:::
|
|
||||||
|
|
||||||
When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making them tricky to handle in automated tests.
|
When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making them tricky to handle in automated tests.
|
||||||
|
|
||||||
This method lets you set up a special function, called a handler, that activates when it detects that overlay is visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
|
This method lets you set up a special function, called a handler, that activates when it detects that overlay is visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
|
||||||
|
|
||||||
Things to keep in mind:
|
Things to keep in mind:
|
||||||
* When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as a part of your normal test flow, instead of using [`method: Page.addLocatorHandler`].
|
* When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as a part of your normal test flow, instead of using [`method: Page.addLocatorHandler`].
|
||||||
* Playwright checks for the overlay every time before executing or retrying an action that requires an [actionability check](../actionability.md), or before performing an auto-waiting assertion check. When overlay is visible, Playwright calls the handler first, and then proceeds with the action/assertion.
|
* Playwright checks for the overlay every time before executing or retrying an action that requires an [actionability check](../actionability.md), or before performing an auto-waiting assertion check. When overlay is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the handler is only called when you perform an action/assertion - if the overlay becomes visible but you don't perform any actions, the handler will not be triggered.
|
||||||
|
* After executing the handler, Playwright will ensure that overlay that triggered the handler is not visible anymore. You can opt-out of this behavior with [`option: noWaitAfter`].
|
||||||
* The execution time of the handler counts towards the timeout of the action/assertion that executed the handler. If your handler takes too long, it might cause timeouts.
|
* The execution time of the handler counts towards the timeout of the action/assertion that executed the handler. If your handler takes too long, it might cause timeouts.
|
||||||
* You can register multiple handlers. However, only a single handler will be running at a time. Make sure the actions within a handler don't depend on another handler.
|
* You can register multiple handlers. However, only a single handler will be running at a time. Make sure the actions within a handler don't depend on another handler.
|
||||||
|
|
||||||
|
|
@ -3286,13 +3283,13 @@ await page.GotoAsync("https://example.com");
|
||||||
await page.GetByRole("button", new() { Name = "Start here" }).ClickAsync();
|
await page.GetByRole("button", new() { Name = "Start here" }).ClickAsync();
|
||||||
```
|
```
|
||||||
|
|
||||||
An example with a custom callback on every actionability check. It uses a `<body>` locator that is always visible, so the handler is called before every actionability check:
|
An example with a custom callback on every actionability check. It uses a `<body>` locator that is always visible, so the handler is called before every actionability check. It is important to specify [`option: noWaitAfter`], because the handler does not hide the `<body>` element.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Setup the handler.
|
// Setup the handler.
|
||||||
await page.addLocatorHandler(page.locator('body'), async () => {
|
await page.addLocatorHandler(page.locator('body'), async () => {
|
||||||
await page.evaluate(() => window.removeObstructionsForTestIfNeeded());
|
await page.evaluate(() => window.removeObstructionsForTestIfNeeded());
|
||||||
});
|
}, { noWaitAfter: true });
|
||||||
|
|
||||||
// Write the test as usual.
|
// Write the test as usual.
|
||||||
await page.goto('https://example.com');
|
await page.goto('https://example.com');
|
||||||
|
|
@ -3303,7 +3300,7 @@ await page.getByRole('button', { name: 'Start here' }).click();
|
||||||
// Setup the handler.
|
// Setup the handler.
|
||||||
page.addLocatorHandler(page.locator("body")), () => {
|
page.addLocatorHandler(page.locator("body")), () => {
|
||||||
page.evaluate("window.removeObstructionsForTestIfNeeded()");
|
page.evaluate("window.removeObstructionsForTestIfNeeded()");
|
||||||
});
|
}, new Page.AddLocatorHandlerOptions.setNoWaitAfter(true));
|
||||||
|
|
||||||
// Write the test as usual.
|
// Write the test as usual.
|
||||||
page.goto("https://example.com");
|
page.goto("https://example.com");
|
||||||
|
|
@ -3314,7 +3311,7 @@ page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
|
||||||
# Setup the handler.
|
# Setup the handler.
|
||||||
def handler():
|
def handler():
|
||||||
page.evaluate("window.removeObstructionsForTestIfNeeded()")
|
page.evaluate("window.removeObstructionsForTestIfNeeded()")
|
||||||
page.add_locator_handler(page.locator("body"), handler)
|
page.add_locator_handler(page.locator("body"), handler, no_wait_after=True)
|
||||||
|
|
||||||
# Write the test as usual.
|
# Write the test as usual.
|
||||||
page.goto("https://example.com")
|
page.goto("https://example.com")
|
||||||
|
|
@ -3325,7 +3322,7 @@ page.get_by_role("button", name="Start here").click()
|
||||||
# Setup the handler.
|
# Setup the handler.
|
||||||
def handler():
|
def handler():
|
||||||
await page.evaluate("window.removeObstructionsForTestIfNeeded()")
|
await page.evaluate("window.removeObstructionsForTestIfNeeded()")
|
||||||
await page.add_locator_handler(page.locator("body"), handler)
|
await page.add_locator_handler(page.locator("body"), handler, no_wait_after=True)
|
||||||
|
|
||||||
# Write the test as usual.
|
# Write the test as usual.
|
||||||
await page.goto("https://example.com")
|
await page.goto("https://example.com")
|
||||||
|
|
@ -3336,13 +3333,45 @@ await page.get_by_role("button", name="Start here").click()
|
||||||
// Setup the handler.
|
// Setup the handler.
|
||||||
await page.AddLocatorHandlerAsync(page.Locator("body"), async () => {
|
await page.AddLocatorHandlerAsync(page.Locator("body"), async () => {
|
||||||
await page.EvaluateAsync("window.removeObstructionsForTestIfNeeded()");
|
await page.EvaluateAsync("window.removeObstructionsForTestIfNeeded()");
|
||||||
});
|
}, new() { NoWaitAfter = true });
|
||||||
|
|
||||||
// Write the test as usual.
|
// Write the test as usual.
|
||||||
await page.GotoAsync("https://example.com");
|
await page.GotoAsync("https://example.com");
|
||||||
await page.GetByRole("button", new() { Name = "Start here" }).ClickAsync();
|
await page.GetByRole("button", new() { Name = "Start here" }).ClickAsync();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Handler takes the original locator as an argument. You can also automatically remove the handler after a number of invocations by setting [`option: times`]:
|
||||||
|
|
||||||
|
```js
|
||||||
|
await page.addLocatorHandler(page.getByLabel('Close'), async locator => {
|
||||||
|
await locator.click();
|
||||||
|
}, { times: 1 });
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
page.addLocatorHandler(page.getByLabel("Close"), locator => {
|
||||||
|
locator.click();
|
||||||
|
}, new Page.AddLocatorHandlerOptions().setTimes(1));
|
||||||
|
```
|
||||||
|
|
||||||
|
```python sync
|
||||||
|
def handler(locator):
|
||||||
|
locator.click()
|
||||||
|
page.add_locator_handler(page.get_by_label("Close"), handler, times=1)
|
||||||
|
```
|
||||||
|
|
||||||
|
```python async
|
||||||
|
def handler(locator):
|
||||||
|
await locator.click()
|
||||||
|
await page.add_locator_handler(page.get_by_label("Close"), handler, times=1)
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await page.AddLocatorHandlerAsync(page.GetByText("Sign up to the newsletter"), async locator => {
|
||||||
|
await locator.ClickAsync();
|
||||||
|
}, new() { Times = 1 });
|
||||||
|
```
|
||||||
|
|
||||||
### param: Page.addLocatorHandler.locator
|
### param: Page.addLocatorHandler.locator
|
||||||
* since: v1.42
|
* since: v1.42
|
||||||
- `locator` <[Locator]>
|
- `locator` <[Locator]>
|
||||||
|
|
@ -3352,24 +3381,49 @@ Locator that triggers the handler.
|
||||||
### param: Page.addLocatorHandler.handler
|
### param: Page.addLocatorHandler.handler
|
||||||
* langs: js, python
|
* langs: js, python
|
||||||
* since: v1.42
|
* since: v1.42
|
||||||
- `handler` <[function]>
|
- `handler` <[function]\([Locator]\): [Promise<any>]>
|
||||||
|
|
||||||
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
|
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
|
||||||
|
|
||||||
### param: Page.addLocatorHandler.handler
|
### param: Page.addLocatorHandler.handler
|
||||||
* langs: csharp
|
* langs: csharp
|
||||||
* since: v1.42
|
* since: v1.42
|
||||||
- `handler` <[function](): [Promise<any>]>
|
- `handler` <[function]\([Locator]\)>
|
||||||
|
|
||||||
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
|
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
|
||||||
|
|
||||||
### param: Page.addLocatorHandler.handler
|
### param: Page.addLocatorHandler.handler
|
||||||
* langs: java
|
* langs: java
|
||||||
* since: v1.42
|
* since: v1.42
|
||||||
- `handler` <[Runnable]>
|
- `handler` <[function]\([Locator]\)>
|
||||||
|
|
||||||
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
|
Function that should be run once [`param: locator`] appears. This function should get rid of the element that blocks actions like click.
|
||||||
|
|
||||||
|
### option: Page.addLocatorHandler.times
|
||||||
|
* since: v1.44
|
||||||
|
- `times` <[int]>
|
||||||
|
|
||||||
|
Specifies the maximum number of times this handler should be called. Unlimited by default.
|
||||||
|
|
||||||
|
### option: Page.addLocatorHandler.noWaitAfter
|
||||||
|
* since: v1.44
|
||||||
|
- `noWaitAfter` <[boolean]>
|
||||||
|
|
||||||
|
By default, after calling the handler Playwright will wait until the overlay becomes hidden, and only then Playwright will continue with the action/assertion that triggered the handler. This option allows to opt-out of this behavior, so that overlay can stay visible after the handler has run.
|
||||||
|
|
||||||
|
|
||||||
|
## async method: Page.removeLocatorHandler
|
||||||
|
* since: v1.44
|
||||||
|
|
||||||
|
Removes all locator handlers added by [`method: Page.addLocatorHandler`] for a specific locator.
|
||||||
|
|
||||||
|
### param: Page.removeLocatorHandler.locator
|
||||||
|
* since: v1.44
|
||||||
|
- `locator` <[Locator]>
|
||||||
|
|
||||||
|
Locator passed to [`method: Page.addLocatorHandler`].
|
||||||
|
|
||||||
|
|
||||||
## async method: Page.reload
|
## async method: Page.reload
|
||||||
* since: v1.8
|
* since: v1.8
|
||||||
- returns: <[null]|[Response]>
|
- returns: <[null]|[Response]>
|
||||||
|
|
@ -3411,6 +3465,10 @@ The handler will only be called for the first url if the response is a redirect.
|
||||||
[`method: Page.route`] will not intercept requests intercepted by Service Worker. See [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using request interception by setting [`option: Browser.newContext.serviceWorkers`] to `'block'`.
|
[`method: Page.route`] will not intercept requests intercepted by Service Worker. See [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using request interception by setting [`option: Browser.newContext.serviceWorkers`] to `'block'`.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
[`method: Page.route`] will not intercept the first request of a popup page. Use [`method: BrowserContext.route`] instead.
|
||||||
|
:::
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
An example of a naive handler that aborts all image requests:
|
An example of a naive handler that aborts all image requests:
|
||||||
|
|
@ -4461,6 +4519,10 @@ Returns when the required load state has been reached.
|
||||||
This resolves when the page reaches a required load state, `load` by default. The navigation must have been committed
|
This resolves when the page reaches a required load state, `load` by default. The navigation must have been committed
|
||||||
when this method is called. If current document has already reached the required state, resolves immediately.
|
when this method is called. If current document has already reached the required state, resolves immediately.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Most of the time, this method is not needed because Playwright [auto-waits before every action](../actionability.md).
|
||||||
|
:::
|
||||||
|
|
||||||
**Usage**
|
**Usage**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,13 @@ The opposite of [`method: PageAssertions.toHaveURL`].
|
||||||
|
|
||||||
Expected URL string or RegExp.
|
Expected URL string or RegExp.
|
||||||
|
|
||||||
|
### option: PageAssertions.NotToHaveURL.ignoreCase
|
||||||
|
* since: v1.44
|
||||||
|
* langs: js
|
||||||
|
- `ignoreCase` <[boolean]>
|
||||||
|
|
||||||
|
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
||||||
|
|
||||||
### option: PageAssertions.NotToHaveURL.timeout = %%-csharp-java-python-assertions-timeout-%%
|
### option: PageAssertions.NotToHaveURL.timeout = %%-csharp-java-python-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
|
|
@ -325,6 +332,12 @@ await Expect(Page).ToHaveURL(new Regex(".*checkout"));
|
||||||
|
|
||||||
Expected URL string or RegExp.
|
Expected URL string or RegExp.
|
||||||
|
|
||||||
|
### option: PageAssertions.toHaveURL.ignoreCase
|
||||||
|
* since: v1.44
|
||||||
|
- `ignoreCase` <[boolean]>
|
||||||
|
|
||||||
|
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
||||||
|
|
||||||
### option: PageAssertions.toHaveURL.timeout = %%-js-assertions-timeout-%%
|
### option: PageAssertions.toHaveURL.timeout = %%-js-assertions-timeout-%%
|
||||||
* since: v1.18
|
* since: v1.18
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,11 @@ A point to use relative to the top-left corner of element padding box. If not sp
|
||||||
element.
|
element.
|
||||||
|
|
||||||
## input-modifiers
|
## input-modifiers
|
||||||
- `modifiers` <[Array]<[KeyboardModifier]<"Alt"|"Control"|"Meta"|"Shift">>>
|
- `modifiers` <[Array]<[KeyboardModifier]<"Alt"|"Control"|"ControlOrMeta"|"Meta"|"Shift">>>
|
||||||
|
|
||||||
Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
|
Modifier keys to press. Ensures that only these modifiers are pressed during the operation, and then restores current
|
||||||
modifiers back. If not specified, currently pressed modifiers are used.
|
modifiers back. If not specified, currently pressed modifiers are used. "ControlOrMeta" resolves to "Control" on Windows
|
||||||
|
and Linux and to "Meta" on macOS.
|
||||||
|
|
||||||
## input-button
|
## input-button
|
||||||
- `button` <[MouseButton]<"left"|"right"|"middle">>
|
- `button` <[MouseButton]<"left"|"right"|"middle">>
|
||||||
|
|
@ -403,9 +404,9 @@ unless explicitly provided.
|
||||||
|
|
||||||
An instance of [FormData] can be created via [`method: APIRequestContext.createFormData`].
|
An instance of [FormData] can be created via [`method: APIRequestContext.createFormData`].
|
||||||
|
|
||||||
## js-python-fetch-option-multipart
|
## js-fetch-option-multipart
|
||||||
* langs: js, python
|
* langs: js
|
||||||
- `multipart` <[Object]<[string], [string]|[float]|[boolean]|[ReadStream]|[Object]>>
|
- `multipart` <[FormData]|[Object]<[string], [string]|[float]|[boolean]|[ReadStream]|[Object]>>
|
||||||
- `name` <[string]> File name
|
- `name` <[string]> File name
|
||||||
- `mimeType` <[string]> File type
|
- `mimeType` <[string]> File type
|
||||||
- `buffer` <[Buffer]> File content
|
- `buffer` <[Buffer]> File content
|
||||||
|
|
@ -415,14 +416,24 @@ this request body. If this parameter is specified `content-type` header will be
|
||||||
unless explicitly provided. File values can be passed either as [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream)
|
unless explicitly provided. File values can be passed either as [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream)
|
||||||
or as file-like object containing file name, mime-type and its content.
|
or as file-like object containing file name, mime-type and its content.
|
||||||
|
|
||||||
|
## python-fetch-option-multipart
|
||||||
|
* langs: python
|
||||||
|
- `multipart` <[Object]<[string], [string]|[float]|[boolean]|[ReadStream]|[Object]>>
|
||||||
|
- `name` <[string]> File name
|
||||||
|
- `mimeType` <[string]> File type
|
||||||
|
- `buffer` <[Buffer]> File content
|
||||||
|
|
||||||
|
Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as
|
||||||
|
this request body. If this parameter is specified `content-type` header will be set to `multipart/form-data`
|
||||||
|
unless explicitly provided. File values can be passed as file-like object containing file name, mime-type and its content.
|
||||||
|
|
||||||
## csharp-fetch-option-multipart
|
## csharp-fetch-option-multipart
|
||||||
* langs: csharp
|
* langs: csharp
|
||||||
- `multipart` <[FormData]>
|
- `multipart` <[FormData]>
|
||||||
|
|
||||||
Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as
|
Provides an object that will be serialized as html form using `multipart/form-data` encoding and sent as
|
||||||
this request body. If this parameter is specified `content-type` header will be set to `multipart/form-data`
|
this request body. If this parameter is specified `content-type` header will be set to `multipart/form-data`
|
||||||
unless explicitly provided. File values can be passed either as [`fs.ReadStream`](https://nodejs.org/api/fs.html#fs_class_fs_readstream)
|
unless explicitly provided. File values can be passed as file-like object containing file name, mime-type and its content.
|
||||||
or as file-like object containing file name, mime-type and its content.
|
|
||||||
|
|
||||||
An instance of [FormData] can be created via [`method: APIRequestContext.createFormData`].
|
An instance of [FormData] can be created via [`method: APIRequestContext.createFormData`].
|
||||||
|
|
||||||
|
|
@ -560,6 +571,7 @@ Whether to emulate network being offline. Defaults to `false`. Learn more about
|
||||||
- `username` <[string]>
|
- `username` <[string]>
|
||||||
- `password` <[string]>
|
- `password` <[string]>
|
||||||
- `origin` ?<[string]> Restrain sending http credentials on specific origin (scheme://host:port).
|
- `origin` ?<[string]> Restrain sending http credentials on specific origin (scheme://host:port).
|
||||||
|
- `sendImmediately` ?<[boolean]> Whether to send `Authorization` header with the first API request. By deafult, the credentials are sent only when 401 (Unauthorized) response with `WWW-Authenticate` header is received. This option does not affect requests sent from the browser.
|
||||||
|
|
||||||
Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
|
Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
|
||||||
If no origin is specified, the username and password are sent to any servers upon unauthorized responses.
|
If no origin is specified, the username and password are sent to any servers upon unauthorized responses.
|
||||||
|
|
@ -846,6 +858,11 @@ Time to retry the assertion for in milliseconds. Defaults to `timeout` in `TestC
|
||||||
|
|
||||||
Time to retry the assertion for in milliseconds. Defaults to `5000`.
|
Time to retry the assertion for in milliseconds. Defaults to `5000`.
|
||||||
|
|
||||||
|
## assertions-ignore-case
|
||||||
|
- `ignoreCase` <[boolean]>
|
||||||
|
|
||||||
|
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
|
||||||
|
|
||||||
## assertions-max-diff-pixels
|
## assertions-max-diff-pixels
|
||||||
* langs: js
|
* langs: js
|
||||||
- `maxDiffPixels` <[int]>
|
- `maxDiffPixels` <[int]>
|
||||||
|
|
@ -999,6 +1016,7 @@ disable timeout.
|
||||||
If specified, traces are saved into this directory.
|
If specified, traces are saved into this directory.
|
||||||
|
|
||||||
## browser-option-devtools
|
## browser-option-devtools
|
||||||
|
* deprecated: Use [debugging tools](../debug.md) instead.
|
||||||
- `devtools` <[boolean]>
|
- `devtools` <[boolean]>
|
||||||
|
|
||||||
**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
|
**Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is `true`, the
|
||||||
|
|
@ -1187,8 +1205,7 @@ Text to locate the element for.
|
||||||
|
|
||||||
Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular expression. Note that exact match still trims whitespace.
|
Whether to find an exact match: case-sensitive and whole-string. Default to false. Ignored when locating by a regular expression. Note that exact match still trims whitespace.
|
||||||
|
|
||||||
## locator-get-by-role-role
|
## get-by-role-to-have-role-role
|
||||||
* since: v1.27
|
|
||||||
- `role` <[AriaRole]<"alert"|"alertdialog"|"application"|"article"|"banner"|"blockquote"|"button"|"caption"|"cell"|"checkbox"|"code"|"columnheader"|"combobox"|"complementary"|"contentinfo"|"definition"|"deletion"|"dialog"|"directory"|"document"|"emphasis"|"feed"|"figure"|"form"|"generic"|"grid"|"gridcell"|"group"|"heading"|"img"|"insertion"|"link"|"list"|"listbox"|"listitem"|"log"|"main"|"marquee"|"math"|"meter"|"menu"|"menubar"|"menuitem"|"menuitemcheckbox"|"menuitemradio"|"navigation"|"none"|"note"|"option"|"paragraph"|"presentation"|"progressbar"|"radio"|"radiogroup"|"region"|"row"|"rowgroup"|"rowheader"|"scrollbar"|"search"|"searchbox"|"separator"|"slider"|"spinbutton"|"status"|"strong"|"subscript"|"superscript"|"switch"|"tab"|"table"|"tablist"|"tabpanel"|"term"|"textbox"|"time"|"timer"|"toolbar"|"tooltip"|"tree"|"treegrid"|"treeitem">>
|
- `role` <[AriaRole]<"alert"|"alertdialog"|"application"|"article"|"banner"|"blockquote"|"button"|"caption"|"cell"|"checkbox"|"code"|"columnheader"|"combobox"|"complementary"|"contentinfo"|"definition"|"deletion"|"dialog"|"directory"|"document"|"emphasis"|"feed"|"figure"|"form"|"generic"|"grid"|"gridcell"|"group"|"heading"|"img"|"insertion"|"link"|"list"|"listbox"|"listitem"|"log"|"main"|"marquee"|"math"|"meter"|"menu"|"menubar"|"menuitem"|"menuitemcheckbox"|"menuitemradio"|"navigation"|"none"|"note"|"option"|"paragraph"|"presentation"|"progressbar"|"radio"|"radiogroup"|"region"|"row"|"rowgroup"|"rowheader"|"scrollbar"|"search"|"searchbox"|"separator"|"slider"|"spinbutton"|"status"|"strong"|"subscript"|"superscript"|"switch"|"tab"|"table"|"tablist"|"tabpanel"|"term"|"textbox"|"time"|"timer"|"toolbar"|"tooltip"|"tree"|"treegrid"|"treeitem">>
|
||||||
|
|
||||||
Required aria role.
|
Required aria role.
|
||||||
|
|
@ -1715,13 +1732,17 @@ test.describe('suite', () => {
|
||||||
|
|
||||||
The list of supported tokens:
|
The list of supported tokens:
|
||||||
|
|
||||||
* `{testDir}` - Project's [`property: TestConfig.testDir`].
|
* `{arg}` - Relative snapshot path **without extension**. These come from the arguments passed to the `toHaveScreenshot()` and `toMatchSnapshot()` calls; if called without arguments, this will be an auto-generated snapshot name.
|
||||||
* Value: `/home/playwright/tests` (absolute path is since `testDir` is resolved relative to directory with config)
|
* Value: `foo/bar/baz`
|
||||||
* `{snapshotDir}` - Project's [`property: TestConfig.snapshotDir`].
|
* `{ext}` - snapshot extension (with dots)
|
||||||
* Value: `/home/playwright/tests` (since `snapshotDir` is not provided in config, it defaults to `testDir`)
|
* Value: `.png`
|
||||||
* `{platform}` - The value of `process.platform`.
|
* `{platform}` - The value of `process.platform`.
|
||||||
* `{projectName}` - Project's file-system-sanitized name, if any.
|
* `{projectName}` - Project's file-system-sanitized name, if any.
|
||||||
* Value: `''` (empty string).
|
* Value: `''` (empty string).
|
||||||
|
* `{snapshotDir}` - Project's [`property: TestConfig.snapshotDir`].
|
||||||
|
* Value: `/home/playwright/tests` (since `snapshotDir` is not provided in config, it defaults to `testDir`)
|
||||||
|
* `{testDir}` - Project's [`property: TestConfig.testDir`].
|
||||||
|
* Value: `/home/playwright/tests` (absolute path is since `testDir` is resolved relative to directory with config)
|
||||||
* `{testFileDir}` - Directories in relative path from `testDir` to **test file**.
|
* `{testFileDir}` - Directories in relative path from `testDir` to **test file**.
|
||||||
* Value: `page`
|
* Value: `page`
|
||||||
* `{testFileName}` - Test file name with extension.
|
* `{testFileName}` - Test file name with extension.
|
||||||
|
|
@ -1730,10 +1751,6 @@ The list of supported tokens:
|
||||||
* Value: `page/page-click.spec.ts`
|
* Value: `page/page-click.spec.ts`
|
||||||
* `{testName}` - File-system-sanitized test title, including parent describes but excluding file name.
|
* `{testName}` - File-system-sanitized test title, including parent describes but excluding file name.
|
||||||
* Value: `suite-test-should-work`
|
* Value: `suite-test-should-work`
|
||||||
* `{arg}` - Relative snapshot path **without extension**. These come from the arguments passed to the `toHaveScreenshot()` and `toMatchSnapshot()` calls; if called without arguments, this will be an auto-generated snapshot name.
|
|
||||||
* Value: `foo/bar/baz`
|
|
||||||
* `{ext}` - snapshot extension (with dots)
|
|
||||||
* Value: `.png`
|
|
||||||
|
|
||||||
Each token can be preceded with a single character that will be used **only if** this token has non-empty value.
|
Each token can be preceded with a single character that will be used **only if** this token has non-empty value.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -296,15 +296,16 @@ context = browser.new_context(storage_state="state.json")
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Save storage state into the file.
|
// Save storage state into the file.
|
||||||
|
// Tests are executed in <TestProject>\bin\Debug\netX.0\ therefore relative path is used to reference playwright/.auth created in project root
|
||||||
await context.StorageStateAsync(new()
|
await context.StorageStateAsync(new()
|
||||||
{
|
{
|
||||||
Path = "state.json"
|
Path = "../../../playwright/.auth/state.json"
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a new context with the saved storage state.
|
// Create a new context with the saved storage state.
|
||||||
var context = await browser.NewContextAsync(new()
|
var context = await browser.NewContextAsync(new()
|
||||||
{
|
{
|
||||||
StorageStatePath = "state.json"
|
StorageStatePath = "../../../playwright/.auth/state.json"
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ To add a [GitHub Actions](https://docs.github.com/en/actions) file first create
|
||||||
#### You will learn
|
#### You will learn
|
||||||
* langs: python, java, csharp
|
* langs: python, java, csharp
|
||||||
|
|
||||||
- [How to run tests on push/pull_request](/ci.md#on-pushpull_request)
|
- [How to run tests on push/pull_request](/ci-intro.md#on-pushpull_request)
|
||||||
- [How to view test logs](/ci-intro.md#viewing-test-logs)
|
- [How to view test logs](/ci-intro.md#viewing-test-logs)
|
||||||
- [How to view the trace](/ci-intro.md#viewing-the-trace)
|
- [How to view the trace](/ci-intro.md#viewing-the-trace)
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ jobs:
|
||||||
- name: Run Playwright tests
|
- name: Run Playwright tests
|
||||||
run: npx playwright test
|
run: npx playwright test
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report
|
name: playwright-report
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
|
|
@ -103,7 +103,7 @@ jobs:
|
||||||
- name: Run your tests
|
- name: Run your tests
|
||||||
run: pytest --tracing=retain-on-failure
|
run: pytest --tracing=retain-on-failure
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
name: playwright-traces
|
name: playwright-traces
|
||||||
path: test-results/
|
path: test-results/
|
||||||
|
|
@ -148,7 +148,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.x
|
dotnet-version: 8.0.x
|
||||||
- run: dotnet build
|
- run: dotnet build
|
||||||
|
|
@ -266,7 +266,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.x
|
dotnet-version: 8.0.x
|
||||||
- run: dotnet build
|
- run: dotnet build
|
||||||
|
|
@ -370,7 +370,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v3
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.x
|
dotnet-version: 8.0.x
|
||||||
- run: dotnet build
|
- run: dotnet build
|
||||||
|
|
@ -388,23 +388,49 @@ jobs:
|
||||||
|
|
||||||
Once you have your [GitHub actions workflow](#setting-up-github-actions) setup then all you need to do is [Create a repo on GitHub](https://docs.github.com/en/get-started/quickstart/create-a-repo) or push your code to an existing repository. Follow the instructions on GitHub and don't forget to [initialize a git repository](https://github.com/git-guides/git-init) using the `git init` command so you can [add](https://github.com/git-guides/git-add), [commit](https://github.com/git-guides/git-commit) and [push](https://github.com/git-guides/git-push) your code.
|
Once you have your [GitHub actions workflow](#setting-up-github-actions) setup then all you need to do is [Create a repo on GitHub](https://docs.github.com/en/get-started/quickstart/create-a-repo) or push your code to an existing repository. Follow the instructions on GitHub and don't forget to [initialize a git repository](https://github.com/git-guides/git-init) using the `git init` command so you can [add](https://github.com/git-guides/git-add), [commit](https://github.com/git-guides/git-commit) and [push](https://github.com/git-guides/git-push) your code.
|
||||||
|
|
||||||
|
######
|
||||||
|
* langs: js, java, python
|
||||||
|
|
||||||
<img width="861" alt="Create a Repo and Push to GitHub" src="https://user-images.githubusercontent.com/13063165/183423254-d2735278-a2ab-4d63-bb99-48d8e5e447bc.png"/>
|
<img width="861" alt="Create a Repo and Push to GitHub" src="https://user-images.githubusercontent.com/13063165/183423254-d2735278-a2ab-4d63-bb99-48d8e5e447bc.png"/>
|
||||||
|
|
||||||
|
|
||||||
|
######
|
||||||
|
* langs: csharp
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Opening the Workflows
|
## Opening the Workflows
|
||||||
|
|
||||||
Click on the **Actions** tab to see the workflows. Here you will see if your tests have passed or failed.
|
Click on the **Actions** tab to see the workflows. Here you will see if your tests have passed or failed.
|
||||||
|
|
||||||
<img width="847" alt="Opening the Workflows" src="https://user-images.githubusercontent.com/13063165/183423584-2ea18038-cd49-4daa-a20c-2205352f0933.png"/>
|
######
|
||||||
|
* langs: js, python, java
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
######
|
||||||
|
* langs: csharp
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
On Pull Requests you can also click on the **Details** link in the [PR status check](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks).
|
On Pull Requests you can also click on the **Details** link in the [PR status check](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks).
|
||||||
|
|
||||||
<img width="645" alt="pr status checked" src="https://user-images.githubusercontent.com/13063165/183722462-17a985db-0e10-4205-b16c-8aaac36117b9.png" />
|
<img width="645" alt="pr status checked" src="https://user-images.githubusercontent.com/13063165/183722462-17a985db-0e10-4205-b16c-8aaac36117b9.png" />
|
||||||
|
|
||||||
|
|
||||||
## Viewing Test Logs
|
## Viewing Test Logs
|
||||||
|
|
||||||
Clicking on the workflow run will show you the all the actions that GitHub performed and clicking on **Run Playwright tests** will show the error messages, what was expected and what was received as well as the call log.
|
Clicking on the workflow run will show you the all the actions that GitHub performed and clicking on **Run Playwright tests** will show the error messages, what was expected and what was received as well as the call log.
|
||||||
|
|
||||||
<img width="839" alt="Viewing Test Logs" src="https://user-images.githubusercontent.com/13063165/183423783-58bf2008-514e-4f96-9c12-c9a55703960c.png"/>
|
######
|
||||||
|
* langs: js, python, java
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
######
|
||||||
|
* langs: csharp
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
## HTML Report
|
## HTML Report
|
||||||
|
|
@ -441,12 +467,22 @@ Once you have served the report using `npx playwright show-report`, click on the
|
||||||

|

|
||||||
|
|
||||||
## Viewing the Trace
|
## Viewing the Trace
|
||||||
* langs: python, java, csharp
|
* langs: python, java
|
||||||
|
|
||||||
[trace.playwright.dev](https://trace.playwright.dev) is a statically hosted variant of the Trace Viewer. You can upload trace files using drag and drop.
|
[trace.playwright.dev](https://trace.playwright.dev) is a statically hosted variant of the Trace Viewer. You can upload trace files using drag and drop.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Viewing the Trace
|
||||||
|
* langs: csharp
|
||||||
|
|
||||||
|
You can upload Traces which get created on your CI like GitHub Actions as artifacts. This requires [starting and stopping the trace](./trace-viewer-intro#recording-a-trace). We recommend only recording traces for failing tests. Once your traces have been uploaded to CI, they can then be downloaded and opened using [trace.playwright.dev](https://trace.playwright.dev), which is a statically hosted variant of the Trace Viewer. You can upload trace files using drag and drop.
|
||||||
|
|
||||||
|
######
|
||||||
|
* langs: csharp
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Publishing report on the web
|
## Publishing report on the web
|
||||||
* langs: js
|
* langs: js
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ playwright codegen demo.playwright.dev/todomvc
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash csharp
|
```bash csharp
|
||||||
pwsh bin/Debug/netX/playwright.ps1 codegen demo.playwright.dev/todomvc
|
pwsh bin/Debug/net8.0/playwright.ps1 codegen demo.playwright.dev/todomvc
|
||||||
```
|
```
|
||||||
|
|
||||||
### Recording a test
|
### Recording a test
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,14 @@ npx playwright test --debug
|
||||||
```
|
```
|
||||||
#### Debug one test on all browsers
|
#### Debug one test on all browsers
|
||||||
|
|
||||||
To debug one test on a specific line run the test command followed by the name of the test file and the line number of the test you want to debug, followed by the `--debug` flag. This will run a single test in each browser configured in your [`playwright.config`](/test-configuration.md#multiple-browsers) and open the inspector.
|
To debug one test on a specific line run the test command followed by the name of the test file and the line number of the test you want to debug, followed by the `--debug` flag. This will run a single test in each browser configured in your [`playwright.config`](./test-projects.md#configure-projects-for-multiple-browsers) and open the inspector.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx playwright test example.spec.ts:10 --debug
|
npx playwright test example.spec.ts:10 --debug
|
||||||
```
|
```
|
||||||
#### Debug on a specific browser
|
#### Debug on a specific browser
|
||||||
|
|
||||||
In Playwright you can configure projects in your [`playwright.config`](/test-configuration.md#multiple-browsers). Once configured you can then debug your tests on a specific browser or mobile viewport using the `--project` flag followed by the name of the project configured in your `playwright.config`.
|
In Playwright you can configure projects in your [`playwright.config`](./test-projects.md#configure-projects-for-multiple-browsers). Once configured you can then debug your tests on a specific browser or mobile viewport using the `--project` flag followed by the name of the project configured in your `playwright.config`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx playwright test --project=chromium --debug
|
npx playwright test --project=chromium --debug
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ To learn more about the trace viewer see our [Trace Viewer guide](./trace-viewer
|
||||||
CodeGen will auto generate your tests for you as you perform actions in the browser and is a great way to quickly get started. The viewport for the browser window is set to a specific width and height. See the [configuration guide](./test-configuration.md) to change the viewport or emulate different environments.
|
CodeGen will auto generate your tests for you as you perform actions in the browser and is a great way to quickly get started. The viewport for the browser window is set to a specific width and height. See the [configuration guide](./test-configuration.md) to change the viewport or emulate different environments.
|
||||||
|
|
||||||
<LiteYouTube
|
<LiteYouTube
|
||||||
id="LM4yqrOzmFE"
|
id="5XIZPqKkdBA"
|
||||||
title="Generating Playwright tests in VS Code"
|
title="Generating Playwright tests in VS Code"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ var jsHandle = await page.EvaluateHandleAsync("window");
|
||||||
|
|
||||||
## Element Handles
|
## Element Handles
|
||||||
|
|
||||||
:::caution Discouraged
|
:::warning[Discouraged]
|
||||||
The use of [ElementHandle] is discouraged, use [Locator] objects and web-first assertions instead.
|
The use of [ElementHandle] is discouraged, use [Locator] objects and web-first assertions instead.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,10 @@ await page.getByText('Item').click({ button: 'right' });
|
||||||
// Shift + click
|
// Shift + click
|
||||||
await page.getByText('Item').click({ modifiers: ['Shift'] });
|
await page.getByText('Item').click({ modifiers: ['Shift'] });
|
||||||
|
|
||||||
|
// Ctrl + click or Windows and Linux
|
||||||
|
// Meta + click on macOS
|
||||||
|
await page.getByText('Item').click({ modifiers: ['ControlOrMeta'] });
|
||||||
|
|
||||||
// Hover over element
|
// Hover over element
|
||||||
await page.getByText('Item').hover();
|
await page.getByText('Item').hover();
|
||||||
|
|
||||||
|
|
@ -237,6 +241,10 @@ page.getByText("Item").click(new Locator.ClickOptions().setButton(MouseButton.RI
|
||||||
// Shift + click
|
// Shift + click
|
||||||
page.getByText("Item").click(new Locator.ClickOptions().setModifiers(Arrays.asList(KeyboardModifier.SHIFT)));
|
page.getByText("Item").click(new Locator.ClickOptions().setModifiers(Arrays.asList(KeyboardModifier.SHIFT)));
|
||||||
|
|
||||||
|
// Ctrl + click or Windows and Linux
|
||||||
|
// Meta + click on macOS
|
||||||
|
page.getByText("Item").click(new Locator.ClickOptions().setModifiers(Arrays.asList(KeyboardModifier.CONTROL_OR_META)));
|
||||||
|
|
||||||
// Hover over element
|
// Hover over element
|
||||||
page.getByText("Item").hover();
|
page.getByText("Item").hover();
|
||||||
|
|
||||||
|
|
@ -257,6 +265,10 @@ await page.get_by_text("Item").click(button="right")
|
||||||
# Shift + click
|
# Shift + click
|
||||||
await page.get_by_text("Item").click(modifiers=["Shift"])
|
await page.get_by_text("Item").click(modifiers=["Shift"])
|
||||||
|
|
||||||
|
# Ctrl + click or Windows and Linux
|
||||||
|
# Meta + click on macOS
|
||||||
|
await page.get_by_text("Item").click(modifiers=["ControlOrMeta"])
|
||||||
|
|
||||||
# Hover over element
|
# Hover over element
|
||||||
await page.get_by_text("Item").hover()
|
await page.get_by_text("Item").hover()
|
||||||
|
|
||||||
|
|
@ -297,6 +309,10 @@ await page.GetByText("Item").ClickAsync(new() { Button = MouseButton.Right });
|
||||||
// Shift + click
|
// Shift + click
|
||||||
await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.Shift } });
|
await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.Shift } });
|
||||||
|
|
||||||
|
// Ctrl + click or Windows and Linux
|
||||||
|
// Meta + click on macOS
|
||||||
|
await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.ControlOrMeta } });
|
||||||
|
|
||||||
// Hover over element
|
// Hover over element
|
||||||
await page.GetByText("Item").HoverAsync();
|
await page.GetByText("Item").HoverAsync();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,13 +69,13 @@ dotnet add package Microsoft.Playwright.MSTest
|
||||||
dotnet build
|
dotnet build
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Install required browsers by replacing `netX` with the actual output folder name, e.g. `net8.0`:
|
1. Install required browsers. This example uses `net8.0`, if you are using a different version of .NET you will need to adjust the command and change `net8.0` to your version.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pwsh bin/Debug/netX/playwright.ps1 install
|
pwsh bin/Debug/net8.0/playwright.ps1 install
|
||||||
```
|
```
|
||||||
|
|
||||||
If `pwsh` is not available, you have to [install PowerShell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell).
|
If `pwsh` is not available, you will have to [install PowerShell](https://docs.microsoft.com/powershell/scripting/install/installing-powershell).
|
||||||
|
|
||||||
## Add Example Tests
|
## Add Example Tests
|
||||||
|
|
||||||
|
|
@ -102,28 +102,28 @@ namespace PlaywrightTests;
|
||||||
|
|
||||||
[Parallelizable(ParallelScope.Self)]
|
[Parallelizable(ParallelScope.Self)]
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class Tests : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public async Task HomepageHasPlaywrightInTitleAndGetStartedLinkLinkingtoTheIntroPage()
|
public async Task HasTitle()
|
||||||
{
|
{
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
|
|
||||||
// Expect a title "to contain" a substring.
|
// Expect a title "to contain" a substring.
|
||||||
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
||||||
|
}
|
||||||
|
|
||||||
// create a locator
|
[Test]
|
||||||
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
|
public async Task GetStartedLink()
|
||||||
|
{
|
||||||
// Expect an attribute "to be strictly equal" to the value.
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
await Expect(getStarted).ToHaveAttributeAsync("href", "/docs/intro");
|
|
||||||
|
|
||||||
// Click the get started link.
|
// Click the get started link.
|
||||||
await getStarted.ClickAsync();
|
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
|
||||||
|
|
||||||
// Expects the URL to contain intro.
|
// Expects page to have a heading with the name of Installation.
|
||||||
await Expect(Page).ToHaveURLAsync(new Regex(".*intro"));
|
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -140,28 +140,28 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
namespace PlaywrightTests;
|
namespace PlaywrightTests;
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTest1 : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task HomepageHasPlaywrightInTitleAndGetStartedLinkLinkingtoTheIntroPage()
|
public async Task HasTitle()
|
||||||
{
|
{
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
|
|
||||||
// Expect a title "to contain" a substring.
|
// Expect a title "to contain" a substring.
|
||||||
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
||||||
|
}
|
||||||
|
|
||||||
// create a locator
|
[TestMethod]
|
||||||
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
|
public async Task GetStartedLink()
|
||||||
|
{
|
||||||
// Expect an attribute "to be strictly equal" to the value.
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
await Expect(getStarted).ToHaveAttributeAsync("href", "/docs/intro");
|
|
||||||
|
|
||||||
// Click the get started link.
|
// Click the get started link.
|
||||||
await getStarted.ClickAsync();
|
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
|
||||||
|
|
||||||
// Expects the URL to contain intro.
|
// Expects page to have a heading with the name of Installation.
|
||||||
await Expect(Page).ToHaveURLAsync(new Regex(".*intro"));
|
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -170,33 +170,13 @@ public class UnitTest1 : PageTest
|
||||||
|
|
||||||
## Running the Example Tests
|
## Running the Example Tests
|
||||||
|
|
||||||
By default tests will be run on Chromium. This can be configured via the `BROWSER` environment variable, or by adjusting the [launch configuration options](./test-runners.md). Tests are run in headless mode meaning no browser will open up when running the tests. Results of the tests and test logs will be shown in the terminal.
|
By default tests will be run on Chromium. This can be configured via the `BROWSER` environment variable, or by adjusting the [launch configuration options](./running-tests.md). Tests are run in headless mode meaning no browser will open up when running the tests. Results of the tests and test logs will be shown in the terminal.
|
||||||
|
|
||||||
<Tabs
|
|
||||||
groupId="test-runners"
|
|
||||||
defaultValue="nunit"
|
|
||||||
values={[
|
|
||||||
{label: 'NUnit', value: 'nunit'},
|
|
||||||
{label: 'MSTest', value: 'mstest'}
|
|
||||||
]
|
|
||||||
}>
|
|
||||||
<TabItem value="nunit">
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dotnet test -- NUnit.NumberOfTestWorkers=5
|
dotnet test
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
See our doc on [Running and Debugging Tests](./running-tests.md) to learn more about running tests in headed mode, running multiple tests, running specific configurations etc.
|
||||||
<TabItem value="mstest">
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet test -- MSTest.Parallelize.Workers=5
|
|
||||||
```
|
|
||||||
|
|
||||||
</TabItem>
|
|
||||||
</Tabs>
|
|
||||||
|
|
||||||
See our doc on [Test Runners](./test-runners.md) to learn more about running tests in headed mode, running multiple tests, running specific configurations etc.
|
|
||||||
|
|
||||||
## System requirements
|
## System requirements
|
||||||
|
|
||||||
|
|
@ -209,7 +189,7 @@ See our doc on [Test Runners](./test-runners.md) to learn more about running tes
|
||||||
|
|
||||||
- [Write tests using web first assertions, page fixtures and locators](./writing-tests.md)
|
- [Write tests using web first assertions, page fixtures and locators](./writing-tests.md)
|
||||||
- [Run single test, multiple tests, headed mode](./running-tests.md)
|
- [Run single test, multiple tests, headed mode](./running-tests.md)
|
||||||
- [Learn more about the NUnit and MSTest base classes](./test-runners.md)
|
|
||||||
- [Generate tests with Codegen](./codegen.md)
|
- [Generate tests with Codegen](./codegen.md)
|
||||||
- [See a trace of your tests](./trace-viewer-intro.md)
|
- [See a trace of your tests](./trace-viewer-intro.md)
|
||||||
- [Using Playwright as library](./library.md)
|
- [Run tests on CI](./ci-intro.md)
|
||||||
|
- [Learn more about the NUnit and MSTest base classes](./test-runners.md)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ Playwright Test was created specifically to accommodate the needs of end-to-end
|
||||||
|
|
||||||
## Installing Playwright
|
## Installing Playwright
|
||||||
|
|
||||||
Get started by installing Playwright using npm or yarn. Alternatively you can also get started and run your tests using the [VS Code Extension](./getting-started-vscode.md).
|
Get started by installing Playwright using npm, yarn or pnpm. Alternatively you can also get started and run your tests using the [VS Code Extension](./getting-started-vscode.md).
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="npm"
|
defaultValue="npm"
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@ Role locators include [buttons, checkboxes, headings, links, lists, tables, and
|
||||||
|
|
||||||
Note that role locators **do not replace** accessibility audits and conformance tests, but rather give early feedback about the ARIA guidelines.
|
Note that role locators **do not replace** accessibility audits and conformance tests, but rather give early feedback about the ARIA guidelines.
|
||||||
|
|
||||||
:::note When to use role locators
|
:::note[When to use role locators]
|
||||||
We recommend prioritizing role locators to locate elements, as it is the closest way to how users and assistive technology perceive the page.
|
We recommend prioritizing role locators to locate elements, as it is the closest way to how users and assistive technology perceive the page.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -301,7 +301,7 @@ page.get_by_label("Password").fill("secret")
|
||||||
await page.GetByLabel("Password").FillAsync("secret");
|
await page.GetByLabel("Password").FillAsync("secret");
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note When to use label locators
|
:::note[When to use label locators]
|
||||||
Use this locator when locating form fields.
|
Use this locator when locating form fields.
|
||||||
:::
|
:::
|
||||||
### Locate by placeholder
|
### Locate by placeholder
|
||||||
|
|
@ -340,7 +340,7 @@ await page
|
||||||
.FillAsync("playwright@microsoft.com");
|
.FillAsync("playwright@microsoft.com");
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note When to use placeholder locators
|
:::note[When to use placeholder locators]
|
||||||
Use this locator when locating form elements that do not have labels but do have placeholder texts.
|
Use this locator when locating form elements that do not have labels but do have placeholder texts.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -433,7 +433,7 @@ await Expect(Page
|
||||||
Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one, turns line breaks into spaces and ignores leading and trailing whitespace.
|
Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one, turns line breaks into spaces and ignores leading and trailing whitespace.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
:::note When to use text locators
|
:::note[When to use text locators]
|
||||||
We recommend using text locators to find non interactive elements like `div`, `span`, `p`, etc. For interactive elements like `button`, `a`, `input`, etc. use [role locators](#locate-by-role).
|
We recommend using text locators to find non interactive elements like `div`, `span`, `p`, etc. For interactive elements like `button`, `a`, `input`, etc. use [role locators](#locate-by-role).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -471,7 +471,7 @@ page.get_by_alt_text("playwright logo").click()
|
||||||
await page.GetByAltText("playwright logo").ClickAsync();
|
await page.GetByAltText("playwright logo").ClickAsync();
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note When to use alt locators
|
:::note[When to use alt locators]
|
||||||
Use this locator when your element supports alt text such as `img` and `area` elements.
|
Use this locator when your element supports alt text such as `img` and `area` elements.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -507,7 +507,7 @@ expect(page.get_by_title("Issues count")).to_have_text("25 issues")
|
||||||
await Expect(Page.GetByTitle("Issues count")).toHaveText("25 issues");
|
await Expect(Page.GetByTitle("Issues count")).toHaveText("25 issues");
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note When to use title locators
|
:::note[When to use title locators]
|
||||||
Use this locator when your element has the `title` attribute.
|
Use this locator when your element has the `title` attribute.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -543,7 +543,7 @@ page.get_by_test_id("directions").click()
|
||||||
await page.GetByTestId("directions").ClickAsync();
|
await page.GetByTestId("directions").ClickAsync();
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note When to use testid locators
|
:::note[When to use testid locators]
|
||||||
You can also use test ids when you choose to use the test id methodology or when you can't locate by [role](#locate-by-role) or [text](#locate-by-text).
|
You can also use test ids when you choose to use the test id methodology or when you can't locate by [role](#locate-by-role) or [text](#locate-by-text).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -693,7 +693,7 @@ await page.Locator("#tsf > div:nth-child(2) > div.A8SBwf > div.RNNXgb > div > di
|
||||||
await page.Locator("//*[@id='tsf']/div[2]/div[1]/div[1]/div/div[2]/input").ClickAsync();
|
await page.Locator("//*[@id='tsf']/div[2]/div[1]/div[1]/div/div[2]/input").ClickAsync();
|
||||||
```
|
```
|
||||||
|
|
||||||
:::note When to use this
|
:::note[When to use this]
|
||||||
CSS and XPath are not recommended as the DOM can often change leading to non resilient tests. Instead, try to come up with a locator that is close to how the user perceives the page such as [role locators](#locate-by-role) or [define an explicit testing contract](#locate-by-test-id) using test ids.
|
CSS and XPath are not recommended as the DOM can often change leading to non resilient tests. Instead, try to come up with a locator that is close to how the user perceives the page such as [role locators](#locate-by-role) or [define an explicit testing contract](#locate-by-test-id) using test ids.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,23 @@ test('show battery status', async ({ page }) => {
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Mocking read-only APIs
|
||||||
|
|
||||||
|
Some APIs are read-only so you won't be able to assign to a navigator property. For example,
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Following line will have no effect.
|
||||||
|
navigator.cookieEnabled = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
However, if the property is [configurable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#configurable), you can still override it using the plain JavaScript:
|
||||||
|
|
||||||
|
```js
|
||||||
|
await page.addInitScript(() => {
|
||||||
|
Object.defineProperty(Object.getPrototypeOf(navigator), 'cookieEnabled', { value: false });
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Verifying API calls
|
## Verifying API calls
|
||||||
|
|
||||||
Sometimes it is useful to check if the page made all expected APIs calls. You can
|
Sometimes it is useful to check if the page made all expected APIs calls. You can
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ Sometimes, it is essential to make an API request, but the response needs to be
|
||||||
allow for reproducible testing. In that case, instead of mocking the request, one
|
allow for reproducible testing. In that case, instead of mocking the request, one
|
||||||
can perform the request and fulfill it with the modified response.
|
can perform the request and fulfill it with the modified response.
|
||||||
|
|
||||||
In the example below we intercept the call to the fruit API and add a new fruit called 'playwright', to the data. We then go to the url and assert that this data is there:
|
In the example below we intercept the call to the fruit API and add a new fruit called 'Loquat', to the data. We then go to the url and assert that this data is there:
|
||||||
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,8 @@ handle new pages opened by `target="_blank"` links.
|
||||||
const pagePromise = context.waitForEvent('page');
|
const pagePromise = context.waitForEvent('page');
|
||||||
await page.getByText('open new tab').click();
|
await page.getByText('open new tab').click();
|
||||||
const newPage = await pagePromise;
|
const newPage = await pagePromise;
|
||||||
await newPage.waitForLoadState();
|
// Interact with the new page normally.
|
||||||
|
await newPage.getByRole('button').click();
|
||||||
console.log(await newPage.title());
|
console.log(await newPage.title());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -152,7 +153,8 @@ console.log(await newPage.title());
|
||||||
Page newPage = context.waitForPage(() -> {
|
Page newPage = context.waitForPage(() -> {
|
||||||
page.getByText("open new tab").click(); // Opens a new tab
|
page.getByText("open new tab").click(); // Opens a new tab
|
||||||
});
|
});
|
||||||
newPage.waitForLoadState();
|
// Interact with the new page normally
|
||||||
|
newPage.getByRole(AriaRole.BUTTON).click();
|
||||||
System.out.println(newPage.title());
|
System.out.println(newPage.title());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -162,7 +164,8 @@ async with context.expect_page() as new_page_info:
|
||||||
await page.get_by_text("open new tab").click() # Opens a new tab
|
await page.get_by_text("open new tab").click() # Opens a new tab
|
||||||
new_page = await new_page_info.value
|
new_page = await new_page_info.value
|
||||||
|
|
||||||
await new_page.wait_for_load_state()
|
# Interact with the new page normally
|
||||||
|
await new_page.get_by_role("button").click()
|
||||||
print(await new_page.title())
|
print(await new_page.title())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -172,7 +175,8 @@ with context.expect_page() as new_page_info:
|
||||||
page.get_by_text("open new tab").click() # Opens a new tab
|
page.get_by_text("open new tab").click() # Opens a new tab
|
||||||
new_page = new_page_info.value
|
new_page = new_page_info.value
|
||||||
|
|
||||||
new_page.wait_for_load_state()
|
# Interact with the new page normally
|
||||||
|
new_page.get_by_role("button").click()
|
||||||
print(new_page.title())
|
print(new_page.title())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -182,7 +186,8 @@ var newPage = await context.RunAndWaitForPageAsync(async () =>
|
||||||
{
|
{
|
||||||
await page.GetByText("open new tab").ClickAsync();
|
await page.GetByText("open new tab").ClickAsync();
|
||||||
});
|
});
|
||||||
await newPage.WaitForLoadStateAsync();
|
// Interact with the new page normally
|
||||||
|
await newPage.GetByRole(AriaRole.Button).ClickAsync();
|
||||||
Console.WriteLine(await newPage.TitleAsync());
|
Console.WriteLine(await newPage.TitleAsync());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -242,8 +247,8 @@ This event is emitted in addition to the `browserContext.on('page')` event, but
|
||||||
const popupPromise = page.waitForEvent('popup');
|
const popupPromise = page.waitForEvent('popup');
|
||||||
await page.getByText('open the popup').click();
|
await page.getByText('open the popup').click();
|
||||||
const popup = await popupPromise;
|
const popup = await popupPromise;
|
||||||
// Wait for the popup to load.
|
// Interact with the new popup normally.
|
||||||
await popup.waitForLoadState();
|
await popup.getByRole('button').click();
|
||||||
console.log(await popup.title());
|
console.log(await popup.title());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -252,7 +257,8 @@ console.log(await popup.title());
|
||||||
Page popup = page.waitForPopup(() -> {
|
Page popup = page.waitForPopup(() -> {
|
||||||
page.getByText("open the popup").click();
|
page.getByText("open the popup").click();
|
||||||
});
|
});
|
||||||
popup.waitForLoadState();
|
// Interact with the popup normally
|
||||||
|
popup.getByRole(AriaRole.BUTTON).click();
|
||||||
System.out.println(popup.title());
|
System.out.println(popup.title());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -262,7 +268,8 @@ async with page.expect_popup() as popup_info:
|
||||||
await page.get_by_text("open the popup").click()
|
await page.get_by_text("open the popup").click()
|
||||||
popup = await popup_info.value
|
popup = await popup_info.value
|
||||||
|
|
||||||
await popup.wait_for_load_state()
|
# Interact with the popup normally
|
||||||
|
await popup.get_by_role("button").click()
|
||||||
print(await popup.title())
|
print(await popup.title())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -272,7 +279,8 @@ with page.expect_popup() as popup_info:
|
||||||
page.get_by_text("open the popup").click()
|
page.get_by_text("open the popup").click()
|
||||||
popup = popup_info.value
|
popup = popup_info.value
|
||||||
|
|
||||||
popup.wait_for_load_state()
|
# Interact with the popup normally
|
||||||
|
popup.get_by_role("button").click()
|
||||||
print(popup.title())
|
print(popup.title())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -282,7 +290,8 @@ var popup = await page.RunAndWaitForPopupAsync(async () =>
|
||||||
{
|
{
|
||||||
await page.GetByText("open the popup").ClickAsync();
|
await page.GetByText("open the popup").ClickAsync();
|
||||||
});
|
});
|
||||||
await popup.WaitForLoadStateAsync();
|
// Interact with the popup normally
|
||||||
|
await popup.GetByRole(AriaRole.Button).ClickAsync();
|
||||||
Console.WriteLine(await popup.TitleAsync());
|
Console.WriteLine(await popup.TitleAsync());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,50 @@ title: "Release notes"
|
||||||
toc_max_heading_level: 2
|
toc_max_heading_level: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Version 1.43
|
||||||
|
|
||||||
|
### New APIs
|
||||||
|
|
||||||
|
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Clear all cookies.
|
||||||
|
await Context.ClearCookiesAsync();
|
||||||
|
// New: clear cookies with a particular name.
|
||||||
|
await Context.ClearCookiesAsync(new() { Name = "session-id" });
|
||||||
|
// New: clear cookies for a particular domain.
|
||||||
|
await Context.ClearCookiesAsync(new() { Domain = "my-origin.com" });
|
||||||
|
```
|
||||||
|
|
||||||
|
- New property [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var locator = Page.Locator("iframe[name='embedded']");
|
||||||
|
// ...
|
||||||
|
var frameLocator = locator.ContentFrame;
|
||||||
|
await frameLocator.GetByRole(AriaRole.Button).ClickAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
- New property [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var frameLocator = page.FrameLocator("iframe[name='embedded']");
|
||||||
|
// ...
|
||||||
|
var locator = frameLocator.Owner;
|
||||||
|
await Expect(locator).ToBeVisibleAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Browser Versions
|
||||||
|
|
||||||
|
* Chromium 124.0.6367.8
|
||||||
|
* Mozilla Firefox 124.0
|
||||||
|
* WebKit 17.4
|
||||||
|
|
||||||
|
This version was also tested against the following stable channels:
|
||||||
|
|
||||||
|
* Google Chrome 123
|
||||||
|
* Microsoft Edge 123
|
||||||
|
|
||||||
## Version 1.42
|
## Version 1.42
|
||||||
|
|
||||||
### New Locator Handler
|
### New Locator Handler
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,50 @@ title: "Release notes"
|
||||||
toc_max_heading_level: 2
|
toc_max_heading_level: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Version 1.43
|
||||||
|
|
||||||
|
### New APIs
|
||||||
|
|
||||||
|
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
|
||||||
|
|
||||||
|
```java
|
||||||
|
// Clear all cookies.
|
||||||
|
context.clearCookies();
|
||||||
|
// New: clear cookies with a particular name.
|
||||||
|
context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("session-id"));
|
||||||
|
// New: clear cookies for a particular domain.
|
||||||
|
context.clearCookies(new BrowserContext.ClearCookiesOptions().setDomain("my-origin.com"));
|
||||||
|
```
|
||||||
|
|
||||||
|
- New method [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
|
||||||
|
|
||||||
|
```java
|
||||||
|
Locator locator = page.locator("iframe[name='embedded']");
|
||||||
|
// ...
|
||||||
|
FrameLocator frameLocator = locator.contentFrame();
|
||||||
|
frameLocator.getByRole(AriaRole.BUTTON).click();
|
||||||
|
```
|
||||||
|
|
||||||
|
- New method [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
|
||||||
|
|
||||||
|
```java
|
||||||
|
FrameLocator frameLocator = page.frameLocator("iframe[name='embedded']");
|
||||||
|
// ...
|
||||||
|
Locator locator = frameLocator.owner();
|
||||||
|
assertThat(locator).isVisible();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Browser Versions
|
||||||
|
|
||||||
|
* Chromium 124.0.6367.8
|
||||||
|
* Mozilla Firefox 124.0
|
||||||
|
* WebKit 17.4
|
||||||
|
|
||||||
|
This version was also tested against the following stable channels:
|
||||||
|
|
||||||
|
* Google Chrome 123
|
||||||
|
* Microsoft Edge 123
|
||||||
|
|
||||||
## Version 1.42
|
## Version 1.42
|
||||||
|
|
||||||
### Experimental JUnit integration
|
### Experimental JUnit integration
|
||||||
|
|
@ -644,7 +688,7 @@ This version was also tested against the following stable channels:
|
||||||
|
|
||||||
### New APIs & changes
|
### New APIs & changes
|
||||||
|
|
||||||
- Default assertions timeout now can be changed with [`setDefaultAssertionTimeout`](./test-assertions#playwright-assertions-set-default-assertion-timeout).
|
- Default assertions timeout now can be changed with [`setDefaultAssertionTimeout`](./api/class-playwrightassertions#playwright-assertions-set-default-assertion-timeout).
|
||||||
|
|
||||||
### Announcements
|
### Announcements
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,186 @@ toc_max_heading_level: 2
|
||||||
|
|
||||||
import LiteYouTube from '@site/src/components/LiteYouTube';
|
import LiteYouTube from '@site/src/components/LiteYouTube';
|
||||||
|
|
||||||
|
## Version 1.44
|
||||||
|
|
||||||
|
### New APIs
|
||||||
|
|
||||||
|
**Accessibility assertions**
|
||||||
|
|
||||||
|
- [`method: LocatorAssertions.toHaveAccessibleName`] checks if the element has the specified accessible name:
|
||||||
|
```js
|
||||||
|
const locator = page.getByRole('button');
|
||||||
|
await expect(locator).toHaveAccessibleName('Submit');
|
||||||
|
```
|
||||||
|
|
||||||
|
- [`method: LocatorAssertions.toHaveAccessibleDescription`] checks if the element has the specified accessible description:
|
||||||
|
```js
|
||||||
|
const locator = page.getByRole('button');
|
||||||
|
await expect(locator).toHaveAccessibleDescription('Upload a photo');
|
||||||
|
```
|
||||||
|
|
||||||
|
- [`method: LocatorAssertions.toHaveRole`] checks if the element has the specified ARIA role:
|
||||||
|
```js
|
||||||
|
const locator = page.getByTestId('save-button');
|
||||||
|
await expect(locator).toHaveRole('button');
|
||||||
|
```
|
||||||
|
|
||||||
|
**Locator handler**
|
||||||
|
|
||||||
|
- After executing the handler added with [`method: Page.addLocatorHandler`], Playwright will now wait until the overlay that triggered the handler is not visible anymore. You can opt-out of this behavior with the new `noWaitAfter` option.
|
||||||
|
- You can use new `times` option in [`method: Page.addLocatorHandler`] to specify maximum number of times the handler should be run.
|
||||||
|
- The handler in [`method: Page.addLocatorHandler`] now accepts the locator as argument.
|
||||||
|
- New [`method: Page.removeLocatorHandler`] method for removing previously added locator handlers.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const locator = page.getByText('This interstitial covers the button');
|
||||||
|
await page.addLocatorHandler(locator, async overlay => {
|
||||||
|
await overlay.locator('#close').click();
|
||||||
|
}, { times: 3, noWaitAfter: true });
|
||||||
|
// Run your tests that can be interrupted by the overlay.
|
||||||
|
// ...
|
||||||
|
await page.removeLocatorHandler(locator);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Miscellaneous options**
|
||||||
|
|
||||||
|
- [`multipart`](./api/class-apirequestcontext#api-request-context-fetch-option-multipart) option in `apiRequestContext.fetch()` now accepts [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) and supports repeating fields with the same name.
|
||||||
|
```js
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', new File(['let x = 2024;'], 'f1.js', { type: 'text/javascript' }));
|
||||||
|
formData.append('file', new File(['hello'], 'f2.txt', { type: 'text/plain' }));
|
||||||
|
context.request.post('https://example.com/uploadFiles', {
|
||||||
|
multipart: formData
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- `expect(callback).toPass({ intervals })` can now be configured by `expect.toPass.inervals` option globally in [`property: TestConfig.expect`] or per project in [`property: TestProject.expect`].
|
||||||
|
- `expect(page).toHaveURL(url)` now supports `ignoreCase` [option](./api/class-pageassertions#page-assertions-to-have-url-option-ignore-case).
|
||||||
|
- [`property: TestProject.ignoreSnapshots`](./api/class-testproject#test-project-ignore-snapshots) allows to configure per project whether to skip screenshot expectations.
|
||||||
|
|
||||||
|
**Reporter API**
|
||||||
|
|
||||||
|
- New method [`method: Suite.entries`] returns child test suites and test cases in their declaration order. [`property: Suite.type`] and [`property: TestCase.type`] can be used to tell apart test cases and suites in the list.
|
||||||
|
- [Blob](./test-reporters#blob-reporter) reporter now allows overriding report file path with a single option `outputFile`. The same option can also be specified as `PLAYWRIGHT_BLOB_OUTPUT_FILE` environment variable that might be more convenient on CI/CD.
|
||||||
|
- [JUnit](./test-reporters#junit-reporter) reporter now supports `includeProjectInTestName` option.
|
||||||
|
|
||||||
|
**Command line**
|
||||||
|
|
||||||
|
- `--last-failed` CLI option to for running only tests that failed in the previous run.
|
||||||
|
|
||||||
|
First run all tests:
|
||||||
|
```sh
|
||||||
|
$ npx playwright test
|
||||||
|
|
||||||
|
Running 103 tests using 5 workers
|
||||||
|
...
|
||||||
|
2 failed
|
||||||
|
[chromium] › my-test.spec.ts:8:5 › two ─────────────────────────────────────────────────────────
|
||||||
|
[chromium] › my-test.spec.ts:13:5 › three ──────────────────────────────────────────────────────
|
||||||
|
101 passed (30.0s)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now fix the failing tests and run Playwright again with `--last-failed` option:
|
||||||
|
```sh
|
||||||
|
$ npx playwright test --last-failed
|
||||||
|
|
||||||
|
Running 2 tests using 2 workers
|
||||||
|
2 passed (1.2s)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Browser Versions
|
||||||
|
|
||||||
|
* Chromium 125.0.6422.14
|
||||||
|
* Mozilla Firefox 125.0.1
|
||||||
|
* WebKit 17.4
|
||||||
|
|
||||||
|
This version was also tested against the following stable channels:
|
||||||
|
|
||||||
|
* Google Chrome 124
|
||||||
|
* Microsoft Edge 124
|
||||||
|
|
||||||
|
## Version 1.43
|
||||||
|
|
||||||
|
### New APIs
|
||||||
|
|
||||||
|
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// Clear all cookies.
|
||||||
|
await context.clearCookies();
|
||||||
|
// New: clear cookies with a particular name.
|
||||||
|
await context.clearCookies({ name: 'session-id' });
|
||||||
|
// New: clear cookies for a particular domain.
|
||||||
|
await context.clearCookies({ domain: 'my-origin.com' });
|
||||||
|
```
|
||||||
|
|
||||||
|
- New mode `retain-on-first-failure` for [`property: TestOptions.trace`]. In this mode, trace is recorded for the first run of each test, but not for retires. When test run fails, the trace file is retained, otherwise it is removed.
|
||||||
|
|
||||||
|
```js title=playwright.config.ts
|
||||||
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
use: {
|
||||||
|
trace: 'retain-on-first-failure',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- New property [`property: TestInfo.tags`] exposes test tags during test execution.
|
||||||
|
|
||||||
|
```js
|
||||||
|
test('example', async ({ page }) => {
|
||||||
|
console.log(test.info().tags);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- New method [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const locator = page.locator('iframe[name="embedded"]');
|
||||||
|
// ...
|
||||||
|
const frameLocator = locator.contentFrame();
|
||||||
|
await frameLocator.getByRole('button').click();
|
||||||
|
```
|
||||||
|
|
||||||
|
- New method [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const frameLocator = page.frameLocator('iframe[name="embedded"]');
|
||||||
|
// ...
|
||||||
|
const locator = frameLocator.owner();
|
||||||
|
await expect(locator).toBeVisible();
|
||||||
|
```
|
||||||
|
|
||||||
|
### UI Mode Updates
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* See tags in the test list.
|
||||||
|
* Filter by tags by typing `@fast` or clicking on the tag itself.
|
||||||
|
* New shortcuts:
|
||||||
|
- "F5" to run tests.
|
||||||
|
- "Shift F5" to stop running tests.
|
||||||
|
- "Ctrl `" to toggle test output.
|
||||||
|
|
||||||
|
### Browser Versions
|
||||||
|
|
||||||
|
* Chromium 124.0.6367.8
|
||||||
|
* Mozilla Firefox 124.0
|
||||||
|
* WebKit 17.4
|
||||||
|
|
||||||
|
This version was also tested against the following stable channels:
|
||||||
|
|
||||||
|
* Google Chrome 123
|
||||||
|
* Microsoft Edge 123
|
||||||
|
|
||||||
## Version 1.42
|
## Version 1.42
|
||||||
|
|
||||||
|
<LiteYouTube
|
||||||
|
id="KjSaIQLlgns"
|
||||||
|
title="Playwright 1.41 & 1.42"
|
||||||
|
/>
|
||||||
|
|
||||||
### New APIs
|
### New APIs
|
||||||
|
|
||||||
- New method [`method: Page.addLocatorHandler`] registers a callback that will be invoked when specified element becomes visible and may block Playwright actions. The callback can get rid of the overlay. Here is an example that closes a cookie dialog when it appears:
|
- New method [`method: Page.addLocatorHandler`] registers a callback that will be invoked when specified element becomes visible and may block Playwright actions. The callback can get rid of the overlay. Here is an example that closes a cookie dialog when it appears:
|
||||||
|
|
@ -182,7 +360,7 @@ test('pass', async ({ page }) => {
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
See the documentation [for a full example](./test-assertions.md#add-custom-matchers-using-expectextend).
|
See the documentation [for a full example](./test-assertions#add-custom-matchers-using-expectextend).
|
||||||
|
|
||||||
### Merge test fixtures
|
### Merge test fixtures
|
||||||
|
|
||||||
|
|
@ -1673,7 +1851,7 @@ This version was also tested against the following stable channels:
|
||||||
### Locator Improvements
|
### Locator Improvements
|
||||||
|
|
||||||
- [`method: Locator.dragTo`]
|
- [`method: Locator.dragTo`]
|
||||||
- [`expect(locator).toBeChecked({ checked })`](./test-assertions#locator-assertions-to-be-checked)
|
- [`expect(locator).toBeChecked({ checked })`](./api/class-locatorassertions#locator-assertions-to-be-checked)
|
||||||
- Each locator can now be optionally filtered by the text it contains:
|
- Each locator can now be optionally filtered by the text it contains:
|
||||||
```js
|
```js
|
||||||
await page.locator('li', { hasText: 'my item' }).locator('button').click();
|
await page.locator('li', { hasText: 'my item' }).locator('button').click();
|
||||||
|
|
@ -1828,7 +2006,7 @@ Playwright Trace Viewer is now **available online** at https://trace.playwright.
|
||||||
- [`testInfo.parallelIndex`](./api/class-testinfo#test-info-parallel-index)
|
- [`testInfo.parallelIndex`](./api/class-testinfo#test-info-parallel-index)
|
||||||
- [`testInfo.titlePath`](./api/class-testinfo#test-info-title-path)
|
- [`testInfo.titlePath`](./api/class-testinfo#test-info-title-path)
|
||||||
- [`testOptions.trace`](./api/class-testoptions#test-options-trace) has new options
|
- [`testOptions.trace`](./api/class-testoptions#test-options-trace) has new options
|
||||||
- [`expect.toMatchSnapshot`](./test-assertions#expectvaluetomatchsnapshotname-options) supports subdirectories
|
- [`expect.toMatchSnapshot`](./api/class-genericassertions.md) supports subdirectories
|
||||||
- [`reporter.printsToStdio()`](./api/class-reporter#reporter-prints-to-stdio)
|
- [`reporter.printsToStdio()`](./api/class-reporter#reporter-prints-to-stdio)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2109,25 +2287,25 @@ By default, the timeout for assertions is not set, so it'll wait forever, until
|
||||||
|
|
||||||
List of all new assertions:
|
List of all new assertions:
|
||||||
|
|
||||||
- [`expect(locator).toBeChecked()`](./test-assertions#expectlocatortobechecked)
|
- [`expect(locator).toBeChecked()`](./api/class-locatorassertions#locator-assertions-to-be-checked)
|
||||||
- [`expect(locator).toBeDisabled()`](./test-assertions#expectlocatortobedisabled)
|
- [`expect(locator).toBeDisabled()`](./api/class-locatorassertions#locator-assertions-to-be-disabled)
|
||||||
- [`expect(locator).toBeEditable()`](./test-assertions#expectlocatortobeeditable)
|
- [`expect(locator).toBeEditable()`](./api/class-locatorassertions#locator-assertions-to-be-editable)
|
||||||
- [`expect(locator).toBeEmpty()`](./test-assertions#expectlocatortobeempty)
|
- [`expect(locator).toBeEmpty()`](./api/class-locatorassertions#locator-assertions-to-be-empty)
|
||||||
- [`expect(locator).toBeEnabled()`](./test-assertions#expectlocatortobeenabled)
|
- [`expect(locator).toBeEnabled()`](./api/class-locatorassertions#locator-assertions-to-be-enabled)
|
||||||
- [`expect(locator).toBeFocused()`](./test-assertions#expectlocatortobefocused)
|
- [`expect(locator).toBeFocused()`](./api/class-locatorassertions#locator-assertions-to-be-focused)
|
||||||
- [`expect(locator).toBeHidden()`](./test-assertions#expectlocatortobehidden)
|
- [`expect(locator).toBeHidden()`](./api/class-locatorassertions#locator-assertions-to-be-hidden)
|
||||||
- [`expect(locator).toBeVisible()`](./test-assertions#expectlocatortobevisible)
|
- [`expect(locator).toBeVisible()`](./api/class-locatorassertions#locator-assertions-to-be-visible)
|
||||||
- [`expect(locator).toContainText(text, options?)`](./test-assertions#expectlocatortocontaintexttext-options)
|
- [`expect(locator).toContainText(text, options?)`](./api/class-locatorassertions#locator-assertions-to-contain-text)
|
||||||
- [`expect(locator).toHaveAttribute(name, value)`](./test-assertions#expectlocatortohaveattributename-value)
|
- [`expect(locator).toHaveAttribute(name, value)`](./api/class-locatorassertions#locator-assertions-to-have-attribute)
|
||||||
- [`expect(locator).toHaveClass(expected)`](./test-assertions#expectlocatortohaveclassexpected)
|
- [`expect(locator).toHaveClass(expected)`](./api/class-locatorassertions#locator-assertions-to-have-class)
|
||||||
- [`expect(locator).toHaveCount(count)`](./test-assertions#expectlocatortohavecountcount)
|
- [`expect(locator).toHaveCount(count)`](./api/class-locatorassertions#locator-assertions-to-have-count)
|
||||||
- [`expect(locator).toHaveCSS(name, value)`](./test-assertions#expectlocatortohavecssname-value)
|
- [`expect(locator).toHaveCSS(name, value)`](./api/class-locatorassertions#locator-assertions-to-have-css)
|
||||||
- [`expect(locator).toHaveId(id)`](./test-assertions#expectlocatortohaveidid)
|
- [`expect(locator).toHaveId(id)`](./api/class-locatorassertions#locator-assertions-to-have-id)
|
||||||
- [`expect(locator).toHaveJSProperty(name, value)`](./test-assertions#expectlocatortohavejspropertyname-value)
|
- [`expect(locator).toHaveJSProperty(name, value)`](./api/class-locatorassertions#locator-assertions-to-have-js-property)
|
||||||
- [`expect(locator).toHaveText(expected, options)`](./test-assertions#expectlocatortohavetextexpected-options)
|
- [`expect(locator).toHaveText(expected, options)`](./api/class-locatorassertions#locator-assertions-to-have-text)
|
||||||
- [`expect(page).toHaveTitle(title)`](./test-assertions#expectpagetohavetitletitle)
|
- [`expect(page).toHaveTitle(title)`](./api/class-pageassertions#page-assertions-to-have-title)
|
||||||
- [`expect(page).toHaveURL(url)`](./test-assertions#expectpagetohaveurlurl)
|
- [`expect(page).toHaveURL(url)`](./api/class-pageassertions#page-assertions-to-have-url)
|
||||||
- [`expect(locator).toHaveValue(value)`](./test-assertions#expectlocatortohavevaluevalue)
|
- [`expect(locator).toHaveValue(value)`](./api/class-locatorassertions#locator-assertions-to-have-value)
|
||||||
|
|
||||||
#### ⛓ Serial mode with [`describe.serial`](./api/class-test#test-describe-serial)
|
#### ⛓ Serial mode with [`describe.serial`](./api/class-test#test-describe-serial)
|
||||||
|
|
||||||
|
|
@ -2163,7 +2341,7 @@ Step information is exposed in reporters API.
|
||||||
|
|
||||||
#### 🌎 Launch web server before running tests
|
#### 🌎 Launch web server before running tests
|
||||||
|
|
||||||
To launch a server during the tests, use the [`webServer`](./test-webserver) option in the configuration file. The server will wait for a given url to be available before running the tests, and the url will be passed over to Playwright as a [`baseURL`](./api/class-fixtures#fixtures-base-url) when creating a context.
|
To launch a server during the tests, use the [`webServer`](./test-webserver) option in the configuration file. The server will wait for a given url to be available before running the tests, and the url will be passed over to Playwright as a [`baseURL`](./api/class-testoptions#test-options-base-url) when creating a context.
|
||||||
|
|
||||||
```ts title="playwright.config.ts"
|
```ts title="playwright.config.ts"
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
@ -2192,7 +2370,7 @@ Learn more in the [documentation](./test-webserver).
|
||||||
#### Playwright Test
|
#### Playwright Test
|
||||||
|
|
||||||
- **⚡️ Introducing [Reporter API](https://github.com/microsoft/playwright/blob/65a9037461ffc15d70cdc2055832a0c5512b227c/packages/playwright-test/types/testReporter.d.ts)** which is already used to create an [Allure Playwright reporter](https://github.com/allure-framework/allure-js/pull/297).
|
- **⚡️ Introducing [Reporter API](https://github.com/microsoft/playwright/blob/65a9037461ffc15d70cdc2055832a0c5512b227c/packages/playwright-test/types/testReporter.d.ts)** which is already used to create an [Allure Playwright reporter](https://github.com/allure-framework/allure-js/pull/297).
|
||||||
- **⛺️ New [`baseURL` fixture](./test-configuration#basic-options)** to support relative paths in tests.
|
- **⛺️ New [`baseURL` fixture](./test-configuration#basic-configuration)** to support relative paths in tests.
|
||||||
|
|
||||||
|
|
||||||
#### Playwright
|
#### Playwright
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,52 @@ title: "Release notes"
|
||||||
toc_max_heading_level: 2
|
toc_max_heading_level: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Version 1.43
|
||||||
|
|
||||||
|
### New APIs
|
||||||
|
|
||||||
|
- Method [`method: BrowserContext.clearCookies`] now supports filters to remove only some cookies.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Clear all cookies.
|
||||||
|
context.clear_cookies()
|
||||||
|
# New: clear cookies with a particular name.
|
||||||
|
context.clear_cookies(name="session-id")
|
||||||
|
# New: clear cookies for a particular domain.
|
||||||
|
context.clear_cookies(domain="my-origin.com")
|
||||||
|
```
|
||||||
|
|
||||||
|
- New method [`method: Locator.contentFrame`] converts a [Locator] object to a [FrameLocator]. This can be useful when you have a [Locator] object obtained somewhere, and later on would like to interact with the content inside the frame.
|
||||||
|
|
||||||
|
```python
|
||||||
|
locator = page.locator("iframe[name='embedded']")
|
||||||
|
# ...
|
||||||
|
frame_locator = locator.content_frame
|
||||||
|
frame_locator.getByRole("button").click()
|
||||||
|
```
|
||||||
|
|
||||||
|
- New method [`method: FrameLocator.owner`] converts a [FrameLocator] object to a [Locator]. This can be useful when you have a [FrameLocator] object obtained somewhere, and later on would like to interact with the `iframe` element.
|
||||||
|
|
||||||
|
```python
|
||||||
|
frame_locator = page.frame_locator("iframe[name='embedded']")
|
||||||
|
# ...
|
||||||
|
locator = frame_locator.owner
|
||||||
|
expect(locator).to_be_visible()
|
||||||
|
```
|
||||||
|
|
||||||
|
- Conda builds are now published for macOS-arm64 and Linux-arm64.
|
||||||
|
|
||||||
|
### Browser Versions
|
||||||
|
|
||||||
|
* Chromium 124.0.6367.8
|
||||||
|
* Mozilla Firefox 124.0
|
||||||
|
* WebKit 17.4
|
||||||
|
|
||||||
|
This version was also tested against the following stable channels:
|
||||||
|
|
||||||
|
* Google Chrome 123
|
||||||
|
* Microsoft Edge 123
|
||||||
|
|
||||||
## Version 1.42
|
## Version 1.42
|
||||||
|
|
||||||
### New Locator Handler
|
### New Locator Handler
|
||||||
|
|
|
||||||
|
|
@ -7,57 +7,130 @@ title: "Running and debugging tests"
|
||||||
|
|
||||||
You can run a single test, a set of tests or all tests. Tests can be run on different browsers. By default, tests are run in a headless manner, meaning no browser window will be opened while running the tests and results will be seen in the terminal. If you prefer, you can run your tests in headed mode by using the `headless` test run parameter.
|
You can run a single test, a set of tests or all tests. Tests can be run on different browsers. By default, tests are run in a headless manner, meaning no browser window will be opened while running the tests and results will be seen in the terminal. If you prefer, you can run your tests in headed mode by using the `headless` test run parameter.
|
||||||
|
|
||||||
- Running all tests
|
**You will learn**
|
||||||
|
|
||||||
```bash
|
- [How to run tests](#running-tests)
|
||||||
dotnet test
|
- [How to debug tests](#debugging-tests)
|
||||||
```
|
|
||||||
|
|
||||||
- Running a single test file
|
## Running tests
|
||||||
|
|
||||||
```bash
|
### Run all tests
|
||||||
dotnet test --filter "MyClassName"
|
|
||||||
```
|
|
||||||
|
|
||||||
- Run a set of test files
|
Use the following command to run all tests.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dotnet test --filter "MyClassName1|MyClassName2"
|
dotnet test
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run the test with the title
|
### Run your tests in headed mode
|
||||||
|
|
||||||
```bash
|
Use the following command to run your tests in headed mode opening a browser window for each test.
|
||||||
dotnet test --filter "Name~TestMethod1"
|
|
||||||
```
|
|
||||||
|
|
||||||
- Running Tests on specific browsers
|
```bash tab=bash-bash lang=csharp
|
||||||
|
HEADED=1 dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
```bash
|
```batch tab=bash-batch lang=csharp
|
||||||
dotnet test -- Playwright.BrowserName=webkit
|
set HEADED=1
|
||||||
```
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
- Running Tests on multiple browsers
|
```powershell tab=bash-powershell lang=csharp
|
||||||
|
$env:HEADED="1"
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
To run your test on multiple browsers or configurations, you need to invoke the `dotnet test` command multiple times. There you can then either specify the `BROWSER` environment variable or set the `Playwright.BrowserName` via the runsettings file:
|
### Run tests on different browsers: Browser env
|
||||||
|
|
||||||
```bash
|
Specify which browser you would like to run your tests on via the `BROWSER` environment variable.
|
||||||
dotnet test --settings:chromium.runsettings
|
|
||||||
dotnet test --settings:firefox.runsettings
|
|
||||||
dotnet test --settings:webkit.runsettings
|
|
||||||
```
|
|
||||||
|
|
||||||
```xml
|
```bash tab=bash-bash lang=csharp
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
BROWSER=webkit dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
```batch tab=bash-batch lang=csharp
|
||||||
|
set BROWSER=webkit
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell tab=bash-powershell lang=csharp
|
||||||
|
$env:BROWSER="webkit"
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run tests on different browsers: launch configuration
|
||||||
|
|
||||||
|
Specify which browser you would like to run your tests on by adjusting the launch configuration options:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test -- Playwright.BrowserName=webkit
|
||||||
|
```
|
||||||
|
|
||||||
|
To run your test on multiple browsers or configurations, you need to invoke the `dotnet test` command multiple times. There you can then either specify the `BROWSER` environment variable or set the `Playwright.BrowserName` via the runsettings file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test --settings:chromium.runsettings
|
||||||
|
dotnet test --settings:firefox.runsettings
|
||||||
|
dotnet test --settings:webkit.runsettings
|
||||||
|
```
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RunSettings>
|
<RunSettings>
|
||||||
<Playwright>
|
<Playwright>
|
||||||
<BrowserName>chromium</BrowserName>
|
<BrowserName>chromium</BrowserName>
|
||||||
</Playwright>
|
</Playwright>
|
||||||
</RunSettings>
|
</RunSettings>
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information see [selective unit tests](https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=mstest) in the Microsoft docs.
|
For more information see [selective unit tests](https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=mstest) in the Microsoft docs.
|
||||||
|
|
||||||
|
### Run specific tests
|
||||||
|
|
||||||
|
To run a single test file, use the filter flag followed by the class name of the test you want to run.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test --filter "ExampleTest"
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a set of test files, use the filter flag followed by the class names of the tests you want to run.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test --filter "ExampleTest1|ExampleTest2"
|
||||||
|
```
|
||||||
|
|
||||||
|
To run a test with a specific title use the filter flag followed by *Name~* and the title of the test.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test --filter "Name~GetStartedLink"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run tests with multiple workers:
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
groupId="test-runners"
|
||||||
|
defaultValue="nunit"
|
||||||
|
values={[
|
||||||
|
{label: 'NUnit', value: 'nunit'},
|
||||||
|
{label: 'MSTest', value: 'mstest'}
|
||||||
|
]
|
||||||
|
}>
|
||||||
|
<TabItem value="nunit">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test -- NUnit.NumberOfTestWorkers=5
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="mstest">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test -- MSTest.Parallelize.Workers=5
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
## Debugging Tests
|
## Debugging Tests
|
||||||
|
|
||||||
Since Playwright runs in .NET, you can debug it with your debugger of choice in e.g. Visual Studio Code or Visual Studio. Playwright comes with the Playwright Inspector which allows you to step through Playwright API calls, see their debug logs and explore [locators](./locators.md).
|
Since Playwright runs in .NET, you can debug it with your debugger of choice in e.g. Visual Studio Code or Visual Studio. Playwright comes with the Playwright Inspector which allows you to step through Playwright API calls, see their debug logs and explore [locators](./locators.md).
|
||||||
|
|
@ -76,7 +149,7 @@ $env:PWDEBUG=1
|
||||||
dotnet test
|
dotnet test
|
||||||
```
|
```
|
||||||
|
|
||||||
<img width="712" alt="Playwright Inspector" src="https://user-images.githubusercontent.com/883973/108614092-8c478a80-73ac-11eb-9597-67dfce110e00.png"></img>
|

|
||||||
|
|
||||||
Check out our [debugging guide](./debug.md) to learn more about the [Playwright Inspector](./debug.md#playwright-inspector) as well as debugging with [Browser Developer tools](./debug.md#browser-developer-tools).
|
Check out our [debugging guide](./debug.md) to learn more about the [Playwright Inspector](./debug.md#playwright-inspector) as well as debugging with [Browser Developer tools](./debug.md#browser-developer-tools).
|
||||||
|
|
||||||
|
|
|
||||||
137
docs/src/test-api/class-fullconfig.md
Normal file
137
docs/src/test-api/class-fullconfig.md
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
# class: FullConfig
|
||||||
|
* since: v1.10
|
||||||
|
* langs: js
|
||||||
|
|
||||||
|
Resolved configuration which is accessible via [`property: TestInfo.config`] and is passed to the test reporters. To see the format of Playwright configuration file, please see [TestConfig] instead.
|
||||||
|
|
||||||
|
## property: FullConfig.configFile
|
||||||
|
* since: v1.20
|
||||||
|
- type: ?<[string]>
|
||||||
|
|
||||||
|
Path to the configuration file used to run the tests. The value is an empty string if no config file was used.
|
||||||
|
|
||||||
|
## property: FullConfig.forbidOnly
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[boolean]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.forbidOnly`].
|
||||||
|
|
||||||
|
## property: FullConfig.fullyParallel
|
||||||
|
* since: v1.20
|
||||||
|
- type: <[boolean]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.fullyParallel`].
|
||||||
|
|
||||||
|
## property: FullConfig.globalSetup
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[string]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.globalSetup`].
|
||||||
|
|
||||||
|
## property: FullConfig.globalTeardown
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[string]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.globalTeardown`].
|
||||||
|
|
||||||
|
## property: FullConfig.globalTimeout
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[int]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.globalTimeout`].
|
||||||
|
|
||||||
|
## property: FullConfig.grep
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[RegExp]|[Array]<[RegExp]>>
|
||||||
|
|
||||||
|
See [`property: TestConfig.grep`].
|
||||||
|
|
||||||
|
## property: FullConfig.grepInvert
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[RegExp]|[Array]<[RegExp]>>
|
||||||
|
|
||||||
|
See [`property: TestConfig.grepInvert`].
|
||||||
|
|
||||||
|
## property: FullConfig.maxFailures
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[int]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.maxFailures`].
|
||||||
|
|
||||||
|
## property: FullConfig.metadata
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[Metadata]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.metadata`].
|
||||||
|
|
||||||
|
## property: FullConfig.preserveOutput
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[PreserveOutput]<"always"|"never"|"failures-only">>
|
||||||
|
|
||||||
|
See [`property: TestConfig.preserveOutput`].
|
||||||
|
|
||||||
|
## property: FullConfig.projects
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[Array]<[FullProject]>>
|
||||||
|
|
||||||
|
List of resolved projects.
|
||||||
|
|
||||||
|
## property: FullConfig.quiet
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[boolean]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.quiet`].
|
||||||
|
|
||||||
|
## property: FullConfig.reporter
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]|[Array]<[Object]>|[BuiltInReporter]<"list"|"dot"|"line"|"github"|"json"|"junit"|"null"|"html">>
|
||||||
|
- `0` <[string]> Reporter name or module or file path
|
||||||
|
- `1` <[Object]> An object with reporter options if any
|
||||||
|
|
||||||
|
See [`property: TestConfig.reporter`].
|
||||||
|
|
||||||
|
## property: FullConfig.reportSlowTests
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[Object]>
|
||||||
|
- `max` <[int]> The maximum number of slow test files to report. Defaults to `5`.
|
||||||
|
- `threshold` <[float]> Test duration in milliseconds that is considered slow. Defaults to 15 seconds.
|
||||||
|
|
||||||
|
See [`property: TestConfig.reportSlowTests`].
|
||||||
|
|
||||||
|
## property: FullConfig.rootDir
|
||||||
|
* since: v1.20
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
Base directory for all relative paths used in the reporters.
|
||||||
|
|
||||||
|
## property: FullConfig.shard
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[Object]>
|
||||||
|
- `total` <[int]> The total number of shards.
|
||||||
|
- `current` <[int]> The index of the shard to execute, one-based.
|
||||||
|
|
||||||
|
See [`property: TestConfig.shard`].
|
||||||
|
|
||||||
|
## property: FullConfig.updateSnapshots
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[UpdateSnapshots]<"all"|"none"|"missing">>
|
||||||
|
|
||||||
|
See [`property: TestConfig.updateSnapshots`].
|
||||||
|
|
||||||
|
## property: FullConfig.version
|
||||||
|
* since: v1.20
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
Playwright version.
|
||||||
|
|
||||||
|
## property: FullConfig.webServer
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[Object]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.webServer`].
|
||||||
|
|
||||||
|
## property: FullConfig.workers
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[int]>
|
||||||
|
|
||||||
|
See [`property: TestConfig.workers`].
|
||||||
95
docs/src/test-api/class-fullproject.md
Normal file
95
docs/src/test-api/class-fullproject.md
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
# class: FullProject
|
||||||
|
* since: v1.10
|
||||||
|
* langs: js
|
||||||
|
|
||||||
|
Runtime representation of the test project configuration. It is accessible in the tests via [`property: TestInfo.project`] and [`property: WorkerInfo.project`] and is passed to the test reporters. To see the format of the project in the Playwright configuration file please see [TestProject] instead.
|
||||||
|
|
||||||
|
## property: FullProject.dependencies
|
||||||
|
* since: v1.31
|
||||||
|
- type: <[Array]<[string]>>
|
||||||
|
|
||||||
|
See [`property: TestProject.dependencies`].
|
||||||
|
|
||||||
|
## property: FullProject.grep
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[RegExp]|[Array]<[RegExp]>>
|
||||||
|
|
||||||
|
See [`property: TestProject.grep`].
|
||||||
|
|
||||||
|
## property: FullProject.grepInvert
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[null]|[RegExp]|[Array]<[RegExp]>>
|
||||||
|
|
||||||
|
See [`property: TestProject.grepInvert`].
|
||||||
|
|
||||||
|
## property: FullProject.metadata
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[Metadata]>
|
||||||
|
|
||||||
|
See [`property: TestProject.metadata`].
|
||||||
|
|
||||||
|
## property: FullProject.name
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
See [`property: TestProject.name`].
|
||||||
|
|
||||||
|
## property: FullProject.snapshotDir
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
See [`property: TestProject.snapshotDir`].
|
||||||
|
|
||||||
|
## property: FullProject.outputDir
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
See [`property: TestProject.outputDir`].
|
||||||
|
|
||||||
|
## property: FullProject.repeatEach
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[int]>
|
||||||
|
|
||||||
|
See [`property: TestProject.repeatEach`].
|
||||||
|
|
||||||
|
## property: FullProject.retries
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[int]>
|
||||||
|
|
||||||
|
See [`property: TestProject.retries`].
|
||||||
|
|
||||||
|
## property: FullProject.teardown
|
||||||
|
* since: v1.34
|
||||||
|
- type: ?<[string]>
|
||||||
|
|
||||||
|
See [`property: TestProject.teardown`].
|
||||||
|
|
||||||
|
## property: FullProject.testDir
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
See [`property: TestProject.testDir`].
|
||||||
|
|
||||||
|
## property: FullProject.testIgnore
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]|[RegExp]|[Array]<[string]|[RegExp]>>
|
||||||
|
|
||||||
|
See [`property: TestProject.testIgnore`].
|
||||||
|
|
||||||
|
## property: FullProject.testMatch
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[string]|[RegExp]|[Array]<[string]|[RegExp]>>
|
||||||
|
|
||||||
|
See [`property: TestProject.testMatch`].
|
||||||
|
|
||||||
|
## property: FullProject.timeout
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[int]>
|
||||||
|
|
||||||
|
See [`property: TestProject.timeout`].
|
||||||
|
|
||||||
|
## property: FullProject.use
|
||||||
|
* since: v1.10
|
||||||
|
- type: <[Fixtures]>
|
||||||
|
|
||||||
|
See [`property: TestProject.use`].
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
* langs: js
|
* langs: js
|
||||||
|
|
||||||
Playwright Test provides many options to configure how your tests are collected and executed, for example `timeout` or `testDir`. These options are described in the [TestConfig] object in the [configuration file](../test-configuration.md).
|
Playwright Test provides many options to configure how your tests are collected and executed, for example `timeout` or `testDir`. These options are described in the [TestConfig] object in the [configuration file](../test-configuration.md). This type describes format of the configuration file, to access resolved configuration parameters at run time use [FullConfig].
|
||||||
|
|
||||||
Playwright Test supports running multiple test projects at the same time. Project-specific options should be put to [`property: TestConfig.projects`], but top-level [TestConfig] can also define base options shared between all projects.
|
Playwright Test supports running multiple test projects at the same time. Project-specific options should be put to [`property: TestConfig.projects`], but top-level [TestConfig] can also define base options shared between all projects.
|
||||||
|
|
||||||
|
|
@ -41,19 +41,20 @@ export default defineConfig({
|
||||||
- type: ?<[Object]>
|
- type: ?<[Object]>
|
||||||
- `timeout` ?<[int]> Default timeout for async expect matchers in milliseconds, defaults to 5000ms.
|
- `timeout` ?<[int]> Default timeout for async expect matchers in milliseconds, defaults to 5000ms.
|
||||||
- `toHaveScreenshot` ?<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot#1`] method.
|
- `toHaveScreenshot` ?<[Object]> Configuration for the [`method: PageAssertions.toHaveScreenshot#1`] method.
|
||||||
- `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
|
|
||||||
- `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default.
|
|
||||||
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
|
|
||||||
- `animations` ?<[ScreenshotAnimations]<"allow"|"disabled">> See [`option: animations`] in [`method: Page.screenshot`]. Defaults to `"disabled"`.
|
- `animations` ?<[ScreenshotAnimations]<"allow"|"disabled">> See [`option: animations`] in [`method: Page.screenshot`]. Defaults to `"disabled"`.
|
||||||
- `caret` ?<[ScreenshotCaret]<"hide"|"initial">> See [`option: caret`] in [`method: Page.screenshot`]. Defaults to `"hide"`.
|
- `caret` ?<[ScreenshotCaret]<"hide"|"initial">> See [`option: caret`] in [`method: Page.screenshot`]. Defaults to `"hide"`.
|
||||||
|
- `maxDiffPixels` ?<[int]> An acceptable amount of pixels that could be different, unset by default.
|
||||||
|
- `maxDiffPixelRatio` ?<[float]> An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
|
||||||
- `scale` ?<[ScreenshotScale]<"css"|"device">> See [`option: scale`] in [`method: Page.screenshot`]. Defaults to `"css"`.
|
- `scale` ?<[ScreenshotScale]<"css"|"device">> See [`option: scale`] in [`method: Page.screenshot`]. Defaults to `"css"`.
|
||||||
- `stylePath` ?<[string]|[Array]<[string]>> See [`option: style`] in [`method: Page.screenshot`].
|
- `stylePath` ?<[string]|[Array]<[string]>> See [`option: style`] in [`method: Page.screenshot`].
|
||||||
|
- `threshold` ?<[float]> An acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
|
||||||
- `toMatchSnapshot` ?<[Object]> Configuration for the [`method: SnapshotAssertions.toMatchSnapshot#1`] method.
|
- `toMatchSnapshot` ?<[Object]> Configuration for the [`method: SnapshotAssertions.toMatchSnapshot#1`] method.
|
||||||
- `threshold` ?<[float]> an acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
|
- `maxDiffPixels` ?<[int]> An acceptable amount of pixels that could be different, unset by default.
|
||||||
- `maxDiffPixels` ?<[int]> an acceptable amount of pixels that could be different, unset by default.
|
- `maxDiffPixelRatio` ?<[float]> An acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
|
||||||
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
|
- `threshold` ?<[float]> An acceptable perceived color difference between the same pixel in compared images, ranging from `0` (strict) and `1` (lax). `"pixelmatch"` comparator computes color difference in [YIQ color space](https://en.wikipedia.org/wiki/YIQ) and defaults `threshold` value to `0.2`.
|
||||||
- `toPass` ?<[Object]> Configuration for the [expect(value).toPass()](../test-assertions.md#expecttopass) method.
|
- `toPass` ?<[Object]> Configuration for the [expect(value).toPass()](../test-assertions.md#expecttopass) method.
|
||||||
- `timeout` ?<[int]> timeout for toPass method in milliseconds.
|
- `intervals` ?<[Array]<[int]>> Probe intervals for toPass method in milliseconds.
|
||||||
|
- `timeout` ?<[int]> Timeout for toPass method in milliseconds.
|
||||||
|
|
||||||
Configuration for the `expect` assertion library. Learn more about [various timeouts](../test-timeouts.md).
|
Configuration for the `expect` assertion library. Learn more about [various timeouts](../test-timeouts.md).
|
||||||
|
|
||||||
|
|
@ -111,7 +112,7 @@ export default defineConfig({
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[string]>
|
- type: ?<[string]>
|
||||||
|
|
||||||
Path to the global setup file. This file will be required and run before all the tests. It must export a single function that takes a [`TestConfig`] argument.
|
Path to the global setup file. This file will be required and run before all the tests. It must export a single function that takes a [FullConfig] argument.
|
||||||
|
|
||||||
Learn more about [global setup and teardown](../test-global-setup-teardown.md).
|
Learn more about [global setup and teardown](../test-global-setup-teardown.md).
|
||||||
|
|
||||||
|
|
@ -457,8 +458,8 @@ export default defineConfig({
|
||||||
## property: TestConfig.shard
|
## property: TestConfig.shard
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[null]|[Object]>
|
- type: ?<[null]|[Object]>
|
||||||
- `total` <[int]> The total number of shards.
|
|
||||||
- `current` <[int]> The index of the shard to execute, one-based.
|
- `current` <[int]> The index of the shard to execute, one-based.
|
||||||
|
- `total` <[int]> The total number of shards.
|
||||||
|
|
||||||
Shard tests and execute only the selected shard. Specify in the one-based form like `{ total: 5, current: 2 }`.
|
Shard tests and execute only the selected shard. Specify in the one-based form like `{ total: 5, current: 2 }`.
|
||||||
|
|
||||||
|
|
@ -588,15 +589,15 @@ export default defineConfig({
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[Object]|[Array]<[Object]>>
|
- type: ?<[Object]|[Array]<[Object]>>
|
||||||
- `command` <[string]> Shell command to start. For example `npm run start`..
|
- `command` <[string]> Shell command to start. For example `npm run start`..
|
||||||
- `port` ?<[int]> The port that your http server is expected to appear on. It does wait until it accepts connections. Either `port` or `url` should be specified.
|
- `cwd` ?<[string]> Current working directory of the spawned process, defaults to the directory of the configuration file.
|
||||||
- `url` ?<[string]> The url on your http server that is expected to return a 2xx, 3xx, 400, 401, 402, or 403 status code when the server is ready to accept connections. Redirects (3xx status codes) are being followed and the new location is checked. Either `port` or `url` should be specified.
|
- `env` ?<[Object]<[string], [string]>> Environment variables to set for the command, `process.env` by default.
|
||||||
- `ignoreHTTPSErrors` ?<[boolean]> Whether to ignore HTTPS errors when fetching the `url`. Defaults to `false`.
|
- `ignoreHTTPSErrors` ?<[boolean]> Whether to ignore HTTPS errors when fetching the `url`. Defaults to `false`.
|
||||||
- `timeout` ?<[int]> How long to wait for the process to start up and be available in milliseconds. Defaults to 60000.
|
- `port` ?<[int]> The port that your http server is expected to appear on. It does wait until it accepts connections. Either `port` or `url` should be specified.
|
||||||
- `reuseExistingServer` ?<[boolean]> If true, it will re-use an existing server on the `port` or `url` when available. If no server is running on that `port` or `url`, it will run the command to start a new server. If `false`, it will throw if an existing process is listening on the `port` or `url`. This should be commonly set to `!process.env.CI` to allow the local dev server when running tests locally.
|
- `reuseExistingServer` ?<[boolean]> If true, it will re-use an existing server on the `port` or `url` when available. If no server is running on that `port` or `url`, it will run the command to start a new server. If `false`, it will throw if an existing process is listening on the `port` or `url`. This should be commonly set to `!process.env.CI` to allow the local dev server when running tests locally.
|
||||||
- `stdout` ?<["pipe"|"ignore"]> If `"pipe"`, it will pipe the stdout of the command to the process stdout. If `"ignore"`, it will ignore the stdout of the command. Default to `"ignore"`.
|
- `stdout` ?<["pipe"|"ignore"]> If `"pipe"`, it will pipe the stdout of the command to the process stdout. If `"ignore"`, it will ignore the stdout of the command. Default to `"ignore"`.
|
||||||
- `stderr` ?<["pipe"|"ignore"]> Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`.
|
- `stderr` ?<["pipe"|"ignore"]> Whether to pipe the stderr of the command to the process stderr or ignore it. Defaults to `"pipe"`.
|
||||||
- `cwd` ?<[string]> Current working directory of the spawned process, defaults to the directory of the configuration file.
|
- `timeout` ?<[int]> How long to wait for the process to start up and be available in milliseconds. Defaults to 60000.
|
||||||
- `env` ?<[Object]<[string], [string]>> Environment variables to set for the command, `process.env` by default.
|
- `url` ?<[string]> The url on your http server that is expected to return a 2xx, 3xx, 400, 401, 402, or 403 status code when the server is ready to accept connections. Redirects (3xx status codes) are being followed and the new location is checked. Either `port` or `url` should be specified.
|
||||||
|
|
||||||
Launch a development web server (or multiple) during the tests.
|
Launch a development web server (or multiple) during the tests.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ Column number where the currently running test is declared.
|
||||||
|
|
||||||
## property: TestInfo.config
|
## property: TestInfo.config
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: <[TestConfig]>
|
- type: <[FullConfig]>
|
||||||
|
|
||||||
Processed configuration from the [configuration file](../test-configuration.md).
|
Processed configuration from the [configuration file](../test-configuration.md).
|
||||||
|
|
||||||
|
|
@ -279,7 +279,7 @@ Also available as `process.env.TEST_PARALLEL_INDEX`. Learn more about [paralleli
|
||||||
|
|
||||||
## property: TestInfo.project
|
## property: TestInfo.project
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: <[TestProject]>
|
- type: <[FullProject]>
|
||||||
|
|
||||||
Processed project configuration from the [configuration file](../test-configuration.md).
|
Processed project configuration from the [configuration file](../test-configuration.md).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -556,10 +556,10 @@ export default defineConfig({
|
||||||
Whether to record trace for each test. Defaults to `'off'`.
|
Whether to record trace for each test. Defaults to `'off'`.
|
||||||
* `'off'`: Do not record trace.
|
* `'off'`: Do not record trace.
|
||||||
* `'on'`: Record trace for each test.
|
* `'on'`: Record trace for each test.
|
||||||
* `'retain-on-failure'`: Record trace for each test, but remove all traces from successful test runs.
|
|
||||||
* `'on-first-retry'`: Record trace only when retrying a test for the first time.
|
* `'on-first-retry'`: Record trace only when retrying a test for the first time.
|
||||||
* `'on-all-retries'`: Record traces only when retrying for all retries.
|
* `'on-all-retries'`: Record trace only when retrying a test.
|
||||||
* `'retain-on-first-failure'`: Record traces only when the test fails for the first time.
|
* `'retain-on-failure'`: Record trace for each test. When test run passes, remove the recorded trace.
|
||||||
|
* `'retain-on-first-failure'`: Record trace for the first run of each test, but not for retires. When test run passes, remove the recorded trace.
|
||||||
|
|
||||||
For more control, pass an object that specifies `mode` and trace features to enable.
|
For more control, pass an object that specifies `mode` and trace features to enable.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
* langs: js
|
* langs: js
|
||||||
|
|
||||||
Playwright Test supports running multiple test projects at the same time. This is useful for running tests in multiple configurations. For example, consider running tests against multiple browsers.
|
Playwright Test supports running multiple test projects at the same time. This is useful for running tests in multiple configurations. For example, consider running tests against multiple browsers. This type describes format of a project in the configuration file, to access resolved configuration parameters at run time use [FullProject].
|
||||||
|
|
||||||
`TestProject` encapsulates configuration specific to a single project. Projects are configured in [`property: TestConfig.projects`] specified in the [configuration file](../test-configuration.md). Note that all properties of [TestProject] are available in the top-level [TestConfig], in which case they are shared between all projects.
|
`TestProject` encapsulates configuration specific to a single project. Projects are configured in [`property: TestConfig.projects`] specified in the [configuration file](../test-configuration.md). Note that all properties of [TestProject] are available in the top-level [TestConfig], in which case they are shared between all projects.
|
||||||
|
|
||||||
|
|
@ -104,6 +104,7 @@ export default defineConfig({
|
||||||
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
|
- `maxDiffPixelRatio` ?<[float]> an acceptable ratio of pixels that are different to the total amount of pixels, between `0` and `1` , unset by default.
|
||||||
- `toPass` ?<[Object]> Configuration for the [expect(value).toPass()](../test-assertions.md) method.
|
- `toPass` ?<[Object]> Configuration for the [expect(value).toPass()](../test-assertions.md) method.
|
||||||
- `timeout` ?<[int]> timeout for toPass method in milliseconds.
|
- `timeout` ?<[int]> timeout for toPass method in milliseconds.
|
||||||
|
- `intervals` ?<[Array]<[int]>> probe intervals for toPass method in milliseconds.
|
||||||
|
|
||||||
Configuration for the `expect` assertion library.
|
Configuration for the `expect` assertion library.
|
||||||
|
|
||||||
|
|
@ -134,6 +135,39 @@ Filter to only run tests with a title **not** matching one of the patterns. This
|
||||||
|
|
||||||
`grepInvert` option is also useful for [tagging tests](../test-annotations.md#tag-tests).
|
`grepInvert` option is also useful for [tagging tests](../test-annotations.md#tag-tests).
|
||||||
|
|
||||||
|
## property: TestProject.ignoreSnapshots
|
||||||
|
* since: v1.44
|
||||||
|
- type: ?<[boolean]>
|
||||||
|
|
||||||
|
Whether to skip snapshot expectations, such as `expect(value).toMatchSnapshot()` and `await expect(page).toHaveScreenshot()`.
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
The following example will only perform screenshot assertions on Chromium.
|
||||||
|
|
||||||
|
```js title="playwright.config.ts"
|
||||||
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: devices['Desktop Chrome'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'firefox',
|
||||||
|
use: devices['Desktop Firefox'],
|
||||||
|
ignoreSnapshots: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'webkit',
|
||||||
|
use: devices['Desktop Safari'],
|
||||||
|
ignoreSnapshots: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## property: TestProject.metadata
|
## property: TestProject.metadata
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[Metadata]>
|
- type: ?<[Metadata]>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
## property: WorkerInfo.config
|
## property: WorkerInfo.config
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: <[TestConfig]>
|
- type: <[FullConfig]>
|
||||||
|
|
||||||
Processed configuration from the [configuration file](../test-configuration.md).
|
Processed configuration from the [configuration file](../test-configuration.md).
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ Also available as `process.env.TEST_PARALLEL_INDEX`. Learn more about [paralleli
|
||||||
|
|
||||||
## property: WorkerInfo.project
|
## property: WorkerInfo.project
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: <[TestProject]>
|
- type: <[FullProject]>
|
||||||
|
|
||||||
Processed project configuration from the [configuration file](../test-configuration.md).
|
Processed project configuration from the [configuration file](../test-configuration.md).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,15 @@ title: "Assertions"
|
||||||
| [`method: LocatorAssertions.toBeInViewport`] | Element intersects viewport |
|
| [`method: LocatorAssertions.toBeInViewport`] | Element intersects viewport |
|
||||||
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
|
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
|
||||||
| [`method: LocatorAssertions.toContainText`] | Element contains text |
|
| [`method: LocatorAssertions.toContainText`] | Element contains text |
|
||||||
|
| [`method: LocatorAssertions.toHaveAccessibleDescription`] | Element has a matching [accessible description](https://w3c.github.io/accname/#dfn-accessible-description) |
|
||||||
|
| [`method: LocatorAssertions.toHaveAccessibleName`] | Element has a matching [accessible name](https://w3c.github.io/accname/#dfn-accessible-name) |
|
||||||
| [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute |
|
| [`method: LocatorAssertions.toHaveAttribute`] | Element has a DOM attribute |
|
||||||
| [`method: LocatorAssertions.toHaveClass`] | Element has a class property |
|
| [`method: LocatorAssertions.toHaveClass`] | Element has a class property |
|
||||||
| [`method: LocatorAssertions.toHaveCount`] | List has exact number of children |
|
| [`method: LocatorAssertions.toHaveCount`] | List has exact number of children |
|
||||||
| [`method: LocatorAssertions.toHaveCSS`] | Element has CSS property |
|
| [`method: LocatorAssertions.toHaveCSS`] | Element has CSS property |
|
||||||
| [`method: LocatorAssertions.toHaveId`] | Element has an ID |
|
| [`method: LocatorAssertions.toHaveId`] | Element has an ID |
|
||||||
| [`method: LocatorAssertions.toHaveJSProperty`] | Element has a JavaScript property |
|
| [`method: LocatorAssertions.toHaveJSProperty`] | Element has a JavaScript property |
|
||||||
|
| [`method: LocatorAssertions.toHaveRole`] | Element has a specific [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles) |
|
||||||
| [`method: LocatorAssertions.toHaveText`] | Element matches text |
|
| [`method: LocatorAssertions.toHaveText`] | Element matches text |
|
||||||
| [`method: LocatorAssertions.toHaveValue`] | Input has a value |
|
| [`method: LocatorAssertions.toHaveValue`] | Input has a value |
|
||||||
| [`method: LocatorAssertions.toHaveValues`] | Select has options selected |
|
| [`method: LocatorAssertions.toHaveValues`] | Select has options selected |
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,15 @@ Note that retrying assertions are async, so you must `await` them.
|
||||||
| [await expect(locator).toBeInViewport()](./api/class-locatorassertions.md#locator-assertions-to-be-in-viewport) | Element intersects viewport |
|
| [await expect(locator).toBeInViewport()](./api/class-locatorassertions.md#locator-assertions-to-be-in-viewport) | Element intersects viewport |
|
||||||
| [await expect(locator).toBeVisible()](./api/class-locatorassertions.md#locator-assertions-to-be-visible) | Element is visible |
|
| [await expect(locator).toBeVisible()](./api/class-locatorassertions.md#locator-assertions-to-be-visible) | Element is visible |
|
||||||
| [await expect(locator).toContainText()](./api/class-locatorassertions.md#locator-assertions-to-contain-text) | Element contains text |
|
| [await expect(locator).toContainText()](./api/class-locatorassertions.md#locator-assertions-to-contain-text) | Element contains text |
|
||||||
|
| [await expect(locator).toHaveAccessibleDescription()](./api/class-locatorassertions.md#locator-assertions-to-have-accessible-description) | Element has a matching [accessible description](https://w3c.github.io/accname/#dfn-accessible-description) |
|
||||||
|
| [await expect(locator).toHaveAccessibleName()](./api/class-locatorassertions.md#locator-assertions-to-have-accessible-name) | Element has a matching [accessible name](https://w3c.github.io/accname/#dfn-accessible-name) |
|
||||||
| [await expect(locator).toHaveAttribute()](./api/class-locatorassertions.md#locator-assertions-to-have-attribute) | Element has a DOM attribute |
|
| [await expect(locator).toHaveAttribute()](./api/class-locatorassertions.md#locator-assertions-to-have-attribute) | Element has a DOM attribute |
|
||||||
| [await expect(locator).toHaveClass()](./api/class-locatorassertions.md#locator-assertions-to-have-class) | Element has a class property |
|
| [await expect(locator).toHaveClass()](./api/class-locatorassertions.md#locator-assertions-to-have-class) | Element has a class property |
|
||||||
| [await expect(locator).toHaveCount()](./api/class-locatorassertions.md#locator-assertions-to-have-count) | List has exact number of children |
|
| [await expect(locator).toHaveCount()](./api/class-locatorassertions.md#locator-assertions-to-have-count) | List has exact number of children |
|
||||||
| [await expect(locator).toHaveCSS()](./api/class-locatorassertions.md#locator-assertions-to-have-css) | Element has CSS property |
|
| [await expect(locator).toHaveCSS()](./api/class-locatorassertions.md#locator-assertions-to-have-css) | Element has CSS property |
|
||||||
| [await expect(locator).toHaveId()](./api/class-locatorassertions.md#locator-assertions-to-have-id) | Element has an ID |
|
| [await expect(locator).toHaveId()](./api/class-locatorassertions.md#locator-assertions-to-have-id) | Element has an ID |
|
||||||
| [await expect(locator).toHaveJSProperty()](./api/class-locatorassertions.md#locator-assertions-to-have-js-property) | Element has a JavaScript property |
|
| [await expect(locator).toHaveJSProperty()](./api/class-locatorassertions.md#locator-assertions-to-have-js-property) | Element has a JavaScript property |
|
||||||
|
| [await expect(locator).toHaveRole()](./api/class-locatorassertions.md#locator-assertions-to-have-role) | Element has a specific [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles) |
|
||||||
| [await expect(locator).toHaveScreenshot()](./api/class-locatorassertions.md#locator-assertions-to-have-screenshot-1) | Element has a screenshot |
|
| [await expect(locator).toHaveScreenshot()](./api/class-locatorassertions.md#locator-assertions-to-have-screenshot-1) | Element has a screenshot |
|
||||||
| [await expect(locator).toHaveText()](./api/class-locatorassertions.md#locator-assertions-to-have-text) | Element matches text |
|
| [await expect(locator).toHaveText()](./api/class-locatorassertions.md#locator-assertions-to-have-text) | Element matches text |
|
||||||
| [await expect(locator).toHaveValue()](./api/class-locatorassertions.md#locator-assertions-to-have-value) | Input has a value |
|
| [await expect(locator).toHaveValue()](./api/class-locatorassertions.md#locator-assertions-to-have-value) | Input has a value |
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,15 @@ Complete set of Playwright Test options is available in the [configuration file]
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| :- | :- |
|
| :- | :- |
|
||||||
| Non-option arguments | Each argument is treated as a regular expression matched against the full test file path. Only tests from the files matching the pattern will be executed. Special symbols like `$` or `*` should be escaped with `\`. In many shells/terminals you may need to quote the arguments. |
|
| Non-option arguments | Each argument is treated as a regular expression matched against the full test file path. Only tests from the files matching the pattern will be executed. Special symbols like `$` or `*` should be escaped with `\`. In many shells/terminals you may need to quote the arguments. |
|
||||||
| `--headed` | Run tests in headed browsers. Useful for debugging. |
|
|
||||||
|`--browser`| Run test in a specific browser. Available options are `"chromium"`, `"firefox"`, `"webkit"` or `"all"` to run tests in all three browsers at the same time. |
|
|
||||||
| `--debug`| Run tests with Playwright Inspector. Shortcut for `PWDEBUG=1` environment variable and `--timeout=0 --max-failures=1 --headed --workers=1` options.|
|
|
||||||
| `-c <file>` or `--config <file>`| Configuration file. If not passed, defaults to `playwright.config.ts` or `playwright.config.js` in the current directory. |
|
| `-c <file>` or `--config <file>`| Configuration file. If not passed, defaults to `playwright.config.ts` or `playwright.config.js` in the current directory. |
|
||||||
|
| `--debug`| Run tests with Playwright Inspector. Shortcut for `PWDEBUG=1` environment variable and `--timeout=0 --max-failures=1 --headed --workers=1` options.|
|
||||||
| `--forbid-only` | Whether to disallow `test.only`. Useful on CI.|
|
| `--forbid-only` | Whether to disallow `test.only`. Useful on CI.|
|
||||||
|
| `--global-timeout <number>` | Total timeout for the whole test run in milliseconds. By default, there is no global timeout. Learn more about [various timeouts](./test-timeouts.md).|
|
||||||
| `-g <grep>` or `--grep <grep>` | Only run tests matching this regular expression. For example, this will run `'should add to cart'` when passed `-g "add to cart"`. The regular expression will be tested against the string that consists of the test file name, `test.describe` titles if any, test title and all test tags, separated by spaces, e.g. `my-test.spec.ts my-suite my-test @smoke`. The filter does not apply to the tests from dependcy projects, i.e. Playwright will still run all tests from [project dependencies](./test-projects.md#dependencies). |
|
| `-g <grep>` or `--grep <grep>` | Only run tests matching this regular expression. For example, this will run `'should add to cart'` when passed `-g "add to cart"`. The regular expression will be tested against the string that consists of the test file name, `test.describe` titles if any, test title and all test tags, separated by spaces, e.g. `my-test.spec.ts my-suite my-test @smoke`. The filter does not apply to the tests from dependcy projects, i.e. Playwright will still run all tests from [project dependencies](./test-projects.md#dependencies). |
|
||||||
| `--grep-invert <grep>` | Only run tests **not** matching this regular expression. The opposite of `--grep`. The filter does not apply to the tests from dependcy projects, i.e. Playwright will still run all tests from [project dependencies](./test-projects.md#dependencies).|
|
| `--grep-invert <grep>` | Only run tests **not** matching this regular expression. The opposite of `--grep`. The filter does not apply to the tests from dependcy projects, i.e. Playwright will still run all tests from [project dependencies](./test-projects.md#dependencies).|
|
||||||
| `--global-timeout <number>` | Total timeout for the whole test run in milliseconds. By default, there is no global timeout. Learn more about [various timeouts](./test-timeouts.md).|
|
| `--headed` | Run tests in headed browsers. Useful for debugging. |
|
||||||
|
| `--ignore-snapshots` | Whether to ignore [snapshots](./test-snapshots.md). Use this when snapshot expectations are known to be different, e.g. running tests on Linux against Windows screenshots. |
|
||||||
|
| `--last-failed` | Only re-run the failures.|
|
||||||
| `--list` | list all the tests, but do not run them.|
|
| `--list` | list all the tests, but do not run them.|
|
||||||
| `--max-failures <N>` or `-x`| Stop after the first `N` test failures. Passing `-x` stops after the first failure.|
|
| `--max-failures <N>` or `-x`| Stop after the first `N` test failures. Passing `-x` stops after the first failure.|
|
||||||
| `--no-deps` | Ignore the dependencies between projects and behave as if they were not specified. |
|
| `--no-deps` | Ignore the dependencies between projects and behave as if they were not specified. |
|
||||||
|
|
@ -101,6 +102,5 @@ Complete set of Playwright Test options is available in the [configuration file]
|
||||||
| `--tag <tag>` | Only run tests with a tag matching this tag expression. Learn more about [tagging](./test-annotations.md#tag-tests). |
|
| `--tag <tag>` | Only run tests with a tag matching this tag expression. Learn more about [tagging](./test-annotations.md#tag-tests). |
|
||||||
| `--timeout <number>` | Maximum timeout in milliseconds for each test, defaults to 30 seconds. Learn more about [various timeouts](./test-timeouts.md).|
|
| `--timeout <number>` | Maximum timeout in milliseconds for each test, defaults to 30 seconds. Learn more about [various timeouts](./test-timeouts.md).|
|
||||||
| `--trace <mode>` | Force tracing mode, can be `on`, `off`, `on-first-retry`, `on-all-retries`, `retain-on-failure` |
|
| `--trace <mode>` | Force tracing mode, can be `on`, `off`, `on-first-retry`, `on-all-retries`, `retain-on-failure` |
|
||||||
| `--ignore-snapshots` | Whether to ignore [snapshots](./test-snapshots.md). Use this when snapshot expectations are known to be different, e.g. running tests on Linux against Windows screenshots. |
|
|
||||||
| `--update-snapshots` or `-u` | Whether to update [snapshots](./test-snapshots.md) with actual results instead of comparing them. Use this when snapshot expectations have changed.|
|
| `--update-snapshots` or `-u` | Whether to update [snapshots](./test-snapshots.md) with actual results instead of comparing them. Use this when snapshot expectations have changed.|
|
||||||
| `--workers <number>` or `-j <number>`| The maximum number of concurrent worker processes that run in [parallel](./test-parallel.md). |
|
| `--workers <number>` or `-j <number>`| The maximum number of concurrent worker processes that run in [parallel](./test-parallel.md). |
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let
|
||||||
|
|
||||||
```js title="src/pages/ProductsPage.spec.tsx"
|
```js title="src/pages/ProductsPage.spec.tsx"
|
||||||
import { test, expect } from '@playwright/experimental-ct-react';
|
import { test, expect } from '@playwright/experimental-ct-react';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '../playwright';
|
||||||
import { ProductsPage } from './pages/ProductsPage';
|
import { ProductsPage } from './pages/ProductsPage';
|
||||||
|
|
||||||
test('configure routing through hooks config', async ({ page, mount }) => {
|
test('configure routing through hooks config', async ({ page, mount }) => {
|
||||||
|
|
@ -343,7 +343,7 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let
|
||||||
|
|
||||||
```js title="src/pages/ProductsPage.spec.tsx"
|
```js title="src/pages/ProductsPage.spec.tsx"
|
||||||
import { test, expect } from '@playwright/experimental-ct-solid';
|
import { test, expect } from '@playwright/experimental-ct-solid';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '../playwright';
|
||||||
import { ProductsPage } from './pages/ProductsPage';
|
import { ProductsPage } from './pages/ProductsPage';
|
||||||
|
|
||||||
test('configure routing through hooks config', async ({ page, mount }) => {
|
test('configure routing through hooks config', async ({ page, mount }) => {
|
||||||
|
|
@ -374,7 +374,7 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let
|
||||||
|
|
||||||
```js title="src/pages/ProductsPage.spec.ts"
|
```js title="src/pages/ProductsPage.spec.ts"
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '../playwright';
|
||||||
import ProductsPage from './pages/ProductsPage.vue';
|
import ProductsPage from './pages/ProductsPage.vue';
|
||||||
|
|
||||||
test('configure routing through hooks config', async ({ page, mount }) => {
|
test('configure routing through hooks config', async ({ page, mount }) => {
|
||||||
|
|
@ -408,7 +408,7 @@ You can use `beforeMount` and `afterMount` hooks to configure your app. This let
|
||||||
|
|
||||||
```js title="src/pages/ProductsPage.spec.ts"
|
```js title="src/pages/ProductsPage.spec.ts"
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue2';
|
import { test, expect } from '@playwright/experimental-ct-vue2';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '../playwright';
|
||||||
import ProductsPage from './pages/ProductsPage.vue';
|
import ProductsPage from './pages/ProductsPage.vue';
|
||||||
|
|
||||||
test('configure routing through hooks config', async ({ page, mount }) => {
|
test('configure routing through hooks config', async ({ page, mount }) => {
|
||||||
|
|
@ -669,7 +669,7 @@ beforeMount<HooksConfig>(async ({ hooksConfig }) => {
|
||||||
|
|
||||||
```js title="src/pinia.spec.ts"
|
```js title="src/pinia.spec.ts"
|
||||||
import { test, expect } from '@playwright/experimental-ct-vue';
|
import { test, expect } from '@playwright/experimental-ct-vue';
|
||||||
import type { HooksConfig } from '@playwright/test';
|
import type { HooksConfig } from '../playwright';
|
||||||
import Store from './Store.vue';
|
import Store from './Store.vue';
|
||||||
|
|
||||||
test('override initialState ', async ({ mount }) => {
|
test('override initialState ', async ({ mount }) => {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ You can use the `globalSetup` option in the [configuration file](./test-configur
|
||||||
Similarly, use `globalTeardown` to run something once after all the tests. Alternatively, let `globalSetup` return a function that will be used as a global teardown. You can pass data such as port number, authentication tokens, etc. from your global setup to your tests using environment variables.
|
Similarly, use `globalTeardown` to run something once after all the tests. Alternatively, let `globalSetup` return a function that will be used as a global teardown. You can pass data such as port number, authentication tokens, etc. from your global setup to your tests using environment variables.
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
Using `globalSetup` and `globalTeardown` will not produce traces or artifacts. If you want to produce traces and artifacts, use [project dependencies](#option-1-project-dependencies).
|
Using `globalSetup` and `globalTeardown` will not produce traces or artifacts, and options like `headless` or `testIdAttribute` specified in the config file are not applied. If you want to produce traces and artifacts and respect config options, use [project dependencies](#option-1-project-dependencies).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
```js title="playwright.config.ts"
|
```js title="playwright.config.ts"
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ You can also teardown your setup by adding a [`property: TestProject.teardown`]
|
||||||
|
|
||||||
### Test filtering
|
### Test filtering
|
||||||
|
|
||||||
If `--grep/--grep-invert` or `--shard` [option](./test-cli.md#reference) is used, test file name filter is specified in [command line](./test-cli.md) or [test.only()](./api/class-test.md#test-only) is used, it will only apply to the tests from the deepest projects in the project dependency chain. In other words, if a matching test belongs to a project that has project dependencies, Playwright will run all the tests from the project depdencies ignoring the filters.
|
If `--grep/--grep-invert` or `--shard` [option](./test-cli.md#reference) is used, test file name filter is specified in [command line](./test-cli.md) or [test.only()](./api/class-test.md#test-only) is used, it will only apply to the tests from the deepest projects in the project dependency chain. In other words, if a matching test belongs to a project that has project dependencies, Playwright will run all the tests from the project dependencies ignoring the filters.
|
||||||
|
|
||||||
## Custom project parameters
|
## Custom project parameters
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ Now use this reporter with [`property: TestConfig.reporter`]. Learn more about [
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
reporter: ['./my-awesome-reporter.ts', { customOption: 'some value' }],
|
reporter: [['./my-awesome-reporter.ts', { customOption: 'some value' }]],
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -87,6 +87,15 @@ and [`method: Reporter.onError`] is called when something went wrong outside of
|
||||||
|
|
||||||
If your custom reporter does not print anything to the terminal, implement [`method: Reporter.printsToStdio`] and return `false`. This way, Playwright will use one of the standard terminal reporters in addition to your custom reporter to enhance user experience.
|
If your custom reporter does not print anything to the terminal, implement [`method: Reporter.printsToStdio`] and return `false`. This way, Playwright will use one of the standard terminal reporters in addition to your custom reporter to enhance user experience.
|
||||||
|
|
||||||
|
**Merged report API notes**
|
||||||
|
|
||||||
|
When merging multiple [`blob`](../test-reporters#blob-reporter) reports via [`merge-reports`](../test-sharding#merge-reports-cli) CLI
|
||||||
|
command, the same [Reporter] API is called to produce final reports and all existing reporters
|
||||||
|
should work without any changes. There some subtle differences though which might affect some custom
|
||||||
|
reporters.
|
||||||
|
|
||||||
|
* Projects from different shards are always kept as separate [TestProject] objects. E.g. if project 'Desktop Chrome' was sharded across 5 machines then there will be 5 instances of projects with the same name in the config passed to [`method: Reporter.onBegin`].
|
||||||
|
|
||||||
## optional method: Reporter.onBegin
|
## optional method: Reporter.onBegin
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
|
|
||||||
|
|
@ -94,7 +103,7 @@ Called once before running tests. All tests have been already discovered and put
|
||||||
|
|
||||||
### param: Reporter.onBegin.config
|
### param: Reporter.onBegin.config
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- `config` <[TestConfig]>
|
- `config` <[FullConfig]>
|
||||||
|
|
||||||
Resolved configuration.
|
Resolved configuration.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
`Suite` is a group of tests. All tests in Playwright Test form the following hierarchy:
|
`Suite` is a group of tests. All tests in Playwright Test form the following hierarchy:
|
||||||
|
|
||||||
* Root suite has a child suite for each [TestProject].
|
* Root suite has a child suite for each [FullProject].
|
||||||
* Project suite #1. Has a child suite for each test file in the project.
|
* Project suite #1. Has a child suite for each test file in the project.
|
||||||
* File suite #1
|
* File suite #1
|
||||||
* [TestCase] #1
|
* [TestCase] #1
|
||||||
|
|
@ -26,6 +26,12 @@ Reporter is given a root suite in the [`method: Reporter.onBegin`] method.
|
||||||
|
|
||||||
Returns the list of all test cases in this suite and its descendants, as opposite to [`property: Suite.tests`].
|
Returns the list of all test cases in this suite and its descendants, as opposite to [`property: Suite.tests`].
|
||||||
|
|
||||||
|
## method: Suite.entries
|
||||||
|
* since: v1.44
|
||||||
|
- type: <[Array]<[TestCase]|[Suite]>>
|
||||||
|
|
||||||
|
Test cases and suites defined directly in this suite. The elements are returned in their declaration order. You can differentiate between various entry types by using [`property: TestCase.type`] and [`property: Suite.type`].
|
||||||
|
|
||||||
## property: Suite.location
|
## property: Suite.location
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: ?<[Location]>
|
- type: ?<[Location]>
|
||||||
|
|
@ -40,7 +46,7 @@ Parent suite, missing for the root suite.
|
||||||
|
|
||||||
## method: Suite.project
|
## method: Suite.project
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- returns: ?<[TestProject]>
|
- returns: <[FullProject]|[undefined]>
|
||||||
|
|
||||||
Configuration of the project this suite belongs to, or [void] for the root suite.
|
Configuration of the project this suite belongs to, or [void] for the root suite.
|
||||||
|
|
||||||
|
|
@ -72,3 +78,10 @@ Suite title.
|
||||||
- returns: <[Array]<[string]>>
|
- returns: <[Array]<[string]>>
|
||||||
|
|
||||||
Returns a list of titles from the root down to this suite.
|
Returns a list of titles from the root down to this suite.
|
||||||
|
|
||||||
|
## property: Suite.type
|
||||||
|
* since: v1.44
|
||||||
|
- returns: <[SuiteType]<"root"|"project"|"file"|"describe">>
|
||||||
|
|
||||||
|
Returns the type of the suite. The Suites form the following hierarchy:
|
||||||
|
`root` -> `project` -> `file` -> `describe` -> ...`describe` -> `test`.
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ See also [`property: TestResult.status`] for the actual status.
|
||||||
* since: v1.25
|
* since: v1.25
|
||||||
- type: <[string]>
|
- type: <[string]>
|
||||||
|
|
||||||
Unique test ID that is computed based on the test file name, test title and project name. Test ID can be used as a history ID.
|
A test ID that is computed based on the test file name, test title and project name. The ID is unique within Playwright session.
|
||||||
|
|
||||||
## property: TestCase.location
|
## property: TestCase.location
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
|
|
@ -108,3 +108,8 @@ Test title as passed to the [`method: Test.(call)`] call.
|
||||||
|
|
||||||
Returns a list of titles from the root down to this test.
|
Returns a list of titles from the root down to this test.
|
||||||
|
|
||||||
|
## property: TestCase.type
|
||||||
|
* since: v1.44
|
||||||
|
- returns: <[TestCaseType]<"test">>
|
||||||
|
|
||||||
|
Returns "test". Useful for detecting test cases in [`method: Suite.entries`].
|
||||||
|
|
|
||||||
|
|
@ -215,16 +215,24 @@ Blob reports contain all the details about the test run and can be used later to
|
||||||
npx playwright test --reporter=blob
|
npx playwright test --reporter=blob
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, the report is written into the `blob-report` directory in the package.json directory or current working directory (if no package.json is found). The report file name is `report.zip` or `report-<shard_number>.zip` when [sharding](./test-sharding.md) is used. Both output directory and report file name can be overridden in the configuration file:
|
By default, the report is written into the `blob-report` directory in the package.json directory or current working directory (if no package.json is found). The report file name looks like `report-<hash>.zip` or `report-<hash>-<shard_number>.zip` when [sharding](./test-sharding.md) is used. The hash is an optional value computed from `--grep`, `--grepInverted`, `--project` and file filters passed as command line arguments. The hash guarantees that running Playwright with different command line options will produce different but stable between runs report names. The output file name can be overridden in the configuration file or pass as `'PLAYWRIGHT_BLOB_OUTPUT_FILE'` environment variable.
|
||||||
|
|
||||||
```js title="playwright.config.ts"
|
```js title="playwright.config.ts"
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
reporter: [['blob', { outputDir: 'my-report', fileName: `report-${os.platform()}.zip` }]],
|
reporter: [['blob', { outputFile: `./blob-report/report-${os.platform()}.zip` }]],
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Blob report supports following configuration options and environment variables:
|
||||||
|
|
||||||
|
| Environment Variable Name | Reporter Config Option| Description | Default
|
||||||
|
|---|---|---|---|
|
||||||
|
| `PLAYWRIGHT_BLOB_OUTPUT_DIR` | `outputDir` | Directory to save the output. Existing content is deleted before writing the new report. | `blob-report`
|
||||||
|
| `PLAYWRIGHT_BLOB_OUTPUT_NAME` | `fileName` | Report file name. | `report-<project>-<hash>-<shard_number>.zip`
|
||||||
|
| `PLAYWRIGHT_BLOB_OUTPUT_FILE` | `outputFile` | Full path to the output file. If defined, `outputDir` and `fileName` will be ignored. | `undefined`
|
||||||
|
|
||||||
### JSON reporter
|
### JSON reporter
|
||||||
|
|
||||||
JSON reporter produces an object with all information about the test run.
|
JSON reporter produces an object with all information about the test run.
|
||||||
|
|
@ -255,6 +263,14 @@ export default defineConfig({
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
JSON report supports following configuration options and environment variables:
|
||||||
|
|
||||||
|
| Environment Variable Name | Reporter Config Option| Description | Default
|
||||||
|
|---|---|---|---|
|
||||||
|
| `PLAYWRIGHT_JSON_OUTPUT_DIR` | | Directory to save the output file. Ignored if output file is specified. | `cwd` or config directory.
|
||||||
|
| `PLAYWRIGHT_JSON_OUTPUT_NAME` | `outputFile` | Base file name for the output, relative to the output dir. | JSON report is printed to the stdout.
|
||||||
|
| `PLAYWRIGHT_JSON_OUTPUT_FILE` | `outputFile` | Full path to the output file. If defined, `PLAYWRIGHT_JSON_OUTPUT_DIR` and `PLAYWRIGHT_JSON_OUTPUT_NAME` will be ignored. | JSON report is printed to the stdout.
|
||||||
|
|
||||||
### JUnit reporter
|
### JUnit reporter
|
||||||
|
|
||||||
JUnit reporter produces a JUnit-style xml report.
|
JUnit reporter produces a JUnit-style xml report.
|
||||||
|
|
@ -285,6 +301,18 @@ export default defineConfig({
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
JUnit report supports following configuration options and environment variables:
|
||||||
|
|
||||||
|
| Environment Variable Name | Reporter Config Option| Description | Default
|
||||||
|
|---|---|---|---|
|
||||||
|
| `PLAYWRIGHT_JUNIT_OUTPUT_DIR` | | Directory to save the output file. Ignored if output file is not specified. | `cwd` or config directory.
|
||||||
|
| `PLAYWRIGHT_JUNIT_OUTPUT_NAME` | `outputFile` | Base file name for the output, relative to the output dir. | JUnit report is printed to the stdout.
|
||||||
|
| `PLAYWRIGHT_JUNIT_OUTPUT_FILE` | `outputFile` | Full path to the output file. If defined, `PLAYWRIGHT_JUNIT_OUTPUT_DIR` and `PLAYWRIGHT_JUNIT_OUTPUT_NAME` will be ignored. | JUnit report is printed to the stdout.
|
||||||
|
| | `stripANSIControlSequences` | Whether to remove ANSI control sequences from the text before writing it in the report. | By default output text is added as is.
|
||||||
|
| | `includeProjectInTestName` | Whether to include Playwright project name in every test case as a name prefix. | By default not included.
|
||||||
|
| `PLAYWRIGHT_JUNIT_SUITE_ID` | | Value of the `id` attribute on the root `<testsuites/>` report entry. | Empty string.
|
||||||
|
| `PLAYWRIGHT_JUNIT_SUITE_NAME` | | Value of the `name` attribute on the root `<testsuites/>` report entry. | Empty string.
|
||||||
|
|
||||||
### GitHub Actions annotations
|
### GitHub Actions annotations
|
||||||
|
|
||||||
You can use the built in `github` reporter to get automatic failure annotations when running in GitHub actions.
|
You can use the built in `github` reporter to get automatic failure annotations when running in GitHub actions.
|
||||||
|
|
@ -355,6 +383,7 @@ npx playwright test --reporter="./myreporter/my-awesome-reporter.ts"
|
||||||
* [Argos Visual Testing](https://argos-ci.com/docs/playwright)
|
* [Argos Visual Testing](https://argos-ci.com/docs/playwright)
|
||||||
* [Currents](https://www.npmjs.com/package/@currents/playwright)
|
* [Currents](https://www.npmjs.com/package/@currents/playwright)
|
||||||
* [GitHub Actions Reporter](https://www.npmjs.com/package/@estruyf/github-actions-reporter)
|
* [GitHub Actions Reporter](https://www.npmjs.com/package/@estruyf/github-actions-reporter)
|
||||||
|
* [GitHub Pull Request Comment](https://github.com/marketplace/actions/playwright-report-comment)
|
||||||
* [Monocart](https://github.com/cenfun/monocart-reporter)
|
* [Monocart](https://github.com/cenfun/monocart-reporter)
|
||||||
* [ReportPortal](https://github.com/reportportal/agent-js-playwright)
|
* [ReportPortal](https://github.com/reportportal/agent-js-playwright)
|
||||||
* [Serenity/JS](https://serenity-js.org/handbook/test-runners/playwright-test)
|
* [Serenity/JS](https://serenity-js.org/handbook/test-runners/playwright-test)
|
||||||
|
|
|
||||||
|
|
@ -5,107 +5,18 @@ title: "Test Runners"
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
While Playwright for .NET isn't tied to a particular test runner or testing framework, in our experience
|
While Playwright for .NET isn't tied to a particular test runner or testing framework, in our experience it works best with the built-in .NET test runner, and using NUnit as the test framework. NUnit is also what we use internally for [our tests](https://github.com/microsoft/playwright-dotnet/tree/main/src/Playwright.Tests).
|
||||||
it works best with the built-in .NET test runner, and using NUnit as the test framework. NUnit is
|
|
||||||
also what we use internally for [our tests](https://github.com/microsoft/playwright-dotnet/tree/main/src/Playwright.Tests).
|
|
||||||
|
|
||||||
Playwright and Browser instances can be reused between tests for better performance. We
|
Playwright and Browser instances can be reused between tests for better performance. We
|
||||||
recommend running each test case in a new BrowserContext, this way browser state will be
|
recommend running each test case in a new BrowserContext, this way browser state will be
|
||||||
isolated between the tests.
|
isolated between the tests.
|
||||||
|
|
||||||
<!-- TOC -->
|
|
||||||
|
|
||||||
## NUnit
|
## NUnit
|
||||||
|
|
||||||
Playwright provides base classes to write tests with NUnit via the [`Microsoft.Playwright.NUnit`](https://www.nuget.org/packages/Microsoft.Playwright.NUnit) package.
|
Playwright provides base classes to write tests with NUnit via the [`Microsoft.Playwright.NUnit`](https://www.nuget.org/packages/Microsoft.Playwright.NUnit) package.
|
||||||
|
|
||||||
|
Check out the [installation guide](./intro.md) to get started.
|
||||||
### Creating an NUnit project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create a new project
|
|
||||||
dotnet new nunit -n PlaywrightTests
|
|
||||||
cd PlaywrightTests
|
|
||||||
|
|
||||||
# Add the required reference
|
|
||||||
dotnet add package Microsoft.Playwright.NUnit
|
|
||||||
dotnet build
|
|
||||||
|
|
||||||
# Install the required browsers and operating system dependencies
|
|
||||||
pwsh bin/Debug/netX/playwright.ps1 install --with-deps
|
|
||||||
```
|
|
||||||
|
|
||||||
Modify the UnitTest1.cs:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using Microsoft.Playwright.NUnit;
|
|
||||||
|
|
||||||
namespace PlaywrightTests;
|
|
||||||
|
|
||||||
[Parallelizable(ParallelScope.Self)]
|
|
||||||
[TestFixture]
|
|
||||||
public class MyTest : PageTest
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public async Task ShouldHaveTheCorrectSlogan()
|
|
||||||
{
|
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
|
||||||
await Expect(Page.Locator("text=enables reliable end-to-end testing for modern web apps")).ToBeVisibleAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public async Task ShouldHaveTheCorrectTitle()
|
|
||||||
{
|
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
|
||||||
var title = Page.Locator(".navbar__inner .navbar__title");
|
|
||||||
await Expect(title).ToHaveTextAsync("Playwright");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Run your tests against Chromium
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
Run your tests against WebKit
|
|
||||||
|
|
||||||
```bash tab=bash-bash lang=csharp
|
|
||||||
BROWSER=webkit dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```batch tab=bash-batch lang=csharp
|
|
||||||
set BROWSER=webkit
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```powershell tab=bash-powershell lang=csharp
|
|
||||||
$env:BROWSER="webkit"
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
Run your tests with GUI
|
|
||||||
|
|
||||||
```bash tab=bash-bash lang=csharp
|
|
||||||
HEADED=1 dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```batch tab=bash-batch lang=csharp
|
|
||||||
set HEADED=1
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```powershell tab=bash-powershell lang=csharp
|
|
||||||
$env:HEADED="1"
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also choose specifically which tests to run, using the [filtering capabilities](https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=nunit):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet test --filter "Name~Slogan"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Running NUnit tests in Parallel
|
### Running NUnit tests in Parallel
|
||||||
|
|
||||||
|
|
@ -114,6 +25,10 @@ Only `ParallelScope.Self` is supported.
|
||||||
|
|
||||||
For CPU-bound tests, we recommend using as many workers as there are cores on your system, divided by 2. For IO-bound tests you can use as many workers as you have cores.
|
For CPU-bound tests, we recommend using as many workers as there are cores on your system, divided by 2. For IO-bound tests you can use as many workers as you have cores.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test -- NUnit.NumberOfTestWorkers=5
|
||||||
|
```
|
||||||
|
|
||||||
### Customizing [BrowserContext] options
|
### Customizing [BrowserContext] options
|
||||||
|
|
||||||
To customize context options, you can override the `ContextOptions` method of your test class derived from `Microsoft.Playwright.MSTest.PageTest` or `Microsoft.Playwright.MSTest.ContextTest`. See the following example:
|
To customize context options, you can override the `ContextOptions` method of your test class derived from `Microsoft.Playwright.MSTest.PageTest` or `Microsoft.Playwright.MSTest.ContextTest`. See the following example:
|
||||||
|
|
@ -223,91 +138,7 @@ There are a few base classes available to you in `Microsoft.Playwright.NUnit` na
|
||||||
|
|
||||||
Playwright provides base classes to write tests with MSTest via the [`Microsoft.Playwright.MSTest`](https://www.nuget.org/packages/Microsoft.Playwright.MSTest) package.
|
Playwright provides base classes to write tests with MSTest via the [`Microsoft.Playwright.MSTest`](https://www.nuget.org/packages/Microsoft.Playwright.MSTest) package.
|
||||||
|
|
||||||
### Creating an MSTest project
|
Check out the [installation guide](./intro.md) to get started.
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create a new project
|
|
||||||
dotnet new mstest -n PlaywrightTests
|
|
||||||
cd PlaywrightTests
|
|
||||||
|
|
||||||
# Add the required reference
|
|
||||||
dotnet add package Microsoft.Playwright.MSTest
|
|
||||||
dotnet build
|
|
||||||
|
|
||||||
# Install the required browsers and operating system dependencies
|
|
||||||
pwsh bin/Debug/netX/playwright.ps1 install --with-deps
|
|
||||||
```
|
|
||||||
|
|
||||||
Modify the UnitTest1.cs:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
using Microsoft.Playwright.MSTest;
|
|
||||||
|
|
||||||
namespace PlaywrightTests;
|
|
||||||
|
|
||||||
[TestClass]
|
|
||||||
public class UnitTest1: PageTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ShouldHaveTheCorrectSlogan()
|
|
||||||
{
|
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
|
||||||
await Expect(Page.Locator("text=enables reliable end-to-end testing for modern web apps")).ToBeVisibleAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestMethod]
|
|
||||||
public async Task ShouldHaveTheCorrectTitle()
|
|
||||||
{
|
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
|
||||||
var title = Page.Locator(".navbar__inner .navbar__title");
|
|
||||||
await Expect(title).ToHaveTextAsync("Playwright");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Run your tests against Chromium
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
Run your tests against WebKit
|
|
||||||
|
|
||||||
```bash tab=bash-bash lang=csharp
|
|
||||||
BROWSER=webkit dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```batch tab=bash-batch lang=csharp
|
|
||||||
set BROWSER=webkit
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```powershell tab=bash-powershell lang=csharp
|
|
||||||
$env:BROWSER="webkit"
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
Run your tests with GUI
|
|
||||||
|
|
||||||
```bash tab=bash-bash lang=csharp
|
|
||||||
HEADED=1 dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```batch tab=bash-batch lang=csharp
|
|
||||||
set HEADED=1
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
```powershell tab=bash-powershell lang=csharp
|
|
||||||
$env:HEADED="1"
|
|
||||||
dotnet test
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also choose specifically which tests to run, using the [filtering capabilities](https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=mstest):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dotnet test --filter "Name~Slogan"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Running MSTest tests in Parallel
|
### Running MSTest tests in Parallel
|
||||||
|
|
||||||
|
|
@ -331,7 +162,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
namespace PlaywrightTests;
|
namespace PlaywrightTests;
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTest1 : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task TestWithCustomContextOptions()
|
public async Task TestWithCustomContextOptions()
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ def test_my_app_is_working(fixture_name):
|
||||||
|
|
||||||
- `context`: New [browser context](./browser-contexts) for a test.
|
- `context`: New [browser context](./browser-contexts) for a test.
|
||||||
- `page`: New [browser page](./pages) for a test.
|
- `page`: New [browser page](./pages) for a test.
|
||||||
|
- `new_context`: Allows creating different [browser contexts](./browser-contexts) for a test. Useful for multi-user scenarios. Accepts the same parameters as [`method: Browser.newContext`].
|
||||||
|
|
||||||
**Session scope**: These fixtures are created when requested in a test function and destroyed when all tests end.
|
**Session scope**: These fixtures are created when requested in a test function and destroyed when all tests end.
|
||||||
|
|
||||||
|
|
@ -211,30 +212,6 @@ def browser_context_args(browser_context_args, playwright):
|
||||||
|
|
||||||
Or via the CLI `--device="iPhone 11 Pro"`
|
Or via the CLI `--device="iPhone 11 Pro"`
|
||||||
|
|
||||||
### Persistent context
|
|
||||||
|
|
||||||
```py title="conftest.py"
|
|
||||||
import pytest
|
|
||||||
from playwright.sync_api import BrowserType
|
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
|
||||||
def context(
|
|
||||||
browser_type: BrowserType,
|
|
||||||
browser_type_launch_args: Dict,
|
|
||||||
browser_context_args: Dict
|
|
||||||
):
|
|
||||||
context = browser_type.launch_persistent_context("./foobar", **{
|
|
||||||
**browser_type_launch_args,
|
|
||||||
**browser_context_args,
|
|
||||||
"locale": "de-DE",
|
|
||||||
})
|
|
||||||
yield context
|
|
||||||
context.close()
|
|
||||||
```
|
|
||||||
|
|
||||||
When using that all pages inside your test are created from the persistent context.
|
|
||||||
|
|
||||||
### Using with `unittest.TestCase`
|
### Using with `unittest.TestCase`
|
||||||
|
|
||||||
See the following example for using it with `unittest.TestCase`. This has a limitation,
|
See the following example for using it with `unittest.TestCase`. This has a limitation,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ title: "Sharding"
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
By default, Playwright runs tests in [parallel](/test-parallel.md) and strives for optimal utilization of CPU cores on your machine. In order to achieve even greater parallelisation, you can further scale Playwright test execution by running tests on multiple machines simultaneously. We call this mode of operation "sharding".
|
By default, Playwright runs test files in [parallel](./test-parallel.md) and strives for optimal utilization of CPU cores on your machine. In order to achieve even greater parallelisation, you can further scale Playwright test execution by running tests on multiple machines simultaneously. We call this mode of operation "sharding".
|
||||||
|
|
||||||
## Sharding tests between multiple machines
|
## Sharding tests between multiple machines
|
||||||
|
|
||||||
|
|
@ -20,6 +20,8 @@ npx playwright test --shard=4/4
|
||||||
|
|
||||||
Now, if you run these shards in parallel on different computers, your test suite completes four times faster.
|
Now, if you run these shards in parallel on different computers, your test suite completes four times faster.
|
||||||
|
|
||||||
|
Note that Playwright can only shard tests that can be run in parallel. By default, this means Playwright will shard test files. Learn about other options in the [parallelism guide](./test-parallel.md).
|
||||||
|
|
||||||
## Merging reports from multiple shards
|
## Merging reports from multiple shards
|
||||||
|
|
||||||
In the previous example, each test shard has its own test report. If you want to have a combined report showing all the test results from all the shards, you can merge them.
|
In the previous example, each test shard has its own test report. If you want to have a combined report showing all the test results from all the shards, you can merge them.
|
||||||
|
|
@ -47,7 +49,7 @@ This will produce a standard HTML report into `playwright-report` directory.
|
||||||
|
|
||||||
## GitHub Actions example
|
## GitHub Actions example
|
||||||
|
|
||||||
GitHub Actions supports [sharding tests between multiple jobs](https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs) using the [`jobs.<job_id>.strategy.matrix`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) option. The `matrix` option will run a separate job for every possible combination of the provided options.
|
GitHub Actions supports [sharding tests between multiple jobs](https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs) using the [`jobs.<job_id>.strategy.matrix`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) option. The `matrix` option will run a separate job for every possible combination of the provided options.
|
||||||
|
|
||||||
The following example shows you how to configure a job to run your tests on four machines in parallel and then merge the reports into a single report. Don't forget to add `reporter: process.env.CI ? 'blob' : 'html',` to your `playwright.config.ts` file as in the example above.
|
The following example shows you how to configure a job to run your tests on four machines in parallel and then merge the reports into a single report. Don't forget to add `reporter: process.env.CI ? 'blob' : 'html',` to your `playwright.config.ts` file as in the example above.
|
||||||
|
|
||||||
|
|
@ -55,7 +57,7 @@ The following example shows you how to configure a job to run your tests on four
|
||||||
|
|
||||||
1. Then we run our Playwright tests with the `--shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}` option. This will run our test command for each shard.
|
1. Then we run our Playwright tests with the `--shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}` option. This will run our test command for each shard.
|
||||||
|
|
||||||
1. Finally we upload our blob report to the GitHub Actions Artifacts. This will make the blob report available to other jobs in the workflow.
|
1. Finally we upload our blob report to the GitHub Actions Artifacts. This will make the blob report available to other jobs in the workflow.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -89,7 +91,7 @@ jobs:
|
||||||
run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
||||||
|
|
||||||
- name: Upload blob report to GitHub Actions Artifacts
|
- name: Upload blob report to GitHub Actions Artifacts
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: blob-report-${{ matrix.shardIndex }}
|
name: blob-report-${{ matrix.shardIndex }}
|
||||||
|
|
@ -104,7 +106,7 @@ jobs:
|
||||||
...
|
...
|
||||||
merge-reports:
|
merge-reports:
|
||||||
# Merge reports after playwright-tests, even if some shards have failed
|
# Merge reports after playwright-tests, even if some shards have failed
|
||||||
if: always()
|
if: ${{ !cancelled() }}
|
||||||
needs: [playwright-tests]
|
needs: [playwright-tests]
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
@ -124,7 +126,7 @@ jobs:
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Merge into HTML Report
|
- name: Merge into HTML Report
|
||||||
run: npx playwright merge-reports --reporter html ./all-blob-reports
|
run: npx playwright merge-reports --reporter html ./all-blob-reports
|
||||||
|
|
||||||
- name: Upload HTML report
|
- name: Upload HTML report
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
@ -150,7 +152,7 @@ Supported options:
|
||||||
|
|
||||||
Which report to produce. Can be multiple reporters separated by comma.
|
Which report to produce. Can be multiple reporters separated by comma.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx playwright merge-reports --reporter=html,github ./blob-reports
|
npx playwright merge-reports --reporter=html,github ./blob-reports
|
||||||
|
|
@ -162,8 +164,8 @@ Supported options:
|
||||||
additional configuration to the output reporter. This configuration file can differ from
|
additional configuration to the output reporter. This configuration file can differ from
|
||||||
the one used during the creation of blob reports.
|
the one used during the creation of blob reports.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx playwright merge-reports --config=merge.config.ts ./blob-reports
|
npx playwright merge-reports --config=merge.config.ts ./blob-reports
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import LiteYouTube from '@site/src/components/LiteYouTube';
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
UI Mode let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. Filter tests by **text** or **@tag** or by **passed**, **failed** and **skipped** tests as well as by [**projects**](./test-projects) as set in your `playwright.config` file. See a full trace of your tests and hover back and forward over each action to see what was happening during each step and pop out the DOM snapshot to a separate window for a better debugging experience.
|
UI Mode lets you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test. Filter tests by **text** or **@tag** or by **passed**, **failed** and **skipped** tests as well as by [**projects**](./test-projects) as set in your `playwright.config` file. See a full trace of your tests and hover back and forward over each action to see what was happening during each step and pop out the DOM snapshot to a separate window for a better debugging experience.
|
||||||
|
|
||||||
<LiteYouTube
|
<LiteYouTube
|
||||||
id="d0u6XhXknzU"
|
id="d0u6XhXknzU"
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ await expect(page.getByText('the lion king')).toBeVisible();
|
||||||
await expect(page.getByText('the mummy')).toBeHidden();
|
await expect(page.getByText('the mummy')).toBeHidden();
|
||||||
```
|
```
|
||||||
|
|
||||||
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#polling) instead.
|
When you cannot find a suitable assertion, use [`expect.poll`](./test-assertions#expectpoll) instead.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await expect.poll(async () => {
|
await expect.poll(async () => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ Playwright Trace Viewer is a GUI tool that lets you explore recorded Playwright
|
||||||
**You will learn**
|
**You will learn**
|
||||||
|
|
||||||
- How to record a trace
|
- How to record a trace
|
||||||
- How to open the HTML report
|
|
||||||
- How to open the trace viewer
|
- How to open the trace viewer
|
||||||
|
|
||||||
## Recording a trace
|
## Recording a trace
|
||||||
|
|
@ -124,8 +123,6 @@ public class Tests : PageTest
|
||||||
[TearDown]
|
[TearDown]
|
||||||
public async Task TearDown()
|
public async Task TearDown()
|
||||||
{
|
{
|
||||||
// This will produce e.g.:
|
|
||||||
// bin/Debug/net8.0/playwright-traces/PlaywrightTests.Tests.Test1.zip
|
|
||||||
await Context.Tracing.StopAsync(new()
|
await Context.Tracing.StopAsync(new()
|
||||||
{
|
{
|
||||||
Path = Path.Combine(
|
Path = Path.Combine(
|
||||||
|
|
@ -152,17 +149,17 @@ using System.Text.RegularExpressions;
|
||||||
using Microsoft.Playwright;
|
using Microsoft.Playwright;
|
||||||
using Microsoft.Playwright.MSTest;
|
using Microsoft.Playwright.MSTest;
|
||||||
|
|
||||||
namespace PlaywrightTestsMSTest;
|
namespace PlaywrightTests;
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTest1 : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[TestInitialize]
|
[TestInitialize]
|
||||||
public async Task TestInitialize()
|
public async Task TestInitialize()
|
||||||
{
|
{
|
||||||
await Context.Tracing.StartAsync(new()
|
await Context.Tracing.StartAsync(new()
|
||||||
{
|
{
|
||||||
Title = TestContext.TestName,
|
Title = TestContext.CurrentContext.Test.ClassName + "." + TestContext.
|
||||||
Screenshots = true,
|
Screenshots = true,
|
||||||
Snapshots = true,
|
Snapshots = true,
|
||||||
Sources = true
|
Sources = true
|
||||||
|
|
@ -172,20 +169,18 @@ public class UnitTest1 : PageTest
|
||||||
[TestCleanup]
|
[TestCleanup]
|
||||||
public async Task TestCleanup()
|
public async Task TestCleanup()
|
||||||
{
|
{
|
||||||
// This will produce e.g.:
|
|
||||||
// bin/Debug/net8.0/playwright-traces/PlaywrightTests.UnitTest1.zip
|
|
||||||
await Context.Tracing.StopAsync(new()
|
await Context.Tracing.StopAsync(new()
|
||||||
{
|
{
|
||||||
Path = Path.Combine(
|
Path = Path.Combine(
|
||||||
Environment.CurrentDirectory,
|
Environment.CurrentDirectory,
|
||||||
"playwright-traces",
|
"playwright-traces",
|
||||||
$"{TestContext.FullyQualifiedTestClassName}.zip"
|
$"{TestContext.CurrentContext.Test.ClassName}.{TestContext.CurrentContext.Test.Name}.zip"
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task TestYourOnlineShop()
|
public async Task GetStartedLink()
|
||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
@ -195,11 +190,11 @@ public class UnitTest1 : PageTest
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
This will record the trace and place it into the `bin/Debug/net8.0/playwright-traces/` directory.
|
This will record a zip file for each test, e.g. `PlaywrightTests.ExampleTest.GetStartedLink.zip` and place it into the `bin/Debug/net8.0/playwright-traces/` directory.
|
||||||
|
|
||||||
## Opening the trace
|
## Opening the trace
|
||||||
|
|
||||||
You can open the saved trace using the Playwright CLI or in your browser on [`trace.playwright.dev`](https://trace.playwright.dev). Make sure to add the full path to where your `trace.zip` file is located. This should include the `test-results` directory followed by the test name and then `trace.zip`.
|
You can open the saved trace using the Playwright CLI or in your browser on [`trace.playwright.dev`](https://trace.playwright.dev). Make sure to add the full path to where your trace's zip file is located. Once opened you can click on each action or use the timeline to see the state of the page before and after each action. You can also inspect the log, source and network during each step of the test. The trace viewer creates a DOM snapshot so you can fully interact with it, open devtools etc.
|
||||||
|
|
||||||
```bash java
|
```bash java
|
||||||
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="show-trace trace.zip"
|
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="show-trace trace.zip"
|
||||||
|
|
@ -210,14 +205,19 @@ playwright show-trace trace.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
```bash csharp
|
```bash csharp
|
||||||
pwsh bin/Debug/netX/playwright.ps1 show-trace trace.zip
|
pwsh bin/Debug/net8.0/playwright.ps1 show-trace bin/Debug/net8.0/playwright-traces/PlaywrightTests.ExampleTest.GetStartedLink.zip
|
||||||
```
|
```
|
||||||
## Viewing the trace
|
|
||||||
|
|
||||||
View traces of your test by clicking through each action or hovering using the timeline and see the state of the page before and after the action. Inspect the log, source and network during each step of the test. The trace viewer creates a DOM snapshot so you can fully interact with it, open devtools etc.
|
######
|
||||||
|
* langs: python, java
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
######
|
||||||
|
* langs: csharp
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
To learn more check out our detailed guide on [Trace Viewer](/trace-viewer.md).
|
To learn more check out our detailed guide on [Trace Viewer](/trace-viewer.md).
|
||||||
|
|
||||||
## What's next
|
## What's next
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ Playwright Trace Viewer is a GUI tool that lets you explore recorded Playwright
|
||||||
|
|
||||||
## Recording a Trace
|
## Recording a Trace
|
||||||
|
|
||||||
By default the [playwright.config](/test-configuration.md#record-test-trace) file will contain the configuration needed to create a `trace.zip` file for each test. Traces are setup to run `on-first-retry` meaning they will be run on the first retry of a failed test. Also `retries` are set to 2 when running on CI and 0 locally. This means the traces will be recorded on the first retry of a failed test but not on the first run and not on the second retry.
|
By default the [playwright.config](./trace-viewer.md#recording-a-trace-on-ci) file will contain the configuration needed to create a `trace.zip` file for each test. Traces are setup to run `on-first-retry` meaning they will be run on the first retry of a failed test. Also `retries` are set to 2 when running on CI and 0 locally. This means the traces will be recorded on the first retry of a failed test but not on the first run and not on the second retry.
|
||||||
|
|
||||||
```js title="playwright.config.ts"
|
```js title="playwright.config.ts"
|
||||||
import { defineConfig } from '@playwright/test';
|
import { defineConfig } from '@playwright/test';
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,33 @@ title: "Writing tests"
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Playwright assertions are created specifically for the dynamic web. Checks are automatically retried until the necessary conditions are met. Playwright comes with [auto-wait](./actionability.md) built in meaning it waits for elements to be actionable prior to performing actions. Playwright provides the [Expect](./test-assertions) function to write assertions.
|
Playwright tests are simple, they
|
||||||
|
|
||||||
Take a look at the example test below to see how to write a test using using [locators](/locators.md) and web first assertions.
|
- **perform actions**, and
|
||||||
|
- **assert the state** against expectations.
|
||||||
|
|
||||||
|
There is no need to wait for anything prior to performing an action: Playwright
|
||||||
|
automatically waits for the wide range of [actionability](./actionability.md)
|
||||||
|
checks to pass prior to performing each action.
|
||||||
|
|
||||||
|
There is also no need to deal with the race conditions when performing the checks -
|
||||||
|
Playwright assertions are designed in a way that they describe the expectations
|
||||||
|
that need to be eventually met.
|
||||||
|
|
||||||
|
That's it! These design choices allow Playwright users to forget about flaky
|
||||||
|
timeouts and racy checks in their tests altogether.
|
||||||
|
|
||||||
|
**You will learn**
|
||||||
|
|
||||||
|
- [How to write the first test](/writing-tests.md#first-test)
|
||||||
|
- [How to perform actions](/writing-tests.md#actions)
|
||||||
|
- [How to use assertions](/writing-tests.md#assertions)
|
||||||
|
- [How tests run in isolation](/writing-tests.md#test-isolation)
|
||||||
|
- [How to use test hooks](/writing-tests.md#using-test-hooks)
|
||||||
|
|
||||||
|
## First test
|
||||||
|
|
||||||
|
Take a look at the following example to see how to write a test.
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
groupId="test-runners"
|
groupId="test-runners"
|
||||||
|
|
@ -30,30 +54,28 @@ namespace PlaywrightTests;
|
||||||
|
|
||||||
[Parallelizable(ParallelScope.Self)]
|
[Parallelizable(ParallelScope.Self)]
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class Tests : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public async Task HomepageHasPlaywrightInTitleAndGetStartedLinkLinkingtoTheIntroPage()
|
public async Task HasTitle()
|
||||||
{
|
{
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
|
|
||||||
// Expect a title "to contain" a substring.
|
// Expect a title "to contain" a substring.
|
||||||
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
||||||
|
}
|
||||||
|
|
||||||
// create a locator
|
[Test]
|
||||||
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
|
public async Task GetStartedLink()
|
||||||
|
{
|
||||||
// Expect an attribute "to be strictly equal" to the value.
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
await Expect(getStarted).ToHaveAttributeAsync("href", "/docs/intro");
|
|
||||||
|
|
||||||
// Click the get started link.
|
// Click the get started link.
|
||||||
await getStarted.ClickAsync();
|
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
|
||||||
|
|
||||||
// Expects page to have a heading with the name of Installation.
|
// Expects page to have a heading with the name of Installation.
|
||||||
await Expect(Page
|
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
|
||||||
.GetByRole(AriaRole.Heading, new() { Name = "Installation" }))
|
}
|
||||||
.ToBeVisibleAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -70,55 +92,109 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
namespace PlaywrightTests;
|
namespace PlaywrightTests;
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTest1 : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task HomepageHasPlaywrightInTitleAndGetStartedLinkLinkingtoTheIntroPage()
|
public async Task HasTitle()
|
||||||
{
|
{
|
||||||
await Page.GotoAsync("https://playwright.dev");
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
|
|
||||||
// Expect a title "to contain" a substring.
|
// Expect a title "to contain" a substring.
|
||||||
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
||||||
|
}
|
||||||
|
|
||||||
// create a locator
|
[TestMethod]
|
||||||
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
|
public async Task GetStartedLink()
|
||||||
|
{
|
||||||
// Expect an attribute "to be strictly equal" to the value.
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
await Expect(getStarted).ToHaveAttributeAsync("href", "/docs/intro");
|
|
||||||
|
|
||||||
// Click the get started link.
|
// Click the get started link.
|
||||||
await getStarted.ClickAsync();
|
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
|
||||||
|
|
||||||
// Expects the URL to contain intro.
|
// Expects page to have a heading with the name of Installation.
|
||||||
await Expect(Page).ToHaveURLAsync(new Regex(".*intro"));
|
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
### Assertions
|
## Actions
|
||||||
|
|
||||||
|
### Navigation
|
||||||
|
|
||||||
|
Most of the tests will start by navigating the page to a URL. After that, the test
|
||||||
|
will be able to interact with the page elements.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await Page.GotoAsync("https://playwright.dev");
|
||||||
|
```
|
||||||
|
|
||||||
|
Playwright will wait for the page to reach the load state prior to moving forward.
|
||||||
|
Learn more about the [`method: Page.goto`] options.
|
||||||
|
|
||||||
|
### Interactions
|
||||||
|
|
||||||
|
Performing actions starts with locating the elements. Playwright uses [Locators API](./locators.md) for that. Locators represent a way to find element(s) on the page at any moment, learn more about the [different types](./locators.md) of locators available. Playwright will wait for the element to be [actionable](./actionability.md) prior to performing the action, so there is no need to wait for it to become available.
|
||||||
|
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Create a locator.
|
||||||
|
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
|
||||||
|
|
||||||
|
// Click it.
|
||||||
|
await getStarted.ClickAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
In most cases, it'll be written in one line:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Basic actions
|
||||||
|
|
||||||
|
This is the list of the most popular Playwright actions. Note that there are many more, so make sure to check the [Locator API](./api/class-locator.md) section to
|
||||||
|
learn more about them.
|
||||||
|
|
||||||
|
| Action | Description |
|
||||||
|
| :- | :- |
|
||||||
|
| [`method: Locator.check`] | Check the input checkbox |
|
||||||
|
| [`method: Locator.click`] | Click the element |
|
||||||
|
| [`method: Locator.uncheck`] | Uncheck the input checkbox |
|
||||||
|
| [`method: Locator.hover`] | Hover mouse over the element |
|
||||||
|
| [`method: Locator.fill`] | Fill the form field, input text |
|
||||||
|
| [`method: Locator.focus`] | Focus the element |
|
||||||
|
| [`method: Locator.press`] | Press single key |
|
||||||
|
| [`method: Locator.setInputFiles`] | Pick files to upload |
|
||||||
|
| [`method: Locator.selectOption`] | Select option in the drop down |
|
||||||
|
|
||||||
|
## Assertions
|
||||||
|
|
||||||
Playwright provides an async function called [Expect](./test-assertions) to assert and wait until the expected condition is met.
|
Playwright provides an async function called [Expect](./test-assertions) to assert and wait until the expected condition is met.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Here is the list of the most popular async assertions. Note that there are [many more](./test-assertions.md) to get familiar with:
|
||||||
|
|
||||||
|
| Assertion | Description |
|
||||||
|
| :- | :- |
|
||||||
|
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
|
||||||
|
| [`method: LocatorAssertions.toBeEnabled`] | Control is enabled |
|
||||||
|
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
|
||||||
|
| [`method: LocatorAssertions.toContainText`] | Element contains text |
|
||||||
|
| [`method: LocatorAssertions.toHaveAttribute`] | Element has attribute |
|
||||||
|
| [`method: LocatorAssertions.toHaveCount`] | List of elements has given length |
|
||||||
|
| [`method: LocatorAssertions.toHaveText`] | Element matches text |
|
||||||
|
| [`method: LocatorAssertions.toHaveValue`] | Input element has value |
|
||||||
|
| [`method: PageAssertions.toHaveTitle`] | Page has title |
|
||||||
|
| [`method: PageAssertions.toHaveURL`] | Page has URL |
|
||||||
|
|
||||||
|
|
||||||
### Locators
|
## Test Isolation
|
||||||
|
|
||||||
[Locators](./locators.md) are the central piece of Playwright's auto-waiting and retry-ability. Locators represent a way to find element(s) on the page at any moment and are used to perform actions on elements such as `.ClickAsync` `.FillAsync` etc.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
|
|
||||||
|
|
||||||
await Expect(getStarted).ToHaveAttributeAsync("href", "/docs/installation");
|
|
||||||
await getStarted.ClickAsync();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Isolation
|
|
||||||
|
|
||||||
The Playwright NUnit and MSTest test framework base classes will isolate each test from each other by providing a separate `Page` instance. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.
|
The Playwright NUnit and MSTest test framework base classes will isolate each test from each other by providing a separate `Page` instance. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.
|
||||||
|
|
||||||
|
|
@ -141,7 +217,7 @@ namespace PlaywrightTests;
|
||||||
|
|
||||||
[Parallelizable(ParallelScope.Self)]
|
[Parallelizable(ParallelScope.Self)]
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class Tests : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public async Task BasicTest()
|
public async Task BasicTest()
|
||||||
|
|
@ -162,7 +238,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
namespace PlaywrightTests;
|
namespace PlaywrightTests;
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTest1 : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task BasicTest()
|
public async Task BasicTest()
|
||||||
|
|
@ -175,7 +251,7 @@ public class UnitTest1 : PageTest
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
### Using Test Hooks
|
## Using Test Hooks
|
||||||
|
|
||||||
You can use `SetUp`/`TearDown` in NUnit or `TestInitialize`/`TestCleanup` in MSTest to prepare and clean up your test environment:
|
You can use `SetUp`/`TearDown` in NUnit or `TestInitialize`/`TestCleanup` in MSTest to prepare and clean up your test environment:
|
||||||
|
|
||||||
|
|
@ -198,7 +274,7 @@ namespace PlaywrightTests;
|
||||||
|
|
||||||
[Parallelizable(ParallelScope.Self)]
|
[Parallelizable(ParallelScope.Self)]
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class Tests : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public async Task MainNavigation()
|
public async Task MainNavigation()
|
||||||
|
|
@ -226,7 +302,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
namespace PlaywrightTests;
|
namespace PlaywrightTests;
|
||||||
|
|
||||||
[TestClass]
|
[TestClass]
|
||||||
public class UnitTest1 : PageTest
|
public class ExampleTest : PageTest
|
||||||
{
|
{
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task MainNavigation()
|
public async Task MainNavigation()
|
||||||
|
|
@ -251,3 +327,5 @@ public class UnitTest1 : PageTest
|
||||||
- [Run single test, multiple tests, headed mode](./running-tests.md)
|
- [Run single test, multiple tests, headed mode](./running-tests.md)
|
||||||
- [Generate tests with Codegen](./codegen.md)
|
- [Generate tests with Codegen](./codegen.md)
|
||||||
- [See a trace of your tests](./trace-viewer-intro.md)
|
- [See a trace of your tests](./trace-viewer-intro.md)
|
||||||
|
- [Run tests on CI](./ci-intro.md)
|
||||||
|
- [Learn more about the NUnit and MSTest base classes](./test-runners.md)
|
||||||
|
|
|
||||||
433
package-lock.json
generated
433
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
"socksv5": "0.0.6",
|
"socksv5": "0.0.6",
|
||||||
"ssim.js": "^3.5.0",
|
"ssim.js": "^3.5.0",
|
||||||
"typescript": "^5.3.2",
|
"typescript": "^5.3.2",
|
||||||
"vite": "^5.0.12",
|
"vite": "^5.0.13",
|
||||||
"ws": "^8.5.0",
|
"ws": "^8.5.0",
|
||||||
"xml2js": "^0.5.0",
|
"xml2js": "^0.5.0",
|
||||||
"yaml": "^2.2.2"
|
"yaml": "^2.2.2"
|
||||||
|
|
@ -853,9 +853,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
|
||||||
"integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==",
|
"integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
|
@ -1518,9 +1518,9 @@
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz",
|
||||||
"integrity": "sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==",
|
"integrity": "sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -1530,9 +1530,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz",
|
||||||
"integrity": "sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==",
|
"integrity": "sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -1542,9 +1542,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz",
|
||||||
"integrity": "sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==",
|
"integrity": "sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -1554,9 +1554,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz",
|
||||||
"integrity": "sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==",
|
"integrity": "sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -1566,9 +1566,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz",
|
||||||
"integrity": "sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==",
|
"integrity": "sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -1578,9 +1578,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz",
|
||||||
"integrity": "sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==",
|
"integrity": "sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -1590,9 +1590,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz",
|
||||||
"integrity": "sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==",
|
"integrity": "sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -1601,10 +1601,22 @@
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
|
"version": "4.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz",
|
||||||
|
"integrity": "sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==",
|
||||||
|
"cpu": [
|
||||||
|
"ppc64le"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz",
|
||||||
"integrity": "sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==",
|
"integrity": "sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
|
@ -1613,10 +1625,22 @@
|
||||||
"linux"
|
"linux"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
|
"version": "4.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz",
|
||||||
|
"integrity": "sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==",
|
||||||
|
"cpu": [
|
||||||
|
"s390x"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz",
|
||||||
"integrity": "sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==",
|
"integrity": "sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -1626,9 +1650,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz",
|
||||||
"integrity": "sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==",
|
"integrity": "sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -1638,9 +1662,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz",
|
||||||
"integrity": "sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==",
|
"integrity": "sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -1650,9 +1674,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz",
|
||||||
"integrity": "sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==",
|
"integrity": "sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
|
@ -1662,9 +1686,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz",
|
||||||
"integrity": "sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==",
|
"integrity": "sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -6009,9 +6033,9 @@
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.33",
|
"version": "8.4.38",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
|
||||||
"integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==",
|
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
|
|
@ -6029,7 +6053,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.7",
|
"nanoid": "^3.3.7",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
|
|
@ -6407,9 +6431,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.9.5",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.5.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.0.tgz",
|
||||||
"integrity": "sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==",
|
"integrity": "sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.5"
|
"@types/estree": "1.0.5"
|
||||||
},
|
},
|
||||||
|
|
@ -6421,19 +6445,21 @@
|
||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.9.5",
|
"@rollup/rollup-android-arm-eabi": "4.14.0",
|
||||||
"@rollup/rollup-android-arm64": "4.9.5",
|
"@rollup/rollup-android-arm64": "4.14.0",
|
||||||
"@rollup/rollup-darwin-arm64": "4.9.5",
|
"@rollup/rollup-darwin-arm64": "4.14.0",
|
||||||
"@rollup/rollup-darwin-x64": "4.9.5",
|
"@rollup/rollup-darwin-x64": "4.14.0",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.9.5",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.14.0",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.9.5",
|
"@rollup/rollup-linux-arm64-gnu": "4.14.0",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.9.5",
|
"@rollup/rollup-linux-arm64-musl": "4.14.0",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.9.5",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.14.0",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.9.5",
|
"@rollup/rollup-linux-riscv64-gnu": "4.14.0",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.9.5",
|
"@rollup/rollup-linux-s390x-gnu": "4.14.0",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.9.5",
|
"@rollup/rollup-linux-x64-gnu": "4.14.0",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.9.5",
|
"@rollup/rollup-linux-x64-musl": "4.14.0",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.9.5",
|
"@rollup/rollup-win32-arm64-msvc": "4.14.0",
|
||||||
|
"@rollup/rollup-win32-ia32-msvc": "4.14.0",
|
||||||
|
"@rollup/rollup-win32-x64-msvc": "4.14.0",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -6740,9 +6766,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
|
||||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
|
|
@ -7232,9 +7258,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "5.28.3",
|
"version": "5.28.4",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
|
||||||
"integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==",
|
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/busboy": "^2.0.0"
|
"@fastify/busboy": "^2.0.0"
|
||||||
|
|
@ -7345,13 +7371,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.0.12",
|
"version": "5.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
|
||||||
"integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==",
|
"integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.19.3",
|
"esbuild": "^0.20.1",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.38",
|
||||||
"rollup": "^4.2.0"
|
"rollup": "^4.13.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"vite": "bin/vite.js"
|
"vite": "bin/vite.js"
|
||||||
|
|
@ -7417,9 +7443,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/android-arm": {
|
"node_modules/vite/node_modules/@esbuild/android-arm": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
|
||||||
"integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==",
|
"integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -7432,9 +7458,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/android-arm64": {
|
"node_modules/vite/node_modules/@esbuild/android-arm64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==",
|
"integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -7447,9 +7473,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/android-x64": {
|
"node_modules/vite/node_modules/@esbuild/android-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==",
|
"integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7462,9 +7488,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/darwin-arm64": {
|
"node_modules/vite/node_modules/@esbuild/darwin-arm64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==",
|
"integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -7477,9 +7503,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/darwin-x64": {
|
"node_modules/vite/node_modules/@esbuild/darwin-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==",
|
"integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7492,9 +7518,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
|
"node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==",
|
"integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -7507,9 +7533,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/freebsd-x64": {
|
"node_modules/vite/node_modules/@esbuild/freebsd-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==",
|
"integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7522,9 +7548,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-arm": {
|
"node_modules/vite/node_modules/@esbuild/linux-arm": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
|
||||||
"integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==",
|
"integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -7537,9 +7563,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-arm64": {
|
"node_modules/vite/node_modules/@esbuild/linux-arm64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==",
|
"integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -7552,9 +7578,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-ia32": {
|
"node_modules/vite/node_modules/@esbuild/linux-ia32": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
|
||||||
"integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==",
|
"integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
|
@ -7567,9 +7593,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-loong64": {
|
"node_modules/vite/node_modules/@esbuild/linux-loong64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
|
||||||
"integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==",
|
"integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
|
|
@ -7582,9 +7608,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-mips64el": {
|
"node_modules/vite/node_modules/@esbuild/linux-mips64el": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
|
||||||
"integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==",
|
"integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
|
|
@ -7597,9 +7623,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-ppc64": {
|
"node_modules/vite/node_modules/@esbuild/linux-ppc64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
|
||||||
"integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==",
|
"integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
|
@ -7612,9 +7638,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-riscv64": {
|
"node_modules/vite/node_modules/@esbuild/linux-riscv64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
|
||||||
"integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==",
|
"integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
|
@ -7627,9 +7653,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-s390x": {
|
"node_modules/vite/node_modules/@esbuild/linux-s390x": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
|
||||||
"integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==",
|
"integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
|
@ -7642,9 +7668,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/linux-x64": {
|
"node_modules/vite/node_modules/@esbuild/linux-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==",
|
"integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7657,9 +7683,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/netbsd-x64": {
|
"node_modules/vite/node_modules/@esbuild/netbsd-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==",
|
"integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7672,9 +7698,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/openbsd-x64": {
|
"node_modules/vite/node_modules/@esbuild/openbsd-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==",
|
"integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7687,9 +7713,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/sunos-x64": {
|
"node_modules/vite/node_modules/@esbuild/sunos-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==",
|
"integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7702,9 +7728,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/win32-arm64": {
|
"node_modules/vite/node_modules/@esbuild/win32-arm64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==",
|
"integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -7717,9 +7743,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/win32-ia32": {
|
"node_modules/vite/node_modules/@esbuild/win32-ia32": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
|
||||||
"integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==",
|
"integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
|
@ -7732,9 +7758,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/win32-x64": {
|
"node_modules/vite/node_modules/@esbuild/win32-x64": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==",
|
"integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -7747,9 +7773,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite/node_modules/esbuild": {
|
"node_modules/vite/node_modules/esbuild": {
|
||||||
"version": "0.19.11",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
||||||
"integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==",
|
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
|
|
@ -7758,29 +7784,29 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@esbuild/aix-ppc64": "0.19.11",
|
"@esbuild/aix-ppc64": "0.20.2",
|
||||||
"@esbuild/android-arm": "0.19.11",
|
"@esbuild/android-arm": "0.20.2",
|
||||||
"@esbuild/android-arm64": "0.19.11",
|
"@esbuild/android-arm64": "0.20.2",
|
||||||
"@esbuild/android-x64": "0.19.11",
|
"@esbuild/android-x64": "0.20.2",
|
||||||
"@esbuild/darwin-arm64": "0.19.11",
|
"@esbuild/darwin-arm64": "0.20.2",
|
||||||
"@esbuild/darwin-x64": "0.19.11",
|
"@esbuild/darwin-x64": "0.20.2",
|
||||||
"@esbuild/freebsd-arm64": "0.19.11",
|
"@esbuild/freebsd-arm64": "0.20.2",
|
||||||
"@esbuild/freebsd-x64": "0.19.11",
|
"@esbuild/freebsd-x64": "0.20.2",
|
||||||
"@esbuild/linux-arm": "0.19.11",
|
"@esbuild/linux-arm": "0.20.2",
|
||||||
"@esbuild/linux-arm64": "0.19.11",
|
"@esbuild/linux-arm64": "0.20.2",
|
||||||
"@esbuild/linux-ia32": "0.19.11",
|
"@esbuild/linux-ia32": "0.20.2",
|
||||||
"@esbuild/linux-loong64": "0.19.11",
|
"@esbuild/linux-loong64": "0.20.2",
|
||||||
"@esbuild/linux-mips64el": "0.19.11",
|
"@esbuild/linux-mips64el": "0.20.2",
|
||||||
"@esbuild/linux-ppc64": "0.19.11",
|
"@esbuild/linux-ppc64": "0.20.2",
|
||||||
"@esbuild/linux-riscv64": "0.19.11",
|
"@esbuild/linux-riscv64": "0.20.2",
|
||||||
"@esbuild/linux-s390x": "0.19.11",
|
"@esbuild/linux-s390x": "0.20.2",
|
||||||
"@esbuild/linux-x64": "0.19.11",
|
"@esbuild/linux-x64": "0.20.2",
|
||||||
"@esbuild/netbsd-x64": "0.19.11",
|
"@esbuild/netbsd-x64": "0.20.2",
|
||||||
"@esbuild/openbsd-x64": "0.19.11",
|
"@esbuild/openbsd-x64": "0.20.2",
|
||||||
"@esbuild/sunos-x64": "0.19.11",
|
"@esbuild/sunos-x64": "0.20.2",
|
||||||
"@esbuild/win32-arm64": "0.19.11",
|
"@esbuild/win32-arm64": "0.20.2",
|
||||||
"@esbuild/win32-ia32": "0.19.11",
|
"@esbuild/win32-ia32": "0.20.2",
|
||||||
"@esbuild/win32-x64": "0.19.11"
|
"@esbuild/win32-x64": "0.20.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vitefu": {
|
"node_modules/vitefu": {
|
||||||
|
|
@ -8136,10 +8162,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright": {
|
"packages/playwright": {
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8153,11 +8179,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-chromium": {
|
"packages/playwright-browser-chromium": {
|
||||||
"name": "@playwright/browser-chromium",
|
"name": "@playwright/browser-chromium",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8165,11 +8191,11 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-firefox": {
|
"packages/playwright-browser-firefox": {
|
||||||
"name": "@playwright/browser-firefox",
|
"name": "@playwright/browser-firefox",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8177,22 +8203,22 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-browser-webkit": {
|
"packages/playwright-browser-webkit": {
|
||||||
"name": "@playwright/browser-webkit",
|
"name": "@playwright/browser-webkit",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-chromium": {
|
"packages/playwright-chromium": {
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8202,7 +8228,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-core": {
|
"packages/playwright-core": {
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
|
|
@ -8213,15 +8239,12 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-core": {
|
"packages/playwright-ct-core": {
|
||||||
"name": "@playwright/experimental-ct-core",
|
"name": "@playwright/experimental-ct-core",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.43.0-next",
|
"playwright": "1.45.0-next",
|
||||||
"playwright-core": "1.43.0-next",
|
"playwright-core": "1.45.0-next",
|
||||||
"vite": "^5.0.12"
|
"vite": "^5.2.8"
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"playwright": "cli.js"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16"
|
"node": ">=16"
|
||||||
|
|
@ -8229,10 +8252,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react": {
|
"packages/playwright-ct-react": {
|
||||||
"name": "@playwright/experimental-ct-react",
|
"name": "@playwright/experimental-ct-react",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.43.0-next",
|
"@playwright/experimental-ct-core": "1.45.0-next",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8244,10 +8267,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-react17": {
|
"packages/playwright-ct-react17": {
|
||||||
"name": "@playwright/experimental-ct-react17",
|
"name": "@playwright/experimental-ct-react17",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.43.0-next",
|
"@playwright/experimental-ct-core": "1.45.0-next",
|
||||||
"@vitejs/plugin-react": "^4.2.1"
|
"@vitejs/plugin-react": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8259,10 +8282,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-solid": {
|
"packages/playwright-ct-solid": {
|
||||||
"name": "@playwright/experimental-ct-solid",
|
"name": "@playwright/experimental-ct-solid",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.43.0-next",
|
"@playwright/experimental-ct-core": "1.45.0-next",
|
||||||
"vite-plugin-solid": "^2.7.0"
|
"vite-plugin-solid": "^2.7.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8277,10 +8300,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-svelte": {
|
"packages/playwright-ct-svelte": {
|
||||||
"name": "@playwright/experimental-ct-svelte",
|
"name": "@playwright/experimental-ct-svelte",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.43.0-next",
|
"@playwright/experimental-ct-core": "1.45.0-next",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
"@sveltejs/vite-plugin-svelte": "^3.0.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8295,10 +8318,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue": {
|
"packages/playwright-ct-vue": {
|
||||||
"name": "@playwright/experimental-ct-vue",
|
"name": "@playwright/experimental-ct-vue",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.43.0-next",
|
"@playwright/experimental-ct-core": "1.45.0-next",
|
||||||
"@vitejs/plugin-vue": "^4.2.1"
|
"@vitejs/plugin-vue": "^4.2.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8310,10 +8333,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-ct-vue2": {
|
"packages/playwright-ct-vue2": {
|
||||||
"name": "@playwright/experimental-ct-vue2",
|
"name": "@playwright/experimental-ct-vue2",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@playwright/experimental-ct-core": "1.43.0-next",
|
"@playwright/experimental-ct-core": "1.45.0-next",
|
||||||
"@vitejs/plugin-vue2": "^2.2.0"
|
"@vitejs/plugin-vue2": "^2.2.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -8362,11 +8385,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-firefox": {
|
"packages/playwright-firefox": {
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8377,10 +8400,10 @@
|
||||||
},
|
},
|
||||||
"packages/playwright-test": {
|
"packages/playwright-test": {
|
||||||
"name": "@playwright/test",
|
"name": "@playwright/test",
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.43.0-next"
|
"playwright": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
@ -8390,11 +8413,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packages/playwright-webkit": {
|
"packages/playwright-webkit": {
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.43.0-next"
|
"playwright-core": "1.45.0-next"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "playwright-internal",
|
"name": "playwright-internal",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.43.0-next",
|
"version": "1.45.0-next",
|
||||||
"description": "A high-level API to automate web browsers",
|
"description": "A high-level API to automate web browsers",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
"socksv5": "0.0.6",
|
"socksv5": "0.0.6",
|
||||||
"ssim.js": "^3.5.0",
|
"ssim.js": "^3.5.0",
|
||||||
"typescript": "^5.3.2",
|
"typescript": "^5.3.2",
|
||||||
"vite": "^5.0.12",
|
"vite": "^5.0.13",
|
||||||
"ws": "^8.5.0",
|
"ws": "^8.5.0",
|
||||||
"xml2js": "^0.5.0",
|
"xml2js": "^0.5.0",
|
||||||
"yaml": "^2.2.2"
|
"yaml": "^2.2.2"
|
||||||
|
|
|
||||||
|
|
@ -98,27 +98,7 @@ export class Filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
matches(test: TestCaseSummary): boolean {
|
matches(test: TestCaseSummary): boolean {
|
||||||
if (!(test as any).searchValues) {
|
const searchValues = cacheSearchValues(test);
|
||||||
let status = 'passed';
|
|
||||||
if (test.outcome === 'unexpected')
|
|
||||||
status = 'failed';
|
|
||||||
if (test.outcome === 'flaky')
|
|
||||||
status = 'flaky';
|
|
||||||
if (test.outcome === 'skipped')
|
|
||||||
status = 'skipped';
|
|
||||||
const searchValues: SearchValues = {
|
|
||||||
text: (status + ' ' + test.projectName + ' ' + test.tags.join(' ') + ' ' + test.location.file + ' ' + test.path.join(' ') + ' ' + test.title).toLowerCase(),
|
|
||||||
project: test.projectName.toLowerCase(),
|
|
||||||
status: status as any,
|
|
||||||
file: test.location.file,
|
|
||||||
line: String(test.location.line),
|
|
||||||
column: String(test.location.column),
|
|
||||||
labels: test.tags.map(tag => tag.toLowerCase()),
|
|
||||||
};
|
|
||||||
(test as any).searchValues = searchValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
const searchValues = (test as any).searchValues as SearchValues;
|
|
||||||
if (this.project.length) {
|
if (this.project.length) {
|
||||||
const matches = !!this.project.find(p => searchValues.project.includes(p));
|
const matches = !!this.project.find(p => searchValues.project.includes(p));
|
||||||
if (!matches)
|
if (!matches)
|
||||||
|
|
@ -128,6 +108,9 @@ export class Filter {
|
||||||
const matches = !!this.status.find(s => searchValues.status.includes(s));
|
const matches = !!this.status.find(s => searchValues.status.includes(s));
|
||||||
if (!matches)
|
if (!matches)
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
if (searchValues.status === 'skipped')
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (this.text.length) {
|
if (this.text.length) {
|
||||||
for (const text of this.text) {
|
for (const text of this.text) {
|
||||||
|
|
@ -159,3 +142,50 @@ type SearchValues = {
|
||||||
labels: string[];
|
labels: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const searchValuesSymbol = Symbol('searchValues');
|
||||||
|
|
||||||
|
function cacheSearchValues(test: TestCaseSummary): SearchValues {
|
||||||
|
const cached = (test as any)[searchValuesSymbol] as SearchValues | undefined;
|
||||||
|
if (cached)
|
||||||
|
return cached;
|
||||||
|
|
||||||
|
let status: SearchValues['status'] = 'passed';
|
||||||
|
if (test.outcome === 'unexpected')
|
||||||
|
status = 'failed';
|
||||||
|
if (test.outcome === 'flaky')
|
||||||
|
status = 'flaky';
|
||||||
|
if (test.outcome === 'skipped')
|
||||||
|
status = 'skipped';
|
||||||
|
const searchValues: SearchValues = {
|
||||||
|
text: (status + ' ' + test.projectName + ' ' + test.tags.join(' ') + ' ' + test.location.file + ' ' + test.path.join(' ') + ' ' + test.title).toLowerCase(),
|
||||||
|
project: test.projectName.toLowerCase(),
|
||||||
|
status,
|
||||||
|
file: test.location.file,
|
||||||
|
line: String(test.location.line),
|
||||||
|
column: String(test.location.column),
|
||||||
|
labels: test.tags.map(tag => tag.toLowerCase()),
|
||||||
|
};
|
||||||
|
(test as any)[searchValuesSymbol] = searchValues;
|
||||||
|
return searchValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function filterWithToken(tokens: string[], token: string, append: boolean): string {
|
||||||
|
if (append) {
|
||||||
|
if (!tokens.includes(token))
|
||||||
|
return '#?q=' + [...tokens, token].join(' ').trim();
|
||||||
|
return '#?q=' + tokens.filter(t => t !== token).join(' ').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if metaKey or ctrlKey is not pressed, replace existing token with new token
|
||||||
|
let prefix: 's:' | 'p:' | '@';
|
||||||
|
if (token.startsWith('s:'))
|
||||||
|
prefix = 's:';
|
||||||
|
if (token.startsWith('p:'))
|
||||||
|
prefix = 'p:';
|
||||||
|
if (token.startsWith('@'))
|
||||||
|
prefix = '@';
|
||||||
|
|
||||||
|
const newTokens = tokens.filter(t => !t.startsWith(prefix));
|
||||||
|
newTokens.push(token);
|
||||||
|
return '#?q=' + newTokens.join(' ').trim();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ test('should render counters', async ({ mount }) => {
|
||||||
skipped: 10,
|
skipped: 10,
|
||||||
ok: false,
|
ok: false,
|
||||||
}} filterText='' setFilterText={() => {}}></HeaderView>);
|
}} filterText='' setFilterText={() => {}}></HeaderView>);
|
||||||
await expect(component.locator('a', { hasText: 'All' }).locator('.counter')).toHaveText('100');
|
await expect(component.locator('a', { hasText: 'All' }).locator('.counter')).toHaveText('90');
|
||||||
await expect(component.locator('a', { hasText: 'Passed' }).locator('.counter')).toHaveText('42');
|
await expect(component.locator('a', { hasText: 'Passed' }).locator('.counter')).toHaveText('42');
|
||||||
await expect(component.locator('a', { hasText: 'Failed' }).locator('.counter')).toHaveText('31');
|
await expect(component.locator('a', { hasText: 'Failed' }).locator('.counter')).toHaveText('31');
|
||||||
await expect(component.locator('a', { hasText: 'Flaky' }).locator('.counter')).toHaveText('17');
|
await expect(component.locator('a', { hasText: 'Flaky' }).locator('.counter')).toHaveText('17');
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import './headerView.css';
|
||||||
import * as icons from './icons';
|
import * as icons from './icons';
|
||||||
import { Link, navigate } from './links';
|
import { Link, navigate } from './links';
|
||||||
import { statusIcon } from './statusIcon';
|
import { statusIcon } from './statusIcon';
|
||||||
|
import { filterWithToken } from './filter';
|
||||||
|
|
||||||
export const HeaderView: React.FC<React.PropsWithChildren<{
|
export const HeaderView: React.FC<React.PropsWithChildren<{
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
|
|
@ -64,20 +65,23 @@ export const HeaderView: React.FC<React.PropsWithChildren<{
|
||||||
const StatsNavView: React.FC<{
|
const StatsNavView: React.FC<{
|
||||||
stats: Stats
|
stats: Stats
|
||||||
}> = ({ stats }) => {
|
}> = ({ stats }) => {
|
||||||
|
const searchParams = new URLSearchParams(window.location.hash.slice(1));
|
||||||
|
const q = searchParams.get('q')?.toString() || '';
|
||||||
|
const tokens = q.split(' ');
|
||||||
return <nav>
|
return <nav>
|
||||||
<Link className='subnav-item' href='#?'>
|
<Link className='subnav-item' href='#?'>
|
||||||
All <span className='d-inline counter'>{stats.total}</span>
|
All <span className='d-inline counter'>{stats.total - stats.skipped}</span>
|
||||||
</Link>
|
</Link>
|
||||||
<Link className='subnav-item' href='#?q=s:passed'>
|
<Link className='subnav-item' click={filterWithToken(tokens, 's:passed', false)} ctrlClick={filterWithToken(tokens, 's:passed', true)}>
|
||||||
Passed <span className='d-inline counter'>{stats.expected}</span>
|
Passed <span className='d-inline counter'>{stats.expected}</span>
|
||||||
</Link>
|
</Link>
|
||||||
<Link className='subnav-item' href='#?q=s:failed'>
|
<Link className='subnav-item' click={filterWithToken(tokens, 's:failed', false)} ctrlClick={filterWithToken(tokens, 's:failed', true)}>
|
||||||
{!!stats.unexpected && statusIcon('unexpected')} Failed <span className='d-inline counter'>{stats.unexpected}</span>
|
{!!stats.unexpected && statusIcon('unexpected')} Failed <span className='d-inline counter'>{stats.unexpected}</span>
|
||||||
</Link>
|
</Link>
|
||||||
<Link className='subnav-item' href='#?q=s:flaky'>
|
<Link className='subnav-item' click={filterWithToken(tokens, 's:flaky', false)} ctrlClick={filterWithToken(tokens, 's:flaky', true)}>
|
||||||
{!!stats.flaky && statusIcon('flaky')} Flaky <span className='d-inline counter'>{stats.flaky}</span>
|
{!!stats.flaky && statusIcon('flaky')} Flaky <span className='d-inline counter'>{stats.flaky}</span>
|
||||||
</Link>
|
</Link>
|
||||||
<Link className='subnav-item' href='#?q=s:skipped'>
|
<Link className='subnav-item' click={filterWithToken(tokens, 's:skipped', false)} ctrlClick={filterWithToken(tokens, 's:skipped', true)}>
|
||||||
Skipped <span className='d-inline counter'>{stats.skipped}</span>
|
Skipped <span className='d-inline counter'>{stats.skipped}</span>
|
||||||
</Link>
|
</Link>
|
||||||
</nav>;
|
</nav>;
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,19 @@ export const Route: React.FunctionComponent<{
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Link: React.FunctionComponent<{
|
export const Link: React.FunctionComponent<{
|
||||||
href: string,
|
href?: string,
|
||||||
|
click?: string,
|
||||||
|
ctrlClick?: string,
|
||||||
className?: string,
|
className?: string,
|
||||||
title?: string,
|
title?: string,
|
||||||
children: any,
|
children: any,
|
||||||
}> = ({ href, className, children, title }) => {
|
}> = ({ href, click, ctrlClick, className, children, title }) => {
|
||||||
return <a style={{ textDecoration: 'none', color: 'var(--color-fg-default)' }} className={`${className || ''}`} href={href} title={title}>{children}</a>;
|
return <a style={{ textDecoration: 'none', color: 'var(--color-fg-default)', cursor: 'pointer' }} href={href} className={`${className || ''}`} title={title} onClick={e => {
|
||||||
|
if (click) {
|
||||||
|
e.preventDefault();
|
||||||
|
navigate(e.metaKey || e.ctrlKey ? ctrlClick || click : click);
|
||||||
|
}
|
||||||
|
}}>{children}</a>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProjectLink: React.FunctionComponent<{
|
export const ProjectLink: React.FunctionComponent<{
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue