@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/dist/index.mjs CHANGED
@@ -1734,6 +1734,8 @@ var TestdinoReporter = class {
1734
1734
  // Deferred initialization - resolves true on success, false on failure
1735
1735
  initPromise = null;
1736
1736
  initFailed = false;
1737
+ // Promises for onTestEnd; must be awaited in onEnd to prevent data loss
1738
+ pendingTestEndPromises = /* @__PURE__ */ new Set();
1737
1739
  constructor(config = {}) {
1738
1740
  const cliConfig = this.loadCliConfig();
1739
1741
  this.config = { ...config, ...cliConfig };
@@ -2018,43 +2020,63 @@ var TestdinoReporter = class {
2018
2020
  await this.buffer.add(event);
2019
2021
  }
2020
2022
  /**
2021
- * Called after each test completes
2022
- */
2023
- async onTestEnd(test, result) {
2023
+ /**
2024
+ * Called after each test.
2025
+ * Playwright does not await onTestEnd promises—pending work is awaited in onEnd.
2026
+ */
2027
+ onTestEnd(test, result) {
2024
2028
  if (!this.initPromise || this.initFailed) return;
2025
- const attachmentsWithUrls = await this.uploadAttachments(result.attachments, test.id);
2026
- const event = {
2027
- type: "test:end",
2028
- runId: this.runId,
2029
- ...this.getEventMetadata(),
2030
- // Test Identification
2031
- testId: test.id,
2032
- // Status Information
2033
- status: result.status,
2034
- outcome: test.outcome(),
2035
- // Timing
2036
- duration: result.duration,
2037
- // Execution Context
2038
- retry: result.retry,
2039
- // Worker Information
2040
- workerIndex: result.workerIndex,
2041
- parallelIndex: result.parallelIndex,
2042
- // Test Metadata
2043
- annotations: test.annotations.map((a) => ({
2044
- type: a.type,
2045
- description: a.description
2046
- })),
2047
- // Error Information
2048
- errors: result.errors.map((e) => this.extractError(e)).filter((e) => e !== void 0),
2049
- // Step Summary
2050
- steps: this.extractTestStepsSummary(result),
2051
- // Attachments Metadata (with Azure URLs when uploaded)
2052
- attachments: attachmentsWithUrls,
2053
- // Console Output
2054
- stdout: result.stdout.length > 0 ? this.extractConsoleOutput(result.stdout) : void 0,
2055
- stderr: result.stderr.length > 0 ? this.extractConsoleOutput(result.stderr) : void 0
2056
- };
2057
- await this.buffer.add(event);
2029
+ const workPromise = this.processTestEnd(test, result);
2030
+ this.pendingTestEndPromises.add(workPromise);
2031
+ workPromise.finally(() => {
2032
+ this.pendingTestEndPromises.delete(workPromise);
2033
+ });
2034
+ }
2035
+ /**
2036
+ * Process test end event asynchronously
2037
+ * Uploads attachments and adds test:end event to buffer
2038
+ */
2039
+ async processTestEnd(test, result) {
2040
+ try {
2041
+ const attachmentsWithUrls = await this.uploadAttachments(result.attachments, test.id);
2042
+ const event = {
2043
+ type: "test:end",
2044
+ runId: this.runId,
2045
+ ...this.getEventMetadata(),
2046
+ // Test Identification
2047
+ testId: test.id,
2048
+ // Status Information
2049
+ status: result.status,
2050
+ outcome: test.outcome(),
2051
+ // Timing
2052
+ duration: result.duration,
2053
+ // Execution Context
2054
+ retry: result.retry,
2055
+ // Worker Information
2056
+ workerIndex: result.workerIndex,
2057
+ parallelIndex: result.parallelIndex,
2058
+ // Test Metadata
2059
+ annotations: test.annotations.map((a) => ({
2060
+ type: a.type,
2061
+ description: a.description
2062
+ })),
2063
+ // Error Information
2064
+ errors: result.errors.map((e) => this.extractError(e)).filter((e) => e !== void 0),
2065
+ // Step Summary
2066
+ steps: this.extractTestStepsSummary(result),
2067
+ // Attachments Metadata (with Azure URLs when uploaded)
2068
+ attachments: attachmentsWithUrls,
2069
+ // Console Output
2070
+ stdout: result.stdout.length > 0 ? this.extractConsoleOutput(result.stdout) : void 0,
2071
+ stderr: result.stderr.length > 0 ? this.extractConsoleOutput(result.stderr) : void 0
2072
+ };
2073
+ await this.buffer.add(event);
2074
+ } catch (error) {
2075
+ console.error(
2076
+ "\u274C TestDino: Failed to process test:end event:",
2077
+ error instanceof Error ? error.message : String(error)
2078
+ );
2079
+ }
2058
2080
  }
2059
2081
  /**
2060
2082
  * Called after all tests complete
@@ -2070,10 +2092,17 @@ var TestdinoReporter = class {
2070
2092
  const success = await this.initPromise;
2071
2093
  if (!success) {
2072
2094
  this.buffer?.clear();
2095
+ this.pendingTestEndPromises.clear();
2073
2096
  this.wsClient?.close();
2074
2097
  this.removeSignalHandlers();
2075
2098
  return;
2076
2099
  }
2100
+ if (this.pendingTestEndPromises.size > 0) {
2101
+ if (this.config.debug) {
2102
+ console.log(`\u{1F50D} TestDino: Waiting for ${this.pendingTestEndPromises.size} pending test:end events...`);
2103
+ }
2104
+ await Promise.allSettled(Array.from(this.pendingTestEndPromises));
2105
+ }
2077
2106
  const event = {
2078
2107
  type: "run:end",
2079
2108
  runId: this.runId,
@@ -2538,6 +2567,17 @@ var TestdinoReporter = class {
2538
2567
  if (!this.initPromise) {
2539
2568
  process.exit(exitCode);
2540
2569
  }
2570
+ const waitForPending = async () => {
2571
+ if (this.pendingTestEndPromises.size > 0) {
2572
+ try {
2573
+ await Promise.race([
2574
+ Promise.allSettled(Array.from(this.pendingTestEndPromises)),
2575
+ this.timeoutPromise(500, "Pending events timeout")
2576
+ ]);
2577
+ } catch {
2578
+ }
2579
+ }
2580
+ };
2541
2581
  const event = {
2542
2582
  type: "run:end",
2543
2583
  runId: this.runId,
@@ -2557,6 +2597,7 @@ var TestdinoReporter = class {
2557
2597
  }, 3e3);
2558
2598
  const sendAndExit = async () => {
2559
2599
  try {
2600
+ await waitForPending();
2560
2601
  await Promise.race([this.sendInterruptionEvent(event), this.timeoutPromise(2500, "Send timeout")]);
2561
2602
  console.log("\u2705 TestDino: Interruption event sent");
2562
2603
  } catch (error) {