Skip to content

Commit e394783

Browse files
committed
Extract slugify(), share TEST_CONTENT, simplify auto-coverage docs
- Extract slugify() as a named exported function in the playwright fixture with a comment explaining why it's needed (titlePath entries contain '/' which would otherwise create subdirectories) - Import slugify in tests instead of duplicating the regex logic - Extract repeated HTML string to TEST_CONTENT const in tests - Collapse beforeEach auto-coverage example to a single line in README
1 parent 5a61cb0 commit e394783

3 files changed

Lines changed: 22 additions & 31 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,12 @@ test('my test', async ({ page, cssCoverage }) => {
8383

8484
The fixture starts coverage when the test begins and stops it when the test ends. JSON files are written to the output directory and attached to the Playwright HTML report.
8585

86-
**Enable for an entire test file** by requesting the fixture in `test.beforeEach`:
86+
**Enable for an entire test file** with a single line:
8787

8888
```ts
8989
import { test, expect } from './fixtures.js'
9090

91-
test.beforeEach(async ({ cssCoverage }) => {
92-
// every test in this file will now collect CSS coverage
93-
})
91+
test.beforeEach(async ({ cssCoverage }) => {})
9492

9593
test('first test', async ({ page }) => { ... })
9694
test('second test', async ({ page }) => { ... })

‎src/playwright.test.ts‎

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
11
import { mergeTests, test as base, expect } from '@playwright/test'
2-
import { test as withCssCoverage } from './playwright/index.js'
2+
import { test as withCssCoverage, slugify } from './playwright/index.js'
33
import * as fs from 'node:fs/promises'
44
import * as os from 'node:os'
55
import * as path from 'node:path'
66

77
const test = mergeTests(base, withCssCoverage)
88

9+
const TEST_CONTENT = '<style>body { margin: 0 }</style><body></body>'
10+
911
function expected_filename(title_path: string[]): string {
10-
return (
11-
title_path
12-
.map((s) =>
13-
s
14-
.replaceAll(/\s+|\/|\./g, '-')
15-
.replaceAll(/[^a-zA-Z0-9-_]/g, '')
16-
.toLowerCase(),
17-
)
18-
.join('-') + '.json'
19-
)
12+
return title_path.map(slugify).join('-') + '.json'
2013
}
2114

2215
test.describe('cssCoverageDir option', () => {
@@ -30,7 +23,7 @@ test.describe('cssCoverageDir option', () => {
3023
})
3124

3225
test('writes coverage to the configured directory', async ({ page, cssCoverage }, testInfo) => {
33-
await page.setContent('<style>body { margin: 0 }</style><body></body>')
26+
await page.setContent(TEST_CONTENT)
3427
filename = expected_filename(testInfo.titlePath)
3528
})
3629

@@ -45,7 +38,7 @@ test.describe('default cssCoverageDir', () => {
4538
let filename = ''
4639

4740
test('defaults to css-coverage relative to cwd', async ({ page, cssCoverage }, testInfo) => {
48-
await page.setContent('<style>body { margin: 0 }</style><body></body>')
41+
await page.setContent(TEST_CONTENT)
4942
filename = expected_filename(testInfo.titlePath)
5043
})
5144

@@ -66,7 +59,7 @@ test.describe('file naming', () => {
6659
})
6760

6861
test('derives filename from the test title path', async ({ page, cssCoverage }, testInfo) => {
69-
await page.setContent('<style>body { margin: 0 }</style><body></body>')
62+
await page.setContent(TEST_CONTENT)
7063
filename = expected_filename(testInfo.titlePath)
7164
})
7265

@@ -79,22 +72,19 @@ test.describe('file naming', () => {
7972

8073
test.describe('file content', () => {
8174
let dir = path.join(os.tmpdir(), 'css-code-coverage-fixture-content-test')
82-
let filename = ''
8375

8476
test.use({ cssCoverageDir: dir })
8577

8678
test.beforeAll(async () => {
8779
await fs.rm(dir, { recursive: true, force: true })
8880
})
8981

90-
test('writes valid JSON', async ({ page, cssCoverage }, testInfo) => {
91-
await page.setContent('<style>body { margin: 0 }</style><body></body>')
92-
filename = expected_filename(testInfo.titlePath)
82+
test('writes valid JSON', async ({ page, cssCoverage }) => {
83+
await page.setContent(TEST_CONTENT)
9384
})
9485

95-
test('content is an array of coverage entries', async ({ page, cssCoverage }, testInfo) => {
86+
test('content is an array of coverage entries', async ({ page, cssCoverage }) => {
9687
await page.setContent('<style>h1 { color: red }</style><body><h1>hi</h1></body>')
97-
filename = expected_filename(testInfo.titlePath)
9888
})
9989

10090
test.afterAll(async () => {

‎src/playwright/index.ts‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ type CssCoverageOptions = {
1010
cssCoverageDir: string
1111
}
1212

13+
// Needed because titlePath entries can contain '/' (creates subdirs), spaces,
14+
// dots, and other chars that are invalid or problematic in file names.
15+
export function slugify(s: string): string {
16+
return s
17+
.replaceAll(/\s+|\/|\./g, '-')
18+
.replaceAll(/[^a-zA-Z0-9-_]/g, '')
19+
.toLowerCase()
20+
}
21+
1322
export const test = base_test.extend<CssCoverageFixtures, CssCoverageOptions>({
1423
cssCoverageDir: ['css-coverage', { option: true }],
1524

@@ -19,13 +28,7 @@ export const test = base_test.extend<CssCoverageFixtures, CssCoverageOptions>({
1928
await use()
2029
let coverage = await page.coverage.stopCSSCoverage()
2130

22-
let parts = testInfo.titlePath.map((s) =>
23-
s
24-
.replaceAll(/\s+|\/|\./g, '-')
25-
.replaceAll(/[^a-zA-Z0-9-_]/g, '')
26-
.toLowerCase(),
27-
)
28-
let file_name = parts.join('-') + '.json'
31+
let file_name = testInfo.titlePath.map(slugify).join('-') + '.json'
2932

3033
let dir = path.resolve(process.cwd(), cssCoverageDir)
3134
await fs.mkdir(dir, { recursive: true })

0 commit comments

Comments
 (0)