@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 CHANGED
@@ -121,11 +121,12 @@ npx playwright test
121
121
 
122
122
  ### TestDino Options
123
123
 
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 |
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
- * Called after each test completes
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
- onTestEnd(test: TestCase, result: TestResult): Promise<void>;
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
- * Called after each test completes
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
- onTestEnd(test: TestCase, result: TestResult): Promise<void>;
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
- * Called after each test completes
2029
- */
2030
- async onTestEnd(test, result) {
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 attachmentsWithUrls = await this.uploadAttachments(result.attachments, test.id);
2033
- const event = {
2034
- type: "test:end",
2035
- runId: this.runId,
2036
- ...this.getEventMetadata(),
2037
- // Test Identification
2038
- testId: test.id,
2039
- // Status Information
2040
- status: result.status,
2041
- outcome: test.outcome(),
2042
- // Timing
2043
- duration: result.duration,
2044
- // Execution Context
2045
- retry: result.retry,
2046
- // Worker Information
2047
- workerIndex: result.workerIndex,
2048
- parallelIndex: result.parallelIndex,
2049
- // Test Metadata
2050
- annotations: test.annotations.map((a) => ({
2051
- type: a.type,
2052
- description: a.description
2053
- })),
2054
- // Error Information
2055
- errors: result.errors.map((e) => this.extractError(e)).filter((e) => e !== void 0),
2056
- // Step Summary
2057
- steps: this.extractTestStepsSummary(result),
2058
- // Attachments Metadata (with Azure URLs when uploaded)
2059
- attachments: attachmentsWithUrls,
2060
- // Console Output
2061
- stdout: result.stdout.length > 0 ? this.extractConsoleOutput(result.stdout) : void 0,
2062
- stderr: result.stderr.length > 0 ? this.extractConsoleOutput(result.stderr) : void 0
2063
- };
2064
- await this.buffer.add(event);
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) {