Skip to content

Commit 9724e18

Browse files
author
Brian Vaughn
authored
Run DevTools e2e tests on Circle CI (#23019)
1 parent 3dc41d8 commit 9724e18

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed

.circleci/config.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,28 @@ jobs:
200200
- store_artifacts:
201201
path: ./build/devtools.tgz
202202

203+
run_devtools_e2e_tests:
204+
docker: *docker
205+
environment: *environment
206+
steps:
207+
- checkout
208+
- attach_workspace:
209+
at: .
210+
- run: yarn workspaces info | head -n -1 > workspace_info.txt
211+
- *restore_node_modules
212+
- run:
213+
name: Install Packages
214+
command: yarn --frozen-lockfile --cache-folder ~/.cache/yarn
215+
- run:
216+
name: Playwright install deps
217+
command: |
218+
npx playwright install
219+
sudo npx playwright install-deps
220+
- run:
221+
environment:
222+
RELEASE_CHANNEL: experimental
223+
command: ./scripts/circleci/run_devtools_e2e_tests.js
224+
203225
yarn_lint_build:
204226
docker: *docker
205227
environment: *environment
@@ -452,6 +474,9 @@ workflows:
452474
- build_devtools_and_process_artifacts:
453475
requires:
454476
- yarn_build_combined
477+
- run_devtools_e2e_tests:
478+
requires:
479+
- build_devtools_and_process_artifacts
455480

456481
fuzz_tests:
457482
unless: << pipeline.parameters.prerelease_commit_sha >>
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#!/usr/bin/env node
2+
3+
'use strict';
4+
5+
const {spawn} = require('child_process');
6+
const {join} = require('path');
7+
8+
const ROOT_PATH = join(__dirname, '..', '..');
9+
10+
const inlinePackagePath = join(ROOT_PATH, 'packages', 'react-devtools-inline');
11+
const shellPackagePath = join(ROOT_PATH, 'packages', 'react-devtools-shell');
12+
13+
let buildProcess = null;
14+
let serverProcess = null;
15+
let testProcess = null;
16+
17+
function format(loggable) {
18+
return `${loggable}`
19+
.split('\n')
20+
.filter(line => {
21+
return line.trim() !== '';
22+
})
23+
.map(line => ` ${line}`)
24+
.join('\n');
25+
}
26+
27+
function logBright(loggable) {
28+
console.log(`\x1b[1m${loggable}\x1b[0m`);
29+
}
30+
31+
function logDim(loggable) {
32+
const formatted = format(loggable, 2);
33+
if (formatted !== '') {
34+
console.log(`\x1b[2m${formatted}\x1b[0m`);
35+
}
36+
}
37+
38+
function logError(loggable) {
39+
const formatted = format(loggable, 2);
40+
if (formatted !== '') {
41+
console.error(`\x1b[31m${formatted}\x1b[0m`);
42+
}
43+
}
44+
45+
function buildInlinePackage() {
46+
logBright('Building inline packages');
47+
48+
buildProcess = spawn('yarn', ['build'], {cwd: inlinePackagePath});
49+
buildProcess.stdout.on('data', data => {
50+
logDim(data);
51+
});
52+
buildProcess.stderr.on('data', data => {
53+
if (`${data}`.includes('Warning')) {
54+
logDim(data);
55+
} else {
56+
logError(`Error:\n${data}`);
57+
58+
exitWithCode(1);
59+
}
60+
});
61+
buildProcess.on('close', code => {
62+
logBright('Inline package built');
63+
64+
runTestShell();
65+
});
66+
}
67+
68+
function runTestShell() {
69+
const timeoutID = setTimeout(() => {
70+
// Assume the test shell server failed to start.
71+
logError('Testing shell server failed to start');
72+
exitWithCode(1);
73+
}, 30000);
74+
75+
logBright('Starting testing shell server');
76+
77+
serverProcess = spawn('yarn', ['start'], {cwd: shellPackagePath});
78+
serverProcess.stdout.on('data', data => {
79+
if (`${data}`.includes('Compiled successfully.')) {
80+
logBright('Testing shell server running');
81+
82+
clearTimeout(timeoutID);
83+
84+
runEndToEndTests();
85+
}
86+
});
87+
serverProcess.stderr.on('data', data => {
88+
if (`${data}`.includes('EADDRINUSE')) {
89+
// Something is occuprying this port;
90+
// We could kill the process and restart but probably better to prompt the user to do this.
91+
92+
logError('Free up the port and re-run tests:');
93+
logBright(' kill -9 $(lsof -ti:8080)');
94+
95+
exitWithCode(1);
96+
} else if (`${data}`.includes('ERROR')) {
97+
logError(`Error:\n${data}`);
98+
99+
exitWithCode(1);
100+
} else {
101+
// Non-fatal stuff like Babel optimization warnings etc.
102+
logDim(data);
103+
}
104+
});
105+
}
106+
107+
async function runEndToEndTests() {
108+
logBright('Running e2e tests');
109+
110+
testProcess = spawn('yarn', ['test:e2e'], {cwd: inlinePackagePath});
111+
testProcess.stdout.on('data', data => {
112+
// Log without formatting because Playwright applies its own formatting.
113+
const formatted = format(data);
114+
if (formatted !== '') {
115+
console.log(formatted);
116+
}
117+
});
118+
testProcess.stderr.on('data', data => {
119+
// Log without formatting because Playwright applies its own formatting.
120+
const formatted = format(data);
121+
if (formatted !== '') {
122+
console.error(formatted);
123+
}
124+
125+
exitWithCode(1);
126+
});
127+
testProcess.on('close', code => {
128+
logBright(`Tests completed with code: ${code}`);
129+
130+
exitWithCode(code);
131+
});
132+
}
133+
134+
function exitWithCode(code) {
135+
if (buildProcess !== null) {
136+
try {
137+
logBright('Shutting down build process');
138+
buildProcess.kill();
139+
} catch (error) {
140+
logError(error);
141+
}
142+
}
143+
144+
if (serverProcess !== null) {
145+
try {
146+
logBright('Shutting down shell server process');
147+
serverProcess.kill();
148+
} catch (error) {
149+
logError(error);
150+
}
151+
}
152+
153+
if (testProcess !== null) {
154+
try {
155+
logBright('Shutting down test process');
156+
testProcess.kill();
157+
} catch (error) {
158+
logError(error);
159+
}
160+
}
161+
162+
process.exit(code);
163+
}
164+
165+
buildInlinePackage();

0 commit comments

Comments
 (0)