Skip to content

Commit af596f6

Browse files
committed
test: migrate E2E tests to puppeteer instead of protractor
1 parent 7d3e0ad commit af596f6

File tree

5 files changed

+87
-1
lines changed

5 files changed

+87
-1
lines changed

tests/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ e2e_suites(
7373
# TODO: Clean this up.
7474
"//:node_modules/express",
7575
"//:node_modules/undici",
76+
"//:node_modules/puppeteer",
7677
],
7778
runner = ":runner_entrypoint",
7879
)

tests/e2e/tests/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ ts_project(
1212
"//:node_modules/@types/semver",
1313
"//:node_modules/express",
1414
"//:node_modules/fast-glob",
15+
"//:node_modules/puppeteer",
1516
"//:node_modules/semver",
1617
"//:node_modules/undici",
1718
"//tests/e2e/utils",

tests/e2e/tests/build/jit-prod.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { getGlobalVariable } from '../../utils/env';
22
import { ng } from '../../utils/process';
33
import { updateJsonFile } from '../../utils/project';
4+
import { runE2eTest } from '../../utils/puppeteer';
45

56
export default async function () {
67
// Make prod use JIT.
@@ -18,5 +19,5 @@ export default async function () {
1819
});
1920

2021
// Test it works
21-
await ng('e2e', '--configuration=production');
22+
await runE2eTest({ configuration: 'production' });
2223
}

tests/e2e/utils/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ts_project(
1515
"//:node_modules/@types/semver",
1616
"//:node_modules/fast-glob",
1717
"//:node_modules/protractor",
18+
"//:node_modules/puppeteer",
1819
"//:node_modules/semver",
1920
"//:node_modules/verdaccio",
2021
"//:node_modules/verdaccio-auth-memory",

tests/e2e/utils/puppeteer.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { type Page, launch } from 'puppeteer';
2+
import { execAndWaitForOutputToMatch, killAllProcesses } from './process';
3+
4+
export interface E2eTestOptions {
5+
project?: string;
6+
configuration?: string;
7+
baseUrl?: string;
8+
checkFn?: (page: Page) => Promise<void>;
9+
expectedTitleText?: string;
10+
}
11+
12+
export async function runE2eTest(options: E2eTestOptions = {}) {
13+
let url = options.baseUrl;
14+
let hasStartedServer = false;
15+
16+
try {
17+
if (!url) {
18+
// Start serving
19+
const match = /open your browser on (http:\/\/localhost:\d+\/)/;
20+
const serveArgs = ['serve', '--port=0'];
21+
if (options.project) {
22+
serveArgs.push(options.project);
23+
}
24+
if (options.configuration) {
25+
serveArgs.push(`--configuration=${options.configuration}`);
26+
}
27+
28+
const { stdout } = await execAndWaitForOutputToMatch('ng', serveArgs, match);
29+
url = stdout.match(match)?.[1];
30+
if (!url) {
31+
throw new Error('Could not find serving URL');
32+
}
33+
hasStartedServer = true;
34+
}
35+
36+
const browser = await launch({ executablePath: process.env['CHROME_BIN'], headless: true });
37+
try {
38+
const page = await browser.newPage();
39+
40+
// Capture errors
41+
const errors: string[] = [];
42+
page.on('console', (msg) => {
43+
if (msg.type() === 'error') {
44+
errors.push(msg.text());
45+
}
46+
});
47+
page.on('pageerror', (err) => {
48+
errors.push(err.toString());
49+
});
50+
51+
await page.goto(url);
52+
53+
if (options.checkFn) {
54+
await options.checkFn(page);
55+
} else {
56+
// Default check: verify h1 content and no browser errors
57+
const expectedText = options.expectedTitleText || 'Hello, test-project';
58+
59+
// Wait for the h1 element to appear and contain the expected text
60+
await page.waitForFunction(
61+
(selector: string, text: string) => {
62+
const doc = (globalThis as any).document;
63+
return doc.querySelector(selector)?.textContent?.includes(text);
64+
},
65+
{ timeout: 5000 }, // Max 5 seconds wait time
66+
'h1',
67+
expectedText,
68+
);
69+
}
70+
71+
if (errors.length > 0) {
72+
throw new Error(`Browser console errors detected:\n${errors.join('\n')}`);
73+
}
74+
} finally {
75+
await browser.close();
76+
}
77+
} finally {
78+
if (hasStartedServer) {
79+
await killAllProcesses();
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)