Skip to content

Commit f7cdfeb

Browse files
committed
Add Playwright E2E test setup
1 parent 51a8b92 commit f7cdfeb

10 files changed

Lines changed: 182 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,21 @@ jobs:
3939
- run: uv run ./manage.py check
4040
- run: uv run ./manage.py makemigrations --check --noinput
4141
- run: uv run ./manage.py test
42+
test-client-integration:
43+
runs-on: ubuntu-latest
44+
env:
45+
DJANGO_SETTINGS_MODULE: bakerydemo.settings.test
46+
PLAYWRIGHT_WEB_SERVER_COMMAND: uv run python manage.py runserver 127.0.0.1:8000 --noreload
47+
steps:
48+
- uses: actions/checkout@v6
49+
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
50+
- uses: actions/setup-node@v6
51+
with:
52+
node-version-file: '.nvmrc'
53+
- run: uv venv
54+
- run: uv pip install -r requirements/development.txt
55+
- run: uv run ./manage.py migrate
56+
- run: uv run ./manage.py load_initial_data
57+
- run: npm ci
58+
- run: npx playwright install --with-deps chromium
59+
- run: npm run test:e2e

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ bakerydemo/settings/local.py
1515
bakerydemodb
1616
*.db
1717
node_modules
18+
playwright-report
19+
test-results
20+
uvenv
1821
venv
1922
.venv
2023
__pycache__

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Irrelevant files ignored for performance reasons.
22
node_modules
3+
playwright-report
4+
test-results
5+
uvenv
36
venv
47
.venv
58
*.min.css

.stylelintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
node_modules
2+
playwright-report
3+
test-results
4+
uvenv
25
venv
36
.venv
47
*.min.css

CONTRIBUTING.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ You can also run the project test suite with:
3737
./manage.py test
3838
```
3939

40+
The browser integration tests use Playwright and the demo fixture data:
41+
42+
```bash
43+
npm ci
44+
npx playwright install chromium
45+
./manage.py migrate
46+
./manage.py load_initial_data
47+
npm run test:e2e
48+
49+
# To open HTML report run below commmand
50+
npx playwright show-report
51+
```
52+
4053
### Demo data management
4154

4255
If you change content or images in this repo and need to prepare a new fixture file for export, do the following on a branch:

eslint.config.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@ import globals from 'globals';
33

44
export default [
55
{
6-
ignores: ['node_modules', 'venv', '.venv', 'bakerydemo/collect_static'],
6+
ignores: [
7+
'node_modules',
8+
'playwright-report',
9+
'test-results',
10+
'uvenv',
11+
'venv',
12+
'.venv',
13+
'bakerydemo/collect_static',
14+
],
715
},
816
{
917
...js.configs.recommended,

package-lock.json

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
},
1111
"devDependencies": {
1212
"@eslint/js": "^9.39.2",
13+
"@playwright/test": "^1.61.1",
1314
"@wagtail/stylelint-config-wagtail": "^2.0.0",
1415
"eslint": "^9.39.2",
1516
"globals": "^16.5.0",
@@ -23,6 +24,7 @@
2324
"lint:js": "eslint --ext .js --report-unused-disable-directives .",
2425
"lint:css": "stylelint **/*.css",
2526
"lint:format": "prettier --check \"**/?(.)*.{css,js,json,yaml,yml}\"",
26-
"lint": "npm run lint:js && npm run lint:css && npm run lint:format"
27+
"lint": "npm run lint:js && npm run lint:css && npm run lint:format",
28+
"test:e2e": "playwright test"
2729
}
2830
}

playwright.config.mjs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
const port = process.env.PORT || '8000';
4+
const baseURL = process.env.PLAYWRIGHT_BASE_URL || `http://127.0.0.1:${port}`;
5+
const webServerCommand =
6+
process.env.PLAYWRIGHT_WEB_SERVER_COMMAND ||
7+
`python3 manage.py runserver 127.0.0.1:${port} --noreload`;
8+
9+
const webServer =
10+
process.env.PLAYWRIGHT_SKIP_WEB_SERVER === '1'
11+
? {}
12+
: {
13+
webServer: {
14+
command: webServerCommand,
15+
url: baseURL,
16+
reuseExistingServer: !process.env.CI,
17+
timeout: 120 * 1000,
18+
},
19+
};
20+
21+
export default defineConfig({
22+
testDir: './tests/e2e',
23+
fullyParallel: true,
24+
reporter: process.env.CI
25+
? [['github'], ['html', { open: 'never' }]]
26+
: [['list'], ['html', { open: 'never' }]],
27+
use: {
28+
baseURL,
29+
trace: 'on-first-retry',
30+
},
31+
projects: [
32+
{
33+
name: 'chromium',
34+
use: { ...devices['Desktop Chrome'] },
35+
},
36+
],
37+
...webServer,
38+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
test.describe('fixture-backed pages', () => {
4+
test('home page renders demo content', async ({ page }) => {
5+
await page.goto('/');
6+
7+
await expect(
8+
page.getByRole('heading', { name: 'Welcome to the Wagtail Bakery!' }),
9+
).toBeVisible();
10+
await expect(
11+
page.getByRole('link', { name: 'Learn more about Wagtail' }),
12+
).toBeVisible();
13+
await expect(page.getByRole('heading', { name: 'Breads' })).toBeVisible();
14+
});
15+
16+
test('desktop search returns fixture content', async ({ page }) => {
17+
await page.goto('/');
18+
19+
await page.locator('#search-input').fill('Anadama');
20+
await page.locator('#search-input').press('Enter');
21+
22+
await expect(page).toHaveURL(/\/search\/\?q=Anadama/);
23+
await expect(
24+
page.getByRole('heading', { name: 'Search results' }),
25+
).toBeVisible();
26+
await expect(page.getByRole('link', { name: /Anadama/ })).toBeVisible();
27+
});
28+
});

0 commit comments

Comments
 (0)