Skip to content

Commit bebabca

Browse files
committed
Merge branch 'playwright'
This topic brings in some UI testing, to build confidence not only in the migration of the website, but also to be able to prevent (or at least swiftly detect) regressions. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents cc86475 + 487f57c commit bebabca

File tree

9 files changed

+417
-0
lines changed

9 files changed

+417
-0
lines changed

.github/actions/deploy-to-github-pages/action.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,17 @@ runs:
144144
await github.rest.issues.update({ ...req, state: 'closed' })
145145
}
146146
}
147+
148+
- name: Install @playwright/test
149+
shell: bash
150+
run: npm install @playwright/test
151+
- name: Run Playwright tests
152+
shell: bash
153+
env:
154+
PLAYWRIGHT_TEST_URL: ${{ steps.pages.outputs.base_url }}
155+
run: npx playwright test --project=chrome
156+
- uses: actions/upload-artifact@v4
157+
if: always()
158+
with:
159+
name: playwright-report
160+
path: playwright-report/

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,10 @@ jobs:
7676
public/
7777
output: lychee.md
7878
jobSummary: true
79+
80+
- name: Install @playwright/test
81+
run: npm install @playwright/test
82+
- name: Run Playwright tests
83+
env:
84+
PLAYWRIGHT_TEST_URL: http://localhost:5000/
85+
run: npx playwright test --project=chrome

.github/workflows/playwright.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Playwright Tests
2+
on:
3+
workflow_dispatch:
4+
inputs:
5+
url:
6+
description: 'URL to test'
7+
required: true
8+
default: 'https://git-scm.com'
9+
jobs:
10+
test:
11+
timeout-minutes: 60
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: lts/*
18+
- name: Install @playwright/test
19+
run: npm install @playwright/test
20+
- name: Run Playwright tests
21+
env:
22+
PLAYWRIGHT_TEST_URL: ${{ github.event.inputs.url }}
23+
run: npx playwright test --project=chrome
24+
- uses: actions/upload-artifact@v4
25+
if: always()
26+
with:
27+
name: playwright-report
28+
path: playwright-report/

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@
1010
/.hugo_build.lock
1111
/public/
1212
/resources/_gen/
13+
/package-lock.json
14+
/node_modules/
15+
/test-results/
16+
/playwright-report/

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ The [list of GUI clients](https://git-scm.com/downloads/guis) has been construct
164164

165165
* https://lychee.cli.rs/
166166

167+
### Playwright (website UI test framework)
168+
169+
* https://playwright.dev/
170+
167171
## License
168172

169173
The source code for the site is licensed under the MIT license, which you can find in

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "git-scm.com",
3+
"version": "0.0.0",
4+
"description": "This is the Git home page.",
5+
"license": "MIT",
6+
"devDependencies": {
7+
"@playwright/test": "^1.47.0",
8+
"@types/node": "^22.5.4"
9+
}
10+
}

playwright.config.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// @ts-check
2+
const { defineConfig, devices } = require('@playwright/test');
3+
4+
/**
5+
* Read environment variables from file.
6+
* https://github.com/motdotla/dotenv
7+
*/
8+
// require('dotenv').config({ path: path.resolve(__dirname, '.env') });
9+
10+
/**
11+
* @see https://playwright.dev/docs/test-configuration
12+
*/
13+
module.exports = defineConfig({
14+
testDir: './tests',
15+
/* Run tests in files in parallel */
16+
fullyParallel: true,
17+
/* Fail the build on CI if you accidentally left test.only in the source code. */
18+
forbidOnly: !!process.env.CI,
19+
/* Retry on CI only */
20+
retries: process.env.CI ? 2 : 0,
21+
/* Opt out of parallel tests on CI. */
22+
workers: process.env.CI ? 1 : undefined,
23+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
24+
/* Uses 'github' for GitHub Actions CI to generate annotations, otherwise 'html' */
25+
reporter: process.env.CI && process.env.PLAYWRIGHT_TEST_URL === 'http://localhost:5000/' ? 'github' : 'html',
26+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
27+
use: {
28+
/* Base URL to use in actions like `await page.goto('/')`. */
29+
// baseURL: 'http://127.0.0.1:3000',
30+
31+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
32+
trace: 'on-first-retry',
33+
},
34+
35+
/* Configure projects for major browsers */
36+
projects: [
37+
{
38+
name: 'chromium',
39+
use: { ...devices['Desktop Chrome'] },
40+
},
41+
42+
{
43+
name: 'firefox',
44+
use: { ...devices['Desktop Firefox'] },
45+
},
46+
47+
{
48+
name: 'webkit',
49+
use: { ...devices['Desktop Safari'] },
50+
},
51+
52+
{
53+
name: 'chrome',
54+
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
55+
},
56+
57+
/* Test against mobile viewports. */
58+
// {
59+
// name: 'Mobile Chrome',
60+
// use: { ...devices['Pixel 5'] },
61+
// },
62+
// {
63+
// name: 'Mobile Safari',
64+
// use: { ...devices['iPhone 12'] },
65+
// },
66+
67+
/* Test against branded browsers. */
68+
// {
69+
// name: 'Microsoft Edge',
70+
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
71+
// },
72+
// {
73+
// name: 'Google Chrome',
74+
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
75+
// },
76+
],
77+
78+
/* Run a local web server before starting the tests as needed */
79+
webServer:
80+
process.env.PLAYWRIGHT_TEST_URL !== 'http://localhost:5000/'
81+
? undefined
82+
: {
83+
command: 'node script/serve-public.js',
84+
url: process.env.PLAYWRIGHT_TEST_URL,
85+
reuseExistingServer: true,
86+
},
87+
});
88+

