@empiricalrun/playwright-utils 0.50.1 → 0.51.0
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.
- package/CHANGELOG.md +6 -0
- package/dist/reporter/harness.d.ts.map +1 -1
- package/dist/reporter/harness.js +0 -3
- package/dist/reporter/incremental-blob-reporter.d.ts +4 -3
- package/dist/reporter/incremental-blob-reporter.d.ts.map +1 -1
- package/dist/reporter/incremental-blob-reporter.js +65 -47
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CA2BD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;AAOtD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC1C,OAAO,CAAC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACzD,GAAG,EAAE,cAAc,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CA2BD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3E;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC;AAOtD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC1C,OAAO,CAAC,SAAS,CAAC,CAiDpB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,SAAS,EAAE,CAAC,CAUtB"}
|
package/dist/reporter/harness.js
CHANGED
|
@@ -75,9 +75,6 @@ async function runPlaywrightWithSigint(ctx, opts) {
|
|
|
75
75
|
TOTAL_SHARDS: "1",
|
|
76
76
|
},
|
|
77
77
|
stdio: ["pipe", "pipe", "pipe"],
|
|
78
|
-
// Must match production: detached creates a new process group so the
|
|
79
|
-
// reporter's SIGKILL on -process.pid only kills browsers + Playwright,
|
|
80
|
-
// not the test runner.
|
|
81
78
|
detached: true,
|
|
82
79
|
});
|
|
83
80
|
let stdout = "";
|
|
@@ -19,18 +19,19 @@ declare class IncrementalBlobReporter implements Reporter {
|
|
|
19
19
|
private _resultIdMap;
|
|
20
20
|
private _stepIdMap;
|
|
21
21
|
private _uploader;
|
|
22
|
-
private _flushPromise;
|
|
23
22
|
private _completedTestIds;
|
|
24
23
|
private _completedResultIds;
|
|
25
24
|
private _testRetries;
|
|
26
25
|
private _testResults;
|
|
27
26
|
private _startTime;
|
|
27
|
+
private _finalizePromise;
|
|
28
28
|
constructor();
|
|
29
29
|
private _sigintHandler;
|
|
30
30
|
private _setupSignalHandler;
|
|
31
31
|
private _removeSignalHandler;
|
|
32
|
-
private
|
|
33
|
-
private
|
|
32
|
+
private _buildSyntheticResult;
|
|
33
|
+
private _finalizeAndMaybeUpload;
|
|
34
|
+
private _finalizeReport;
|
|
34
35
|
private _computeCompletedSets;
|
|
35
36
|
private _removeIncompleteTestArtifacts;
|
|
36
37
|
private _patchProjectSuites;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"incremental-blob-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/incremental-blob-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAuBnC;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,cAAM,uBAAwB,YAAW,QAAQ;IAC/C,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,WAAW,CAIjB;IACF,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"incremental-blob-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/incremental-blob-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACT,MAAM,2BAA2B,CAAC;AAuBnC;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,cAAM,uBAAwB,YAAW,QAAQ;IAC/C,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,WAAW,CAIjB;IACF,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,UAAU,CAAoC;IACtD,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,mBAAmB,CAA0B;IACrD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,YAAY,CAGN;IACd,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,gBAAgB,CAA8B;;IAetD,OAAO,CAAC,cAAc,CAA6B;IAEnD,OAAO,CAAC,mBAAmB;IA+B3B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,qBAAqB;YASf,uBAAuB;IAqErC,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,8BAA8B;IAStC,OAAO,CAAC,mBAAmB;IAkB3B,OAAO,KAAK,QAAQ,GAKnB;IAED,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;YAUP,SAAS;IAwBvB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAgB/C,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAIrD,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAyBnD,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAYrE,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAY7D,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9C;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI5D,aAAa,IAAI,OAAO;CAGzB;AAID,wBAAgB,0BAA0B,IAAI,uBAAuB,GAAG,IAAI,CAE3E;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,uBAAuB,GAChC,IAAI,CAEN;AAED,eAAe,uBAAuB,CAAC"}
|
|
@@ -25,12 +25,12 @@ class IncrementalBlobReporter {
|
|
|
25
25
|
_resultIdMap = new Map(); // testId+retry -> resultId
|
|
26
26
|
_stepIdMap = new Map(); // step -> stepId
|
|
27
27
|
_uploader = null;
|
|
28
|
-
_flushPromise = null;
|
|
29
28
|
_completedTestIds = new Set();
|
|
30
29
|
_completedResultIds = new Set();
|
|
31
30
|
_testRetries = new Map(); // testId → configured retries
|
|
32
31
|
_testResults = new Map(); // testId → retryIndex → {resultId, status, expectedStatus}
|
|
33
32
|
_startTime = Date.now();
|
|
33
|
+
_finalizePromise = null;
|
|
34
34
|
constructor() {
|
|
35
35
|
if (process.env.SHARD_INDEX && process.env.TOTAL_SHARDS) {
|
|
36
36
|
this._shardIndex = Number.parseInt(process.env.SHARD_INDEX, 10);
|
|
@@ -47,28 +47,25 @@ class IncrementalBlobReporter {
|
|
|
47
47
|
_sigintHandler = null;
|
|
48
48
|
_setupSignalHandler() {
|
|
49
49
|
this._sigintHandler = () => {
|
|
50
|
-
if ((0, reporter_state_1.isFinalized)())
|
|
50
|
+
if (this._finalizePromise || (0, reporter_state_1.isFinalized)()) {
|
|
51
51
|
return;
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
}
|
|
53
|
+
console.log("[IncrementalBlobReporter] SIGINT received, finalizing...");
|
|
54
|
+
this._finalizePromise = this._finalizeAndMaybeUpload({
|
|
55
|
+
result: this._buildSyntheticResult("interrupted"),
|
|
56
|
+
source: "SIGINT",
|
|
57
|
+
markGlobalFinalized: true,
|
|
58
|
+
pruneIncompleteTests: true,
|
|
59
|
+
upload: true,
|
|
60
|
+
})
|
|
54
61
|
.then(() => {
|
|
55
|
-
console.log("[IncrementalBlobReporter]
|
|
62
|
+
console.log("[IncrementalBlobReporter] Finalize and upload complete on SIGINT");
|
|
56
63
|
})
|
|
57
64
|
.catch((err) => {
|
|
58
|
-
console.error("[IncrementalBlobReporterFailure]
|
|
65
|
+
console.error("[IncrementalBlobReporterFailure] Finalize/upload failed on SIGINT:", err);
|
|
59
66
|
})
|
|
60
67
|
.finally(() => {
|
|
61
68
|
this._removeSignalHandler();
|
|
62
|
-
// Kill the entire process group (browsers + self) to avoid
|
|
63
|
-
// orphaned browser processes writing to test-results/ after exit.
|
|
64
|
-
// Using process.exit(0) alone only exits the Node process, leaving
|
|
65
|
-
// browser processes alive which blocks cleanup on worker warm reuse.
|
|
66
|
-
try {
|
|
67
|
-
process.kill(-process.pid, "SIGKILL");
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
process.exit(0);
|
|
71
|
-
}
|
|
72
69
|
});
|
|
73
70
|
};
|
|
74
71
|
process.on("SIGINT", this._sigintHandler);
|
|
@@ -79,8 +76,23 @@ class IncrementalBlobReporter {
|
|
|
79
76
|
this._sigintHandler = null;
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
_buildSyntheticResult(status) {
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
return {
|
|
82
|
+
status,
|
|
83
|
+
startTime: new Date(this._startTime),
|
|
84
|
+
duration: now - this._startTime,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async _finalizeAndMaybeUpload({ result, source, markGlobalFinalized, pruneIncompleteTests, upload, }) {
|
|
88
|
+
const finalizeStart = Date.now();
|
|
89
|
+
const logFinalizeComplete = () => {
|
|
90
|
+
const durationMs = Date.now() - finalizeStart;
|
|
91
|
+
console.log(`[IncrementalBlobReporter] Finalize from ${source} completed in ${durationMs}ms (${(durationMs / 1_000).toFixed(1)}s)`);
|
|
92
|
+
};
|
|
93
|
+
if (markGlobalFinalized) {
|
|
94
|
+
(0, reporter_state_1.setFinalized)();
|
|
95
|
+
}
|
|
84
96
|
if (!(0, ibr_utils_1.hasValidReport)(this._reportLines)) {
|
|
85
97
|
console.warn("[IncrementalBlobReporterFailure] No onBegin received, skipping upload (nothing to merge)");
|
|
86
98
|
return;
|
|
@@ -89,39 +101,37 @@ class IncrementalBlobReporter {
|
|
|
89
101
|
if (this._uploader) {
|
|
90
102
|
await this._uploader.waitForUploads();
|
|
91
103
|
}
|
|
92
|
-
this.
|
|
104
|
+
this._finalizeReport(result, pruneIncompleteTests);
|
|
93
105
|
await this._writeZip();
|
|
106
|
+
if (!upload) {
|
|
107
|
+
logFinalizeComplete();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
94
110
|
if (!this._uploader) {
|
|
95
111
|
console.warn("[IncrementalBlobReporterFailure] No uploader available, skipping upload");
|
|
112
|
+
logFinalizeComplete();
|
|
96
113
|
return;
|
|
97
114
|
}
|
|
98
115
|
await this._uploader.uploadFile(this._zipPath, `blobs/incremental-report-${this._shardIndex}.zip`);
|
|
99
116
|
await this._uploader.waitForUploads();
|
|
100
|
-
console.log(
|
|
117
|
+
console.log(`[IncrementalBlobReporter] Finalize and upload complete from ${source}`);
|
|
101
118
|
if ((0, ibr_utils_1.isLocalTesting)()) {
|
|
102
119
|
await (0, local_test_1.mergeForLocalTest)(this._currentWorkingDir, this._outputDir);
|
|
103
120
|
}
|
|
121
|
+
logFinalizeComplete();
|
|
104
122
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
result: {
|
|
118
|
-
status: "interrupted",
|
|
119
|
-
startTime: this._startTime,
|
|
120
|
-
duration: now - this._startTime,
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
this._reportLines.push(JSON.stringify(onEndEvent));
|
|
123
|
+
_finalizeReport(result, pruneIncompleteTests) {
|
|
124
|
+
if (pruneIncompleteTests) {
|
|
125
|
+
// Determine which tests are fully complete (passed or all retries finished)
|
|
126
|
+
this._computeCompletedSets();
|
|
127
|
+
// Remove unrun tests from onProject suites
|
|
128
|
+
this._patchProjectSuites();
|
|
129
|
+
// Remove events (onTestBegin, onStepBegin, etc.) for incomplete tests
|
|
130
|
+
this._removeIncompleteTestArtifacts();
|
|
131
|
+
}
|
|
132
|
+
// Push onEnd directly. SIGINT marks the reporter finalized before this,
|
|
133
|
+
// so using _appendEvent would drop the synthetic onEnd event.
|
|
134
|
+
this._reportLines.push(JSON.stringify((0, lifecycle_events_1.buildOnEndEvent)(result)));
|
|
125
135
|
}
|
|
126
136
|
_computeCompletedSets() {
|
|
127
137
|
for (const [testId, results] of this._testResults) {
|
|
@@ -233,14 +243,22 @@ class IncrementalBlobReporter {
|
|
|
233
243
|
}
|
|
234
244
|
async onEnd(result) {
|
|
235
245
|
this._removeSignalHandler();
|
|
236
|
-
|
|
237
|
-
//
|
|
238
|
-
if (this.
|
|
239
|
-
await this.
|
|
246
|
+
// If SIGINT already started the partial-report finalization, let that
|
|
247
|
+
// finish instead of appending a second onEnd or racing another zip write.
|
|
248
|
+
if (this._finalizePromise) {
|
|
249
|
+
await this._finalizePromise;
|
|
250
|
+
return;
|
|
240
251
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
252
|
+
this._finalizePromise = this._finalizeAndMaybeUpload({
|
|
253
|
+
result,
|
|
254
|
+
source: "onEnd",
|
|
255
|
+
markGlobalFinalized: false,
|
|
256
|
+
pruneIncompleteTests: false,
|
|
257
|
+
// Normal completion already has Playwright's blob/html reporters.
|
|
258
|
+
// Only the SIGINT path uploads this incremental fallback blob.
|
|
259
|
+
upload: false,
|
|
260
|
+
});
|
|
261
|
+
await this._finalizePromise;
|
|
244
262
|
console.log(`[IncrementalBlobReporter] Finished with status: ${result.status}`);
|
|
245
263
|
}
|
|
246
264
|
/**
|