@testdino/playwright 1.0.1 → 1.0.2
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 +77 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +77 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,11 +121,12 @@ npx playwright test
|
|
|
121
121
|
|
|
122
122
|
### TestDino Options
|
|
123
123
|
|
|
124
|
-
| Option
|
|
125
|
-
|
|
|
126
|
-
| `token`
|
|
127
|
-
| `debug`
|
|
128
|
-
| `ciRunId`
|
|
124
|
+
| Option | CLI Flag | Environment Variable | Description |
|
|
125
|
+
| ----------- | ---------------- | -------------------- | --------------------------------------------------------------------------------------------------- |
|
|
126
|
+
| `token` | `--token`, `-t` | `TESTDINO_TOKEN` | Authentication token (required) |
|
|
127
|
+
| `debug` | `--debug` | `TESTDINO_DEBUG` | Enable debug logging |
|
|
128
|
+
| `ciRunId` | `--ci-run-id` | - | Group sharded test runs |
|
|
129
|
+
| `artifacts` | `--no-artifacts` | - | Upload artifacts (screenshots, videos, traces). Enabled by default; use `--no-artifacts` to disable |
|
|
129
130
|
|
|
130
131
|
### Configuration File
|
|
131
132
|
|
package/dist/index.d.mts
CHANGED
|
@@ -588,6 +588,7 @@ declare class TestdinoReporter implements Reporter {
|
|
|
588
588
|
private artifactsEnabled;
|
|
589
589
|
private initPromise;
|
|
590
590
|
private initFailed;
|
|
591
|
+
private pendingTestEndPromises;
|
|
591
592
|
constructor(config?: TestdinoConfig);
|
|
592
593
|
/**
|
|
593
594
|
* Load configuration from CLI temp file if available
|
|
@@ -622,9 +623,16 @@ declare class TestdinoReporter implements Reporter {
|
|
|
622
623
|
*/
|
|
623
624
|
onStepEnd(test: TestCase, result: TestResult, step: TestStep): Promise<void>;
|
|
624
625
|
/**
|
|
625
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Called after each test.
|
|
628
|
+
* Playwright does not await onTestEnd promises—pending work is awaited in onEnd.
|
|
629
|
+
*/
|
|
630
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
631
|
+
/**
|
|
632
|
+
* Process test end event asynchronously
|
|
633
|
+
* Uploads attachments and adds test:end event to buffer
|
|
626
634
|
*/
|
|
627
|
-
|
|
635
|
+
private processTestEnd;
|
|
628
636
|
/**
|
|
629
637
|
* Called after all tests complete
|
|
630
638
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -588,6 +588,7 @@ declare class TestdinoReporter implements Reporter {
|
|
|
588
588
|
private artifactsEnabled;
|
|
589
589
|
private initPromise;
|
|
590
590
|
private initFailed;
|
|
591
|
+
private pendingTestEndPromises;
|
|
591
592
|
constructor(config?: TestdinoConfig);
|
|
592
593
|
/**
|
|
593
594
|
* Load configuration from CLI temp file if available
|
|
@@ -622,9 +623,16 @@ declare class TestdinoReporter implements Reporter {
|
|
|
622
623
|
*/
|
|
623
624
|
onStepEnd(test: TestCase, result: TestResult, step: TestStep): Promise<void>;
|
|
624
625
|
/**
|
|
625
|
-
|
|
626
|
+
/**
|
|
627
|
+
* Called after each test.
|
|
628
|
+
* Playwright does not await onTestEnd promises—pending work is awaited in onEnd.
|
|
629
|
+
*/
|
|
630
|
+
onTestEnd(test: TestCase, result: TestResult): void;
|
|
631
|
+
/**
|
|
632
|
+
* Process test end event asynchronously
|
|
633
|
+
* Uploads attachments and adds test:end event to buffer
|
|
626
634
|
*/
|
|
627
|
-
|
|
635
|
+
private processTestEnd;
|
|
628
636
|
/**
|
|
629
637
|
* Called after all tests complete
|
|
630
638
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1741,6 +1741,8 @@ var TestdinoReporter = class {
|
|
|
1741
1741
|
// Deferred initialization - resolves true on success, false on failure
|
|
1742
1742
|
initPromise = null;
|
|
1743
1743
|
initFailed = false;
|
|
1744
|
+
// Promises for onTestEnd; must be awaited in onEnd to prevent data loss
|
|
1745
|
+
pendingTestEndPromises = /* @__PURE__ */ new Set();
|
|
1744
1746
|
constructor(config = {}) {
|
|
1745
1747
|
const cliConfig = this.loadCliConfig();
|
|
1746
1748
|
this.config = { ...config, ...cliConfig };
|
|
@@ -2025,43 +2027,63 @@ var TestdinoReporter = class {
|
|
|
2025
2027
|
await this.buffer.add(event);
|
|
2026
2028
|
}
|
|
2027
2029
|
/**
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2030
|
+
/**
|
|
2031
|
+
* Called after each test.
|
|
2032
|
+
* Playwright does not await onTestEnd promises—pending work is awaited in onEnd.
|
|
2033
|
+
*/
|
|
2034
|
+
onTestEnd(test, result) {
|
|
2031
2035
|
if (!this.initPromise || this.initFailed) return;
|
|
2032
|
-
const
|
|
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
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2036
|
+
const workPromise = this.processTestEnd(test, result);
|
|
2037
|
+
this.pendingTestEndPromises.add(workPromise);
|
|
2038
|
+
workPromise.finally(() => {
|
|
2039
|
+
this.pendingTestEndPromises.delete(workPromise);
|
|
2040
|
+
});
|
|
2041
|
+
}
|
|
2042
|
+
/**
|
|
2043
|
+
* Process test end event asynchronously
|
|
2044
|
+
* Uploads attachments and adds test:end event to buffer
|
|
2045
|
+
*/
|
|
2046
|
+
async processTestEnd(test, result) {
|
|
2047
|
+
try {
|
|
2048
|
+
const attachmentsWithUrls = await this.uploadAttachments(result.attachments, test.id);
|
|
2049
|
+
const event = {
|
|
2050
|
+
type: "test:end",
|
|
2051
|
+
runId: this.runId,
|
|
2052
|
+
...this.getEventMetadata(),
|
|
2053
|
+
// Test Identification
|
|
2054
|
+
testId: test.id,
|
|
2055
|
+
// Status Information
|
|
2056
|
+
status: result.status,
|
|
2057
|
+
outcome: test.outcome(),
|
|
2058
|
+
// Timing
|
|
2059
|
+
duration: result.duration,
|
|
2060
|
+
// Execution Context
|
|
2061
|
+
retry: result.retry,
|
|
2062
|
+
// Worker Information
|
|
2063
|
+
workerIndex: result.workerIndex,
|
|
2064
|
+
parallelIndex: result.parallelIndex,
|
|
2065
|
+
// Test Metadata
|
|
2066
|
+
annotations: test.annotations.map((a) => ({
|
|
2067
|
+
type: a.type,
|
|
2068
|
+
description: a.description
|
|
2069
|
+
})),
|
|
2070
|
+
// Error Information
|
|
2071
|
+
errors: result.errors.map((e) => this.extractError(e)).filter((e) => e !== void 0),
|
|
2072
|
+
// Step Summary
|
|
2073
|
+
steps: this.extractTestStepsSummary(result),
|
|
2074
|
+
// Attachments Metadata (with Azure URLs when uploaded)
|
|
2075
|
+
attachments: attachmentsWithUrls,
|
|
2076
|
+
// Console Output
|
|
2077
|
+
stdout: result.stdout.length > 0 ? this.extractConsoleOutput(result.stdout) : void 0,
|
|
2078
|
+
stderr: result.stderr.length > 0 ? this.extractConsoleOutput(result.stderr) : void 0
|
|
2079
|
+
};
|
|
2080
|
+
await this.buffer.add(event);
|
|
2081
|
+
} catch (error) {
|
|
2082
|
+
console.error(
|
|
2083
|
+
"\u274C TestDino: Failed to process test:end event:",
|
|
2084
|
+
error instanceof Error ? error.message : String(error)
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2065
2087
|
}
|
|
2066
2088
|
/**
|
|
2067
2089
|
* Called after all tests complete
|
|
@@ -2077,10 +2099,17 @@ var TestdinoReporter = class {
|
|
|
2077
2099
|
const success = await this.initPromise;
|
|
2078
2100
|
if (!success) {
|
|
2079
2101
|
this.buffer?.clear();
|
|
2102
|
+
this.pendingTestEndPromises.clear();
|
|
2080
2103
|
this.wsClient?.close();
|
|
2081
2104
|
this.removeSignalHandlers();
|
|
2082
2105
|
return;
|
|
2083
2106
|
}
|
|
2107
|
+
if (this.pendingTestEndPromises.size > 0) {
|
|
2108
|
+
if (this.config.debug) {
|
|
2109
|
+
console.log(`\u{1F50D} TestDino: Waiting for ${this.pendingTestEndPromises.size} pending test:end events...`);
|
|
2110
|
+
}
|
|
2111
|
+
await Promise.allSettled(Array.from(this.pendingTestEndPromises));
|
|
2112
|
+
}
|
|
2084
2113
|
const event = {
|
|
2085
2114
|
type: "run:end",
|
|
2086
2115
|
runId: this.runId,
|
|
@@ -2545,6 +2574,17 @@ var TestdinoReporter = class {
|
|
|
2545
2574
|
if (!this.initPromise) {
|
|
2546
2575
|
process.exit(exitCode);
|
|
2547
2576
|
}
|
|
2577
|
+
const waitForPending = async () => {
|
|
2578
|
+
if (this.pendingTestEndPromises.size > 0) {
|
|
2579
|
+
try {
|
|
2580
|
+
await Promise.race([
|
|
2581
|
+
Promise.allSettled(Array.from(this.pendingTestEndPromises)),
|
|
2582
|
+
this.timeoutPromise(500, "Pending events timeout")
|
|
2583
|
+
]);
|
|
2584
|
+
} catch {
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
};
|
|
2548
2588
|
const event = {
|
|
2549
2589
|
type: "run:end",
|
|
2550
2590
|
runId: this.runId,
|
|
@@ -2564,6 +2604,7 @@ var TestdinoReporter = class {
|
|
|
2564
2604
|
}, 3e3);
|
|
2565
2605
|
const sendAndExit = async () => {
|
|
2566
2606
|
try {
|
|
2607
|
+
await waitForPending();
|
|
2567
2608
|
await Promise.race([this.sendInterruptionEvent(event), this.timeoutPromise(2500, "Send timeout")]);
|
|
2568
2609
|
console.log("\u2705 TestDino: Interruption event sent");
|
|
2569
2610
|
} catch (error) {
|