Skip to content

Commit aee66c4

Browse files
msebastianbEomm
andauthored
test: add e2e tests with playwright (#99)
* feat: add e2e tests with playwright * test: enhance and define port in one place * test: adapt playwright workflow * Update .github/workflows/playwright.yml Co-authored-by: Manuel Spigolon <[email protected]> * Update .github/workflows/playwright.yml Co-authored-by: Manuel Spigolon <[email protected]> * test: run playwright tests in ci workflow * test: add playwright job permissions --------- Co-authored-by: Manuel Spigolon <[email protected]>
1 parent 1bb92b1 commit aee66c4

File tree

8 files changed

+162
-0
lines changed

8 files changed

+162
-0
lines changed

.github/workflows/ci.yml

+4
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ on:
1616
- '*.md'
1717

1818
jobs:
19+
e2e:
20+
uses: ./.github/workflows/playwright.yml
21+
1922
test:
2023
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v3
24+
needs: e2e
2125
with:
2226
license-check: true
2327
lint: true

.github/workflows/playwright.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Playwright Tests
2+
3+
on:
4+
workflow_dispatch:
5+
workflow_call:
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
12+
13+
timeout-minutes: 60
14+
15+
steps:
16+
- uses: actions/checkout@v3
17+
- uses: actions/setup-node@v3
18+
with:
19+
node-version: lts/*
20+
- name: Install dependencies
21+
run: npm i
22+
- name: Install Playwright Browsers
23+
run: npx playwright@1 install chromium --with-deps
24+
- name: Run Playwright tests
25+
run: npx playwright@1 test

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,6 @@ yarn.lock
150150
# editor files
151151
.vscode
152152
.idea
153+
/test-results/
154+
/playwright-report/
155+
/playwright/.cache/

e2e/custom.test.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict'
2+
3+
const { test, expect } = require('@playwright/test')
4+
5+
const URL_DOCUMENTATION = '/documentation'
6+
const URL_FAVICON = '/documentation/static/theme/favicon.svg'
7+
8+
test.describe('Check customizations', () => {
9+
test('Check JS injection', async ({ page }) => {
10+
await page.goto(URL_DOCUMENTATION)
11+
await page.waitForLoadState('networkidle')
12+
13+
page.on('dialog', async dialog => {
14+
expect(dialog.type() === 'beforeunload').toBeTruthy()
15+
expect(dialog.message() === 'unloaded test-theme').toBeTruthy()
16+
await dialog.dismiss()
17+
})
18+
await page.close({ runBeforeUnload: true })
19+
})
20+
21+
test('Check CSS injection', async ({ page }) => {
22+
await page.goto(URL_DOCUMENTATION)
23+
await page.waitForLoadState('networkidle')
24+
25+
const element = await page.waitForSelector('button.download-url-button')
26+
const color = await element.evaluate(el => window.getComputedStyle(el).getPropertyValue('background-color'))
27+
expect(color).toBe('rgb(255, 0, 0)')
28+
})
29+
30+
test('Check custom favicon', async ({ page }) => {
31+
await page.goto(URL_FAVICON)
32+
33+
const faviconId = await (await page.waitForSelector('svg')).getAttribute('id')
34+
expect(faviconId).toBe('example-logo') // it is included in the svg file
35+
})
36+
37+
test('Check custom logo', async ({ page }) => {
38+
await page.goto(URL_DOCUMENTATION)
39+
await page.waitForLoadState('networkidle')
40+
41+
const logoSrc = await page.locator('img').first().getAttribute('src')
42+
await page.goto(logoSrc)
43+
44+
const logoId = await (await page.waitForSelector('svg')).getAttribute('id')
45+
expect(logoId).toBe('example-logo') // it is included in the svg file
46+
})
47+
})

examples/example-e2e.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict'
2+
3+
const fastify = require('fastify')({ logger: true })
4+
const readFileSync = require('node:fs').readFileSync
5+
const resolve = require('node:path').resolve
6+
7+
const exampleLogo = readFileSync(
8+
resolve(__dirname, '..', 'examples/static', 'example-logo.svg'),
9+
'utf8'
10+
)
11+
12+
fastify.register(require('@fastify/swagger'), {
13+
mode: 'static',
14+
specification: {
15+
path: './examples/example-static-specification.json'
16+
}
17+
})
18+
19+
fastify.register(require('../index'), {
20+
theme: {
21+
js: [
22+
{ filename: 'unloaded.js', content: 'window.onbeforeunload = function(){alert("unloaded test-theme")}' }
23+
],
24+
css: [
25+
{ filename: 'theme.css', content: '.download-url-button {background: red !important;}' }
26+
],
27+
favicon: [
28+
{
29+
filename: 'favicon.svg',
30+
rel: 'icon',
31+
sizes: '16x16',
32+
type: 'image/svg+xml',
33+
content: exampleLogo
34+
}
35+
]
36+
},
37+
logo: {
38+
type: 'image/svg+xml',
39+
content: exampleLogo
40+
}
41+
})
42+
43+
fastify.listen({ port: process.env.PORT }, (err) => {
44+
if (err) throw err
45+
fastify.log.info(`visit the documentation at http://127.0.0.1:${process.env.PORT}/documentation/`)
46+
})

examples/static/example-logo.svg

+1
Loading

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
"prepublishOnly": "npm run prepare",
1414
"test": "npm run prepare && npm run coverage && npm run typescript",
1515
"test:dev": "npm run lint && npm run unit && npm run typescript",
16+
"test:e2e:command": "node ./examples/example-e2e.js",
17+
"test:e2e": "npx playwright test",
18+
"test:e2e:ui": "npx playwright test --ui",
1619
"typescript": "tsd",
1720
"unit": "tap",
1821
"unit:report": "npm run unit -- --coverage-report=html",
@@ -48,6 +51,7 @@
4851
"@fastify/helmet": "^11.0.0",
4952
"@fastify/pre-commit": "^2.0.2",
5053
"@fastify/swagger": "^8.0.0",
54+
"@playwright/test": "^1.39.0",
5155
"@types/node": "^20.1.1",
5256
"ajv": "^8.11.0",
5357
"fastify": "^4.0.0",

playwright.config.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict'
2+
3+
const { defineConfig, devices } = require('@playwright/test')
4+
5+
const PORT = 3000
6+
7+
/**
8+
* @see https://playwright.dev/docs/test-configuration
9+
*/
10+
module.exports = defineConfig({
11+
testDir: './e2e',
12+
fullyParallel: true,
13+
forbidOnly: !!process.env.CI,
14+
retries: process.env.CI ? 2 : 0,
15+
workers: process.env.CI ? 1 : undefined,
16+
reporter: 'html',
17+
use: {
18+
baseURL: `http://127.0.0.1:${PORT}/documentation`,
19+
trace: 'on-first-retry'
20+
},
21+
projects: [
22+
{
23+
name: 'chromium',
24+
use: { ...devices['Desktop Chrome'] }
25+
}
26+
],
27+
webServer: {
28+
command: `PORT=${PORT} npm run test:e2e:command`,
29+
url: `http://127.0.0.1:${PORT}/documentation`,
30+
reuseExistingServer: !process.env.CI
31+
}
32+
})

0 commit comments

Comments
 (0)