@stanterprise/playwright-reporter 0.0.20 → 0.1.0

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.
@@ -1,10 +1,16 @@
1
1
  import { StanterpriseReporterOptions } from "../types";
2
2
  import * as grpc from "@grpc/grpc-js";
3
+ import { MessageQueue } from "./messageQueue";
3
4
  export default function getClient(options: StanterpriseReporterOptions): grpc.Client | null;
4
5
  /**
5
- * Helper: generic unary call using raw method path with retry support
6
+ * Helper: generic unary call using raw method path with retry support.
7
+ *
8
+ * When a `queue` is provided the call is enqueued and executed only after all
9
+ * previously enqueued calls have completed, guaranteeing sequential delivery to
10
+ * the server. Without a queue the call is executed immediately (legacy / test
11
+ * behaviour).
6
12
  */
7
- export declare function reportUnary(options: StanterpriseReporterOptions, grpcClient: grpc.Client, path: string, message: {
13
+ export declare function reportUnary(options: StanterpriseReporterOptions, grpcClient: grpc.Client, grpcPath: string, message: {
8
14
  serialize?: (w?: any) => Uint8Array;
9
15
  serializeBinary?: () => Uint8Array;
10
- }, deadlineMs?: number): Promise<Buffer>;
16
+ }, deadlineMs?: number, queue?: MessageQueue): Promise<Buffer>;
@@ -146,13 +146,24 @@ async function attemptWithRetries(options, grpcClient, path, message, deadlineMs
146
146
  throw lastError || new Error("Retry loop exhausted without result");
147
147
  }
148
148
  /**
149
- * Helper: generic unary call using raw method path with retry support
149
+ * Helper: generic unary call using raw method path with retry support.
150
+ *
151
+ * When a `queue` is provided the call is enqueued and executed only after all
152
+ * previously enqueued calls have completed, guaranteeing sequential delivery to
153
+ * the server. Without a queue the call is executed immediately (legacy / test
154
+ * behaviour).
150
155
  */
