diff --git a/.github/workflows/create_test_report.yml b/.github/workflows/create_test_report.yml index b20f57573b..dfc6961c2c 100644 --- a/.github/workflows/create_test_report.yml +++ b/.github/workflows/create_test_report.yml @@ -35,7 +35,7 @@ jobs: run: | npx playwright merge-reports --config .github/workflows/merge.config.ts ./all-blob-reports env: - NODE_OPTIONS: --max-old-space-size=4096 + NODE_OPTIONS: --max-old-space-size=8192 - name: Azure Login uses: azure/login@v2 diff --git a/.github/workflows/tests_secondary.yml b/.github/workflows/tests_secondary.yml index 71c7ed105f..6f47843edf 100644 --- a/.github/workflows/tests_secondary.yml +++ b/.github/workflows/tests_secondary.yml @@ -268,23 +268,6 @@ jobs: - run: npx playwright install-deps - run: utils/build/build-playwright-driver.sh - test_linux_chromium_headless_new: - name: Linux Chromium Headless New - environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/run-test - with: - browsers-to-install: chromium - command: npm run ctest - bot-name: "headless-new" - 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: - PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1 - test_linux_chromium_headless_shell: name: Chromium Headless Shell environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }} diff --git a/README.md b/README.md index df47df9121..ce154c60d9 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-131.0.6778.13-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) +[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) [![Chromium version](https://img.shields.io/badge/chromium-131.0.6778.24-blue.svg?logo=google-chrome)](https://www.chromium.org/Home) [![Firefox version](https://img.shields.io/badge/firefox-131.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/) [![WebKit version](https://img.shields.io/badge/webkit-18.0-blue.svg?logo=safari)](https://webkit.org/) [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord) ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright) @@ -8,7 +8,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr | | Linux | macOS | Windows | | :--- | :---: | :---: | :---: | -| Chromium 131.0.6778.13 | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Chromium 131.0.6778.24 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | WebKit 18.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | | Firefox 131.0 | :white_check_mark: | :white_check_mark: | :white_check_mark: | diff --git a/docs/src/best-practices-js.md b/docs/src/best-practices-js.md index 0c4e71d3a5..20f55c61d0 100644 --- a/docs/src/best-practices-js.md +++ b/docs/src/best-practices-js.md @@ -90,7 +90,7 @@ await page #### Prefer user-facing attributes to XPath or CSS selectors -Your DOM can easily change so having your tests depend on your DOM structure can lead to failing tests. For example consider selecting this button by its CSS classes. Should the designer change something then the class might change breaking your test. +Your DOM can easily change so having your tests depend on your DOM structure can lead to failing tests. For example consider selecting this button by its CSS classes. Should the designer change something then the class might change, thus breaking your test. ```js diff --git a/docs/src/browsers.md b/docs/src/browsers.md index 1b12ff534c..fc3dfb38a1 100644 --- a/docs/src/browsers.md +++ b/docs/src/browsers.md @@ -401,6 +401,23 @@ pytest test_login.py --browser-channel msedge dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=msedge ``` +###### +* langs: python + +Alternatively when using the library directly, you can specify the browser [`option: BrowserType.launch.channel`] when launching the browser: + +```python +from playwright.sync_api import sync_playwright + +with sync_playwright() as p: + # Channel can be "chrome", "msedge", "chrome-beta", "msedge-beta" or "msedge-dev". + browser = p.chromium.launch(channel="msedge") + page = browser.new_page() + page.goto("http://playwright.dev") + print(page.title()) + browser.close() +``` + #### Installing Google Chrome & Microsoft Edge If Google Chrome or Microsoft Edge is not available on your machine, you can install diff --git a/docs/src/test-runners-python.md b/docs/src/test-runners-python.md index d07fa2e53f..0dd4bbeca3 100644 --- a/docs/src/test-runners-python.md +++ b/docs/src/test-runners-python.md @@ -111,16 +111,21 @@ def test_visit_admin_dashboard(page: Page): If you're using VSCode with Pylance, these types can be inferred by enabling the `python.testing.pytestEnabled` setting so you don't need the type annotation. -### Configure slow mo +### Using multiple contexts -Run tests with slow mo with the `--slowmo` argument. +In order to simulate multiple users, you can create multiple [`BrowserContext`](./browser-contexts) instances. -```bash -pytest --slowmo 100 +```py title="test_my_application.py" +from playwright.sync_api import Page, BrowserContext +from pytest_playwright.pytest_playwright import CreateContextCallback + +def test_foo(page: Page, new_context: CreateContextCallback) -> None: + page.goto("https://example.com") + context = new_context() + page2 = context.new_page() + # page and page2 are in different contexts ``` -Slows down Playwright operations by 100 milliseconds. - ### Skip test by browser ```py title="test_my_application.py" @@ -198,7 +203,7 @@ def browser_context_args(browser_context_args): } ``` -### Device emulation +### Device emulation / BrowserContext option overrides ```py title="conftest.py" import pytest diff --git a/package-lock.json b/package-lock.json index 3f503e4c09..3bc7c072e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2412,28 +2412,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/ansi-to-html": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", - "integrity": "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==", - "dependencies": { - "entities": "^2.2.0" - }, - "bin": { - "ansi-to-html": "bin/ansi-to-html" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/ansi-to-html/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -7895,10 +7873,7 @@ } }, "packages/html-reporter": { - "version": "0.0.0", - "dependencies": { - "ansi-to-html": "^0.7.2" - } + "version": "0.0.0" }, "packages/playwright": { "version": "1.49.0-next", diff --git a/packages/html-reporter/package.json b/packages/html-reporter/package.json index bdd0485a07..c1beb75b89 100644 --- a/packages/html-reporter/package.json +++ b/packages/html-reporter/package.json @@ -7,8 +7,5 @@ "dev": "vite", "build": "vite build && tsc", "preview": "vite preview" - }, - "dependencies": { - "ansi-to-html": "^0.7.2" } } diff --git a/packages/html-reporter/src/chip.spec.tsx b/packages/html-reporter/src/chip.spec.tsx index 3a0cfe908a..8c88fee071 100644 --- a/packages/html-reporter/src/chip.spec.tsx +++ b/packages/html-reporter/src/chip.spec.tsx @@ -48,3 +48,14 @@ test('setExpanded is called', async ({ mount }) => { await component.getByText('Title').click(); expect(expandedValues).toEqual([true]); }); + +test('setExpanded should work', async ({ mount }) => { + const component = await mount( + Body + ); + await component.getByText('Title').click(); + await expect(component).toMatchAriaSnapshot(` + - button "Title" [expanded] + - region: Body + `); +}); diff --git a/packages/html-reporter/src/chip.tsx b/packages/html-reporter/src/chip.tsx index 8f4badf97f..0965a40888 100644 --- a/packages/html-reporter/src/chip.tsx +++ b/packages/html-reporter/src/chip.tsx @@ -30,8 +30,12 @@ export const Chip: React.FC<{ dataTestId?: string, targetRef?: React.RefObject, }> = ({ header, expanded, setExpanded, children, noInsets, dataTestId, targetRef }) => { + const id = React.useId(); return
setExpanded?.(!expanded)} title={typeof header === 'string' ? header : undefined}> @@ -39,7 +43,7 @@ export const Chip: React.FC<{ {setExpanded && !expanded && icons.rightArrow()} {header}
- {(!setExpanded || expanded) &&
{children}
} + {(!setExpanded || expanded) &&
{children}
}
; }; diff --git a/packages/html-reporter/src/headerView.spec.tsx b/packages/html-reporter/src/headerView.spec.tsx index 3131ae645d..f783a33c1d 100644 --- a/packages/html-reporter/src/headerView.spec.tsx +++ b/packages/html-reporter/src/headerView.spec.tsx @@ -33,6 +33,11 @@ test('should render counters', async ({ mount }) => { 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: 'Skipped' }).locator('.counter')).toHaveText('10'); + await expect(component).toMatchAriaSnapshot(` + - navigation: + - link "All 90" + - text: Passed 42 Failed 31 Flaky 17 Skipped 10 + `); }); test('should toggle filters', async ({ page, mount }) => { diff --git a/packages/html-reporter/src/headerView.tsx b/packages/html-reporter/src/headerView.tsx index 925bc64721..01f92f1ecb 100644 --- a/packages/html-reporter/src/headerView.tsx +++ b/packages/html-reporter/src/headerView.tsx @@ -20,7 +20,7 @@ import './colors.css'; import './common.css'; import './headerView.css'; import * as icons from './icons'; -import { Link, navigate } from './links'; +import { Link, navigate, SearchParamsContext } from './links'; import { statusIcon } from './statusIcon'; import { filterWithToken } from './filter'; @@ -65,7 +65,7 @@ export const HeaderView: React.FC = ({ stats }) => { - const searchParams = new URLSearchParams(window.location.hash.slice(1)); + const searchParams = React.useContext(SearchParamsContext); const q = searchParams.get('q')?.toString() || ''; const tokens = q.split(' '); return