script/serve-public.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env node
2+
3+
const http = require('http');
4+
const url = require('url');
5+
const fs = require('fs');
6+
const path = require('path');
7+
8+
const basePath = path.join(__dirname, '..', 'public');
9+
10+
const mimeTypes = {
11+
"html": "text/html",
12+
"jpeg": "image/jpeg",
13+
"jpg": "image/jpeg",
14+
"png": "image/png",
15+
"ico": "image/x-icon",
16+
"js": "text/javascript",
17+
"css": "text/css",
18+
"json": "application/json",
19+
'pf_filter': 'application/gzip',
20+
'pf_fragment': 'application/gzip',
21+
'pf_index': 'application/gzip',
22+
'pf_meta': 'application/gzip',
23+
'pagefind': 'application/gzip',
24+
};
25+
26+
const handler = (request, response) => {
27+
const pathname = decodeURIComponent(url.parse(request.url).pathname);
28+
let filename = path.join(basePath, pathname === "/" ? "index.html" : pathname);
29+
30+
let stats = fs.statSync(filename, { throwIfNoEntry: false });
31+
if (!stats?.isFile() && !filename.match(/\.[A-Za-z0-9]{1,11}$/)) {
32+
filename += ".html";
33+
stats = fs.statSync(filename, { throwIfNoEntry: false });
34+
}
35+
try{
36+
if (!stats?.isFile()) throw new Error(`Not a file: ${filename}`);
37+
const fileStream = fs.createReadStream(filename);
38+
let mimeType = mimeTypes[path.extname(filename).split(".")[1]];
39+
if (!mimeType) throw new Error(`Could not get mime type for '${filename}'`)
40+
response.writeHead(200, {'Content-Type':mimeType});
41+
fileStream.pipe(response);
42+
} catch(e) {
43+
console.log(`Could not read ${filename}`);
44+
response.writeHead(404, {'Content-Type': 'text/plain'});
45+
response.write('404 Not Found\n');
46+
response.end();
47+
return;
48+
}
49+
};
50+
51+
const server = http.createServer(handler);
52+
53+
server.on("listening", () => {
54+
console.log(`Now listening on: http://localhost:${server.address().port}/`);
55+
});
56+
server.listen(5000);

0 commit comments

Comments
 (0)