151
- async function reportUnary(options, grpcClient, path, message, deadlineMs = 1000) {
156
+ async function reportUnary(options, grpcClient, grpcPath, message, deadlineMs = 1000, queue) {
152
157
  if (!options.grpcEnabled || !grpcClient) {
153
158
  return Buffer.alloc(0);
154
159
  }
155
- await (0, debugLogger_1.writeDebugEntry)(options, path, message);
156
- const maxRetries = options.grpcMaxRetries ?? 3;
157
- return attemptWithRetries(options, grpcClient, path, message, deadlineMs, maxRetries);
160
+ const execute = async () => {
161
+ await (0, debugLogger_1.writeDebugEntry)(options, grpcPath, message);
162
+ const maxRetries = options.grpcMaxRetries ?? 3;
163
+ return attemptWithRetries(options, grpcClient, grpcPath, message, deadlineMs, maxRetries);
164
+ };
165
+ if (queue) {
166
+ return queue.enqueue(execute);
167
+ }
168
+ return execute();
158
169
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A sequential async message queue that processes enqueued tasks one at a time,
3
+ * guaranteeing that each task completes before the next one begins.
4
+ *
5
+ * This ensures that gRPC messages are delivered to the server in the exact order
6
+ * they were enqueued, regardless of how quickly each individual call completes.
7
+ * It also serializes debug file writes as a side effect, since those are performed
8
+ * inside each task.
9
+ */
10
+ export declare class MessageQueue {
11
+ private tasks;
12
+ private processing;
13
+ private drainResolvers;
14
+ /**
15
+ * Adds a task to the queue and returns a Promise that resolves (or rejects)
16
+ * when the task has been executed. If the queue is idle the task starts
17
+ * immediately; otherwise it waits for all preceding tasks to finish first.
18
+ */
19
+ enqueue<T>(fn: () => Promise<T>): Promise<T>;
20
+ /**
21
+ * Returns a Promise that resolves once the queue has been fully drained
22
+ * (i.e. all currently enqueued tasks have finished). Resolves immediately
23
+ * if the queue is already empty.
24
+ */
25
+ drain(): Promise<void>;
26
+ private processNext;
27
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageQueue = void 0;
4
+ /**
5
+ * A sequential async message queue that processes enqueued tasks one at a time,
6
+ * guaranteeing that each task completes before the next one begins.
7
+ *
8
+ * This ensures that gRPC messages are delivered to the server in the exact order
9
+ * they were enqueued, regardless of how quickly each individual call completes.
10
+ * It also serializes debug file writes as a side effect, since those are performed
11
+ * inside each task.
12
+ */
13
+ class MessageQueue {
14
+ constructor() {
15
+ this.tasks = [];
16
+ this.processing = false;
17
+ this.drainResolvers = [];
18
+ }
19
+ /**
20
+ * Adds a task to the queue and returns a Promise that resolves (or rejects)
21
+ * when the task has been executed. If the queue is idle the task starts
22
+ * immediately; otherwise it waits for all preceding tasks to finish first.
23
+ */
24
+ enqueue(fn) {
25
+ return new Promise((resolve, reject) => {
26
+ this.tasks.push(async () => {
27
+ try {
28
+ const result = await fn();
29
+ resolve(result);
30
+ }
31
+ catch (e) {
32
+ reject(e);
33
+ }
34
+ });
35
+ if (!this.processing) {
36
+ this.processNext();
37
+ }
38
+ });
39
+ }
40
+ /**
41
+ * Returns a Promise that resolves once the queue has been fully drained
42
+ * (i.e. all currently enqueued tasks have finished). Resolves immediately
43
+ * if the queue is already empty.
44
+ */
45
+ drain() {
46
+ if (!this.processing && this.tasks.length === 0) {
47
+ return Promise.resolve();
48
+ }
49
+ return new Promise((resolve) => {
50
+ this.drainResolvers.push(resolve);
51
+ });
52
+ }
53
+ async processNext() {
54
+ this.processing = true;
55
+ while (this.tasks.length > 0) {
56
+ const task = this.tasks.shift();
57
+ try {
58
+ await task();
59
+ }
60
+ catch {
61
+ // Each task's promise already carries the error to its caller.
62
+ // Errors must not stop the queue from processing subsequent tasks.
63
+ }
64
+ }
65
+ this.processing = false;
66
+ const resolvers = this.drainResolvers;
67
+ this.drainResolvers = [];
68
+ resolvers.forEach((r) => r());
69
+ }
70
+ }
71
+ exports.MessageQueue = MessageQueue;
@@ -2,4 +2,5 @@ import { FullConfig } from "@playwright/test";
2
2
  import { Suite } from "@playwright/test/reporter";
3
3
  import { StanterpriseReporterOptions } from "../types";
4
4
  import * as grpc from "@grpc/grpc-js";
5
- export declare function handleOnBeginEvent(config: FullConfig, suite: Suite, name: string, runId: string, client: grpc.Client, options: StanterpriseReporterOptions): void;
5
+ import { MessageQueue } from "../client/messageQueue";
6
+ export declare function handleOnBeginEvent(config: FullConfig, suite: Suite, name: string, runId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -6,7 +6,7 @@ const grpcClient_1 = require("../client/grpcClient");
6
6
  const entities_1 = require("@stanterprise/protobuf/testsystem/v1/entities");
7
7
  const utils_1 = require("../utils");
8
8
  const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
9
- function handleOnBeginEvent(config, suite, name, runId, client, options) {
9
+ function handleOnBeginEvent(config, suite, name, runId, client, options, queue) {
10
10
  // Report root suite and all child suites recursively
11
11
  // Convert all metadata values to strings for protobuf compatibility
12
12
  // Use plain object instead of Map - protobuf expects object literals
@@ -31,7 +31,7 @@ function handleOnBeginEvent(config, suite, name, runId, client, options) {
31
31
  total_tests: suite.allTests().length,
32
32
  metadata: (0, utils_1.toMetadataMap)(metadata),
33
33
  });
34
- (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportRunStart", request, options.grpcTimeout).catch((e) => {
34
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportRunStart", request, options.grpcTimeout, queue).catch((e) => {
35
35
  const details = e instanceof Error ? `${e.message}` : String(e);
36
36
  console.warn(`onBegin. gRPC disabled for the remainder of the run. Address=${options.grpcAddress}. Details: ${details}`);
37
37
  });
@@ -1,4 +1,5 @@
1
1
  import { FullResult } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnEndEvent(result: FullResult, runId: string, client: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnEndEvent(result: FullResult, runId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue, metadata?: Record<string, string>): void;
@@ -19,7 +19,7 @@ function mapTestStatus(status) {
19
19
  return common_1.TestStatus.UNKNOWN;
20
20
  }
21
21
  }
22
- function handleOnEndEvent(result, runId, client, options) {
22
+ function handleOnEndEvent(result, runId, client, options, queue, metadata) {
23
23
  // Validate and sanitize inputs to prevent serialization failures
24
24
  const startTimeMs = result.startTime?.getTime();
25
25
  const duration = result.duration;
@@ -35,8 +35,9 @@ function handleOnEndEvent(result, runId, client, options) {
35
35
  final_status: mapTestStatus(result.status),
36
36
  start_time: (0, utils_1.createTimestampFromMs)(validStartTimeMs),
37
37
  duration: (0, utils_1.createDuration)(validDuration),
38
+ metadata: (0, utils_1.toMetadataMap)(metadata || {}),
38
39
  });
39
- (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportRunEnd", request, options.grpcTimeout).catch((error) => {
40
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportRunEnd", request, options.grpcTimeout, queue).catch((error) => {
40
41
  if (error instanceof Error) {
41
42
  console.error(`Failed to report end event: ${error.message}`, {
42
43
  stack: error.stack,
@@ -1,4 +1,5 @@
1
1
  import { TestError } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnErrorEvent(error: TestError, runId: string, grpcClient: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnErrorEvent(error: TestError, runId: string, grpcClient: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -4,12 +4,12 @@ exports.handleOnErrorEvent = handleOnErrorEvent;
4
4
  const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
5
5
  const timeHelpers_1 = require("../utils/timeHelpers");
6
6
  const grpcClient_1 = require("../client/grpcClient");
7
- function handleOnErrorEvent(error, runId, grpcClient, options) {
7
+ function handleOnErrorEvent(error, runId, grpcClient, options, queue) {
8
8
  const request = new events_1.StdErrorEventRequest({
9
9
  run_id: runId,
10
10
  message: error.message,
11
11
  timestamp: (0, timeHelpers_1.createTimestampFromMs)(Date.now()),
12
12
  });
13
13
  // Fire-and-forget to avoid slowing tests
14
- (0, grpcClient_1.reportUnary)(options, grpcClient, "/testsystem.v1.observer.TestEventCollector/ReportStdError", request, options.grpcTimeout).catch((e) => console.error("Failed to report standard error", e));
14
+ (0, grpcClient_1.reportUnary)(options, grpcClient, "/testsystem.v1.observer.TestEventCollector/ReportStdError", request, options.grpcTimeout, queue).catch((e) => console.error("Failed to report standard error", e));
15
15
  }
@@ -1,4 +1,5 @@
1
1
  import { TestCase, TestResult, TestStep } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnStepBeginEvent(test: TestCase, result: TestResult, step: TestStep, runId: string, client: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnStepBeginEvent(test: TestCase, result: TestResult, step: TestStep, runId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -7,7 +7,7 @@ const utils_1 = require("../utils");
7
7
  const grpcClient_1 = require("../client/grpcClient");
8
8
  const utils_2 = require("../utils");
9
9
  const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
10
- function handleOnStepBeginEvent(test, result, step, runId, client, options) {
10
+ function handleOnStepBeginEvent(test, result, step, runId, client, options, queue) {
11
11
  // Build metadata from step annotations
12
12
  const metadata = (0, utils_1.buildStepMetadata)(step);
13
13
  // Get parent step ID if this step has a parent
@@ -34,5 +34,5 @@ function handleOnStepBeginEvent(test, result, step, runId, client, options) {
34
34
  }),
35
35
  });
36
36
  // Fire-and-forget to avoid slowing tests
37
- (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportStepBegin", request, options.grpcTimeout).catch((e) => console.error("Failed to report step begin", e));
37
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportStepBegin", request, options.grpcTimeout, queue).catch((e) => console.error("Failed to report step begin", e));
38
38
  }
@@ -1,4 +1,5 @@
1
1
  import { TestCase, TestResult, TestStep } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnStepEndEvent(test: TestCase, result: TestResult, step: TestStep, runId: string, client: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnStepEndEvent(test: TestCase, result: TestResult, step: TestStep, runId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -6,7 +6,7 @@ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
6
  const utils_1 = require("../utils");
7
7
  const grpcClient_1 = require("../client/grpcClient");
8
8
  const utils_2 = require("../utils");
9
- function handleOnStepEndEvent(test, result, step, runId, client, options) {
9
+ function handleOnStepEndEvent(test, result, step, runId, client, options, queue) {
10
10
  // Map step error to status
11
11
  const stepStatus = (0, utils_1.mapStepStatus)(!!step.error);
12
12
  // Build metadata from step annotations
@@ -55,5 +55,5 @@ function handleOnStepEndEvent(test, result, step, runId, client, options) {
55
55
  }),
56
56
  });
57
57
  // Fire-and-forget to avoid slowing tests
58
- (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportStepEnd", request, options.grpcTimeout).catch((e) => console.error("Failed to report step end", e));
58
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportStepEnd", request, options.grpcTimeout, queue).catch((e) => console.error("Failed to report step end", e));
59
59
  }
@@ -1,4 +1,5 @@
1
1
  import { TestCase, TestResult } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnTestBeginEvent(test: TestCase, result: TestResult, runId: string, client: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnTestBeginEvent(test: TestCase, result: TestResult, runId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -6,7 +6,7 @@ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
6
  const utils_1 = require("../utils");
7
7
  const grpcClient_1 = require("../client/grpcClient");
8
8
  const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
9
- function handleOnTestBeginEvent(test, result, runId, client, options) {
9
+ function handleOnTestBeginEvent(test, result, runId, client, options, queue) {
10
10
  // Build and send the TestBegin event via generic unary call.
11
11
  const request = new events_1.TestBeginEventRequest({
12
12
  test_case: new entities_1.TestCaseRun({
@@ -25,7 +25,7 @@ function handleOnTestBeginEvent(test, result, runId, client, options) {
25
25
  }),
26
26
  });
27
27
  // Fire-and-forget to avoid slowing tests; log errors once.
28
- (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportTestBegin", request, options.grpcTimeout).catch((e) => {
28
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportTestBegin", request, options.grpcTimeout, queue).catch((e) => {
29
29
  const details = e instanceof Error ? `${e.message}` : String(e);
30
30
  console.warn(`Failed to report test begin. Details: ${details}`);
31
31
  });
@@ -1,4 +1,5 @@
1
1
  import { TestCase, TestResult } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnTestEndEvent(test: TestCase, result: TestResult, runId: string, client: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnTestEndEvent(test: TestCase, result: TestResult, runId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -10,7 +10,7 @@ const utils_2 = require("../utils");
10
10
  * Constant for converting bytes to megabytes
11
11
  */
12
12
  const BYTES_PER_MB = 1048576;
13
- function handleOnTestEndEvent(test, result, runId, client, options) {
13
+ function handleOnTestEndEvent(test, result, runId, client, options, queue) {
14
14
  // Map Playwright test status to protobuf TestStatus
15
15
  const testStatus = (0, utils_1.mapTestStatus)(result.status);
16
16
  // Process attachments (screenshots, videos, etc.)
@@ -51,7 +51,7 @@ function handleOnTestEndEvent(test, result, runId, client, options) {
51
51
  `Error length: ${errorMessage.length + stackTrace.length} bytes`);
52
52
  }
53
53
  // Fire-and-forget to avoid slowing tests
54
- (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportTestEnd", request, options.grpcTimeout).catch((e) => {
54
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportTestEnd", request, options.grpcTimeout, queue).catch((e) => {
55
55
  console.error(`Failed to report test end for "${test.title}" (payload size: ${(payloadSize / BYTES_PER_MB).toFixed(2)}MB)`, e);
56
56
  });
57
57
  }
@@ -1,4 +1,5 @@
1
1
  import { TestCase, TestResult } from "@playwright/test/reporter";
2
2
  import { StanterpriseReporterOptions } from "../types";
3
3
  import * as grpc from "@grpc/grpc-js";
4
- export declare function handleOnTestFailEvent(test: TestCase, result: TestResult, runId: string, grpcClient: grpc.Client, options: StanterpriseReporterOptions): void;
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnTestFailEvent(test: TestCase, result: TestResult, runId: string, grpcClient: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -4,7 +4,7 @@ exports.handleOnTestFailEvent = handleOnTestFailEvent;
4
4
  const utils_1 = require("../utils");
5
5
  const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
6
  const grpcClient_1 = require("../client/grpcClient");
7
- function handleOnTestFailEvent(test, result, runId, grpcClient, options) {
7
+ function handleOnTestFailEvent(test, result, runId, grpcClient, options, queue) {
8
8
  // Extract failure details
9
9
  const { errorMessage: failureMessage, stackTrace } = (0, utils_1.extractErrorInfo)(result);
10
10
  // Process attachments for failed tests
@@ -20,5 +20,5 @@ function handleOnTestFailEvent(test, result, runId, grpcClient, options) {
20
20
  retry_index: result.retry,
21
21
  });
22
22
  // Fire-and-forget to avoid slowing tests
23
- (0, grpcClient_1.reportUnary)(options, grpcClient, "/testsystem.v1.observer.TestEventCollector/ReportTestFailure", request, options.grpcTimeout).catch((e) => console.error("Failed to report test failure", e));
23
+ (0, grpcClient_1.reportUnary)(options, grpcClient, "/testsystem.v1.observer.TestEventCollector/ReportTestFailure", request, options.grpcTimeout, queue).catch((e) => console.error("Failed to report test failure", e));
24
24
  }
@@ -5,6 +5,8 @@ export default class StanterpriseReporter implements Reporter {
5
5
  private options;
6
6
  private runId;
7
7
  private runStartTime;
8
+ private messageQueue;
9
+ private metadata;
8
10
  constructor(options?: StanterpriseReporterOptions);
9
11
  onBegin(config: FullConfig, suite: Suite): void;
10
12
  onExit(): Promise<void>;
package/dist/reporter.js CHANGED
@@ -7,6 +7,7 @@ const crypto_1 = require("crypto");
7
7
  const optionsMapper_1 = __importDefault(require("./utils/optionsMapper"));
8
8
  const debugLogger_1 = require("./utils/debugLogger");
9
9
  const grpcClient_1 = __importDefault(require("./client/grpcClient"));
10
+ const messageQueue_1 = require("./client/messageQueue");
10
11
  const handlers_1 = require("./handlers");
11
12
  class StanterpriseReporter {
12
13
  constructor(options = {}) {
@@ -16,6 +17,9 @@ class StanterpriseReporter {
16
17
  // Generate a unique run ID for this test run
17
18
  this.runId = "";
18
19
  this.runStartTime = new Date();
20
+ // Sequential message queue – guarantees ordered delivery to the server
21
+ this.messageQueue = new messageQueue_1.MessageQueue();
22
+ this.metadata = {};
19
23
  this.options = (0, optionsMapper_1.default)(options);
20
24
  if (this.options.verbose) {
21
25
  console.log("Stanterprise Reporter: Initialized with options:", {
@@ -31,6 +35,10 @@ class StanterpriseReporter {
31
35
  (0, debugLogger_1.initDebugFile)(this.options);
32
36
  }
33
37
  onBegin(config, suite) {
38
+ if (config.shard) {
39
+ this.metadata["shard.current"] = String(config.shard.current);
40
+ this.metadata["shard.total"] = String(config.shard.total);
41
+ }
34
42
  // Lazily create the client if enabled.
35
43
  if (this.options.grpcEnabled) {
36
44
  this.grpcClient = (0, grpcClient_1.default)(this.options);
@@ -53,10 +61,12 @@ class StanterpriseReporter {
53
61
  }
54
62
  }
55
63
  if (this.options.grpcEnabled) {
56
- (0, handlers_1.handleOnBeginEvent)(config, suite, process.env.STANTERPRISE_TEST_RUN_NAME || "Playwright Test Run", this.runId, this.grpcClient, this.options);
64
+ (0, handlers_1.handleOnBeginEvent)(config, suite, process.env.STANTERPRISE_TEST_RUN_NAME || "Playwright Test Run", this.runId, this.grpcClient, this.options, this.messageQueue);
57
65
  }
58
66
  }
59
67
  async onExit() {
68
+ // Wait for all enqueued messages to be sent before closing the connection.
69
+ await this.messageQueue.drain();
60
70
  console.log(`Stanterprise Reporter: Test run completed - Run ID: ${this.runId}`);
61
71
  // Cleanup gRPC client
62
72
  try {
@@ -76,7 +86,7 @@ class StanterpriseReporter {
76
86
  console.log(`Playwright start time: ${result.startTime.toISOString()}`);
77
87
  }
78
88
  if (this.options.grpcEnabled) {
79
- (0, handlers_1.handleOnEndEvent)(result, this.runId, this.grpcClient, this.options);
89
+ (0, handlers_1.handleOnEndEvent)(result, this.runId, this.grpcClient, this.options, this.messageQueue, this.metadata);
80
90
  }
81
91
  return Promise.resolve();
82
92
  }
@@ -88,7 +98,7 @@ class StanterpriseReporter {
88
98
  console.log(` Test ID: ${test.id}`);
89
99
  }
90
100
  if (this.options.grpcEnabled) {
91
- (0, handlers_1.handleOnTestBeginEvent)(test, result, this.runId, this.grpcClient, this.options);
101
+ (0, handlers_1.handleOnTestBeginEvent)(test, result, this.runId, this.grpcClient, this.options, this.messageQueue);
92
102
  }
93
103
  }
94
104
  async onStepBegin(test, result, step) {
@@ -97,7 +107,7 @@ class StanterpriseReporter {
97
107
  console.log(` Category: ${step.category}`);
98
108
  }
99
109
  if (this.options.grpcEnabled) {
100
- (0, handlers_1.handleOnStepBeginEvent)(test, result, step, this.runId, this.grpcClient, this.options);
110
+ (0, handlers_1.handleOnStepBeginEvent)(test, result, step, this.runId, this.grpcClient, this.options, this.messageQueue);
101
111
  }
102
112
  }
103
113
  onStepEnd(test, result, step) {
@@ -106,7 +116,7 @@ class StanterpriseReporter {
106
116
  console.log(` Duration: ${step.duration}ms`);
107
117
  }
108
118
  if (this.options.grpcEnabled) {
109
- (0, handlers_1.handleOnStepEndEvent)(test, result, step, this.runId, this.grpcClient, this.options);
119
+ (0, handlers_1.handleOnStepEndEvent)(test, result, step, this.runId, this.grpcClient, this.options, this.messageQueue);
110
120
  }
111
121
  }
112
122
  onTestEnd(test, result) {
@@ -116,7 +126,7 @@ class StanterpriseReporter {
116
126
  console.log(` Duration: ${result.duration}ms`);
117
127
  }
118
128
  if (this.options.grpcEnabled) {
119
- (0, handlers_1.handleOnTestEndEvent)(test, result, this.runId, this.grpcClient, this.options);
129
+ (0, handlers_1.handleOnTestEndEvent)(test, result, this.runId, this.grpcClient, this.options, this.messageQueue);
120
130
  }
121
131
  }
122
132
  onTestFail(test, result) {
@@ -124,7 +134,7 @@ class StanterpriseReporter {
124
134
  console.log(`Stanterprise Reporter: Test failed - ${test.title}`);
125
135
  }
126
136
  if (this.options.grpcEnabled) {
127
- (0, handlers_1.handleOnTestFailEvent)(test, result, this.runId, this.grpcClient, this.options);
137
+ (0, handlers_1.handleOnTestFailEvent)(test, result, this.runId, this.grpcClient, this.options, this.messageQueue);
128
138
  }
129
139
  }
130
140
  onError(error) {
@@ -134,7 +144,7 @@ class StanterpriseReporter {
134
144
  console.error(`Stack trace: ${error.stack}`);
135
145
  }
136
146
  if (this.options.grpcEnabled) {
137
- (0, handlers_1.handleOnErrorEvent)(error, this.runId, this.grpcClient, this.options);
147
+ (0, handlers_1.handleOnErrorEvent)(error, this.runId, this.grpcClient, this.options, this.messageQueue);
138
148
  }
139
149
  }
140
150
  onStdErr(chunk, test, result) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stanterprise/playwright-reporter",
3
- "version": "0.0.20",
3
+ "version": "0.1.0",
4
4
  "description": "Custom Playwright test reporter that sends test results to Stanterprise via gRPC",
5
5
  "homepage": "https://github.com/stanterprise/stanterprise-playwright-reporter#readme",
6
6
  "bugs": {
@@ -53,6 +53,6 @@
53
53
  "@grpc/grpc-js": "^1.14.1",
54
54
  "@protobuf-ts/grpc-transport": "^2.11.1",
55
55
  "@protobuf-ts/grpcweb-transport": "^2.11.1",
56
- "@stanterprise/protobuf": "^0.0.21"
56
+ "@stanterprise/protobuf": "^0.1.1"
57
57
  }
58
58
  }