@empiricalrun/playwright-utils 0.62.1 → 0.63.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 +26 -0
- package/dist/api-worker-client.d.ts +0 -13
- package/dist/api-worker-client.d.ts.map +1 -1
- package/dist/api-worker-client.js +0 -15
- package/dist/auth/google.d.ts.map +1 -1
- package/dist/auth/google.js +0 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +0 -9
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +0 -8
- package/dist/generated/api-worker-openapi.d.ts +3031 -1420
- package/dist/generated/api-worker-openapi.d.ts.map +1 -1
- package/dist/overlay-tests/cache.spec.js +31 -17
- package/dist/overlay-tests/click.spec.js +2 -25
- package/dist/overlay-tests/dismiss-mechanics.spec.d.ts +2 -0
- package/dist/overlay-tests/dismiss-mechanics.spec.d.ts.map +1 -0
- package/dist/overlay-tests/dismiss-mechanics.spec.js +59 -0
- package/dist/overlay-tests/dropdown.spec.d.ts +2 -0
- package/dist/overlay-tests/dropdown.spec.d.ts.map +1 -0
- package/dist/overlay-tests/dropdown.spec.js +53 -0
- package/dist/overlay-tests/fixtures.d.ts +3 -1
- package/dist/overlay-tests/fixtures.d.ts.map +1 -1
- package/dist/overlay-tests/fixtures.js +15 -0
- package/dist/overlay-tests/typesafe-hit-check.spec.d.ts +2 -0
- package/dist/overlay-tests/typesafe-hit-check.spec.d.ts.map +1 -0
- package/dist/overlay-tests/typesafe-hit-check.spec.js +57 -0
- package/dist/overlay-tests/typesafe.spec.d.ts +2 -0
- package/dist/overlay-tests/typesafe.spec.d.ts.map +1 -0
- package/dist/overlay-tests/typesafe.spec.js +86 -0
- package/dist/playwright-extensions.d.ts.map +1 -1
- package/dist/playwright-extensions.js +0 -1
- package/dist/reporter/attachment-cleanup-test-reporter.d.ts +0 -6
- package/dist/reporter/attachment-cleanup-test-reporter.d.ts.map +1 -1
- package/dist/reporter/attachment-cleanup-test-reporter.js +0 -6
- package/dist/reporter/attachment-cleanup.d.ts +0 -33
- package/dist/reporter/attachment-cleanup.d.ts.map +1 -1
- package/dist/reporter/attachment-cleanup.js +2 -51
- package/dist/reporter/empirical-reporter.d.ts.map +1 -1
- package/dist/reporter/empirical-reporter.js +0 -9
- package/dist/reporter/harness.d.ts +0 -62
- package/dist/reporter/harness.d.ts.map +1 -1
- package/dist/reporter/harness.js +1 -53
- package/dist/reporter/ibr-utils.d.ts +0 -5
- package/dist/reporter/ibr-utils.d.ts.map +1 -1
- package/dist/reporter/ibr-utils.js +0 -5
- package/dist/reporter/incremental-blob-reporter.d.ts +0 -17
- package/dist/reporter/incremental-blob-reporter.d.ts.map +1 -1
- package/dist/reporter/incremental-blob-reporter.js +5 -35
- package/dist/reporter/lifecycle-events.d.ts.map +1 -1
- package/dist/reporter/lifecycle-events.js +0 -9
- package/dist/reporter/parity-utils.d.ts +0 -30
- package/dist/reporter/parity-utils.d.ts.map +1 -1
- package/dist/reporter/parity-utils.js +4 -28
- package/dist/reporter/reporter-state.d.ts +0 -12
- package/dist/reporter/reporter-state.d.ts.map +1 -1
- package/dist/reporter/reporter-state.js +0 -12
- package/dist/reporter/test-case-sync.d.ts.map +1 -1
- package/dist/reporter/test-case-sync.js +0 -12
- package/dist/reporter/uploader.d.ts.map +1 -1
- package/dist/reporter/uploader.js +0 -6
- package/dist/reporter/util.d.ts +0 -33
- package/dist/reporter/util.d.ts.map +1 -1
- package/dist/reporter/util.js +0 -37
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +1 -10
- package/dist/test/coverage.d.ts.map +1 -1
- package/dist/test/coverage.js +1 -3
- package/dist/test/expect/visual.d.ts.map +1 -1
- package/dist/test/expect/visual.js +1 -9
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +4 -21
- package/dist/test/scripts/agent-capabilities.js +2 -2
- package/dist/test/scripts/index.d.ts +2 -2
- package/dist/test/scripts/index.d.ts.map +1 -1
- package/dist/test/scripts/index.js +3 -16
- package/dist/test/scripts/pw-locator-patch/actions/click.d.ts.map +1 -0
- package/dist/test/scripts/pw-locator-patch/{highlight → actions}/click.js +8 -6
- package/dist/test/scripts/pw-locator-patch/actions/hover.d.ts.map +1 -0
- package/dist/test/scripts/pw-locator-patch/{highlight → actions}/hover.js +0 -3
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.d.ts +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/cache.js +9 -13
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.d.ts +3 -0
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/index.js +14 -12
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/prompt.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/prompt.js +0 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.d.ts +38 -0
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.d.ts.map +1 -0
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/typesafe.js +159 -0
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.d.ts +3 -0
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/dismiss-overlays/utils.js +13 -5
- package/dist/test/scripts/pw-locator-patch/utils/index.d.ts +0 -1
- package/dist/test/scripts/pw-locator-patch/utils/index.d.ts.map +1 -1
- package/dist/test/scripts/pw-locator-patch/utils/index.js +0 -18
- package/dist/test/types.d.ts +2 -5
- package/dist/test/types.d.ts.map +1 -1
- package/dist/test/video-labels.d.ts.map +1 -1
- package/dist/test/video-labels.js +0 -1
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +0 -3
- package/docs/fixtures.md +4 -5
- package/package.json +6 -6
- package/playwright.config.ts +0 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/upstream-oracle/ibr-adapter.js +0 -23
- package/upstream-oracle/run.mjs +1 -69
- package/dist/test/scripts/locator-highlights.d.ts +0 -4
- package/dist/test/scripts/locator-highlights.d.ts.map +0 -1
- package/dist/test/scripts/locator-highlights.js +0 -28
- package/dist/test/scripts/pw-locator-patch/highlight/click.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/expect.d.ts +0 -5
- package/dist/test/scripts/pw-locator-patch/highlight/expect.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/expect.js +0 -23
- package/dist/test/scripts/pw-locator-patch/highlight/hover.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/inner-text.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/inner-text.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/inner-text.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/input-value.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/input-value.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/input-value.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/is-checked.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/is-checked.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/is-checked.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/is-disabled.js +0 -30
- package/dist/test/scripts/pw-locator-patch/highlight/is-editable.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/is-editable.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/is-editable.js +0 -29
- package/dist/test/scripts/pw-locator-patch/highlight/text-content.d.ts +0 -6
- package/dist/test/scripts/pw-locator-patch/highlight/text-content.d.ts.map +0 -1
- package/dist/test/scripts/pw-locator-patch/highlight/text-content.js +0 -30
- /package/dist/test/scripts/pw-locator-patch/{highlight → actions}/click.d.ts +0 -0
- /package/dist/test/scripts/pw-locator-patch/{highlight → actions}/hover.d.ts +0 -0
|
@@ -16,7 +16,7 @@ function getDefaultDiskLimitBytes() {
|
|
|
16
16
|
}
|
|
17
17
|
logger_1.logger.warn(`[AttachmentCleanup] Invalid ATTACHMENT_CLEANUP_LIMIT_BYTES=${raw}, using default`);
|
|
18
18
|
}
|
|
19
|
-
return 10 * 1024 * 1024 * 1024;
|
|
19
|
+
return 10 * 1024 * 1024 * 1024;
|
|
20
20
|
}
|
|
21
21
|
const DISK_LOG_INTERVAL_MS = 30_000;
|
|
22
22
|
function formatBytes(bytes) {
|
|
@@ -39,12 +39,9 @@ function getDiskUsage() {
|
|
|
39
39
|
return "unavailable";
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
// Where the test-run worker checks out the test repo.
|
|
43
42
|
const WORKER_REPO_DIR = "/app/source-repo";
|
|
44
43
|
function getDiskBreakdown() {
|
|
45
44
|
try {
|
|
46
|
-
// /tmp also holds browser profiles and download dirs that no attachment
|
|
47
|
-
// accounts for, so it is listed whole alongside its artifact dirs.
|
|
48
45
|
const output = (0, child_process_1.execSync)("du -sh test-results/.playwright-artifacts-* test-results/ blob-report/ blob-report-incremental/ playwright-report/ /tmp/playwright-artifacts-* /tmp 2>/dev/null | sort -rh", { encoding: "utf8", timeout: 8000, cwd: WORKER_REPO_DIR }).trim();
|
|
49
46
|
if (!output) {
|
|
50
47
|
return "none";
|
|
@@ -58,31 +55,6 @@ function getDiskBreakdown() {
|
|
|
58
55
|
return "none";
|
|
59
56
|
}
|
|
60
57
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Tracks test attachments and evicts the oldest uploaded ones from disk
|
|
63
|
-
* when total size exceeds the configured limit.
|
|
64
|
-
*
|
|
65
|
-
* Two-phase tracking:
|
|
66
|
-
* 1. register() — called immediately when an attachment is created.
|
|
67
|
-
* Adds the file to the total size accounting so the LRU knows about
|
|
68
|
-
* all disk usage, even while uploads are still queued.
|
|
69
|
-
* 2. markUploaded() — called after the file is uploaded to R2.
|
|
70
|
-
* Marks the file as safe to evict (delete from disk).
|
|
71
|
-
*
|
|
72
|
-
* Eviction only deletes files that have been uploaded. This ensures we
|
|
73
|
-
* never delete a file before its upload completes.
|
|
74
|
-
*
|
|
75
|
-
* Why this exists:
|
|
76
|
-
* Test attachments (videos, traces, screenshots) accumulate on disk during a
|
|
77
|
-
* test run. On Fargate workers with 50 GB ephemeral storage, large test suites
|
|
78
|
-
* can exhaust disk space. Since attachments are already uploaded to R2, we can
|
|
79
|
-
* safely delete them from disk — but we can't delete them immediately because
|
|
80
|
-
* Playwright's blob reporter reads them during onEnd to embed as resources/.
|
|
81
|
-
*
|
|
82
|
-
* The blob reporter's statSync guard (Playwright 1.57+) gracefully skips
|
|
83
|
-
* missing files, and patchBlobZip replaces resources/ with
|
|
84
|
-
* _empirical_urls.json pointing to R2 URLs anyway.
|
|
85
|
-
*/
|
|
86
58
|
class AttachmentCleanup {
|
|
87
59
|
_pending = new Map();
|
|
88
60
|
_uploaded = [];
|
|
@@ -97,19 +69,11 @@ class AttachmentCleanup {
|
|
|
97
69
|
_onEvict = null;
|
|
98
70
|
constructor(limitBytes = getDefaultDiskLimitBytes()) {
|
|
99
71
|
this._limitBytes = limitBytes;
|
|
100
|
-
// logger.debug(
|
|
101
|
-
// `[AttachmentCleanup] Initialized with limit: ${formatBytes(limitBytes)}`,
|
|
102
|
-
// );
|
|
103
72
|
this._diskLogTimer = setInterval(() => {
|
|
104
73
|
this._logDiskStatus();
|
|
105
74
|
}, DISK_LOG_INTERVAL_MS);
|
|
106
|
-
// Don't keep the process alive just for this timer
|
|
107
75
|
this._diskLogTimer.unref();
|
|
108
76
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Phase 1: Register an attachment immediately when it's created.
|
|
111
|
-
* Adds to total size accounting and attempts eviction of already-uploaded files.
|
|
112
|
-
*/
|
|
113
77
|
register(attachment) {
|
|
114
78
|
try {
|
|
115
79
|
if (!attachment.path) {
|
|
@@ -125,14 +89,8 @@ class AttachmentCleanup {
|
|
|
125
89
|
this._registeredCount++;
|
|
126
90
|
this._evict();
|
|
127
91
|
}
|
|
128
|
-
catch {
|
|
129
|
-
// Ignore errors (file may not exist)
|
|
130
|
-
}
|
|
92
|
+
catch { }
|
|
131
93
|
}
|
|
132
|
-
/**
|
|
133
|
-
* Phase 2: Mark an attachment as uploaded (safe to evict).
|
|
134
|
-
* Moves from pending to the uploaded queue and attempts eviction.
|
|
135
|
-
*/
|
|
136
94
|
markUploaded(attachmentPath) {
|
|
137
95
|
const size = this._pending.get(attachmentPath);
|
|
138
96
|
if (size === undefined) {
|
|
@@ -170,19 +128,12 @@ class AttachmentCleanup {
|
|
|
170
128
|
}
|
|
171
129
|
_logDiskStatus() {
|
|
172
130
|
this._diskLogTick++;
|
|
173
|
-
// const artifactsSuffix =
|
|
174
|
-
// this._diskLogTick % 15 === 0 ? `, breakdown=${getDiskBreakdown()}` : "";
|
|
175
|
-
// logger.info(
|
|
176
|
-
// `[AttachmentCleanup] Periodic: registered=${this._registeredCount}, pending=${this._pending.size}, uploaded=${this._uploadedCount}, evicted=${this._evictedCount} (${formatBytes(this._evictedBytes)}), totalSize=${formatBytes(this._totalSize)}, limit=${formatBytes(this._limitBytes)}, disk=${getDiskUsage()}${artifactsSuffix}`,
|
|
177
|
-
// );
|
|
178
131
|
}
|
|
179
132
|
logSummary() {
|
|
180
133
|
if (this._diskLogTimer) {
|
|
181
134
|
clearInterval(this._diskLogTimer);
|
|
182
135
|
this._diskLogTimer = null;
|
|
183
136
|
}
|
|
184
|
-
// One line per run, only on the worker: the only record of what filled the
|
|
185
|
-
// disk when a run hits ENOSPC. Local runs stay quiet.
|
|
186
137
|
if (!fs_1.default.existsSync(WORKER_REPO_DIR)) {
|
|
187
138
|
return;
|
|
188
139
|
}
|
|
@@ -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;
|
|
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;IACrD,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,QA+I3C;IAEK,KAAK,CAAC,MAAM,EAAE,UAAU,iBAkH7B;IAED,OAAO,CAAC,qBAAqB;YAkBf,gBAAgB;YAOhB,iBAAiB;CAqChC;eAEc,iBAAiB"}
|
|
@@ -23,8 +23,6 @@ class EmpiricalReporter {
|
|
|
23
23
|
_testRetryCounts = new Map();
|
|
24
24
|
_uploader = null;
|
|
25
25
|
_attachmentCleanup = new attachment_cleanup_1.AttachmentCleanup();
|
|
26
|
-
// Resolved Playwright maxFailures (0 = no cap), sent on every run-end event
|
|
27
|
-
// so the server-side early-end enforces the client's configured cap.
|
|
28
26
|
_maxFailures;
|
|
29
27
|
constructor() {
|
|
30
28
|
this._uploader = (0, uploader_1.getUploader)();
|
|
@@ -62,11 +60,6 @@ class EmpiricalReporter {
|
|
|
62
60
|
}
|
|
63
61
|
};
|
|
64
62
|
onTestEnd(test, result) {
|
|
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
63
|
if ((0, reporter_state_1.isFinalized)() && (0, reporter_state_1.isShutdownArtifact)(result.status, true)) {
|
|
71
64
|
return;
|
|
72
65
|
}
|
|
@@ -186,8 +179,6 @@ class EmpiricalReporter {
|
|
|
186
179
|
}
|
|
187
180
|
async onEnd(result) {
|
|
188
181
|
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
182
|
await Promise.allSettled(this._pendingTestCaseEvents);
|
|
192
183
|
return;
|
|
193
184
|
}
|
|
@@ -8,10 +8,6 @@ export interface TestCaseSyncTestContext {
|
|
|
8
8
|
outputPath: string;
|
|
9
9
|
}
|
|
10
10
|
export declare function sleep(ms: number): Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Sets up a temp directory with the IBR fixture files.
|
|
13
|
-
* Returns a context object and a cleanup function.
|
|
14
|
-
*/
|
|
15
11
|
export declare function setupFixture(suite: string): Promise<{
|
|
16
12
|
ctx: IBRTestContext;
|
|
17
13
|
cleanup: () => Promise<void>;
|
|
@@ -20,16 +16,12 @@ export declare function setupTestCaseSyncFixture(suite: string): Promise<{
|
|
|
20
16
|
ctx: TestCaseSyncTestContext;
|
|
21
17
|
cleanup: () => Promise<void>;
|
|
22
18
|
}>;
|
|
23
|
-
/**
|
|
24
|
-
* Cleans blob artifacts from a previous run inside the same temp dir.
|
|
25
|
-
*/
|
|
26
19
|
export declare function cleanBlobArtifacts(ctx: IBRTestContext): Promise<void>;
|
|
27
20
|
export interface RunResult {
|
|
28
21
|
stdout: string;
|
|
29
22
|
stderr: string;
|
|
30
23
|
}
|
|
31
24
|
export type WaitFor = "first-passed" | "first-failed";
|
|
32
|
-
/** A `@@ NAME @@` line printed by a fixture suite, with its offset from run start. */
|
|
33
25
|
export interface Marker {
|
|
34
26
|
name: string;
|
|
35
27
|
atMs: number;
|
|
@@ -38,79 +30,40 @@ export interface SignalRunResult extends RunResult {
|
|
|
38
30
|
exitCode: number | null;
|
|
39
31
|
exitSignal: NodeJS.Signals | null;
|
|
40
32
|
markers: Marker[];
|
|
41
|
-
/** Offset from run start at which the first signal was delivered. */
|
|
42
33
|
signalSentAtMs: number;
|
|
43
|
-
/** Wall clock at run start, so `atMs` offsets can be compared to file mtimes. */
|
|
44
34
|
startedAtEpochMs: number;
|
|
45
35
|
}
|
|
46
36
|
export interface SignalRunOptions {
|
|
47
37
|
workers: number;
|
|
48
|
-
/**
|
|
49
|
-
* Signal as soon as this `@@ MARKER @@` is printed. Preferred over `waitFor`:
|
|
50
|
-
* it pins the signal to a known point in the run instead of a sleep.
|
|
51
|
-
*/
|
|
52
38
|
waitForMarker?: string;
|
|
53
|
-
/** Legacy trigger: wait for the first pass/fail line in stdout. */
|
|
54
39
|
waitFor?: WaitFor;
|
|
55
|
-
/** Settling delay between the trigger and the signal. */
|
|
56
40
|
delayBeforeSignalMs?: number;
|
|
57
|
-
/** Defaults to SIGINT, which is what production sends. */
|
|
58
41
|
signal?: NodeJS.Signals;
|
|
59
|
-
/** Send the same signal again this long after the first one. */
|
|
60
42
|
secondSignalAfterMs?: number;
|
|
61
|
-
/** SIGKILL the group this long after the first signal, like the cmd.ts grace cap. */
|
|
62
43
|
killAfterMs?: number;
|
|
63
|
-
/** How long to wait for the trigger before giving up and signalling anyway. */
|
|
64
44
|
triggerTimeoutMs?: number;
|
|
65
|
-
/** Extra env for the runner, e.g. from `startDashboardStub`. */
|
|
66
45
|
env?: NodeJS.ProcessEnv;
|
|
67
46
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Spawns `playwright test` with the IBR reporter in its own process group,
|
|
70
|
-
* signals the group mid-run, and waits for exit.
|
|
71
|
-
*
|
|
72
|
-
* The process group and the signal both match production: `cmd.ts` spawns the
|
|
73
|
-
* runner detached and does `process.kill(-pid, signal)`.
|
|
74
|
-
*/
|
|
75
47
|
export declare function runPlaywrightWithSignal(ctx: IBRTestContext, opts: SignalRunOptions): Promise<SignalRunResult>;
|
|
76
|
-
/**
|
|
77
|
-
* Spawns `playwright test` with the IBR reporter, waits for a test outcome,
|
|
78
|
-
* sends SIGINT, and waits for the process to exit.
|
|
79
|
-
*
|
|
80
|
-
* Returns captured stdout/stderr.
|
|
81
|
-
*/
|
|
82
48
|
export declare function runPlaywrightWithSigint(ctx: IBRTestContext, opts: {
|
|
83
49
|
workers: number;
|
|
84
50
|
waitFor: WaitFor;
|
|
85
51
|
}): Promise<RunResult>;
|
|
86
|
-
/** Marker names in the order they were printed. */
|
|
87
52
|
export declare function markerNames(result: SignalRunResult): string[];
|
|
88
53
|
export declare function runPlaywrightList(ctx: TestCaseSyncTestContext): Promise<RunResult>;
|
|
89
54
|
export interface BlobEvent {
|
|
90
55
|
method: string;
|
|
91
56
|
params?: Record<string, unknown>;
|
|
92
57
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Reads `report.jsonl` from the blob zip and returns parsed events.
|
|
95
|
-
*/
|
|
96
58
|
export declare function readBlobEvents(ctx: IBRTestContext): Promise<BlobEvent[]>;
|
|
97
|
-
/**
|
|
98
|
-
* Reads `report.jsonl` from any blob-format zip (standard or incremental).
|
|
99
|
-
*/
|
|
100
59
|
export declare function readEventsFromZip(zipPath: string): Promise<BlobEvent[]>;
|
|
101
60
|
export interface ParityTestContext {
|
|
102
61
|
tempDir: string;
|
|
103
|
-
/** Playwright's built-in blob reporter output: blob-report/report-1.zip */
|
|
104
62
|
standardZipPath: string;
|
|
105
63
|
standardBlobDir: string;
|
|
106
|
-
/** IBR output: blob-report-incremental/incremental-report-1.zip */
|
|
107
64
|
incrementalZipPath: string;
|
|
108
65
|
incrementalBlobDir: string;
|
|
109
66
|
}
|
|
110
|
-
/**
|
|
111
|
-
* Sets up a fixture whose config runs BOTH the built-in blob reporter and the
|
|
112
|
-
* IBR on the same invocation, so one event stream feeds both zips.
|
|
113
|
-
*/
|
|
114
67
|
export declare function setupParityFixture(suite: string): Promise<{
|
|
115
68
|
ctx: ParityTestContext;
|
|
116
69
|
cleanup: () => Promise<void>;
|
|
@@ -118,10 +71,6 @@ export declare function setupParityFixture(suite: string): Promise<{
|
|
|
118
71
|
export interface CleanRunResult extends RunResult {
|
|
119
72
|
exitCode: number | null;
|
|
120
73
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Spawns `playwright test` and lets it run to completion — the clean-finish
|
|
123
|
-
* half of the matrix (the SIGINT helpers above cover interruption).
|
|
124
|
-
*/
|
|
125
74
|
export declare function runPlaywrightClean(ctx: ParityTestContext, opts: {
|
|
126
75
|
workers: number;
|
|
127
76
|
shard?: {
|
|
@@ -129,22 +78,11 @@ export declare function runPlaywrightClean(ctx: ParityTestContext, opts: {
|
|
|
129
78
|
total: number;
|
|
130
79
|
};
|
|
131
80
|
}): Promise<CleanRunResult>;
|
|
132
|
-
/**
|
|
133
|
-
* Runs `playwright merge-reports <blobDir> --reporter json` and returns the
|
|
134
|
-
* parsed summary. Distinct output names let one temp dir hold both merges.
|
|
135
|
-
*/
|
|
136
81
|
export declare function mergeBlobDirToSummary(cwd: string, blobDir: string, outputName: string): Record<string, unknown>;
|
|
137
82
|
export interface DashboardStub {
|
|
138
|
-
/** `test_case_run_end` payloads EmpiricalReporter sent, in arrival order. */
|
|
139
83
|
testCaseEvents: () => Array<Record<string, any>>;
|
|
140
|
-
/** Runner env that points EmpiricalReporter's API calls and uploads here. */
|
|
141
84
|
env: NodeJS.ProcessEnv;
|
|
142
85
|
close: () => Promise<void>;
|
|
143
86
|
}
|
|
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
87
|
export declare function startDashboardStub(): Promise<DashboardStub>;
|
|
150
88
|
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/reporter/harness.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED
|
|
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
|
@@ -31,10 +31,6 @@ const PLAYWRIGHT_BIN = path_1.default.resolve(__dirname, "../../node_modules/.bi
|
|
|
31
31
|
async function sleep(ms) {
|
|
32
32
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Sets up a temp directory with the IBR fixture files.
|
|
36
|
-
* Returns a context object and a cleanup function.
|
|
37
|
-
*/
|
|
38
34
|
async function setupFixture(suite) {
|
|
39
35
|
const { tempDir, cleanup } = await setupReporterFixture({
|
|
40
36
|
suite,
|
|
@@ -58,7 +54,6 @@ async function setupReporterFixture({ suite, reporterPath, tempPrefix, }) {
|
|
|
58
54
|
const src = path_1.default.join(fixtureDir, entry.name);
|
|
59
55
|
const dest = path_1.default.join(tempDir, entry.name);
|
|
60
56
|
if (entry.isDirectory()) {
|
|
61
|
-
// Fixtures that put specs under a testDir subdir.
|
|
62
57
|
await fs_1.default.promises.cp(src, dest, { recursive: true });
|
|
63
58
|
}
|
|
64
59
|
else if (entry.name === "playwright.config.ts") {
|
|
@@ -90,9 +85,6 @@ async function setupTestCaseSyncFixture(suite) {
|
|
|
90
85
|
cleanup,
|
|
91
86
|
};
|
|
92
87
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Cleans blob artifacts from a previous run inside the same temp dir.
|
|
95
|
-
*/
|
|
96
88
|
async function cleanBlobArtifacts(ctx) {
|
|
97
89
|
if (fs_1.default.existsSync(ctx.blobDir)) {
|
|
98
90
|
await fs_1.default.promises.rm(ctx.blobDir, { recursive: true, force: true });
|
|
@@ -103,13 +95,6 @@ const WAIT_FOR_PATTERNS = {
|
|
|
103
95
|
"first-failed": /failed|✘|×/,
|
|
104
96
|
};
|
|
105
97
|
const MARKER_RE = /@@ ([A-Z0-9-]+) @@/g;
|
|
106
|
-
/**
|
|
107
|
-
* Spawns `playwright test` with the IBR reporter in its own process group,
|
|
108
|
-
* signals the group mid-run, and waits for exit.
|
|
109
|
-
*
|
|
110
|
-
* The process group and the signal both match production: `cmd.ts` spawns the
|
|
111
|
-
* runner detached and does `process.kill(-pid, signal)`.
|
|
112
|
-
*/
|
|
113
98
|
async function runPlaywrightWithSignal(ctx, opts) {
|
|
114
99
|
const { workers, waitForMarker, waitFor, delayBeforeSignalMs = 0, signal = "SIGINT", secondSignalAfterMs, killAfterMs, triggerTimeoutMs = 30_000, env, } = opts;
|
|
115
100
|
const startedAt = Date.now();
|
|
@@ -162,9 +147,7 @@ async function runPlaywrightWithSignal(ctx, opts) {
|
|
|
162
147
|
try {
|
|
163
148
|
process.kill(-child.pid, sig);
|
|
164
149
|
}
|
|
165
|
-
catch {
|
|
166
|
-
// The group is already gone.
|
|
167
|
-
}
|
|
150
|
+
catch { }
|
|
168
151
|
};
|
|
169
152
|
const pattern = waitFor ? WAIT_FOR_PATTERNS[waitFor] : undefined;
|
|
170
153
|
const isTriggered = () => waitForMarker
|
|
@@ -199,7 +182,6 @@ async function runPlaywrightWithSignal(ctx, opts) {
|
|
|
199
182
|
if (killAfterMs !== undefined) {
|
|
200
183
|
timers.push(setTimeout(() => signalGroup("SIGKILL"), killAfterMs));
|
|
201
184
|
}
|
|
202
|
-
// Backstop: never leave a runner behind if the suite misbehaves.
|
|
203
185
|
timers.push(setTimeout(() => signalGroup("SIGKILL"), 120_000));
|
|
204
186
|
try {
|
|
205
187
|
await closed;
|
|
@@ -219,21 +201,13 @@ async function runPlaywrightWithSignal(ctx, opts) {
|
|
|
219
201
|
startedAtEpochMs: startedAt,
|
|
220
202
|
};
|
|
221
203
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Spawns `playwright test` with the IBR reporter, waits for a test outcome,
|
|
224
|
-
* sends SIGINT, and waits for the process to exit.
|
|
225
|
-
*
|
|
226
|
-
* Returns captured stdout/stderr.
|
|
227
|
-
*/
|
|
228
204
|
async function runPlaywrightWithSigint(ctx, opts) {
|
|
229
205
|
return runPlaywrightWithSignal(ctx, {
|
|
230
206
|
workers: opts.workers,
|
|
231
207
|
waitFor: opts.waitFor,
|
|
232
|
-
// Waiting for 1 sec to ensure second test has started
|
|
233
208
|
delayBeforeSignalMs: 1_000,
|
|
234
209
|
});
|
|
235
210
|
}
|
|
236
|
-
/** Marker names in the order they were printed. */
|
|
237
211
|
function markerNames(result) {
|
|
238
212
|
return result.markers.map((m) => m.name);
|
|
239
213
|
}
|
|
@@ -262,15 +236,9 @@ async function runPlaywrightList(ctx) {
|
|
|
262
236
|
}
|
|
263
237
|
return { stdout, stderr };
|
|
264
238
|
}
|
|
265
|
-
/**
|
|
266
|
-
* Reads `report.jsonl` from the blob zip and returns parsed events.
|
|
267
|
-
*/
|
|
268
239
|
async function readBlobEvents(ctx) {
|
|
269
240
|
return readEventsFromZip(ctx.zipPath);
|
|
270
241
|
}
|
|
271
|
-
/**
|
|
272
|
-
* Reads `report.jsonl` from any blob-format zip (standard or incremental).
|
|
273
|
-
*/
|
|
274
242
|
async function readEventsFromZip(zipPath) {
|
|
275
243
|
const reportBuffer = await (0, zip_1.readZipEntry)(zipPath, "report.jsonl");
|
|
276
244
|
if (!reportBuffer) {
|
|
@@ -282,10 +250,6 @@ async function readEventsFromZip(zipPath) {
|
|
|
282
250
|
.split("\n")
|
|
283
251
|
.map((line) => JSON.parse(line));
|
|
284
252
|
}
|
|
285
|
-
/**
|
|
286
|
-
* Sets up a fixture whose config runs BOTH the built-in blob reporter and the
|
|
287
|
-
* IBR on the same invocation, so one event stream feeds both zips.
|
|
288
|
-
*/
|
|
289
253
|
async function setupParityFixture(suite) {
|
|
290
254
|
const { tempDir, cleanup } = await setupReporterFixture({
|
|
291
255
|
suite,
|
|
@@ -305,10 +269,6 @@ async function setupParityFixture(suite) {
|
|
|
305
269
|
cleanup,
|
|
306
270
|
};
|
|
307
271
|
}
|
|
308
|
-
/**
|
|
309
|
-
* Spawns `playwright test` and lets it run to completion — the clean-finish
|
|
310
|
-
* half of the matrix (the SIGINT helpers above cover interruption).
|
|
311
|
-
*/
|
|
312
272
|
async function runPlaywrightClean(ctx, opts) {
|
|
313
273
|
const args = ["test", `--workers=${opts.workers}`];
|
|
314
274
|
if (opts.shard) {
|
|
@@ -319,8 +279,6 @@ async function runPlaywrightClean(ctx, opts) {
|
|
|
319
279
|
env: {
|
|
320
280
|
...process.env,
|
|
321
281
|
LOCAL_TEST: "false",
|
|
322
|
-
// With --shard, the env vars are cleared on purpose so IBR falls back to
|
|
323
|
-
// the same config.shard the built-in blob reporter sees.
|
|
324
282
|
SHARD_INDEX: opts.shard ? undefined : "1",
|
|
325
283
|
TOTAL_SHARDS: opts.shard ? undefined : "1",
|
|
326
284
|
FORCE_COLOR: "0",
|
|
@@ -340,10 +298,6 @@ async function runPlaywrightClean(ctx, opts) {
|
|
|
340
298
|
});
|
|
341
299
|
return { stdout, stderr, exitCode };
|
|
342
300
|
}
|
|
343
|
-
/**
|
|
344
|
-
* Runs `playwright merge-reports <blobDir> --reporter json` and returns the
|
|
345
|
-
* parsed summary. Distinct output names let one temp dir hold both merges.
|
|
346
|
-
*/
|
|
347
301
|
function mergeBlobDirToSummary(cwd, blobDir, outputName) {
|
|
348
302
|
const outputPath = path_1.default.join(cwd, outputName);
|
|
349
303
|
(0, child_process_1.execFileSync)(PLAYWRIGHT_BIN, ["merge-reports", blobDir, "--reporter", "json"], {
|
|
@@ -357,11 +311,6 @@ function mergeBlobDirToSummary(cwd, blobDir, outputName) {
|
|
|
357
311
|
});
|
|
358
312
|
return JSON.parse(fs_1.default.readFileSync(outputPath, "utf8"));
|
|
359
313
|
}
|
|
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
314
|
async function startDashboardStub() {
|
|
366
315
|
const events = [];
|
|
367
316
|
const server = http_1.default.createServer((req, res) => {
|
|
@@ -379,7 +328,6 @@ async function startDashboardStub() {
|
|
|
379
328
|
res.end("{}");
|
|
380
329
|
return;
|
|
381
330
|
}
|
|
382
|
-
// Everything else is the S3 client; r2-uploader always goes multipart.
|
|
383
331
|
res.writeHead(200, { "content-type": "application/xml", etag: '"etag"' });
|
|
384
332
|
if (req.method === "POST" && req.url?.includes("?uploads")) {
|
|
385
333
|
res.end("<InitiateMultipartUploadResult><UploadId>upload</UploadId></InitiateMultipartUploadResult>");
|
|
@@ -43,11 +43,6 @@ export declare function relativeLocation(location: JsonLocation | undefined, roo
|
|
|
43
43
|
export declare function relativeAnnotationLocations(annotations: TestAnnotation[], rootDir: string): TestAnnotation[];
|
|
44
44
|
export declare function serializeTest(test: TestCase, rootDir: string): JsonTestCase;
|
|
45
45
|
export declare function serializeSuite(suite: Suite, rootDir: string): JsonSuite;
|
|
46
|
-
/**
|
|
47
|
-
* Recursively filters a serialized suite tree to only include tests
|
|
48
|
-
* whose testId is in the completedTestIds set. Removes empty parent suites.
|
|
49
|
-
* Returns null if the suite has no completed test descendants.
|
|
50
|
-
*/
|
|
51
46
|
export declare function filterSuiteByCompletedTests(suite: JsonSuite, completedTestIds: Set<string>): JsonSuite | null;
|
|
52
47
|
export declare function hasValidReport(reportLines: string[]): boolean;
|
|
53
48
|
export declare function buildUrlsJson(attachmentUrlMap: Map<string, string>): Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ibr-utils.d.ts","sourceRoot":"","sources":["../../src/reporter/ibr-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAO3E,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,CAAC;AAIF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAChD,WAAW,EAAE,CAOf;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3E;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC1B,IAAI,EAAE,QAAQ,GACb,MAAM,CAOR;AAID,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD,CAAC;AAIF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB,CAAC;AAMF,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAKpB;AAID,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,MAAM,GACd,YAAY,CAAC;AAChB,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,YAAY,GAAG,SAAS,EAClC,OAAO,EAAE,MAAM,GACd,YAAY,GAAG,SAAS,CAAC;AAa5B,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,cAAc,EAAE,EAC7B,OAAO,EAAE,MAAM,GACd,cAAc,EAAE,CAKlB;AAID,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAU3E;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAoBvE;AAMD
|
|
1
|
+
{"version":3,"file":"ibr-utils.d.ts","sourceRoot":"","sources":["../../src/reporter/ibr-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -108,11 +108,6 @@ function serializeSuite(suite, rootDir) {
|
|
|
108
108
|
function isTestEntry(entry) {
|
|
109
109
|
return "testId" in entry;
|
|
110
110
|
}
|
|
111
|
-
/**
|
|
112
|
-
* Recursively filters a serialized suite tree to only include tests
|
|
113
|
-
* whose testId is in the completedTestIds set. Removes empty parent suites.
|
|
114
|
-
* Returns null if the suite has no completed test descendants.
|
|
115
|
-
*/
|
|
116
111
|
function filterSuiteByCompletedTests(suite, completedTestIds) {
|
|
117
112
|
const filteredEntries = [];
|
|
118
113
|
for (const entry of suite.entries) {
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import type { FullConfig, FullResult, Reporter, Suite, TestCase, TestError, TestResult, TestStep, WorkerInfo } from "@playwright/test/reporter";
|
|
2
|
-
/**
|
|
3
|
-
* IncrementalBlobReporter
|
|
4
|
-
*
|
|
5
|
-
* This reporter builds a report.jsonl incrementally matching Playwright's blob format.
|
|
6
|
-
* The zip can be uploaded for merge at any point (e.g., on SIGTERM).
|
|
7
|
-
*
|
|
8
|
-
* Format matches Playwright's blob reporter exactly.
|
|
9
|
-
*/
|
|
10
2
|
export type AttachmentUrlMap = Map<string, string>;
|
|
11
3
|
declare class IncrementalBlobReporter implements Reporter {
|
|
12
4
|
private _currentWorkingDir;
|
|
@@ -33,12 +25,6 @@ declare class IncrementalBlobReporter implements Reporter {
|
|
|
33
25
|
private _removeSignalHandler;
|
|
34
26
|
private _buildSyntheticResult;
|
|
35
27
|
private _finalizeAndMaybeUpload;
|
|
36
|
-
/**
|
|
37
|
-
* Computes the lines to write, without touching `_reportLines`: recording
|
|
38
|
-
* continues after the SIGINT salvage, and the onEnd pass re-finalizes from
|
|
39
|
-
* the full stream — mutating here would make the second pass work from the
|
|
40
|
-
* first pass's pruned leftovers.
|
|
41
|
-
*/
|
|
42
28
|
private _buildFinalReportLines;
|
|
43
29
|
private _computeCompletedSets;
|
|
44
30
|
private _removeIncompleteTestArtifacts;
|
|
@@ -60,9 +46,6 @@ declare class IncrementalBlobReporter implements Reporter {
|
|
|
60
46
|
onStepBegin(test: TestCase, result: TestResult, step: TestStep): void;
|
|
61
47
|
onStepEnd(test: TestCase, result: TestResult, step: TestStep): void;
|
|
62
48
|
onEnd(result: FullResult): Promise<void>;
|
|
63
|
-
/**
|
|
64
|
-
* Add a single attachment URL mapping
|
|
65
|
-
*/
|
|
66
49
|
addAttachmentUrl(localPath: string, remoteUrl: string): void;
|
|
67
50
|
printsToStdio(): boolean;
|
|
68
51
|
}
|
|
@@ -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;AA8BnC
|
|
1
|
+
{"version":3,"file":"incremental-blob-reporter.d.ts","sourceRoot":"","sources":["../../src/reporter/incremental-blob-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,14 +22,14 @@ class IncrementalBlobReporter {
|
|
|
22
22
|
_totalShards;
|
|
23
23
|
_reportLines = [];
|
|
24
24
|
_attachmentUrlMap = new Map();
|
|
25
|
-
_resultIdMap = new Map();
|
|
26
|
-
_stepIdMap = new Map();
|
|
27
|
-
_knownAttachmentCounts = new Map();
|
|
25
|
+
_resultIdMap = new Map();
|
|
26
|
+
_stepIdMap = new Map();
|
|
27
|
+
_knownAttachmentCounts = new Map();
|
|
28
28
|
_uploader = null;
|
|
29
29
|
_completedTestIds = new Set();
|
|
30
30
|
_completedResultIds = new Set();
|
|
31
|
-
_testRetries = new Map();
|
|
32
|
-
_testResults = new Map();
|
|
31
|
+
_testRetries = new Map();
|
|
32
|
+
_testResults = new Map();
|
|
33
33
|
_startTime = Date.now();
|
|
34
34
|
_finalizePromise = null;
|
|
35
35
|
_rootDir = process.cwd();
|
|
@@ -99,7 +99,6 @@ class IncrementalBlobReporter {
|
|
|
99
99
|
console.warn("[IncrementalBlobReporterFailure] No onBegin received, skipping upload (nothing to merge)");
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
-
// Wait for pending attachment uploads FIRST so URLs are available
|
|
103
102
|
if (this._uploader) {
|
|
104
103
|
await this._uploader.waitForUploads();
|
|
105
104
|
}
|
|
@@ -127,33 +126,19 @@ class IncrementalBlobReporter {
|
|
|
127
126
|
}
|
|
128
127
|
logFinalizeComplete();
|
|
129
128
|
}
|
|
130
|
-
/**
|
|
131
|
-
* Computes the lines to write, without touching `_reportLines`: recording
|
|
132
|
-
* continues after the SIGINT salvage, and the onEnd pass re-finalizes from
|
|
133
|
-
* the full stream — mutating here would make the second pass work from the
|
|
134
|
-
* first pass's pruned leftovers.
|
|
135
|
-
*/
|
|
136
129
|
_buildFinalReportLines(result, pruneIncompleteTests) {
|
|
137
130
|
let lines = [...this._reportLines];
|
|
138
131
|
if (pruneIncompleteTests) {
|
|
139
|
-
// Determine which tests are fully complete (passed or all retries finished)
|
|
140
132
|
this._computeCompletedSets();
|
|
141
|
-
// Remove unrun tests from onProject suites
|
|
142
133
|
lines = this._patchProjectSuites(lines);
|
|
143
|
-
// Remove events (onTestBegin, onStepBegin, etc.) for incomplete tests
|
|
144
134
|
lines = this._removeIncompleteTestArtifacts(lines);
|
|
145
135
|
}
|
|
146
|
-
// The onEnd event belongs only in the written report, never in the
|
|
147
|
-
// in-memory stream — a later finalize pass appends its own.
|
|
148
136
|
lines.push(JSON.stringify((0, lifecycle_events_1.buildOnEndEvent)(result)));
|
|
149
137
|
return lines;
|
|
150
138
|
}
|
|
151
139
|
_computeCompletedSets() {
|
|
152
140
|
for (const [testId, results] of this._testResults) {
|
|
153
141
|
const maxRetries = this._testRetries.get(testId);
|
|
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
142
|
const finished = new Map([...results].filter(([, r]) => !(0, reporter_state_1.isShutdownArtifact)(r.status, r.postSignal)));
|
|
158
143
|
if ((0, reporter_1.areRetriesComplete)(maxRetries, finished)) {
|
|
159
144
|
this._completedTestIds.add(testId);
|
|
@@ -222,13 +207,10 @@ class IncrementalBlobReporter {
|
|
|
222
207
|
}
|
|
223
208
|
async _writeZip(lines) {
|
|
224
209
|
this._ensureDirs();
|
|
225
|
-
// Write report.jsonl to the output directory
|
|
226
210
|
const jsonlContent = lines.join("\n") + "\n";
|
|
227
211
|
fs_1.default.writeFileSync(this._jsonlPath, jsonlContent, "utf8");
|
|
228
|
-
// Write _empirical_urls.json with attachment URL mappings
|
|
229
212
|
const urlsJson = (0, ibr_utils_1.buildUrlsJson)(this._attachmentUrlMap);
|
|
230
213
|
fs_1.default.writeFileSync(this._urlsJsonPath, JSON.stringify(urlsJson, null, 2), "utf8");
|
|
231
|
-
// Create zip from the staging directory
|
|
232
214
|
const zipBuffer = await (0, zip_1.createZipFromDirectory)(this._stagingDir);
|
|
233
215
|
fs_1.default.writeFileSync(this._zipPath, zipBuffer);
|
|
234
216
|
console.log(`[IncrementalBlobReporter] Zip updated: ${this._zipPath} (${lines.length} events, ${this._attachmentUrlMap.size} attachments)`);
|
|
@@ -236,9 +218,6 @@ class IncrementalBlobReporter {
|
|
|
236
218
|
onBegin(config, suite) {
|
|
237
219
|
this._ensureDirs();
|
|
238
220
|
this._rootDir = config.rootDir;
|
|
239
|
-
// The env vars win (production sets them), but a sharded run without
|
|
240
|
-
// them should still stamp the right shard into the blob metadata and
|
|
241
|
-
// the zip name instead of defaulting every shard to 1/1.
|
|
242
221
|
if (!process.env.SHARD_INDEX && config.shard) {
|
|
243
222
|
this._shardIndex = config.shard.current;
|
|
244
223
|
this._totalShards = config.shard.total;
|
|
@@ -264,8 +243,6 @@ class IncrementalBlobReporter {
|
|
|
264
243
|
resultId,
|
|
265
244
|
status: result.status,
|
|
266
245
|
expectedStatus: test.expectedStatus,
|
|
267
|
-
// The SIGINT salvage has started; this result arrived during
|
|
268
|
-
// interruption shutdown rather than the normal run.
|
|
269
246
|
postSignal: this._finalizePromise !== null,
|
|
270
247
|
});
|
|
271
248
|
}
|
|
@@ -288,10 +265,6 @@ class IncrementalBlobReporter {
|
|
|
288
265
|
}
|
|
289
266
|
async onEnd(result) {
|
|
290
267
|
this._removeSignalHandler();
|
|
291
|
-
// Second phase of an interrupted run: the SIGINT pass salvaged a snapshot
|
|
292
|
-
// within milliseconds (SIGKILL insurance); by the time Playwright calls
|
|
293
|
-
// onEnd the teardown chain has finished, so re-finalize from the full
|
|
294
|
-
// stream and overwrite the salvage blob with the post-teardown report.
|
|
295
268
|
if (this._finalizePromise) {
|
|
296
269
|
await this._finalizePromise;
|
|
297
270
|
this._finalizePromise = this._finalizeAndMaybeUpload({
|
|
@@ -314,9 +287,6 @@ class IncrementalBlobReporter {
|
|
|
314
287
|
await this._finalizePromise;
|
|
315
288
|
console.log(`[IncrementalBlobReporter] Finished with status: ${result.status}`);
|
|
316
289
|
}
|
|
317
|
-
/**
|
|
318
|
-
* Add a single attachment URL mapping
|
|
319
|
-
*/
|
|
320
290
|
addAttachmentUrl(localPath, remoteUrl) {
|
|
321
291
|
this._attachmentUrlMap.set((0, ibr_utils_1.toResourcePath)(localPath), remoteUrl);
|
|
322
292
|
}
|