@empiricalrun/playwright-utils 0.60.4 → 0.61.1
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 +25 -0
- package/dist/generated/api-worker-openapi.d.ts +2040 -454
- package/dist/generated/api-worker-openapi.d.ts.map +1 -1
- package/dist/reporter/empirical-reporter.d.ts.map +1 -1
- package/dist/reporter/empirical-reporter.js +9 -1
- package/dist/reporter/harness.d.ts +15 -0
- package/dist/reporter/harness.d.ts.map +1 -1
- package/dist/reporter/harness.js +68 -2
- package/dist/reporter/incremental-blob-reporter.d.ts.map +1 -1
- package/dist/reporter/incremental-blob-reporter.js +4 -9
- package/dist/reporter/reporter-state.d.ts +13 -0
- package/dist/reporter/reporter-state.d.ts.map +1 -1
- package/dist/reporter/reporter-state.js +16 -0
- package/package.json +10 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"empirical-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/empirical-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;AAuBnC,cAAM,iBAAkB,YAAW,QAAQ;IACzC,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,oBAAoB,CAG1B;IACF,OAAO,CAAC,sBAAsB,CAAuB;IACrD,OAAO,CAAC,YAAY,CAAgD;IACpE,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,gBAAgB,CAAkC;IAC1D,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,kBAAkB,CAA2B;IAGrD,OAAO,CAAC,YAAY,CAAqB;IAEzC,cAEC;IAED,OAAO,CAAC,MAAM,EAAE,UAAU,QAEzB;IAED,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,6BAA6B,CA2CnC;IAEF,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"empirical-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/empirical-reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;AAuBnC,cAAM,iBAAkB,YAAW,QAAQ;IACzC,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,oBAAoB,CAG1B;IACF,OAAO,CAAC,sBAAsB,CAAuB;IACrD,OAAO,CAAC,YAAY,CAAgD;IACpE,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,gBAAgB,CAAkC;IAC1D,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,kBAAkB,CAA2B;IAGrD,OAAO,CAAC,YAAY,CAAqB;IAEzC,cAEC;IAED,OAAO,CAAC,MAAM,EAAE,UAAU,QAEzB;IAED,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,6BAA6B,CA2CnC;IAEF,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,QAoJ3C;IAEK,KAAK,CAAC,MAAM,EAAE,UAAU,iBAoH7B;IAED,OAAO,CAAC,qBAAqB;YAkBf,gBAAgB;YAOhB,iBAAiB;CAqChC;eAEc,iBAAiB"}
|
|
@@ -62,7 +62,12 @@ class EmpiricalReporter {
|
|
|
62
62
|
}
|
|
63
63
|
};
|
|
64
64
|
onTestEnd(test, result) {
|
|
65
|
-
|
|
65
|
+
// After the SIGINT salvage, an attempt that really finished (its body
|
|
66
|
+
// completed, only its teardown overlapped the signal) is still reported:
|
|
67
|
+
// the blob keeps it, and a ledger that misses it calls the test unfinished,
|
|
68
|
+
// so the resume shard re-runs it and the merged report holds it twice.
|
|
69
|
+
// Shutdown artifacts stay out, as they do in the blob.
|
|
70
|
+
if ((0, reporter_state_1.isFinalized)() && (0, reporter_state_1.isShutdownArtifact)(result.status, true)) {
|
|
66
71
|
return;
|
|
67
72
|
}
|
|
68
73
|
if (!this._uploader) {
|
|
@@ -181,6 +186,9 @@ class EmpiricalReporter {
|
|
|
181
186
|
}
|
|
182
187
|
async onEnd(result) {
|
|
183
188
|
if ((0, reporter_state_1.isFinalized)()) {
|
|
189
|
+
// The salvage owns the report upload. Only flush the test-case events
|
|
190
|
+
// sent during shutdown, so they land before the process exits.
|
|
191
|
+
await Promise.allSettled(this._pendingTestCaseEvents);
|
|
184
192
|
return;
|
|
185
193
|
}
|
|
186
194
|
if (!this._uploader) {
|
|
@@ -62,6 +62,8 @@ export interface SignalRunOptions {
|
|
|
62
62
|
killAfterMs?: number;
|
|
63
63
|
/** How long to wait for the trigger before giving up and signalling anyway. */
|
|
64
64
|
triggerTimeoutMs?: number;
|
|
65
|
+
/** Extra env for the runner, e.g. from `startDashboardStub`. */
|
|
66
|
+
env?: NodeJS.ProcessEnv;
|
|
65
67
|
}
|
|
66
68
|
/**
|
|
67
69
|
* Spawns `playwright test` with the IBR reporter in its own process group,
|
|
@@ -132,4 +134,17 @@ export declare function runPlaywrightClean(ctx: ParityTestContext, opts: {
|
|
|
132
134
|
* parsed summary. Distinct output names let one temp dir hold both merges.
|
|
133
135
|
*/
|
|
134
136
|
export declare function mergeBlobDirToSummary(cwd: string, blobDir: string, outputName: string): Record<string, unknown>;
|
|
137
|
+
export interface DashboardStub {
|
|
138
|
+
/** `test_case_run_end` payloads EmpiricalReporter sent, in arrival order. */
|
|
139
|
+
testCaseEvents: () => Array<Record<string, any>>;
|
|
140
|
+
/** Runner env that points EmpiricalReporter's API calls and uploads here. */
|
|
141
|
+
env: NodeJS.ProcessEnv;
|
|
142
|
+
close: () => Promise<void>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* A local stand-in for api-worker and the report bucket, so EmpiricalReporter
|
|
146
|
+
* runs unmodified inside a real Playwright run. Records test-case events and
|
|
147
|
+
* accepts every upload.
|
|
148
|
+
*/
|
|
149
|
+
export declare function startDashboardStub(): Promise<DashboardStub>;
|
|
135
150
|
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"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"}
|
package/dist/reporter/harness.js
CHANGED
|
@@ -16,13 +16,16 @@ exports.readEventsFromZip = readEventsFromZip;
|
|
|
16
16
|
exports.setupParityFixture = setupParityFixture;
|
|
17
17
|
exports.runPlaywrightClean = runPlaywrightClean;
|
|
18
18
|
exports.mergeBlobDirToSummary = mergeBlobDirToSummary;
|
|
19
|
+
exports.startDashboardStub = startDashboardStub;
|
|
19
20
|
const zip_1 = require("@empiricalrun/r2-uploader/zip");
|
|
20
21
|
const child_process_1 = require("child_process");
|
|
21
22
|
const fs_1 = __importDefault(require("fs"));
|
|
23
|
+
const http_1 = __importDefault(require("http"));
|
|
22
24
|
const os_1 = __importDefault(require("os"));
|
|
23
25
|
const path_1 = __importDefault(require("path"));
|
|
24
26
|
const TEST_DATA_DIR = path_1.default.resolve(__dirname, "../../test-data");
|
|
25
27
|
const REPORTER_PATH = path_1.default.resolve(__dirname, "../../dist/reporter/incremental-blob-reporter.js");
|
|
28
|
+
const EMPIRICAL_REPORTER_PATH = path_1.default.resolve(__dirname, "../../dist/reporter/empirical-reporter.js");
|
|
26
29
|
const TEST_CASE_SYNC_REPORTER_PATH = path_1.default.resolve(__dirname, "../../dist/reporter/test-case-sync-reporter.js");
|
|
27
30
|
const PLAYWRIGHT_BIN = path_1.default.resolve(__dirname, "../../node_modules/.bin/playwright");
|
|
28
31
|
async function sleep(ms) {
|
|
@@ -60,7 +63,9 @@ async function setupReporterFixture({ suite, reporterPath, tempPrefix, }) {
|
|
|
60
63
|
}
|
|
61
64
|
else if (entry.name === "playwright.config.ts") {
|
|
62
65
|
const content = await fs_1.default.promises.readFile(src, "utf8");
|
|
63
|
-
await fs_1.default.promises.writeFile(dest, content
|
|
66
|
+
await fs_1.default.promises.writeFile(dest, content
|
|
67
|
+
.replace("__REPORTER_PATH__", reporterPath)
|
|
68
|
+
.replace("__EMPIRICAL_REPORTER_PATH__", EMPIRICAL_REPORTER_PATH));
|
|
64
69
|
}
|
|
65
70
|
else {
|
|
66
71
|
await fs_1.default.promises.copyFile(src, dest);
|
|
@@ -106,7 +111,7 @@ const MARKER_RE = /@@ ([A-Z0-9-]+) @@/g;
|
|
|
106
111
|
* runner detached and does `process.kill(-pid, signal)`.
|
|
107
112
|
*/
|
|
108
113
|
async function runPlaywrightWithSignal(ctx, opts) {
|
|
109
|
-
const { workers, waitForMarker, waitFor, delayBeforeSignalMs = 0, signal = "SIGINT", secondSignalAfterMs, killAfterMs, triggerTimeoutMs = 30_000, } = opts;
|
|
114
|
+
const { workers, waitForMarker, waitFor, delayBeforeSignalMs = 0, signal = "SIGINT", secondSignalAfterMs, killAfterMs, triggerTimeoutMs = 30_000, env, } = opts;
|
|
110
115
|
const startedAt = Date.now();
|
|
111
116
|
const since = () => Date.now() - startedAt;
|
|
112
117
|
const child = (0, child_process_1.spawn)(PLAYWRIGHT_BIN, ["test", `--workers=${workers}`], {
|
|
@@ -117,6 +122,7 @@ async function runPlaywrightWithSignal(ctx, opts) {
|
|
|
117
122
|
SHARD_INDEX: "1",
|
|
118
123
|
TOTAL_SHARDS: "1",
|
|
119
124
|
FORCE_COLOR: "0",
|
|
125
|
+
...env,
|
|
120
126
|
},
|
|
121
127
|
stdio: ["pipe", "pipe", "pipe"],
|
|
122
128
|
detached: true,
|
|
@@ -351,3 +357,63 @@ function mergeBlobDirToSummary(cwd, blobDir, outputName) {
|
|
|
351
357
|
});
|
|
352
358
|
return JSON.parse(fs_1.default.readFileSync(outputPath, "utf8"));
|
|
353
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* A local stand-in for api-worker and the report bucket, so EmpiricalReporter
|
|
362
|
+
* runs unmodified inside a real Playwright run. Records test-case events and
|
|
363
|
+
* accepts every upload.
|
|
364
|
+
*/
|
|
365
|
+
async function startDashboardStub() {
|
|
366
|
+
const events = [];
|
|
367
|
+
const server = http_1.default.createServer((req, res) => {
|
|
368
|
+
const chunks = [];
|
|
369
|
+
req.on("data", (c) => chunks.push(c));
|
|
370
|
+
req.on("end", () => {
|
|
371
|
+
if (req.url?.startsWith("/api/")) {
|
|
372
|
+
if (req.method === "PUT" && req.url === "/api/test-runs/events") {
|
|
373
|
+
const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
374
|
+
if (body.name === "test_case_run_end") {
|
|
375
|
+
events.push(body.data);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
379
|
+
res.end("{}");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
// Everything else is the S3 client; r2-uploader always goes multipart.
|
|
383
|
+
res.writeHead(200, { "content-type": "application/xml", etag: '"etag"' });
|
|
384
|
+
if (req.method === "POST" && req.url?.includes("?uploads")) {
|
|
385
|
+
res.end("<InitiateMultipartUploadResult><UploadId>upload</UploadId></InitiateMultipartUploadResult>");
|
|
386
|
+
}
|
|
387
|
+
else if (req.method === "POST") {
|
|
388
|
+
res.end('<CompleteMultipartUploadResult><ETag>"etag"</ETag></CompleteMultipartUploadResult>');
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
res.end();
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
396
|
+
const url = `http://127.0.0.1:${server.address().port}`;
|
|
397
|
+
return {
|
|
398
|
+
testCaseEvents: () => [...events],
|
|
399
|
+
env: {
|
|
400
|
+
PROJECT_NAME: "reporter-test",
|
|
401
|
+
TEST_RUN_GITHUB_ACTION_ID: "1",
|
|
402
|
+
HAS_SHARDING: "true",
|
|
403
|
+
EMPIRICALRUN_API_KEY: "test-key",
|
|
404
|
+
DASHBOARD_DOMAIN: url,
|
|
405
|
+
// An IP endpoint makes the S3 client use path-style URLs, so uploads
|
|
406
|
+
// land on this server instead of a bucket subdomain.
|
|
407
|
+
REPORT_STORAGE_BACKEND: "s3",
|
|
408
|
+
S3_REGION: "us-east-1",
|
|
409
|
+
S3_UPLOAD_BUCKET: "reports",
|
|
410
|
+
AWS_ENDPOINT_URL_S3: url,
|
|
411
|
+
AWS_ACCESS_KEY_ID: "test",
|
|
412
|
+
AWS_SECRET_ACCESS_KEY: "test",
|
|
413
|
+
AWS_SESSION_TOKEN: undefined,
|
|
414
|
+
AWS_PROFILE: undefined,
|
|
415
|
+
REPORTS_BASE_URL: url,
|
|
416
|
+
},
|
|
417
|
+
close: () => new Promise((resolve) => server.close(() => resolve())),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
@@ -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,SAAS,EACT,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"incremental-blob-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/incremental-blob-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -151,15 +151,10 @@ class IncrementalBlobReporter {
|
|
|
151
151
|
_computeCompletedSets() {
|
|
152
152
|
for (const [testId, results] of this._testResults) {
|
|
153
153
|
const maxRetries = this._testRetries.get(testId);
|
|
154
|
-
// Shutdown artifacts are not finished retries
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
// the final zip alongside the resume shard's, duplicating tests in the
|
|
159
|
-
// merge. A post-signal passed/failed is real, though: the test finished
|
|
160
|
-
// its body and only its aftermath overlapped the shutdown.
|
|
161
|
-
const finished = new Map([...results].filter(([, r]) => r.status !== "interrupted" &&
|
|
162
|
-
!(r.postSignal && r.status === "skipped")));
|
|
154
|
+
// Shutdown artifacts are not finished retries. Counting them as
|
|
155
|
+
// complete would put their results in the final zip alongside the
|
|
156
|
+
// resume shard's, duplicating tests in the merge.
|
|
157
|
+
const finished = new Map([...results].filter(([, r]) => !(0, reporter_state_1.isShutdownArtifact)(r.status, r.postSignal)));
|
|
163
158
|
if ((0, reporter_1.areRetriesComplete)(maxRetries, finished)) {
|
|
164
159
|
this._completedTestIds.add(testId);
|
|
165
160
|
for (const { resultId } of finished.values()) {
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
export declare function isFinalized(): boolean;
|
|
2
2
|
export declare function setFinalized(): void;
|
|
3
|
+
/**
|
|
4
|
+
* Whether a result is a by-product of interruption shutdown rather than a
|
|
5
|
+
* finished attempt: an "interrupted" result is a test cut off mid-flight, and
|
|
6
|
+
* a post-signal "skipped" is a serial sibling Playwright marks off while
|
|
7
|
+
* shutting down. The resume shard re-runs both. A post-signal passed/failed is
|
|
8
|
+
* real, though: the test finished its body and only its aftermath overlapped
|
|
9
|
+
* the shutdown.
|
|
10
|
+
*
|
|
11
|
+
* Shared so the blob and the run ledger agree on which results count; when
|
|
12
|
+
* they disagree, the ledger calls a test unfinished that the blob already
|
|
13
|
+
* holds, and the merged report gets it twice.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isShutdownArtifact(status: string, postSignal: boolean): boolean;
|
|
3
16
|
//# sourceMappingURL=reporter-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter-state.d.ts","sourceRoot":"","sources":["../../src/reporter/reporter-state.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}
|
|
1
|
+
{"version":3,"file":"reporter-state.d.ts","sourceRoot":"","sources":["../../src/reporter/reporter-state.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,GAClB,OAAO,CAET"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isFinalized = isFinalized;
|
|
4
4
|
exports.setFinalized = setFinalized;
|
|
5
|
+
exports.isShutdownArtifact = isShutdownArtifact;
|
|
5
6
|
let _finalized = false;
|
|
6
7
|
function isFinalized() {
|
|
7
8
|
return _finalized;
|
|
@@ -9,3 +10,18 @@ function isFinalized() {
|
|
|
9
10
|
function setFinalized() {
|
|
10
11
|
_finalized = true;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Whether a result is a by-product of interruption shutdown rather than a
|
|
15
|
+
* finished attempt: an "interrupted" result is a test cut off mid-flight, and
|
|
16
|
+
* a post-signal "skipped" is a serial sibling Playwright marks off while
|
|
17
|
+
* shutting down. The resume shard re-runs both. A post-signal passed/failed is
|
|
18
|
+
* real, though: the test finished its body and only its aftermath overlapped
|
|
19
|
+
* the shutdown.
|
|
20
|
+
*
|
|
21
|
+
* Shared so the blob and the run ledger agree on which results count; when
|
|
22
|
+
* they disagree, the ledger calls a test unfinished that the blob already
|
|
23
|
+
* holds, and the merged report gets it twice.
|
|
24
|
+
*/
|
|
25
|
+
function isShutdownArtifact(status, postSignal) {
|
|
26
|
+
return status === "interrupted" || (postSignal && status === "skipped");
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/playwright-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.1",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": ">=22"
|
|
6
|
+
},
|
|
4
7
|
"publishConfig": {
|
|
5
8
|
"registry": "https://registry.npmjs.org/",
|
|
6
9
|
"access": "public"
|
|
@@ -42,7 +45,7 @@
|
|
|
42
45
|
"openapi-typescript": "7.6.1",
|
|
43
46
|
"playwright-core": "1.63.0",
|
|
44
47
|
"serve-handler": "^6.1.6",
|
|
45
|
-
"@empiricalrun/shared-types": "0.20.
|
|
48
|
+
"@empiricalrun/shared-types": "0.20.3"
|
|
46
49
|
},
|
|
47
50
|
"dependencies": {
|
|
48
51
|
"@babel/code-frame": "^7.24.7",
|
|
@@ -51,14 +54,14 @@
|
|
|
51
54
|
"console-log-level": "^1.4.1",
|
|
52
55
|
"mime": "3.0.0",
|
|
53
56
|
"openapi-fetch": "0.14.1",
|
|
54
|
-
"openai": "^
|
|
57
|
+
"openai": "^7.19.0",
|
|
55
58
|
"puppeteer-extra-plugin-recaptcha": "^3.6.8",
|
|
56
59
|
"rimraf": "^6.0.1",
|
|
57
60
|
"ts-morph": "^23.0.0",
|
|
58
|
-
"@empiricalrun/
|
|
59
|
-
"@empiricalrun/
|
|
60
|
-
"@empiricalrun/reporter": "^0.30.
|
|
61
|
-
"@empiricalrun/
|
|
61
|
+
"@empiricalrun/llm": "^0.28.0",
|
|
62
|
+
"@empiricalrun/r2-uploader": "^0.10.3",
|
|
63
|
+
"@empiricalrun/reporter": "^0.30.2",
|
|
64
|
+
"@empiricalrun/cua": "^0.5.0"
|
|
62
65
|
},
|
|
63
66
|
"scripts": {
|
|
64
67
|
"dev": "pnpm gen:api-worker-openapi && tsgo --build --watch",
|