@stanterprise/playwright-reporter 1.0.0 → 1.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.
Files changed (44) hide show
  1. package/README.md +270 -12
  2. package/dist/client/grpcClient.d.ts +16 -0
  3. package/dist/client/grpcClient.js +180 -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 +9 -10
@@ -3,25 +3,54 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.processAttachments = processAttachments;
4
4
  exports.extractErrorInfo = extractErrorInfo;
5
5
  const protobuf_1 = require("@stanterprise/protobuf");
6
+ const Attachment = protobuf_1.common.v1.common.Attachment;
7
+ /**
8
+ * Constant for converting bytes to megabytes
9
+ */
10
+ const BYTES_PER_MB = 1048576;
6
11
  /**
7
12
  * Process Playwright test attachments into protobuf Attachment objects
13
+ * @param result Test result or test step containing attachments
14
+ * @param maxAttachmentSize Maximum size for attachment content (default 1MB, reduced from 10MB)
8
15
  */
9
- function processAttachments(result) {
16
+ function processAttachments(result, maxAttachmentSize = 1048576) {
10
17
  const attachments = [];
11
18
  if (!result.attachments || result.attachments.length === 0) {
12
19
  return attachments;
13
20
  }
21
+ let totalAttachmentSize = 0;
22
+ const MAX_TOTAL_ATTACHMENT_SIZE = 2097152; // 2MB total limit across all attachments
14
23
  for (const attachment of result.attachments) {
15
- const att = new protobuf_1.common.Attachment({
24
+ const att = new Attachment({
16
25
  name: attachment.name,
17
26
  mime_type: attachment.contentType,
18
27
  });
19
- // Use path as URI if available, otherwise use the body content
28
+ // Always prefer path if available to avoid large payloads
20
29
  if (attachment.path) {
21
30
  att.uri = attachment.path;
31
+ attachments.push(att);
32
+ continue;
22
33
  }
23
- else if (attachment.body) {
34
+ if (attachment.body) {
35
+ const bodySize = attachment.body.length;
36
+ // Check individual attachment size
37
+ if (bodySize > maxAttachmentSize) {
38
+ console.warn(`Attachment "${attachment.name}" (${(bodySize / BYTES_PER_MB).toFixed(2)}MB) exceeds max size ` +
39
+ `(${(maxAttachmentSize / BYTES_PER_MB).toFixed(2)}MB) and has no path. Skipping content.`);
40
+ // Still add the attachment metadata without content
41
+ attachments.push(att);
42
+ continue;
43
+ }
44
+ // Check total accumulated size
45
+ if (totalAttachmentSize + bodySize > MAX_TOTAL_ATTACHMENT_SIZE) {
46
+ console.warn(`Attachment "${attachment.name}" (${(bodySize / BYTES_PER_MB).toFixed(2)}MB) would exceed total attachment size limit ` +
47
+ `(${(MAX_TOTAL_ATTACHMENT_SIZE / BYTES_PER_MB).toFixed(2)}MB). Skipping content.`);
48
+ attachments.push(att);
49
+ continue;
50
+ }
51
+ // Include content if within limits
24
52
  att.content = attachment.body;
53
+ totalAttachmentSize += bodySize;
25
54
  }
26
55
  attachments.push(att);
27
56
  }
@@ -0,0 +1,13 @@
1
+ import { StanterpriseReporterOptions } from "../types";
2
+ /**
3
+ * Creates or truncates the debug JSONL file so each test run starts with a clean file.
4
+ * No-op when debug mode is disabled.
5
+ */
6
+ export declare function initDebugFile(options: StanterpriseReporterOptions): void;
7
+ /**
8
+ * Appends a single JSONL entry for an outgoing gRPC message.
9
+ * Each entry is a JSON object on its own line containing the timestamp,
10
+ * gRPC method path, and the serialized message payload.
11
+ * No-op when debug mode is disabled.
12
+ */
13
+ export declare function writeDebugEntry(options: StanterpriseReporterOptions, path: string, message: unknown): Promise<void>;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.initDebugFile = initDebugFile;
37
+ exports.writeDebugEntry = writeDebugEntry;
38
+ const fs = __importStar(require("fs"));
39
+ const nodePath = __importStar(require("path"));
40
+ /**
41
+ * Ensures the parent directory of `filePath` exists, creating it recursively if needed.
42
+ */
43
+ function ensureParentDir(filePath) {
44
+ const dir = nodePath.dirname(filePath);
45
+ if (dir && dir !== ".") {
46
+ fs.mkdirSync(dir, { recursive: true });
47
+ }
48
+ }
49
+ /**
50
+ * Creates or truncates the debug JSONL file so each test run starts with a clean file.
51
+ * No-op when debug mode is disabled.
52
+ */
53
+ function initDebugFile(options) {
54
+ if (!options.debug)
55
+ return;
56
+ const filePath = options.debugFile || "stanterprise-debug.jsonl";
57
+ try {
58
+ ensureParentDir(filePath);
59
+ fs.writeFileSync(filePath, "");
60
+ }
61
+ catch (e) {
62
+ console.error(`Stanterprise Reporter: Failed to initialize debug file "${filePath}":`, e);
63
+ }
64
+ }
65
+ /**
66
+ * Appends a single JSONL entry for an outgoing gRPC message.
67
+ * Each entry is a JSON object on its own line containing the timestamp,
68
+ * gRPC method path, and the serialized message payload.
69
+ * No-op when debug mode is disabled.
70
+ */
71
+ async function writeDebugEntry(options, path, message) {
72
+ if (!options.debug)
73
+ return;
74
+ const filePath = options.debugFile || "stanterprise-debug.jsonl";
75
+ const entry = {
76
+ timestamp: new Date().toISOString(),
77
+ path,
78
+ message,
79
+ };
80
+ try {
81
+ ensureParentDir(filePath);
82
+ await fs.promises.appendFile(filePath, JSON.stringify(entry) + "\n");
83
+ }
84
+ catch (e) {
85
+ console.error(`Stanterprise Reporter: Failed to write debug entry to "${filePath}":`, e);
86
+ }
87
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Retrieves environment variables with the STANTERPRISE_META_ prefix
3
+ * and returns them as a Map with the prefix stripped from keys.
4
+ *
5
+ * For example, STANTERPRISE_META_BUILD_ID=123 becomes BUILD_ID=123 in the metadata.
6
+ *
7
+ * @returns Map of metadata key-value pairs with prefix removed
8
+ */
9
+ export declare function getEnvVariables(): Map<string, string>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEnvVariables = getEnvVariables;
4
+ /**
5
+ * Retrieves environment variables with the STANTERPRISE_META_ prefix
6
+ * and returns them as a Map with the prefix stripped from keys.
7
+ *
8
+ * For example, STANTERPRISE_META_BUILD_ID=123 becomes BUILD_ID=123 in the metadata.
9
+ *
10
+ * @returns Map of metadata key-value pairs with prefix removed
11
+ */
12
+ function getEnvVariables() {
13
+ const envValues = process.env;
14
+ const prefix = "STANTERPRISE_META_";
15
+ const filteredEntries = Object.entries(envValues)
16
+ .filter(([key]) => key.startsWith(prefix))
17
+ .map(([key, value]) => {
18
+ // Strip the STANTERPRISE_META_ prefix so metadata keys are cleaner
19
+ const strippedKey = key.substring(prefix.length);
20
+ return [strippedKey, value || ""];
21
+ });
22
+ return new Map(filteredEntries);
23
+ }
@@ -0,0 +1,20 @@
1
+ import { Suite, TestCase, TestStep } from "@playwright/test/reporter";
2
+ /**
3
+ * Generates a unique suite ID based on the suite's title path.
4
+ * @param suite The Playwright Suite object.
5
+ * @returns A unique string ID for the suite.
6
+ */
7
+ export declare function generateSuiteId(suite: Suite): string;
8
+ /**
9
+ * Generates a unique test ID based on the test case. Currently uses the test's existing ID.
10
+ * @param test The Playwright TestCase object.
11
+ * @returns A unique string ID for the test case.
12
+ */
13
+ export declare function generateTestId(test: TestCase): string;
14
+ /**
15
+ * Generates a unique step ID based on the step and its parent test case.
16
+ * @param step The Playwright TestStep object.
17
+ * @param test The Playwright TestCase object that the step belongs to.
18
+ * @returns A unique string ID for the step.
19
+ */
20
+ export declare function generateStepId(step: TestStep, test: TestCase): string;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateSuiteId = generateSuiteId;
7
+ exports.generateTestId = generateTestId;
8
+ exports.generateStepId = generateStepId;
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ /**
11
+ * Generates a unique suite ID based on the suite's title path.
12
+ * @param suite The Playwright Suite object.
13
+ * @returns A unique string ID for the suite.
14
+ */
15
+ function generateSuiteId(suite) {
16
+ return crypto_1.default
17
+ .createHash("sha256")
18
+ .update(suite.titlePath().join(":"))
19
+ .digest("hex");
20
+ }
21
+ /**
22
+ * Generates a unique test ID based on the test case. Currently uses the test's existing ID.
23
+ * @param test The Playwright TestCase object.
24
+ * @returns A unique string ID for the test case.
25
+ */
26
+ function generateTestId(test) {
27
+ return test.id;
28
+ }
29
+ /**
30
+ * Generates a unique step ID based on the step and its parent test case.
31
+ * @param step The Playwright TestStep object.
32
+ * @param test The Playwright TestCase object that the step belongs to.
33
+ * @returns A unique string ID for the step.
34
+ */
35
+ function generateStepId(step, test) {
36
+ return crypto_1.default
37
+ .createHash("sha256")
38
+ .update(`${test.id}:${step.titlePath().join(":")}`)
39
+ .digest("hex");
40
+ }
@@ -4,3 +4,7 @@
4
4
  export * from "./statusMapper";
5
5
  export * from "./attachmentProcessor";
6
6
  export * from "./timeHelpers";
7
+ export * from "./idGenerators";
8
+ export * from "./envRetriever";
9
+ export * from "./metadataHelpers";
10
+ export * from "./debugLogger";
@@ -20,3 +20,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  __exportStar(require("./statusMapper"), exports);
21
21
  __exportStar(require("./attachmentProcessor"), exports);
22
22
  __exportStar(require("./timeHelpers"), exports);
23
+ __exportStar(require("./idGenerators"), exports);
24
+ __exportStar(require("./envRetriever"), exports);
25
+ __exportStar(require("./metadataHelpers"), exports);
26
+ __exportStar(require("./debugLogger"), exports);
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Utility functions for building metadata objects
3
+ */
4
+ import type { TestCase, TestResult, TestStep } from "@playwright/test/reporter";
5
+ /**
6
+ * Truncate a string to a maximum length with ellipsis indicator
7
+ * @param value String value to truncate
8
+ * @param maxLength Maximum length (default 100KB)
9
+ * @returns Truncated string with warning suffix if truncated
10
+ */
11
+ export declare function truncateValue(value: string, maxLength?: number): string;
12
+ /**
13
+ * Build metadata from annotations array
14
+ * @param annotations Array of annotations with type and optional description
15
+ * @param prefix Prefix for metadata keys (e.g., "annotation", "result_annotation")
16
+ * @returns Record of metadata key-value pairs
17
+ */
18
+ export declare function buildAnnotationsMetadata(annotations: Array<{
19
+ type: string;
20
+ description?: string;
21
+ }>, prefix?: string): Record<string, string>;
22
+ /**
23
+ * Build metadata from test case and result annotations
24
+ * Combines annotations from both the test case and the result
25
+ * @param test Test case containing annotations
26
+ * @param result Test result containing additional annotations
27
+ * @returns Record of metadata key-value pairs
28
+ */
29
+ export declare function buildTestMetadata(test: TestCase, result: TestResult): Record<string, string>;
30
+ /**
31
+ * Build metadata from step annotations and category
32
+ * @param step Test step containing annotations and category
33
+ * @returns Record of metadata key-value pairs
34
+ */
35
+ export declare function buildStepMetadata(step: TestStep): Record<string, string>;
36
+ /**
37
+ * Convert metadata object to Map for protobuf serialization
38
+ * Protobuf requires Map<string, string> for metadata fields
39
+ * @param metadata Record of metadata key-value pairs
40
+ * @returns Map ready for protobuf constructors
41
+ */
42
+ export declare function toMetadataMap(metadata: Record<string, string>): Map<string, string>;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.truncateValue = truncateValue;
4
+ exports.buildAnnotationsMetadata = buildAnnotationsMetadata;
5
+ exports.buildTestMetadata = buildTestMetadata;
6
+ exports.buildStepMetadata = buildStepMetadata;
7
+ exports.toMetadataMap = toMetadataMap;
8
+ /**
9
+ * Maximum length for a single metadata value (100KB)
10
+ * Large values are often accidentally embedded test data or debug output
11
+ */
12
+ const MAX_METADATA_VALUE_LENGTH = 102400;
13
+ /**
14
+ * Maximum total metadata size across all values (1MB)
15
+ */
16
+ const MAX_TOTAL_METADATA_SIZE = 1048576;
17
+ /**
18
+ * Truncate a string to a maximum length with ellipsis indicator
19
+ * @param value String value to truncate
20
+ * @param maxLength Maximum length (default 100KB)
21
+ * @returns Truncated string with warning suffix if truncated
22
+ */
23
+ function truncateValue(value, maxLength = MAX_METADATA_VALUE_LENGTH) {
24
+ if (value.length <= maxLength) {
25
+ return value;
26
+ }
27
+ const truncated = value.substring(0, maxLength - 100);
28
+ return `${truncated}... [TRUNCATED: original length ${value.length} bytes, showing first ${maxLength - 100} bytes]`;
29
+ }
30
+ /**
31
+ * Build metadata from annotations array
32
+ * @param annotations Array of annotations with type and optional description
33
+ * @param prefix Prefix for metadata keys (e.g., "annotation", "result_annotation")
34
+ * @returns Record of metadata key-value pairs
35
+ */
36
+ function buildAnnotationsMetadata(annotations, prefix = "annotation") {
37
+ const metadata = {};
38
+ let totalSize = 0;
39
+ for (let index = 0; index < annotations.length; index++) {
40
+ const annotation = annotations[index];
41
+ const typeKey = `${prefix}_${index}_type`;
42
+ const typeValue = annotation.type;
43
+ metadata[typeKey] = typeValue;
44
+ totalSize += typeValue.length;
45
+ if (annotation.description) {
46
+ const descKey = `${prefix}_${index}_description`;
47
+ const descValue = truncateValue(annotation.description);
48
+ // Skip if adding this would exceed total metadata size
49
+ if (totalSize + descValue.length > MAX_TOTAL_METADATA_SIZE) {
50
+ console.warn(`Skipping annotation description for ${typeKey}: would exceed total metadata size limit (${MAX_TOTAL_METADATA_SIZE} bytes)`);
51
+ continue;
52
+ }
53
+ metadata[descKey] = descValue;
54
+ totalSize += descValue.length;
55
+ }
56
+ }
57
+ return metadata;
58
+ }
59
+ /**
60
+ * Build metadata from test case and result annotations
61
+ * Combines annotations from both the test case and the result
62
+ * @param test Test case containing annotations
63
+ * @param result Test result containing additional annotations
64
+ * @returns Record of metadata key-value pairs
65
+ */
66
+ function buildTestMetadata(test, result) {
67
+ return {
68
+ ...buildAnnotationsMetadata(test.annotations, "annotation"),
69
+ ...buildAnnotationsMetadata(result.annotations, "result_annotation"),
70
+ };
71
+ }
72
+ /**
73
+ * Build metadata from step annotations and category
74
+ * @param step Test step containing annotations and category
75
+ * @returns Record of metadata key-value pairs
76
+ */
77
+ function buildStepMetadata(step) {
78
+ return {
79
+ category: step.category,
80
+ ...buildAnnotationsMetadata(step.annotations, "annotation"),
81
+ };
82
+ }
83
+ /**
84
+ * Convert metadata object to Map for protobuf serialization
85
+ * Protobuf requires Map<string, string> for metadata fields
86
+ * @param metadata Record of metadata key-value pairs
87
+ * @returns Map ready for protobuf constructors
88
+ */
89
+ function toMetadataMap(metadata) {
90
+ return new Map(Object.entries(metadata));
91
+ }
@@ -0,0 +1,7 @@
1
+ import { StanterpriseReporterOptions } from "../types";
2
+ /**
3
+ * Define and map reporter options from provided options and environment variables. Apply defaults where necessary.
4
+ * @param providedOptions Options provided during reporter initialization
5
+ * @returns Mapped and completed StanterpriseReporterOptions
6
+ */
7
+ export default function defineOptions(providedOptions: StanterpriseReporterOptions): StanterpriseReporterOptions;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = defineOptions;
4
+ /**
5
+ * Define and map reporter options from provided options and environment variables. Apply defaults where necessary.
6
+ * @param providedOptions Options provided during reporter initialization
7
+ * @returns Mapped and completed StanterpriseReporterOptions
8
+ */
9
+ function defineOptions(providedOptions) {
10
+ const result = {};
11
+ result.grpcAddress = identifyAddress(providedOptions);
12
+ result.grpcEnabled =
13
+ providedOptions.grpcEnabled ??
14
+ (process.env.STANTERPRISE_GRPC_ENABLED || "true").toLowerCase() !== "false";
15
+ result.grpcTimeout = providedOptions.grpcTimeout ?? 1000;
16
+ result.grpcMaxMessageSize = providedOptions.grpcMaxMessageSize ?? 104857600;
17
+ result.maxAttachmentSize = providedOptions.maxAttachmentSize ?? 10485760;
18
+ result.verbose = providedOptions.verbose ?? false;
19
+ result.grpcMaxRetries = providedOptions.grpcMaxRetries ?? 3;
20
+ result.grpcRetryDelay = providedOptions.grpcRetryDelay ?? 100;
21
+ result.debug =
22
+ providedOptions.debug ??
23
+ (process.env.STANTERPRISE_DEBUG || "").toLowerCase() === "true";
24
+ result.debugFile =
25
+ providedOptions.debugFile ||
26
+ process.env.STANTERPRISE_DEBUG_FILE ||
27
+ "stanterprise-debug.jsonl";
28
+ result.tls =
29
+ providedOptions.tls ??
30
+ (process.env.STANTERPRISE_GRPC_TLS || "true").toLowerCase() === "true";
31
+ return result;
32
+ }
33
+ function identifyAddress(providedOptions) {
34
+ if (providedOptions.grpcAddress) {
35
+ return providedOptions.grpcAddress;
36
+ }
37
+ if (process.env.STANTERPRISE_GRPC_ADDRESS) {
38
+ return process.env.STANTERPRISE_GRPC_ADDRESS;
39
+ }
40
+ if (process.env.STANTERPRISE_GRPC_HOST) {
41
+ const host = process.env.STANTERPRISE_GRPC_HOST;
42
+ const port = process.env.STANTERPRISE_GRPC_PORT || "50051";
43
+ return `${host}:${port}`;
44
+ }
45
+ if (providedOptions.grpcHost) {
46
+ const host = providedOptions.grpcHost;
47
+ const port = providedOptions.grpcPort ?? 50051;
48
+ return `${host}:${port}`;
49
+ }
50
+ return "localhost:50051";
51
+ }
@@ -3,26 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mapTestStatus = mapTestStatus;
4
4
  exports.mapStepStatus = mapStepStatus;
5
5
  const protobuf_1 = require("@stanterprise/protobuf");
6
+ const TestStatus = protobuf_1.common.v1.common.TestStatus;
6
7
  /**
7
8
  * Map Playwright test status to protobuf TestStatus
8
9
  */
9
10
  function mapTestStatus(status) {
10
11
  switch (status) {
11
12
  case "passed":
12
- return protobuf_1.common.TestStatus.PASSED;
13
+ return TestStatus.PASSED;
13
14
  case "failed":
14
- return protobuf_1.common.TestStatus.FAILED;
15
+ return TestStatus.FAILED;
15
16
  case "skipped":
16
- return protobuf_1.common.TestStatus.SKIPPED;
17
+ return TestStatus.SKIPPED;
17
18
  case "timedOut":
18
- return protobuf_1.common.TestStatus.FAILED; // Treat timeout as failed
19
+ return TestStatus.FAILED; // Treat timeout as failed
19
20
  default:
20
- return protobuf_1.common.TestStatus.UNKNOWN;
21
+ return TestStatus.UNKNOWN;
21
22
  }
22
23
  }
23
24
  /**
24
25
  * Map step error to test status
25
26
  */
26
27
  function mapStepStatus(hasError) {
27
- return hasError ? protobuf_1.common.TestStatus.FAILED : protobuf_1.common.TestStatus.PASSED;
28
+ return hasError ? TestStatus.FAILED : TestStatus.PASSED;
28
29
  }
@@ -2,15 +2,15 @@
2
2
  * Utility functions for creating timestamps and durations
3
3
  */
4
4
  import { google } from "@stanterprise/protobuf";
5
- import type { google as googleTypes } from "@stanterprise/protobuf/dist/lib/google/protobuf/duration";
5
+ declare const Timestamp: typeof google.google.protobuf.Timestamp;
6
6
  /**
7
7
  * Create a protobuf Timestamp from a JavaScript Date
8
8
  */
9
- export declare function createTimestamp(date: Date): InstanceType<typeof google.protobuf.Timestamp>;
9
+ export declare function createTimestamp(date: Date): InstanceType<typeof Timestamp>;
10
10
  /**
11
11
  * Create a protobuf Timestamp from milliseconds since epoch
12
12
  */
13
- export declare function createTimestampFromMs(ms: number): InstanceType<typeof google.protobuf.Timestamp>;
13
+ export declare function createTimestampFromMs(ms: number): InstanceType<typeof Timestamp>;
14
14
  /**
15
15
  * Create a duration object from milliseconds.
16
16
  *
@@ -18,9 +18,9 @@ export declare function createTimestampFromMs(ms: number): InstanceType<typeof g
18
18
  * but not exported in the package's main barrel export. Since Duration and Timestamp
19
19
  * have identical structure (seconds: number, nanos: number) and the protobuf serialization
20
20
  * is wire-compatible, we use Timestamp as a Duration substitute. This works correctly at runtime.
21
- * The return type is cast to Duration for proper type checking with the schema.
22
21
  *
23
22
  * @param durationMs Duration in milliseconds
24
23
  * @returns A Duration object (implemented as Timestamp due to export limitations)
25
24
  */
26
- export declare function createDuration(durationMs: number): googleTypes.protobuf.Duration;
25
+ export declare function createDuration(durationMs: number): any;
26
+ export {};
@@ -7,22 +7,32 @@ exports.createDuration = createDuration;
7
7
  * Utility functions for creating timestamps and durations
8
8
  */
9
9
  const protobuf_1 = require("@stanterprise/protobuf");
10
+ const Timestamp = protobuf_1.google.google.protobuf.Timestamp;
10
11
  /**
11
12
  * Create a protobuf Timestamp from a JavaScript Date
12
13
  */
13
14
  function createTimestamp(date) {
14
- return new protobuf_1.google.protobuf.Timestamp({
15
- seconds: Math.floor(date.getTime() / 1000),
16
- nanos: (date.getTime() % 1000) * 1000000,
15
+ const ms = date.getTime();
16
+ // Validate to prevent NaN from causing protobuf serialization failures
17
+ if (isNaN(ms)) {
18
+ throw new Error(`Invalid date provided to createTimestamp: ${date.toString()}`);
19
+ }
20
+ return new Timestamp({
21
+ seconds: Math.floor(ms / 1000),
22
+ nanos: Math.floor((ms % 1000) * 1000000),
17
23
  });
18
24
  }
19
25
  /**
20
26
  * Create a protobuf Timestamp from milliseconds since epoch
21
27
  */
22
28
  function createTimestampFromMs(ms) {
23
- return new protobuf_1.google.protobuf.Timestamp({
29
+ // Validate to prevent NaN from causing protobuf serialization failures
30
+ if (typeof ms !== "number" || isNaN(ms)) {
31
+ throw new Error(`Invalid milliseconds provided to createTimestampFromMs: ${ms}`);
32
+ }
33
+ return new Timestamp({
24
34
  seconds: Math.floor(ms / 1000),
25
- nanos: (ms % 1000) * 1000000,
35
+ nanos: Math.floor((ms % 1000) * 1000000),
26
36
  });
27
37
  }
28
38
  /**
@@ -32,14 +42,20 @@ function createTimestampFromMs(ms) {
32
42
  * but not exported in the package's main barrel export. Since Duration and Timestamp
33
43
  * have identical structure (seconds: number, nanos: number) and the protobuf serialization
34
44
  * is wire-compatible, we use Timestamp as a Duration substitute. This works correctly at runtime.
35
- * The return type is cast to Duration for proper type checking with the schema.
36
45
  *
37
46
  * @param durationMs Duration in milliseconds
38
47
  * @returns A Duration object (implemented as Timestamp due to export limitations)
39
48
  */
40
49
  function createDuration(durationMs) {
41
- return new protobuf_1.google.protobuf.Timestamp({
50
+ // Validate to prevent NaN from causing protobuf serialization failures
51
+ if (typeof durationMs !== "number" || isNaN(durationMs)) {
52
+ throw new Error(`Invalid duration provided to createDuration: ${durationMs}`);
53
+ }
54
+ if (durationMs < 0) {
55
+ throw new Error(`Negative duration provided to createDuration: ${durationMs}`);
56
+ }
57
+ return new Timestamp({
42
58
  seconds: Math.floor(durationMs / 1000),
43
- nanos: (durationMs % 1000) * 1000000,
59
+ nanos: Math.floor((durationMs % 1000) * 1000000),
44
60
  });
45
61
  }
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@stanterprise/playwright-reporter",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Custom Playwright test reporter that sends test results to Stanterprise via gRPC",
5
- "homepage": "https://github.com/stanterprise/stanterprise-playwright-reporter#readme",
5
+ "homepage": "https://github.com/stanterprise/playwright-reporter#readme",
6
6
  "bugs": {
7
- "url": "https://github.com/stanterprise/stanterprise-playwright-reporter/issues"
7
+ "url": "https://github.com/stanterprise/playwright-reporter/issues"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/stanterprise/stanterprise-playwright-reporter.git"
11
+ "url": "git+https://github.com/stanterprise/playwright-reporter.git"
12
12
  },
13
13
  "license": "ISC",
14
14
  "author": "Stanterprise Team",
@@ -16,8 +16,7 @@
16
16
  "main": "dist/index.js",
17
17
  "types": "dist/index.d.ts",
18
18
  "files": [
19
- "dist/**/*",
20
- "README.md"
19
+ "dist/**/*"
21
20
  ],
22
21
  "keywords": [
23
22
  "playwright",
@@ -44,9 +43,9 @@
44
43
  },
45
44
  "devDependencies": {
46
45
  "@playwright/test": "^1.52.0",
47
- "@types/jest": "^30.0.0",
48
- "@types/node": "^22.15.29",
49
- "jest": "^30.2.0",
46
+ "@types/jest": "^29.5.14",
47
+ "@types/node": "^22.19.7",
48
+ "jest": "^29.7.0",
50
49
  "ts-jest": "^29.4.5",
51
50
  "typescript": "^5.9.3"
52
51
  },
@@ -54,6 +53,6 @@
54
53
  "@grpc/grpc-js": "^1.14.1",
55
54
  "@protobuf-ts/grpc-transport": "^2.11.1",
56
55
  "@protobuf-ts/grpcweb-transport": "^2.11.1",
57
- "@stanterprise/protobuf": "^0.0.9"
56
+ "@stanterprise/protobuf": "^0.1.3"
58
57
  }
59
58
  }