@stanterprise/playwright-reporter 1.0.0 → 1.0.1

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.
Files changed (44) hide show
  1. package/README.md +261 -11
  2. package/dist/client/grpcClient.d.ts +16 -0
  3. package/dist/client/grpcClient.js +172 -0
  4. package/dist/client/messageQueue.d.ts +27 -0
  5. package/dist/client/messageQueue.js +71 -0
  6. package/dist/handlers/index.d.ts +9 -0
  7. package/dist/handlers/index.js +19 -0
  8. package/dist/handlers/onBeginHandler.d.ts +6 -0
  9. package/dist/handlers/onBeginHandler.js +98 -0
  10. package/dist/handlers/onEndHandler.d.ts +5 -0
  11. package/dist/handlers/onEndHandler.js +53 -0
  12. package/dist/handlers/onErrorHandler.d.ts +5 -0
  13. package/dist/handlers/onErrorHandler.js +16 -0
  14. package/dist/handlers/onStepBeginHandler.d.ts +5 -0
  15. package/dist/handlers/onStepBeginHandler.js +39 -0
  16. package/dist/handlers/onStepEndHandler.d.ts +5 -0
  17. package/dist/handlers/onStepEndHandler.js +62 -0
  18. package/dist/handlers/onTestBeginHandler.d.ts +5 -0
  19. package/dist/handlers/onTestBeginHandler.js +33 -0
  20. package/dist/handlers/onTestEndHandler.d.ts +5 -0
  21. package/dist/handlers/onTestEndHandler.js +58 -0
  22. package/dist/handlers/onTestFailHandler.d.ts +5 -0
  23. package/dist/handlers/onTestFailHandler.js +25 -0
  24. package/dist/reporter.d.ts +4 -15
  25. package/dist/reporter.js +97 -386
  26. package/dist/types.d.ts +56 -0
  27. package/dist/utils/attachmentProcessor.d.ts +6 -2
  28. package/dist/utils/attachmentProcessor.js +33 -4
  29. package/dist/utils/debugLogger.d.ts +13 -0
  30. package/dist/utils/debugLogger.js +87 -0
  31. package/dist/utils/envRetriever.d.ts +9 -0
  32. package/dist/utils/envRetriever.js +23 -0
  33. package/dist/utils/idGenerators.d.ts +20 -0
  34. package/dist/utils/idGenerators.js +40 -0
  35. package/dist/utils/index.d.ts +4 -0
  36. package/dist/utils/index.js +4 -0
  37. package/dist/utils/metadataHelpers.d.ts +42 -0
  38. package/dist/utils/metadataHelpers.js +91 -0
  39. package/dist/utils/optionsMapper.d.ts +7 -0
  40. package/dist/utils/optionsMapper.js +51 -0
  41. package/dist/utils/statusMapper.js +7 -6
  42. package/dist/utils/timeHelpers.d.ts +5 -5
  43. package/dist/utils/timeHelpers.js +24 -8
  44. package/package.json +6 -7
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnErrorEvent = exports.handleOnTestFailEvent = exports.handleOnTestEndEvent = exports.handleOnTestBeginEvent = exports.handleOnStepEndEvent = exports.handleOnStepBeginEvent = exports.handleOnEndEvent = exports.handleOnBeginEvent = void 0;
4
+ const onBeginHandler_1 = require("./onBeginHandler");
5
+ Object.defineProperty(exports, "handleOnBeginEvent", { enumerable: true, get: function () { return onBeginHandler_1.handleOnBeginEvent; } });
6
+ const onEndHandler_1 = require("./onEndHandler");
7
+ Object.defineProperty(exports, "handleOnEndEvent", { enumerable: true, get: function () { return onEndHandler_1.handleOnEndEvent; } });
8
+ const onStepBeginHandler_1 = require("./onStepBeginHandler");
9
+ Object.defineProperty(exports, "handleOnStepBeginEvent", { enumerable: true, get: function () { return onStepBeginHandler_1.handleOnStepBeginEvent; } });
10
+ const onStepEndHandler_1 = require("./onStepEndHandler");
11
+ Object.defineProperty(exports, "handleOnStepEndEvent", { enumerable: true, get: function () { return onStepEndHandler_1.handleOnStepEndEvent; } });
12
+ const onTestBeginHandler_1 = require("./onTestBeginHandler");
13
+ Object.defineProperty(exports, "handleOnTestBeginEvent", { enumerable: true, get: function () { return onTestBeginHandler_1.handleOnTestBeginEvent; } });
14
+ const onTestEndHandler_1 = require("./onTestEndHandler");
15
+ Object.defineProperty(exports, "handleOnTestEndEvent", { enumerable: true, get: function () { return onTestEndHandler_1.handleOnTestEndEvent; } });
16
+ const onTestFailHandler_1 = require("./onTestFailHandler");
17
+ Object.defineProperty(exports, "handleOnTestFailEvent", { enumerable: true, get: function () { return onTestFailHandler_1.handleOnTestFailEvent; } });
18
+ const onErrorHandler_1 = require("./onErrorHandler");
19
+ Object.defineProperty(exports, "handleOnErrorEvent", { enumerable: true, get: function () { return onErrorHandler_1.handleOnErrorEvent; } });
@@ -0,0 +1,6 @@
1
+ import { FullConfig } from "@playwright/test";
2
+ import { Suite } from "@playwright/test/reporter";
3
+ import { StanterpriseReporterOptions } from "../types";
4
+ import * as grpc from "@grpc/grpc-js";
5
+ import { MessageQueue } from "../client/messageQueue";
6
+ export declare function handleOnBeginEvent(config: FullConfig, suite: Suite, name: string, runId: string, executionId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnBeginEvent = handleOnBeginEvent;
4
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
5
+ const grpcClient_1 = require("../client/grpcClient");
6
+ const entities_1 = require("@stanterprise/protobuf/testsystem/v1/entities");
7
+ const utils_1 = require("../utils");
8
+ const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
9
+ function handleOnBeginEvent(config, suite, name, runId, executionId, client, options, queue) {
10
+ // Report root suite and all child suites recursively
11
+ // Convert all metadata values to strings for protobuf compatibility
12
+ // Use plain object instead of Map - protobuf expects object literals
13
+ const metadata = {};
14
+ Object.entries(config.metadata || {}).forEach(([key, value]) => {
15
+ metadata[key] = String(value);
16
+ });
17
+ const variables = (0, utils_1.getEnvVariables)();
18
+ // Merge environment variables into metadata
19
+ variables.forEach((value, key) => {
20
+ metadata[key] = value;
21
+ });
22
+ // Add shard information if present
23
+ if (config.shard) {
24
+ metadata["shard.current"] = String(config.shard.current);
25
+ metadata["shard.total"] = String(config.shard.total);
26
+ }
27
+ const request = new events_1.ReportRunStartEventRequest({
28
+ run_id: runId,
29
+ execution_id: executionId,
30
+ name: name,
31
+ test_suites: mapSuites(suite, runId, executionId),
32
+ total_tests: suite.allTests().length,
33
+ metadata: (0, utils_1.toMetadataMap)(metadata),
34
+ });
35
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportRunStart", request, options.grpcTimeout, queue).catch((e) => {
36
+ const details = e instanceof Error ? `${e.message}` : String(e);
37
+ console.warn(`onBegin. gRPC disabled for the remainder of the run. Address=${options.grpcAddress}. Details: ${details}`);
38
+ });
39
+ }
40
+ function mapSuites(suite, runId, executionId) {
41
+ let allSuites = getAllSuites(suite);
42
+ return allSuites.map((currentSuite) => mapSingleSuite(currentSuite, runId, executionId));
43
+ }
44
+ function getAllSuites(suite) {
45
+ let suites = [];
46
+ suites.push(suite);
47
+ suite.suites.forEach((childSuite) => {
48
+ suites = suites.concat(getAllSuites(childSuite));
49
+ });
50
+ return suites;
51
+ }
52
+ function mapSingleSuite(suite, runId, executionId) {
53
+ const suiteId = (0, utils_1.generateSuiteId)(suite);
54
+ const parentSuiteId = suite.parent
55
+ ? (0, utils_1.generateSuiteId)(suite.parent)
56
+ : undefined;
57
+ let type;
58
+ switch (suite.type) {
59
+ case "root":
60
+ type = entities_1.SuiteType.ROOT;
61
+ break;
62
+ case "describe":
63
+ type = entities_1.SuiteType.SUBSUITE;
64
+ break;
65
+ case "file":
66
+ type = entities_1.SuiteType.FILE;
67
+ break;
68
+ case "project":
69
+ type = entities_1.SuiteType.PROJECT;
70
+ break;
71
+ }
72
+ return new entities_1.TestSuiteRun({
73
+ id: suiteId,
74
+ name: suite.title,
75
+ run_id: runId,
76
+ parent_suite_id: parentSuiteId,
77
+ status: common_1.TestStatus.NOT_RUN,
78
+ test_cases: suite.tests.map((test) => new entities_1.TestCaseRun({
79
+ id: test.id,
80
+ name: test.title,
81
+ run_id: runId,
82
+ test_suite_id: suiteId,
83
+ tags: test.tags,
84
+ location: test.location
85
+ ? `${test.location.file}:${test.location.line}:${test.location.column}`
86
+ : undefined,
87
+ status: common_1.TestStatus.NOT_RUN,
88
+ retry_count: test.retries,
89
+ retry_index: 0,
90
+ execution_id: executionId,
91
+ })),
92
+ test_case_ids: suite.tests.map((test) => test.id),
93
+ type: type,
94
+ location: suite.location
95
+ ? `${suite.location.file}:${suite.location.line}:${suite.location.column}`
96
+ : undefined,
97
+ });
98
+ }
@@ -0,0 +1,5 @@
1
+ import { FullResult } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnEndEvent(result: FullResult, runId: string, executionId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue, metadata?: Record<string, string>): void;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnEndEvent = handleOnEndEvent;
4
+ const grpcClient_1 = require("../client/grpcClient");
5
+ const utils_1 = require("../utils");
6
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
7
+ const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
8
+ function mapTestStatus(status) {
9
+ switch (status) {
10
+ case "passed":
11
+ return common_1.TestStatus.PASSED;
12
+ case "failed":
13
+ return common_1.TestStatus.FAILED;
14
+ case "timedout":
15
+ return common_1.TestStatus.TIMEDOUT;
16
+ case "interrupted":
17
+ return common_1.TestStatus.INTERRUPTED;
18
+ default:
19
+ return common_1.TestStatus.UNKNOWN;
20
+ }
21
+ }
22
+ function handleOnEndEvent(result, runId, executionId, client, options, queue, metadata) {
23
+ // Validate and sanitize inputs to prevent serialization failures
24
+ const startTimeMs = result.startTime?.getTime();
25
+ const duration = result.duration;
26
+ // Ensure valid numeric values (protobuf cannot serialize NaN or undefined)
27
+ const validStartTimeMs = typeof startTimeMs === "number" && !isNaN(startTimeMs)
28
+ ? startTimeMs
29
+ : Date.now();
30
+ const validDuration = typeof duration === "number" && !isNaN(duration) && duration >= 0
31
+ ? duration
32
+ : 0;
33
+ const request = new events_1.TestRunEndEventRequest({
34
+ run_id: runId,
35
+ final_status: mapTestStatus(result.status),
36
+ start_time: (0, utils_1.createTimestampFromMs)(validStartTimeMs),
37
+ duration: (0, utils_1.createDuration)(validDuration),
38
+ metadata: (0, utils_1.toMetadataMap)(metadata || {}),
39
+ execution_id: executionId,
40
+ });
41
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportRunEnd", request, options.grpcTimeout, queue).catch((error) => {
42
+ if (error instanceof Error) {
43
+ console.error(`Failed to report end event: ${error.message}`, {
44
+ stack: error.stack,
45
+ });
46
+ }
47
+ else {
48
+ console.error("Failed to report end event: Unknown error type", {
49
+ error,
50
+ });
51
+ }
52
+ });
53
+ }
@@ -0,0 +1,5 @@
1
+ import { TestError } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnErrorEvent(error: TestError, runId: string, executionId: string, grpcClient: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnErrorEvent = handleOnErrorEvent;
4
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
5
+ const timeHelpers_1 = require("../utils/timeHelpers");
6
+ const grpcClient_1 = require("../client/grpcClient");
7
+ function handleOnErrorEvent(error, runId, executionId, grpcClient, options, queue) {
8
+ const request = new events_1.StdErrorEventRequest({
9
+ run_id: runId,
10
+ message: error.message,
11
+ timestamp: (0, timeHelpers_1.createTimestampFromMs)(Date.now()),
12
+ execution_id: executionId,
13
+ });
14
+ // Fire-and-forget to avoid slowing tests
15
+ (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));
16
+ }
@@ -0,0 +1,5 @@
1
+ import { TestCase, TestResult, TestStep } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnStepBeginEvent(test: TestCase, result: TestResult, step: TestStep, runId: string, executionId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnStepBeginEvent = handleOnStepBeginEvent;
4
+ const entities_1 = require("@stanterprise/protobuf/testsystem/v1/entities");
5
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
+ const utils_1 = require("../utils");
7
+ const grpcClient_1 = require("../client/grpcClient");
8
+ const utils_2 = require("../utils");
9
+ const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
10
+ function handleOnStepBeginEvent(test, result, step, runId, executionId, client, options, queue) {
11
+ // Build metadata from step annotations
12
+ const metadata = (0, utils_1.buildStepMetadata)(step);
13
+ // Get parent step ID if this step has a parent
14
+ const stepId = (0, utils_2.generateStepId)(step, test);
15
+ // Build and send the StepBegin event
16
+ const request = new events_1.StepBeginEventRequest({
17
+ step: new entities_1.StepRun({
18
+ id: stepId,
19
+ run_id: runId,
20
+ test_case_id: test.id,
21
+ title: step.title,
22
+ status: common_1.TestStatus.RUNNING,
23
+ type: step.category,
24
+ start_time: (0, utils_1.createTimestamp)(step.startTime),
25
+ location: step.location
26
+ ? `${step.location.file}:${step.location.line}:${step.location.column}`
27
+ : undefined,
28
+ metadata: (0, utils_1.toMetadataMap)(metadata),
29
+ parent_step_id: step.parent
30
+ ? (0, utils_2.generateStepId)(step.parent, test)
31
+ : undefined,
32
+ worker_index: result.workerIndex.toString(),
33
+ retry_index: result.retry,
34
+ execution_id: executionId,
35
+ }),
36
+ });
37
+ // Fire-and-forget to avoid slowing tests
38
+ (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));
39
+ }
@@ -0,0 +1,5 @@
1
+ import { TestCase, TestResult, TestStep } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnStepEndEvent(test: TestCase, result: TestResult, step: TestStep, runId: string, executionId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnStepEndEvent = handleOnStepEndEvent;
4
+ const entities_1 = require("@stanterprise/protobuf/testsystem/v1/entities");
5
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
+ const utils_1 = require("../utils");
7
+ const grpcClient_1 = require("../client/grpcClient");
8
+ const utils_2 = require("../utils");
9
+ function handleOnStepEndEvent(test, result, step, runId, executionId, client, options, queue) {
10
+ // Map step error to status
11
+ const stepStatus = (0, utils_1.mapStepStatus)(!!step.error);
12
+ const attachments = (0, utils_1.processAttachments)(result, options.maxAttachmentSize || 10485760);
13
+ // Build metadata from step annotations
14
+ const metadata = (0, utils_1.buildStepMetadata)(step);
15
+ const stepId = (0, utils_2.generateStepId)(step, test);
16
+ // Extract comprehensive error details if present
17
+ const errorMessage = step.error?.message || "";
18
+ const errorStack = step.error?.stack || "";
19
+ const errorValue = step.error?.value || "";
20
+ const errorSnippet = step.error?.snippet || "";
21
+ const errorLocation = step.error?.location
22
+ ? `${step.error.location.file}:${step.error.location.line}:${step.error.location.column}`
23
+ : "";
24
+ // Combine all error information into metadata for comprehensive error tracking
25
+ const errorMetadata = {};
26
+ if (errorStack)
27
+ errorMetadata.error_stack = (0, utils_1.truncateValue)(errorStack);
28
+ if (errorValue)
29
+ errorMetadata.error_value = (0, utils_1.truncateValue)(errorValue);
30
+ if (errorSnippet)
31
+ errorMetadata.error_snippet = (0, utils_1.truncateValue)(errorSnippet);
32
+ if (errorLocation)
33
+ errorMetadata.error_location = (0, utils_1.truncateValue)(errorLocation);
34
+ // Build and send the StepEnd event
35
+ const request = new events_1.StepEndEventRequest({
36
+ step: new entities_1.StepRun({
37
+ id: stepId,
38
+ run_id: runId,
39
+ test_case_id: test.id,
40
+ title: step.title,
41
+ type: step.category,
42
+ start_time: (0, utils_1.createTimestamp)(step.startTime),
43
+ duration: (0, utils_1.createDuration)(step.duration),
44
+ status: stepStatus,
45
+ error: errorMessage,
46
+ errors: errorMessage ? [errorMessage] : [],
47
+ location: step.location
48
+ ? `${step.location.file}:${step.location.line}:${step.location.column}`
49
+ : "",
50
+ metadata: (0, utils_1.toMetadataMap)({ ...metadata, ...errorMetadata }),
51
+ parent_step_id: step.parent
52
+ ? (0, utils_2.generateStepId)(step.parent, test)
53
+ : undefined,
54
+ worker_index: result.workerIndex.toString(),
55
+ retry_index: result.retry,
56
+ attachments: attachments,
57
+ execution_id: executionId,
58
+ }),
59
+ });
60
+ // Fire-and-forget to avoid slowing tests
61
+ (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));
62
+ }
@@ -0,0 +1,5 @@
1
+ import { TestCase, TestResult } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnTestBeginEvent(test: TestCase, result: TestResult, runId: string, executionId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnTestBeginEvent = handleOnTestBeginEvent;
4
+ const entities_1 = require("@stanterprise/protobuf/testsystem/v1/entities");
5
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
+ const utils_1 = require("../utils");
7
+ const grpcClient_1 = require("../client/grpcClient");
8
+ const common_1 = require("@stanterprise/protobuf/testsystem/v1/common");
9
+ function handleOnTestBeginEvent(test, result, runId, executionId, client, options, queue) {
10
+ // Build and send the TestBegin event via generic unary call.
11
+ const request = new events_1.TestBeginEventRequest({
12
+ test_case: new entities_1.TestCaseRun({
13
+ id: test.id,
14
+ name: test.title,
15
+ run_id: runId,
16
+ retry_index: result.retry,
17
+ retry_count: test.retries,
18
+ location: test.location
19
+ ? `${test.location.file}:${test.location.line}:${test.location.column}`
20
+ : undefined,
21
+ status: common_1.TestStatus.RUNNING,
22
+ test_suite_id: (0, utils_1.generateSuiteId)(test.parent),
23
+ start_time: (0, utils_1.createTimestamp)(result.startTime),
24
+ tags: test.tags,
25
+ execution_id: executionId,
26
+ }),
27
+ });
28
+ // Fire-and-forget to avoid slowing tests; log errors once.
29
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportTestBegin", request, options.grpcTimeout, queue).catch((e) => {
30
+ const details = e instanceof Error ? `${e.message}` : String(e);
31
+ console.warn(`Failed to report test begin. Details: ${details}`);
32
+ });
33
+ }
@@ -0,0 +1,5 @@
1
+ import { TestCase, TestResult } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnTestEndEvent(test: TestCase, result: TestResult, runId: string, executionId: string, client: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnTestEndEvent = handleOnTestEndEvent;
4
+ const entities_1 = require("@stanterprise/protobuf/testsystem/v1/entities");
5
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
+ const utils_1 = require("../utils");
7
+ const grpcClient_1 = require("../client/grpcClient");
8
+ const utils_2 = require("../utils");
9
+ /**
10
+ * Constant for converting bytes to megabytes
11
+ */
12
+ const BYTES_PER_MB = 1048576;
13
+ function handleOnTestEndEvent(test, result, runId, executionId, client, options, queue) {
14
+ // Map Playwright test status to protobuf TestStatus
15
+ const testStatus = (0, utils_1.mapTestStatus)(result.status);
16
+ // Process attachments (screenshots, videos, etc.)
17
+ const attachments = (0, utils_1.processAttachments)(result, options.maxAttachmentSize || 10485760);
18
+ // Extract error information if the test failed
19
+ const { errorMessage, stackTrace, errors } = (0, utils_1.extractErrorInfo)(result);
20
+ // Get test suite run ID from parent suite if available, ensuring suite is reported
21
+ const suiteId = (0, utils_2.generateSuiteId)(test.parent);
22
+ // Build metadata from test annotations and result metadata
23
+ const metadata = (0, utils_1.buildTestMetadata)(test, result);
24
+ // Build and send the TestEnd event
25
+ const request = new events_1.TestEndEventRequest({
26
+ test_case: new entities_1.TestCaseRun({
27
+ id: test.id,
28
+ name: test.title,
29
+ run_id: runId,
30
+ test_suite_id: suiteId,
31
+ status: testStatus,
32
+ start_time: (0, utils_1.createTimestamp)(result.startTime),
33
+ duration: (0, utils_1.createDuration)(result.duration),
34
+ attachments: attachments,
35
+ error_message: errorMessage,
36
+ stack_trace: stackTrace,
37
+ errors: errors,
38
+ metadata: (0, utils_1.toMetadataMap)(metadata),
39
+ tags: test.tags,
40
+ retry_index: result.retry,
41
+ retry_count: test.retries,
42
+ execution_id: executionId,
43
+ }),
44
+ });
45
+ // Serialize once to capture payload size for potential error logging
46
+ const serializedPayload = request.serializeBinary();
47
+ const payloadSize = serializedPayload.length;
48
+ // Warn if payload is unusually large (>1MB)
49
+ if (payloadSize > 1048576) {
50
+ console.warn(`Large payload detected for test "${test.title}": ${(payloadSize / BYTES_PER_MB).toFixed(2)}MB. ` +
51
+ `Attachments: ${attachments.length}, Metadata keys: ${Object.keys(metadata).length}, ` +
52
+ `Error length: ${errorMessage.length + stackTrace.length} bytes`);
53
+ }
54
+ // Fire-and-forget to avoid slowing tests
55
+ (0, grpcClient_1.reportUnary)(options, client, "/testsystem.v1.observer.TestEventCollector/ReportTestEnd", request, options.grpcTimeout, queue).catch((e) => {
56
+ console.error(`Failed to report test end for "${test.title}" (payload size: ${(payloadSize / BYTES_PER_MB).toFixed(2)}MB)`, e);
57
+ });
58
+ }
@@ -0,0 +1,5 @@
1
+ import { TestCase, TestResult } from "@playwright/test/reporter";
2
+ import { StanterpriseReporterOptions } from "../types";
3
+ import * as grpc from "@grpc/grpc-js";
4
+ import { MessageQueue } from "../client/messageQueue";
5
+ export declare function handleOnTestFailEvent(test: TestCase, result: TestResult, runId: string, executionId: string, grpcClient: grpc.Client, options: StanterpriseReporterOptions, queue?: MessageQueue): void;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleOnTestFailEvent = handleOnTestFailEvent;
4
+ const utils_1 = require("../utils");
5
+ const events_1 = require("@stanterprise/protobuf/testsystem/v1/events");
6
+ const grpcClient_1 = require("../client/grpcClient");
7
+ function handleOnTestFailEvent(test, result, runId, executionId, grpcClient, options, queue) {
8
+ // Extract failure details
9
+ const { errorMessage: failureMessage, stackTrace } = (0, utils_1.extractErrorInfo)(result);
10
+ // Process attachments for failed tests
11
+ const attachments = (0, utils_1.processAttachments)(result);
12
+ // Build and send the TestFailure event
13
+ const request = new events_1.TestFailureEventRequest({
14
+ test_id: test.id,
15
+ run_id: runId,
16
+ failure_message: failureMessage,
17
+ stack_trace: stackTrace,
18
+ timestamp: (0, utils_1.createTimestampFromMs)(Date.now()),
19
+ attachments: attachments,
20
+ retry_index: result.retry,
21
+ execution_id: executionId,
22
+ });
23
+ // Fire-and-forget to avoid slowing tests
24
+ (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));
25
+ }
@@ -2,20 +2,15 @@ import type { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult, Tes
2
2
  import { StanterpriseReporterOptions } from "./types";
3
3
  export default class StanterpriseReporter implements Reporter {
4
4
  private grpcClient;
5
- private grpcAddress;
6
- private grpcEnabled;
7
- private grpcTimeout;
8
- private grpcFirstErrorLogged;
9
- private verbose;
5
+ private options;
10
6
  private runId;
7
+ private executionId;
11
8
  private runStartTime;
12
- private rootSuite;
13
- private reportedSuites;
9
+ private messageQueue;
10
+ private metadata;
14
11
  constructor(options?: StanterpriseReporterOptions);
15
12
  onBegin(config: FullConfig, suite: Suite): void;
16
13
  onExit(): Promise<void>;
17
- getRunId(): string;
18
- getRunStartTime(): Date;
19
14
  onEnd(result: FullResult): Promise<{
20
15
  status?: FullResult["status"];
21
16
  } | undefined | void> | void;
@@ -27,10 +22,4 @@ export default class StanterpriseReporter implements Reporter {
27
22
  onError(error: TestError): void;
28
23
  onStdErr(chunk: string | Buffer, test: void | TestCase, result: void | TestResult): void;
29
24
  onStdOut(chunk: string | Buffer, test: void | TestCase, result: void | TestResult): void;
30
- private getSuiteId;
31
- private reportSuiteBegin;
32
- private reportSuiteEnd;
33
- private mapSuiteStatus;
34
- private logGrpcErrorOnce;
35
- private reportUnary;
36
25
  }