@testdino/playwright 1.0.1 → 1.0.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.
- package/README.md +6 -5
- package/dist/index.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +101 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +101 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -384,7 +384,7 @@ var EventBuffer = class {
|
|
|
384
384
|
events = [];
|
|
385
385
|
maxSize;
|
|
386
386
|
onFlush;
|
|
387
|
-
|
|
387
|
+
flushPromise = null;
|
|
388
388
|
constructor(options) {
|
|
389
389
|
this.maxSize = options.maxSize || 10;
|
|
390
390
|
this.onFlush = options.onFlush || (async () => {
|
|
@@ -402,12 +402,30 @@ var EventBuffer = class {
|
|
|
402
402
|
}
|
|
403
403
|
/**
|
|
404
404
|
* Flush all buffered events
|
|
405
|
+
* If a flush is already in progress, waits for it to complete then flushes any new events
|
|
405
406
|
*/
|
|
406
407
|
async flush() {
|
|
407
|
-
if (this.
|
|
408
|
+
if (this.flushPromise) {
|
|
409
|
+
await this.flushPromise;
|
|
410
|
+
if (this.events.length > 0) {
|
|
411
|
+
return this.flush();
|
|
412
|
+
}
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (this.events.length === 0) {
|
|
408
416
|
return;
|
|
409
417
|
}
|
|
410
|
-
this.
|
|
418
|
+
this.flushPromise = this.doFlush();
|
|
419
|
+
try {
|
|
420
|
+
await this.flushPromise;
|
|
421
|
+
} finally {
|
|
422
|
+
this.flushPromise = null;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Internal flush implementation
|
|
427
|
+
*/
|
|
428
|
+
async doFlush() {
|
|
411
429
|
try {
|
|
412
430
|
const eventsToFlush = [...this.events];
|
|
413
431
|
this.events = [];
|
|
@@ -415,8 +433,6 @@ var EventBuffer = class {
|
|
|
415
433
|
} catch (error) {
|
|
416
434
|
console.error("Failed to flush events:", error);
|
|
417
435
|
throw error;
|
|
418
|
-
} finally {
|
|
419
|
-
this.isFlushing = false;
|
|
420
436
|
}
|
|
421
437
|
}
|
|
422
438
|
/**
|
|
@@ -1734,6 +1750,8 @@ var TestdinoReporter = class {
|
|
|
1734
1750
|
// Deferred initialization - resolves true on success, false on failure
|
|
1735
1751
|
initPromise = null;
|
|
1736
1752
|
initFailed = false;
|
|
1753
|
+
// Promises for onTestEnd; must be awaited in onEnd to prevent data loss
|
|
1754
|
+
pendingTestEndPromises = /* @__PURE__ */ new Set();
|
|
1737
1755
|
constructor(config = {}) {
|
|
1738
1756
|
const cliConfig = this.loadCliConfig();
|
|
1739
1757
|
this.config = { ...config, ...cliConfig };
|
|
@@ -2018,49 +2036,72 @@ var TestdinoReporter = class {
|
|
|
2018
2036
|
await this.buffer.add(event);
|
|
2019
2037
|
}
|
|
2020
2038
|
/**
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2039
|
+
/**
|
|
2040
|
+
* Called after each test.
|
|
2041
|
+
* Playwright does not await onTestEnd promises—pending work is awaited in onEnd.
|
|
2042
|
+
*/
|
|
2043
|
+
onTestEnd(test, result) {
|
|
2024
2044
|
if (!this.initPromise || this.initFailed) return;
|
|
2025
|
-
const
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2045
|
+
const workPromise = this.processTestEnd(test, result);
|
|
2046
|
+
this.pendingTestEndPromises.add(workPromise);
|
|
2047
|
+
workPromise.finally(() => {
|
|
2048
|
+
this.pendingTestEndPromises.delete(workPromise);
|
|
2049
|
+
});
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* Process test end event asynchronously
|
|
2053
|
+
* Uploads attachments and adds test:end event to buffer
|
|
2054
|
+
*/
|
|
2055
|
+
async processTestEnd(test, result) {
|
|
2056
|
+
try {
|
|
2057
|
+
const attachmentsWithUrls = await this.uploadAttachments(result.attachments, test.id);
|
|
2058
|
+
const event = {
|
|
2059
|
+
type: "test:end",
|
|
2060
|
+
runId: this.runId,
|
|
2061
|
+
...this.getEventMetadata(),
|
|
2062
|
+
// Test Identification
|
|
2063
|
+
testId: test.id,
|
|
2064
|
+
// Status Information
|
|
2065
|
+
status: result.status,
|
|
2066
|
+
outcome: test.outcome(),
|
|
2067
|
+
// Timing
|
|
2068
|
+
duration: result.duration,
|
|
2069
|
+
// Execution Context
|
|
2070
|
+
retry: result.retry,
|
|
2071
|
+
// Worker Information
|
|
2072
|
+
workerIndex: result.workerIndex,
|
|
2073
|
+
parallelIndex: result.parallelIndex,
|
|
2074
|
+
// Test Metadata
|
|
2075
|
+
annotations: test.annotations.map((a) => ({
|
|
2076
|
+
type: a.type,
|
|
2077
|
+
description: a.description
|
|
2078
|
+
})),
|
|
2079
|
+
// Error Information
|
|
2080
|
+
errors: result.errors.map((e) => this.extractError(e)).filter((e) => e !== void 0),
|
|
2081
|
+
// Step Summary
|
|
2082
|
+
steps: this.extractTestStepsSummary(result),
|
|
2083
|
+
// Attachments Metadata (with Azure URLs when uploaded)
|
|
2084
|
+
attachments: attachmentsWithUrls,
|
|
2085
|
+
// Console Output
|
|
2086
|
+
stdout: result.stdout.length > 0 ? this.extractConsoleOutput(result.stdout) : void 0,
|
|
2087
|
+
stderr: result.stderr.length > 0 ? this.extractConsoleOutput(result.stderr) : void 0
|
|
2088
|
+
};
|
|
2089
|
+
await this.buffer.add(event);
|
|
2090
|
+
} catch (error) {
|
|
2091
|
+
console.error(
|
|
2092
|
+
"\u274C TestDino: Failed to process test:end event:",
|
|
2093
|
+
error instanceof Error ? error.message : String(error)
|
|
2094
|
+
);
|
|
2095
|
+
}
|
|
2058
2096
|
}
|
|
2059
2097
|
/**
|
|
2060
2098
|
* Called after all tests complete
|
|
2061
2099
|
*/
|
|
2062
2100
|
async onEnd(result) {
|
|
2063
2101
|
if (this.quotaExceeded) {
|
|
2102
|
+
if (this.pendingTestEndPromises.size > 0) {
|
|
2103
|
+
await Promise.allSettled(Array.from(this.pendingTestEndPromises));
|
|
2104
|
+
}
|
|
2064
2105
|
console.log("\u2705 TestDino: Tests completed (quota limit reached; not streamed to TestDino)");
|
|
2065
2106
|
this.wsClient?.close();
|
|
2066
2107
|
this.removeSignalHandlers();
|
|
@@ -2070,10 +2111,17 @@ var TestdinoReporter = class {
|
|
|
2070
2111
|
const success = await this.initPromise;
|
|
2071
2112
|
if (!success) {
|
|
2072
2113
|
this.buffer?.clear();
|
|
2114
|
+
this.pendingTestEndPromises.clear();
|
|
2073
2115
|
this.wsClient?.close();
|
|
2074
2116
|
this.removeSignalHandlers();
|
|
2075
2117
|
return;
|
|
2076
2118
|
}
|
|
2119
|
+
if (this.pendingTestEndPromises.size > 0) {
|
|
2120
|
+
if (this.config.debug) {
|
|
2121
|
+
console.log(`\u{1F50D} TestDino: Waiting for ${this.pendingTestEndPromises.size} pending test:end events...`);
|
|
2122
|
+
}
|
|
2123
|
+
await Promise.allSettled(Array.from(this.pendingTestEndPromises));
|
|
2124
|
+
}
|
|
2077
2125
|
const event = {
|
|
2078
2126
|
type: "run:end",
|
|
2079
2127
|
runId: this.runId,
|
|
@@ -2538,6 +2586,17 @@ var TestdinoReporter = class {
|
|
|
2538
2586
|
if (!this.initPromise) {
|
|
2539
2587
|
process.exit(exitCode);
|
|
2540
2588
|
}
|
|
2589
|
+
const waitForPending = async () => {
|
|
2590
|
+
if (this.pendingTestEndPromises.size > 0) {
|
|
2591
|
+
try {
|
|
2592
|
+
await Promise.race([
|
|
2593
|
+
Promise.allSettled(Array.from(this.pendingTestEndPromises)),
|
|
2594
|
+
this.timeoutPromise(2e3, "Pending events timeout")
|
|
2595
|
+
]);
|
|
2596
|
+
} catch {
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2541
2600
|
const event = {
|
|
2542
2601
|
type: "run:end",
|
|
2543
2602
|
runId: this.runId,
|
|
@@ -2557,6 +2616,7 @@ var TestdinoReporter = class {
|
|
|
2557
2616
|
}, 3e3);
|
|
2558
2617
|
const sendAndExit = async () => {
|
|
2559
2618
|
try {
|
|
2619
|
+
await waitForPending();
|
|
2560
2620
|
await Promise.race([this.sendInterruptionEvent(event), this.timeoutPromise(2500, "Send timeout")]);
|
|
2561
2621
|
console.log("\u2705 TestDino: Interruption event sent");
|
|
2562
2622
|
} catch (error) {
|