@dionlarson/playwright-orchestrator-core 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs';
|
|
1
2
|
export default class TestResultReporter {
|
|
2
3
|
testResults = [];
|
|
3
4
|
testCases = [];
|
|
@@ -58,6 +59,13 @@ export default class TestResultReporter {
|
|
|
58
59
|
retry,
|
|
59
60
|
})),
|
|
60
61
|
};
|
|
61
|
-
|
|
62
|
+
const outputFile = process.env.PLAYWRIGHT_ORCHESTRATOR_RESULT_FILE;
|
|
63
|
+
if (outputFile) {
|
|
64
|
+
writeFileSync(outputFile, JSON.stringify(output));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Fallback to stdout if no file specified
|
|
68
|
+
console.log(JSON.stringify(output));
|
|
69
|
+
}
|
|
62
70
|
}
|
|
63
71
|
}
|
package/dist/test-runner.d.ts
CHANGED
package/dist/test-runner.js
CHANGED
|
@@ -1,37 +1,19 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import child_process, { spawn } from 'node:child_process';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
|
-
import { rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
5
5
|
import { TestExecutionReporter } from './reporters/test-execution-reporter.js';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import * as uuid from 'uuid';
|
|
8
8
|
const exec = promisify(child_process.exec);
|
|
9
|
-
function
|
|
9
|
+
function spawnPassthrough(command, env) {
|
|
10
10
|
return new Promise((resolve, reject) => {
|
|
11
|
-
const proc = spawn(command,
|
|
11
|
+
const proc = spawn(command, {
|
|
12
12
|
env,
|
|
13
13
|
shell: true,
|
|
14
|
-
stdio:
|
|
15
|
-
});
|
|
16
|
-
let stdout = '';
|
|
17
|
-
proc.stdout?.on('data', (data) => {
|
|
18
|
-
const str = data.toString();
|
|
19
|
-
stdout += str;
|
|
20
|
-
// Stream output but filter out the JSON reporter output
|
|
21
|
-
if (!str.trim().startsWith('{')) {
|
|
22
|
-
process.stdout.write(data);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
proc.on('close', (code) => {
|
|
26
|
-
if (code === 0) {
|
|
27
|
-
resolve(stdout);
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
const error = new Error(`Process exited with code ${code}`);
|
|
31
|
-
error.stdout = stdout;
|
|
32
|
-
reject(error);
|
|
33
|
-
}
|
|
14
|
+
stdio: 'inherit' // Full passthrough - all output goes directly to terminal
|
|
34
15
|
});
|
|
16
|
+
proc.on('close', (code) => resolve(code ?? 1));
|
|
35
17
|
proc.on('error', reject);
|
|
36
18
|
});
|
|
37
19
|
}
|
|
@@ -88,45 +70,56 @@ export class TestRunner {
|
|
|
88
70
|
}
|
|
89
71
|
async removePreviousReports() {
|
|
90
72
|
await rm(`./${this.outputFolder}`, { recursive: true, force: true });
|
|
73
|
+
await mkdir(`./${this.outputFolder}`, { recursive: true });
|
|
91
74
|
}
|
|
92
75
|
async runTest(test, config) {
|
|
93
76
|
const testPosition = `${test.file}:${test.position}`;
|
|
94
77
|
const testName = `[${test.project}] > ${testPosition}`;
|
|
95
78
|
const testHash = createHash('md5').update(testName).digest('hex');
|
|
79
|
+
const resultFile = `${this.outputFolder}/${testHash}.result.json`;
|
|
96
80
|
const args = [testPosition, ...this.buildParams(test, config, testHash).split(' ')];
|
|
97
81
|
const env = {
|
|
98
82
|
...process.env,
|
|
99
83
|
PLAYWRIGHT_BLOB_OUTPUT_FILE: `${this.outputFolder}/${testHash}.zip`,
|
|
84
|
+
PLAYWRIGHT_ORCHESTRATOR_RESULT_FILE: resultFile,
|
|
100
85
|
};
|
|
86
|
+
const fullCommand = `npx playwright test ${args.join(' ')}`;
|
|
87
|
+
const exitCode = await spawnPassthrough(fullCommand, env);
|
|
88
|
+
let testResult;
|
|
101
89
|
try {
|
|
102
|
-
const
|
|
90
|
+
const resultJson = await readFile(resultFile, 'utf-8');
|
|
91
|
+
testResult = JSON.parse(resultJson);
|
|
92
|
+
await rm(resultFile, { force: true });
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
console.error(`[orchestrator] Failed to read test result for [${test.project}] ${test.file}:${test.position}`, e);
|
|
96
|
+
throw e;
|
|
97
|
+
}
|
|
98
|
+
if (exitCode === 0) {
|
|
99
|
+
console.log(`[orchestrator] Test passed: [${test.project}] ${test.file}:${test.position}`);
|
|
103
100
|
this.reporter.finishTest(test);
|
|
104
101
|
await this.adapter.finishTest({
|
|
105
102
|
runId: this.runId,
|
|
106
103
|
test,
|
|
107
|
-
testResult
|
|
104
|
+
testResult,
|
|
108
105
|
config,
|
|
109
106
|
});
|
|
110
107
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
throw error;
|
|
108
|
+
else {
|
|
109
|
+
console.log(`[orchestrator] Test failed: [${test.project}] ${test.file}:${test.position}`);
|
|
114
110
|
this.reporter.failTest(test);
|
|
115
111
|
await this.adapter.failTest({
|
|
116
112
|
runId: this.runId,
|
|
117
113
|
test,
|
|
118
|
-
testResult
|
|
114
|
+
testResult,
|
|
119
115
|
config,
|
|
120
116
|
});
|
|
121
117
|
}
|
|
122
118
|
}
|
|
123
|
-
parseTestResult(stdout) {
|
|
124
|
-
return JSON.parse(stdout);
|
|
125
|
-
}
|
|
126
119
|
buildParams(test, config, testHash) {
|
|
127
120
|
const args = [...config.args];
|
|
128
121
|
args.push('--workers', '1');
|
|
129
|
-
args.push('--reporter', 'blob,@dionlarson/playwright-orchestrator-core/test-result-reporter');
|
|
122
|
+
args.push('--reporter', 'list,blob,@dionlarson/playwright-orchestrator-core/test-result-reporter');
|
|
130
123
|
args.push('--project', `"${test.project}"`);
|
|
131
124
|
args.push('--output', `"${this.outputFolder}/${testHash}"`);
|
|
132
125
|
if (config.configFile) {
|