@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
- console.log(JSON.stringify(output));
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
  }
@@ -12,7 +12,6 @@ export declare class TestRunner {
12
12
  private runTestsUntilAvailable;
13
13
  private removePreviousReports;
14
14
  private runTest;
15
- private parseTestResult;
16
15
  private buildParams;
17
16
  private createTempConfig;
18
17
  }
@@ -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 spawnWithOutput(command, args, env) {
9
+ function spawnPassthrough(command, env) {
10
10
  return new Promise((resolve, reject) => {
11
- const proc = spawn(command, args, {
11
+ const proc = spawn(command, {
12
12
  env,
13
13
  shell: true,
14
- stdio: ['inherit', 'pipe', 'inherit'] // stdin inherit, stdout pipe, stderr inherit
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 stdout = await spawnWithOutput('npx', ['playwright', 'test', ...args], env);
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: this.parseTestResult(stdout),
104
+ testResult,
108
105
  config,
109
106
  });
110
107
  }
111
- catch (error) {
112
- if (!error.stdout)
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: this.parseTestResult(error.stdout),
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dionlarson/playwright-orchestrator-core",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Core lib and cli for Playwright test orchestration",
5
5
  "keywords": [
6
6
  "playwright",