diff --git a/.github/actions/download-artifact/action.yml b/.github/actions/download-artifact/action.yml index d279df5f8d..3ab38a4c17 100644 --- a/.github/actions/download-artifact/action.yml +++ b/.github/actions/download-artifact/action.yml @@ -4,12 +4,10 @@ inputs: namePrefix: description: 'Name prefix of the artifacts to download' required: true - type: string default: 'blob-report' path: description: 'Directory with downloaded artifacts' required: true - type: string default: '.' runs: using: "composite" diff --git a/.github/actions/download-blob-report-from-azure/action.yml b/.github/actions/download-blob-report-from-azure/action.yml index 8026de64ea..848b98cfbc 100644 --- a/.github/actions/download-blob-report-from-azure/action.yml +++ b/.github/actions/download-blob-report-from-azure/action.yml @@ -4,16 +4,13 @@ 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: diff --git a/.github/actions/upload-blob-report/action.yml b/.github/actions/upload-blob-report/action.yml index 87eda3baf8..72a084142a 100644 --- a/.github/actions/upload-blob-report/action.yml +++ b/.github/actions/upload-blob-report/action.yml @@ -4,29 +4,30 @@ inputs: report_dir: description: 'Directory containing blob report' required: true - type: string default: 'test-results/blob-report' job_name: description: 'Unique job name' required: true - type: string default: '' runs: using: "composite" steps: + - name: Integrity check + shell: bash + run: find "${{ inputs.report_dir }}" -name "*.zip" -exec unzip -t {} \; - 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 with: name: blob-report-${{ inputs.job_name }} path: ${{ inputs.report_dir }}/** retention-days: 7 - 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 run: echo '${{ github.event.number }}' > pull_request_number.txt; - 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 with: name: pull-request-${{ inputs.job_name }} diff --git a/.github/workflows/publish_release_npm.yml b/.github/workflows/publish_release_npm.yml index 3b92a01b14..46b5816834 100644 --- a/.github/workflows/publish_release_npm.yml +++ b/.github/workflows/publish_release_npm.yml @@ -25,10 +25,10 @@ jobs: - run: npm run build - run: npx playwright install-deps - run: utils/publish_all_packages.sh --release-candidate - if: "github.event.release.prerelease" + if: ${{ github.event.release.prerelease }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: utils/publish_all_packages.sh --release - if: "!github.event.release.prerelease" + if: ${{ !github.event.release.prerelease }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/tests_electron.yml b/.github/workflows/tests_electron.yml index 4427cc5e9c..05f7302747 100644 --- a/.github/workflows/tests_electron.yml +++ b/.github/workflows/tests_electron.yml @@ -42,7 +42,7 @@ jobs: - run: npm run etest if: matrix.os != 'ubuntu-latest' - run: node tests/config/checkCoverage.js electron - if: always() && matrix.os == 'ubuntu-latest' + if: ${{ !cancelled() && matrix.os == 'ubuntu-latest' }} - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash diff --git a/.github/workflows/tests_primary.yml b/.github/workflows/tests_primary.yml index 8c491514ae..5b4b080287 100644 --- a/.github/workflows/tests_primary.yml +++ b/.github/workflows/tests_primary.yml @@ -58,10 +58,10 @@ jobs: - 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() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -92,10 +92,10 @@ jobs: 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() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -145,10 +145,10 @@ jobs: - 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() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -172,18 +172,18 @@ jobs: env: PWTEST_BOT_NAME: "web-components-html-reporter" - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: packages/html-reporter/blob-report job_name: "web-components-html-reporter" - run: npm run test-web - if: always() + if: ${{ !cancelled() }} env: PWTEST_BOT_NAME: "web-components-web" - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: packages/web/blob-report @@ -219,7 +219,7 @@ jobs: run: npm run test -- --workers=1 working-directory: ./playwright-vscode - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: playwright-vscode/blob-report @@ -255,10 +255,10 @@ jobs: - 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() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index 7659c338bc..0ba6b9d848 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -45,10 +45,10 @@ jobs: - 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() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -77,10 +77,10 @@ jobs: - run: npx playwright install --with-deps ${{ matrix.browser }} chromium - run: npm run test -- --project=${{ matrix.browser }}-* - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -113,10 +113,10 @@ jobs: if: matrix.browser != 'firefox' shell: bash - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -151,7 +151,7 @@ jobs: - 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() + if: ${{ !cancelled() }} shell: bash headed_tests: @@ -176,14 +176,14 @@ jobs: - run: npm run build - run: npx playwright install --with-deps ${{ matrix.browser }} chromium - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test -- --project=${{ matrix.browser }}-* --headed - if: always() && startsWith(matrix.os, 'ubuntu-') + if: ${{ !cancelled() && startsWith(matrix.os, 'ubuntu-') }} - run: npm run test -- --project=${{ matrix.browser }}-* --headed - if: always() && !startsWith(matrix.os, 'ubuntu-') + if: ${{ !cancelled() && !startsWith(matrix.os, 'ubuntu-') }} - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -213,10 +213,10 @@ jobs: env: PWTEST_MODE: ${{ matrix.mode }} - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -252,10 +252,10 @@ jobs: PWTEST_TRACE: 1 PWTEST_CHANNEL: ${{ matrix.channel }} - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -280,10 +280,10 @@ jobs: env: PWTEST_CHANNEL: chrome - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -309,10 +309,10 @@ jobs: env: PWTEST_CHANNEL: chrome - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -337,10 +337,10 @@ jobs: env: PWTEST_CHANNEL: chrome - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -371,10 +371,10 @@ jobs: - run: npm run ctest if: matrix.os != 'ubuntu-20.04' - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -405,10 +405,10 @@ jobs: - run: npm run ctest -- --headed if: matrix.os != 'ubuntu-latest' - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -433,10 +433,10 @@ jobs: env: PWTEST_CHANNEL: firefox-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -462,10 +462,10 @@ jobs: env: PWTEST_CHANNEL: firefox-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -490,10 +490,10 @@ jobs: env: PWTEST_CHANNEL: firefox-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -518,10 +518,10 @@ jobs: env: PWTEST_CHANNEL: msedge - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -547,10 +547,10 @@ jobs: env: PWTEST_CHANNEL: msedge - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -575,10 +575,10 @@ jobs: env: PWTEST_CHANNEL: msedge - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -603,10 +603,10 @@ jobs: env: PWTEST_CHANNEL: msedge-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -632,10 +632,10 @@ jobs: env: PWTEST_CHANNEL: msedge-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -660,10 +660,10 @@ jobs: env: PWTEST_CHANNEL: msedge-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -688,10 +688,10 @@ jobs: env: PWTEST_CHANNEL: msedge-dev - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -717,10 +717,10 @@ jobs: env: PWTEST_CHANNEL: msedge-dev - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -745,10 +745,10 @@ jobs: env: PWTEST_CHANNEL: msedge-dev - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -773,10 +773,10 @@ jobs: env: PWTEST_CHANNEL: chrome-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -802,10 +802,10 @@ jobs: env: PWTEST_CHANNEL: chrome-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -830,10 +830,10 @@ jobs: env: PWTEST_CHANNEL: chrome-beta - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report @@ -873,10 +873,10 @@ jobs: PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1 - run: node tests/config/checkCoverage.js chromium - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash - name: Upload blob report - if: always() + if: ${{ !cancelled() }} uses: ./.github/actions/upload-blob-report with: report_dir: blob-report diff --git a/.github/workflows/tests_service.yml b/.github/workflows/tests_service.yml index b8c192f988..2739680712 100644 --- a/.github/workflows/tests_service.yml +++ b/.github/workflows/tests_service.yml @@ -33,7 +33,7 @@ jobs: PLAYWRIGHT_SERVICE_OS: ${{ matrix.service-os }} PLAYWRIGHT_SERVICE_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }} - name: Upload blob report to GitHub - if: always() + if: ${{ !cancelled() }} uses: actions/upload-artifact@v3 with: name: all-blob-reports @@ -43,7 +43,7 @@ jobs: merge_reports: name: "Merge reports" needs: [test] - if: always() + if: ${{ !cancelled() }} runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tests_stress.yml b/.github/workflows/tests_stress.yml index 7c2ce79088..d0409cd585 100644 --- a/.github/workflows/tests_stress.yml +++ b/.github/workflows/tests_stress.yml @@ -37,22 +37,22 @@ jobs: - run: npx playwright install firefox-asan if: matrix.os != 'windows-latest' - run: npm run stest contexts -- --project=chromium - if: always() + if: ${{ !cancelled() }} - run: npm run stest browsers -- --project=chromium - if: always() + if: ${{ !cancelled() }} - run: npm run stest frames -- --project=chromium - if: always() + if: ${{ !cancelled() }} - run: npm run stest contexts -- --project=webkit - if: always() + if: ${{ !cancelled() }} - run: npm run stest browsers -- --project=webkit - if: always() + if: ${{ !cancelled() }} - run: npm run stest frames -- --project=webkit - if: always() + if: ${{ !cancelled() }} - run: npm run stest contexts -- --project=firefox - if: always() + if: ${{ !cancelled() }} - run: npm run stest browsers -- --project=firefox - if: always() + if: ${{ !cancelled() }} - run: npm run stest frames -- --project=firefox - if: always() + if: ${{ !cancelled() }} - run: npm run stest heap -- --project=chromium - if: always() + if: ${{ !cancelled() }} diff --git a/.github/workflows/tests_video.yml b/.github/workflows/tests_video.yml index 3acda7cec7..b51c0e4e76 100644 --- a/.github/workflows/tests_video.yml +++ b/.github/workflows/tests_video.yml @@ -36,5 +36,5 @@ jobs: env: PWTEST_VIDEO: 1 - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash diff --git a/.github/workflows/tests_webview2.yml b/.github/workflows/tests_webview2.yml index 26c97f6062..cf9a2ef0e9 100644 --- a/.github/workflows/tests_webview2.yml +++ b/.github/workflows/tests_webview2.yml @@ -46,5 +46,5 @@ jobs: Start-Process -FilePath setup.exe -Verb RunAs -Wait - run: npm run webview2test - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json - if: always() + if: ${{ !cancelled() }} shell: bash diff --git a/README.md b/README.md index 93be49146e..0bb303f52d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🎭 Playwright -[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-124.0.6367.8-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-123.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-124.0.6367.8-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-124.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -10,7 +10,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | :--- | :---: | :---: | :---: | | Chromium 124.0.6367.8 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 17.4 | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| Firefox 123.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Firefox 124.0 | :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. diff --git a/docs/src/accessibility-testing-js.md b/docs/src/accessibility-testing-js.md index d367662545..96fe1f1865 100644 --- a/docs/src/accessibility-testing-js.md +++ b/docs/src/accessibility-testing-js.md @@ -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. -:::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. 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. diff --git a/docs/src/api/class-apirequestcontext.md b/docs/src/api/class-apirequestcontext.md index dacd5dd343..addf5baacb 100644 --- a/docs/src/api/class-apirequestcontext.md +++ b/docs/src/api/class-apirequestcontext.md @@ -566,7 +566,7 @@ api_request_context.post("https://example.com/api/createBook", data=data) ```csharp var data = new Dictionary() { - { "firstNam", "John" }, + { "firstName", "John" }, { "lastName", "Doe" } }; await request.PostAsync("https://example.com/api/createBook", new() { DataObject = data }); diff --git a/docs/src/api/class-elementhandle.md b/docs/src/api/class-elementhandle.md index 6d727f675a..3f27509a0d 100644 --- a/docs/src/api/class-elementhandle.md +++ b/docs/src/api/class-elementhandle.md @@ -4,7 +4,7 @@ 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. ::: diff --git a/docs/src/api/class-formdata.md b/docs/src/api/class-formdata.md index c578021653..76a1f85619 100644 --- a/docs/src/api/class-formdata.md +++ b/docs/src/api/class-formdata.md @@ -14,6 +14,72 @@ FormData form = FormData.create() page.request().post("http://localhost/submit", RequestOptions.create().setForm(form)); ``` +## method: FormData.add +* since: v1.43 +- returns: <[FormData]> + +Adds a field to the form. File values can be passed either as `Path` or as `FilePayload`. +Multiple fields with the same name can be added. + +```java +import com.microsoft.playwright.options.FormData; +... +FormData form = FormData.create() + // Only name and value are set. + .add("firstName", "John") + // Name and value are set, filename and Content-Type are inferred from the file path. + .add("attachment", Paths.get("pic.jpg")) + // Name, value, filename and Content-Type are set. + .add("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.Add("firstName", "John"); +// Name, value, filename and Content-Type are set. +multipart.Add("attachment", new FilePayload() +{ + Name = "pic.jpg", + MimeType = "image/jpeg", + Buffer = File.ReadAllBytes("john.jpg") +}); +// Name, value, filename and Content-Type are set. +multipart.Add("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.add.name +* since: v1.43 +- `name` <[string]> + +Field name. + +### param: FormData.add.value +* since: v1.43 +- `value` <[string]|[boolean]|[int]|[Path]|[Object]> + - `name` <[string]> File name + - `mimeType` <[string]> File type + - `buffer` <[Buffer]> File content + +Field value. + +### param: FormData.add.value +* since: v1.43 +* langs: csharp +- `value` <[string]|[boolean]|[int]|[Object]> + - `name` <[string]> File name + - `mimeType` <[string]> File type + - `buffer` <[Buffer]> File content + +Field value. + ## method: FormData.create * since: v1.18 * langs: java @@ -36,7 +102,7 @@ FormData form = FormData.create() // Name and value are set, filename and Content-Type are inferred from the file path. .set("profilePicture1", Paths.get("john.jpg")) // 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); page.request().post("http://localhost/submit", RequestOptions.create().setForm(form)); ``` @@ -52,6 +118,7 @@ multipart.Set("profilePicture", new FilePayload() MimeType = "image/jpeg", Buffer = File.ReadAllBytes("john.jpg") }); +multipart.Set("age", 30); await Page.APIRequest.PostAsync("https://localhost/submit", new() { Multipart = multipart }); ``` diff --git a/docs/src/api/class-framelocator.md b/docs/src/api/class-framelocator.md index cf75fc8422..320ad36ba2 100644 --- a/docs/src/api/class-framelocator.md +++ b/docs/src/api/class-framelocator.md @@ -74,57 +74,11 @@ await page.FrameLocator(".result-frame").First.getByRole(AriaRole.Button).ClickA **Converting Locator to FrameLocator** -If you have a [Locator] object pointing to an `iframe` it can be converted to [FrameLocator] using [`method: Locator.enterFrame`]. +If you have a [Locator] object pointing to an `iframe` it can be converted to [FrameLocator] using [`method: Locator.contentFrame`]. **Converting FrameLocator to Locator** -If you have a [FrameLocator] object it can be converted to [Locator] pointing to the same `iframe` using [`method: FrameLocator.exitFrame`]. - - -## method: FrameLocator.exitFrame -* 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. - -**Usage** - -```js -const frameLocator = page.frameLocator('iframe[name="embedded"]'); -// ... -const locator = frameLocator.exitFrame(); -await expect(locator).toBeVisible(); -``` - -```java -FrameLocator frameLocator = page.frameLocator("iframe[name=\"embedded\"]"); -// ... -Locator locator = frameLocator.exitFrame(); -assertThat(locator).isVisible(); -``` - -```python async -frame_locator = page.frame_locator("iframe[name=\"embedded\"]") -# ... -locator = frame_locator.exit_frame -await expect(locator).to_be_visible() -``` - -```python sync -frame_locator = page.frame_locator("iframe[name=\"embedded\"]") -# ... -locator = frame_locator.exit_frame -expect(locator).to_be_visible() -``` - -```csharp -var frameLocator = Page.FrameLocator("iframe[name=\"embedded\"]"); -// ... -var locator = frameLocator.ExitFrame; -await Expect(locator).ToBeVisibleAsync(); -``` +If you have a [FrameLocator] object it can be converted to [Locator] pointing to the same `iframe` using [`method: FrameLocator.owner`]. ## method: FrameLocator.first @@ -248,3 +202,51 @@ Returns locator to the n-th matching frame. It's zero based, `nth(0)` selects th ### param: FrameLocator.nth.index * since: v1.17 - `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(); +``` + diff --git a/docs/src/api/class-locator.md b/docs/src/api/class-locator.md index c254adc1c0..9ccfa6c2b1 100644 --- a/docs/src/api/class-locator.md +++ b/docs/src/api/class-locator.md @@ -53,7 +53,7 @@ foreach (var li in await page.GetByRole("listitem").AllAsync()) 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. ::: @@ -85,7 +85,7 @@ var texts = await page.GetByRole(AriaRole.Link).AllInnerTextsAsync(); 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. ::: @@ -443,7 +443,7 @@ await page.Locator("canvas").ClickAsync(new() { 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. ::: @@ -747,7 +747,7 @@ 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. -## method: Locator.enterFrame +## method: Locator.contentFrame * since: v1.43 - returns: <[FrameLocator]> @@ -755,40 +755,42 @@ 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.enterFrame(); +const frameLocator = locator.contentFrame(); await frameLocator.getByRole('button').click(); ``` ```java Locator locator = page.locator("iframe[name=\"embedded\"]"); // ... -FrameLocator frameLocator = locator.enterFrame(); +FrameLocator frameLocator = locator.contentFrame(); frameLocator.getByRole(AriaRole.BUTTON).click(); ``` ```python async locator = page.locator("iframe[name=\"embedded\"]") # ... -frame_locator = locator.enter_frame +frame_locator = locator.content_frame await frame_locator.get_by_role("button").click() ``` ```python sync locator = page.locator("iframe[name=\"embedded\"]") # ... -frame_locator = locator.enter_frame +frame_locator = locator.content_frame frame_locator.get_by_role("button").click() ``` ```csharp var locator = Page.Locator("iframe[name=\"embedded\"]"); // ... -var frameLocator = locator.EnterFrame; +var frameLocator = locator.ContentFrame; await frameLocator.GetByRole(AriaRole.Button).ClickAsync(); ``` @@ -1119,7 +1121,7 @@ await locator.ClickAsync(); 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. ::: @@ -1291,7 +1293,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). -:::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. ::: @@ -1307,7 +1309,7 @@ If you need to assert text on the page, prefer [`method: LocatorAssertions.toHav Returns the value for the matching `` or `