Skip to content

Commit c40b8ac

Browse files
committed
Create utilities to reduce duplicate testing logic
1 parent 67a0c2f commit c40b8ac

File tree

9 files changed

+74
-88
lines changed

9 files changed

+74
-88
lines changed

tests/cascading.spec.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate, innerHTML } from './utilities';
77

88
const css = `
99
a {
@@ -23,35 +23,29 @@ a {
2323

2424
test('Cascading', async ({ page }) => {
2525
const conditions = async () => {
26-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, css);
26+
await evaluate(page, css);
2727

2828
// The body should have exactly two direct children.
2929
const bodyDirectChildren = page.locator('body > *');
3030
await expect(bodyDirectChildren).toHaveCount(2);
3131

3232
// There should be exactly one anchor element,
33-
// and its href attribute should be populated.
33+
// its href attribute should be populated,
34+
// and it should not have any text content.
3435
const anchor = page.locator('a');
3536
await expect(anchor).toHaveCount(1);
3637
await expect(anchor).toHaveAttribute('href', 'https://example.com/page');
37-
38-
// The anchor should not have any text content.
39-
const anchorElement = await anchor.elementHandle();
40-
const anchorContent = await anchorElement?.innerHTML();
41-
expect(anchorContent).toBe('');
38+
await expect(innerHTML(anchor)).resolves.toBe('');
4239

4340
// The element with class `.more` should follow the anchor.
4441
const more = page.locator('a + .more');
4542
await expect(more).toHaveCount(1);
4643

47-
// There should be exactly one span element.
44+
// There should be exactly one span element,
45+
// and it should have specific text content.
4846
const span = page.locator('span');
4947
await expect(span).toHaveCount(1);
50-
51-
// The span should have specific text content.
52-
const spanElement = await span.elementHandle();
53-
const spanContent = await spanElement?.innerHTML();
54-
expect(spanContent).toBe('B');
48+
await expect(innerHTML(span)).resolves.toBe('B');
5549
};
5650

5751
// Bundle.

tests/comma.spec.ts

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate, innerHTML } from './utilities';
77

88
const css = `
99
h1,
@@ -15,38 +15,29 @@ p.content {
1515

1616
test('Comma', async ({ page }) => {
1717
const conditions = async () => {
18-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, css);
18+
await evaluate(page, css);
1919

2020
// The body should have exactly three direct children.
2121
const bodyDirectChildren = page.locator('body > *');
2222
await expect(bodyDirectChildren).toHaveCount(3);
2323

24-
// There should be exactly one heading element.
24+
// There should be exactly one heading element,
25+
// and it should have specific text content.
2526
const heading = page.locator('h1');
2627
await expect(heading).toHaveCount(1);
28+
await expect(innerHTML(heading)).resolves.toBe('A');
2729

28-
// The heading should have specific text content.
29-
const headingElement = await heading.elementHandle();
30-
const headingContent = await headingElement?.innerHTML();
31-
expect(headingContent).toBe('A');
32-
33-
// There should be exactly one element with class `.subtitle`.
30+
// There should be exactly one element with class `.subtitle`,
31+
// and it should have specific text content.
3432
const subtitle = page.locator('.subtitle');
3533
await expect(subtitle).toHaveCount(1);
34+
await expect(innerHTML(subtitle)).resolves.toBe('A');
3635

37-
// The element with class `.subtitle` should have specific text content.
38-
const subtitleElement = await subtitle.elementHandle();
39-
const subtitleContent = await subtitleElement?.innerHTML();
40-
expect(subtitleContent).toBe('A');
41-
42-
// There should be exactly one element with class `.content`.
36+
// There should be exactly one element with class `.content`,
37+
// and it should have specific text content.
4338
const content = page.locator('.content');
4439
await expect(content).toHaveCount(1);
45-
46-
// The element with class `.content` should have specific text content.
47-
const contentElement = await content.elementHandle();
48-
const contentContent = await contentElement?.innerHTML();
49-
expect(contentContent).toBe('A');
40+
await expect(innerHTML(content)).resolves.toBe('A');
5041
};
5142

5243
// Bundle.

tests/ignored.spec.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate, innerHTML } from './utilities';
77

88
const css = `
99
:root {
@@ -31,16 +31,14 @@ div:hover {
3131

3232
test('Ignored', async ({ page }) => {
3333
const conditions = async () => {
34-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, css);
34+
await evaluate(page, css);
3535

3636
// The body should have exactly one child.
3737
const bodyDirectChildren = page.locator('body *');
3838
await expect(bodyDirectChildren).toHaveCount(1);
3939

4040
// That element should have specific text content.
41-
const element = await bodyDirectChildren.elementHandle();
42-
const content = await element?.innerHTML();
43-
expect(content).toBe('C');
41+
await expect(innerHTML(bodyDirectChildren)).resolves.toBe('C');
4442
};
4543

4644
// Bundle.

tests/import.spec.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate, innerHTML } from './utilities';
77

88
const css = `
99
@import url('http://localhost:5173/import1.css');
@@ -14,7 +14,7 @@ div.last {
1414

1515
test('Import', async ({ page }) => {
1616
const conditions = async () => {
17-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css, { imports: 'include' }); return document.body.outerHTML; }, css);
17+
await evaluate(page, css, { imports: 'include' });
1818

1919
// The body should have exactly four direct children.
2020
const bodyDirectChildren = page.locator('body > *');
@@ -24,14 +24,12 @@ test('Import', async ({ page }) => {
2424
const last = page.locator('.first:first-child + .second + .third + .last:last-child');
2525
await expect(last).toHaveCount(1);
2626

27-
// There should be exactly one span element.
27+
// There should be exactly one span element,
28+
// and it should have specific text content.
2829
const span = page.locator('span');
2930
await expect(span).toHaveCount(1);
31+
await expect(innerHTML(span)).resolves.toBe('A');
3032

31-
// The span should have specific text content.
32-
const spanElement = await span.elementHandle();
33-
const spanContent = await spanElement?.innerHTML();
34-
expect(spanContent).toBe('A');
3533
};
3634

3735
// Bundle.

tests/nested.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate } from './utilities';
77

88
const css = `
99
nav > a#logo.icon img {
@@ -79,8 +79,8 @@ const html = `<body><nav><a href="" class="icon" id="logo"><img src="https://exa
7979

8080
test('Nested', async ({ page }) => {
8181
const conditions = async () => {
82-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, css);
83-
const nestedBody = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, nestedCss);
82+
const body = await evaluate(page, css);
83+
const nestedBody = await evaluate(page, nestedCss);
8484

8585
expect(body).toBe(html);
8686
expect(nestedBody).toBe(html);

tests/nth-child.spec.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate, innerHTML } from './utilities';
77

88
const css = `
99
span:nth-child(5) {
@@ -28,7 +28,7 @@ span.second-to-last:nth-last-child(2) {
2828

2929
test('Nth-Child', async ({ page }) => {
3030
const conditions = async () => {
31-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, css);
31+
await evaluate(page, css);
3232

3333
// The body should have exactly eight direct children.
3434
const bodyDirectChildren = page.locator('body > *');
@@ -40,29 +40,21 @@ test('Nth-Child', async ({ page }) => {
4040

4141
// The first element should have specific text content.
4242
const first = page.locator('div.first:first-child');
43-
const firstElement = await first.elementHandle();
44-
const firstContent = await firstElement?.innerHTML();
45-
expect(firstContent).toBe('B');
4643
await expect(first).toHaveCount(1);
44+
await expect(innerHTML(first)).resolves.toBe('B');
4745

4846
// The fifth element should have specific text content.
4947
const fifth = page.locator('span.last:nth-child(5)');
50-
const fifthElement = await fifth.elementHandle();
51-
const fifthContent = await fifthElement?.innerHTML();
52-
expect(fifthContent).toBe('C');
5348
await expect(fifth).toHaveCount(1);
49+
await expect(innerHTML(fifth)).resolves.toBe('C');
5450

5551
// The seventh element should have specific text content.
5652
const seventh = page.locator('span.second-to-last:nth-child(7)');
57-
const seventhElement = await seventh.elementHandle();
58-
const seventhContent = await seventhElement?.innerHTML();
59-
expect(seventhContent).toBe('F');
6053
await expect(seventh).toHaveCount(1);
54+
await expect(innerHTML(seventh)).resolves.toBe('F');
6155

6256
// The last element should have specific text content.
63-
const lastElement = await last.elementHandle();
64-
const lastContent = await lastElement?.innerHTML();
65-
expect(lastContent).toBe('E');
57+
await expect(innerHTML(last)).resolves.toBe('E');
6658
};
6759

6860
// Bundle.

tests/sanitize.spec.ts

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// TODO: Make these tests more comprehensive. They should cover a wider range of sanitization cases.
66

77
import { test, expect, type Page } from '@playwright/test';
8-
import { cssToHtml } from '../src/index';
8+
import { evaluate, innerHTML } from './utilities';
99

1010
const css = `
1111
@import url('http://localhost:5173/import4.css');
@@ -19,7 +19,7 @@ test('Sanitization Off', async ({ page }) => {
1919
page.on('console', message => consoleMessages.push(message.text()));
2020

2121
const conditions = async () => {
22-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css, { imports: 'include', sanitize: 'off' }); return document.body.outerHTML; }, css);
22+
await evaluate(page, css, { imports: 'include', sanitize: 'off' });
2323

2424
// The body should have exactly two direct children.
2525
const bodyDirectChildren = page.locator('body > *');
@@ -37,14 +37,11 @@ test('Sanitization Off', async ({ page }) => {
3737
await expect(img).toHaveAttribute('onerror', /.{10}/);
3838
await expect(img).toHaveClass('xss');
3939

40-
// There should be exactly one div element.
40+
// There should be exactly one div element,
41+
// and it should have specific text content.
4142
const div = page.locator('div');
4243
await expect(div).toHaveCount(1);
43-
44-
// The div should have specific text content.
45-
const divElement = await div.elementHandle();
46-
const divContent = await divElement?.innerHTML();
47-
expect(divContent).toBe('A');
44+
await expect(innerHTML(div)).resolves.toBe('A');
4845

4946
// The div should have an `onclick` attribute.
5047
await expect(div).toHaveAttribute('onclick', 'console.log(\'foo\')');
@@ -67,7 +64,7 @@ test('Sanitize Imports Only', async ({ page }) => {
6764
page.on('console', message => consoleMessages.push(message.text()));
6865

6966
const conditions = async () => {
70-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css, { imports: 'include', sanitize: 'imports' }); return document.body.outerHTML; }, css);
67+
await evaluate(page, css, { imports: 'include', sanitize: 'imports' });
7168

7269
// The body should have exactly two direct children.
7370
const bodyDirectChildren = page.locator('body > *');
@@ -85,14 +82,11 @@ test('Sanitize Imports Only', async ({ page }) => {
8582
await expect(img).not.toHaveAttribute('onerror');
8683
await expect(img).not.toHaveClass('xss');
8784

88-
// There should be exactly one div element.
85+
// There should be exactly one div element,
86+
// and it should have specific text content.
8987
const div = page.locator('div');
9088
await expect(div).toHaveCount(1);
91-
92-
// The div should have specific text content.
93-
const divElement = await div.elementHandle();
94-
const divContent = await divElement?.innerHTML();
95-
expect(divContent).toBe('A');
89+
await expect(innerHTML(div)).resolves.toBe('A');
9690

9791
// The div should have an `onclick` attribute.
9892
await expect(div).toHaveAttribute('onclick', 'console.log(\'foo\')');
@@ -127,14 +121,11 @@ async function expectEverythingToBeSanitized (page: Page): Promise<void> {
127121
await expect(img).not.toHaveAttribute('onerror');
128122
await expect(img).not.toHaveClass('xss');
129123

130-
// There should be exactly one div element.
124+
// There should be exactly one div element,
125+
// and it should have specific text content.
131126
const div = page.locator('div');
132127
await expect(div).toHaveCount(1);
133-
134-
// The div should have specific text content.
135-
const divElement = await div.elementHandle();
136-
const divContent = await divElement?.innerHTML();
137-
expect(divContent).toBe('A');
128+
await expect(innerHTML(div)).resolves.toBe('A');
138129

139130
// The div should not have an `onclick` attribute.
140131
await expect(div).not.toHaveAttribute('onclick');
@@ -145,7 +136,7 @@ test('Sanitize Everything', async ({ page }) => {
145136
page.on('console', message => consoleMessages.push(message.text()));
146137

147138
const conditions = async () => {
148-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css, { imports: 'include', sanitize: 'all' }); return document.body.outerHTML; }, css);
139+
await evaluate(page, css, { imports: 'include', sanitize: 'all' });
149140

150141
await expectEverythingToBeSanitized(page);
151142

@@ -167,7 +158,7 @@ test('Sanitize Everything By Default', async ({ page }) => {
167158
page.on('console', message => consoleMessages.push(message.text()));
168159

169160
const conditions = async () => {
170-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css, { imports: 'include' }); return document.body.outerHTML; }, css);
161+
await evaluate(page, css, { imports: 'include' });
171162

172163
await expectEverythingToBeSanitized(page);
173164

tests/selector.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44

55
import { test, expect } from '@playwright/test';
6-
import { cssToHtml } from '../src/index';
6+
import { evaluate } from './utilities';
77

88
const css = `
99
#cat + .mouse >span.flea+i {
@@ -26,7 +26,7 @@ const html = `<body><div id="cat"></div><div class="mouse"><span class="flea"></
2626

2727
test('Selector', async ({ page }) => {
2828
const conditions = async () => {
29-
const body = await page.evaluate(async css => { document.body = await cssToHtml(css); return document.body.outerHTML; }, css);
29+
const body = await evaluate(page, css);
3030

3131
expect(body).toBe(html);
3232
};

tests/utilities.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { Locator, Page } from "@playwright/test";
2+
import { cssToHtml } from '../src/index';
3+
4+
/**
5+
* Evaluate the `cssToHtml` function against a given CSS string.
6+
* @returns The generated `body` element's outer HTML.
7+
*/
8+
export async function evaluate(page: Page, css: string, options?: Parameters<typeof cssToHtml>[1]): Promise<string> {
9+
const args = [css, options] as const;
10+
const body = await page.evaluate(async ([css, options]) => {
11+
document.body = await cssToHtml(css, options);
12+
return document.body.outerHTML;
13+
}, args);
14+
return body;
15+
}
16+
17+
/** Retrieve the inner HTML content of a given locator. */
18+
export async function innerHTML(locator: Locator): Promise<string | undefined> {
19+
const handle = await locator.elementHandle();
20+
const content = await handle?.innerHTML();
21+
return content;
22+
}

0 commit comments

Comments
 (0)