@testrelic/playwright-analytics 1.2.1 → 1.3.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.
package/dist/merge.cjs CHANGED
@@ -1,117 +1,2 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/merge.ts
21
- var merge_exports = {};
22
- __export(merge_exports, {
23
- mergeReports: () => mergeReports
24
- });
25
- module.exports = __toCommonJS(merge_exports);
26
- var import_node_crypto = require("crypto");
27
- var import_node_fs = require("fs");
28
- var import_node_path = require("path");
29
- var import_core = require("@testrelic/core");
30
- async function mergeReports(files, options) {
31
- const reports = [];
32
- for (const file of files) {
33
- let raw;
34
- try {
35
- raw = (0, import_node_fs.readFileSync)(file, "utf-8");
36
- } catch (err) {
37
- throw (0, import_core.createError)(
38
- import_core.ErrorCode.MERGE_READ_FAILED,
39
- `Failed to read file: ${file}`,
40
- err
41
- );
42
- }
43
- let parsed;
44
- try {
45
- parsed = JSON.parse(raw);
46
- } catch (err) {
47
- throw (0, import_core.createError)(
48
- import_core.ErrorCode.MERGE_INVALID_SCHEMA,
49
- `Invalid JSON in file: ${file}`,
50
- err
51
- );
52
- }
53
- if (!(0, import_core.isValidTestRunReport)(parsed)) {
54
- throw (0, import_core.createError)(
55
- import_core.ErrorCode.MERGE_INVALID_SCHEMA,
56
- `Invalid report schema in file: ${file}`
57
- );
58
- }
59
- reports.push(parsed);
60
- }
61
- const shardRunIds = reports.map((r) => r.testRunId);
62
- const allTimelines = [];
63
- for (const report of reports) {
64
- allTimelines.push(...report.timeline);
65
- }
66
- allTimelines.sort(
67
- (a, b) => new Date(a.visitedAt).getTime() - new Date(b.visitedAt).getTime()
68
- );
69
- const summary = recalculateSummary(reports);
70
- const startedAt = reports.reduce(
71
- (earliest, r) => r.startedAt < earliest ? r.startedAt : earliest,
72
- reports[0]?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
73
- );
74
- const completedAt = reports.reduce(
75
- (latest, r) => r.completedAt > latest ? r.completedAt : latest,
76
- reports[0]?.completedAt ?? (/* @__PURE__ */ new Date()).toISOString()
77
- );
78
- const totalDuration = new Date(completedAt).getTime() - new Date(startedAt).getTime();
79
- const merged = {
80
- schemaVersion: reports[0]?.schemaVersion ?? "1.0.0",
81
- testRunId: options.testRunId ?? (0, import_node_crypto.randomUUID)(),
82
- startedAt,
83
- completedAt,
84
- totalDuration,
85
- summary,
86
- ci: reports.find((r) => r.ci !== null)?.ci ?? null,
87
- metadata: reports.find((r) => r.metadata !== null)?.metadata ?? null,
88
- timeline: allTimelines,
89
- shardRunIds
90
- };
91
- const dir = (0, import_node_path.dirname)(options.output);
92
- (0, import_node_fs.mkdirSync)(dir, { recursive: true });
93
- (0, import_node_fs.writeFileSync)(options.output, JSON.stringify(merged, null, 2), "utf-8");
94
- return merged;
95
- }
96
- function recalculateSummary(reports) {
97
- let total = 0;
98
- let passed = 0;
99
- let failed = 0;
100
- let flaky = 0;
101
- let skipped = 0;
102
- let timedout = 0;
103
- for (const report of reports) {
104
- total += report.summary.total;
105
- passed += report.summary.passed;
106
- failed += report.summary.failed;
107
- flaky += report.summary.flaky;
108
- skipped += report.summary.skipped;
109
- timedout += report.summary.timedout ?? 0;
110
- }
111
- return { total, passed, failed, flaky, skipped, timedout };
112
- }
113
- // Annotate the CommonJS export names for ESM import in node:
114
- 0 && (module.exports = {
115
- mergeReports
116
- });
1
+ 'use strict';var crypto=require('crypto'),fs=require('fs'),path=require('path'),core=require('@testrelic/core');async function k(l,o){let e=[];for(let t of l){let r;try{r=fs.readFileSync(t,"utf-8");}catch(d){throw core.createError(core.ErrorCode.MERGE_READ_FAILED,`Failed to read file: ${t}`,d)}let u;try{u=JSON.parse(r);}catch(d){throw core.createError(core.ErrorCode.MERGE_INVALID_SCHEMA,`Invalid JSON in file: ${t}`,d)}if(!core.isValidTestRunReport(u))throw core.createError(core.ErrorCode.MERGE_INVALID_SCHEMA,`Invalid report schema in file: ${t}`);e.push(u);}let a=e.map(t=>t.testRunId),i=[];for(let t of e)i.push(...t.timeline);i.sort((t,r)=>new Date(t.visitedAt).getTime()-new Date(r.visitedAt).getTime());let m=w(e),s=e.reduce((t,r)=>r.startedAt<t?r.startedAt:t,e[0]?.startedAt??new Date().toISOString()),n=e.reduce((t,r)=>r.completedAt>t?r.completedAt:t,e[0]?.completedAt??new Date().toISOString()),y=new Date(n).getTime()-new Date(s).getTime(),f={schemaVersion:e[0]?.schemaVersion??"1.0.0",testRunId:o.testRunId??crypto.randomUUID(),startedAt:s,completedAt:n,totalDuration:y,summary:m,ci:e.find(t=>t.ci!==null)?.ci??null,metadata:e.find(t=>t.metadata!==null)?.metadata??null,timeline:i,shardRunIds:a},R=path.dirname(o.output);return fs.mkdirSync(R,{recursive:true}),fs.writeFileSync(o.output,JSON.stringify(f,null,2),"utf-8"),f}function w(l){let o=0,e=0,a=0,i=0,m=0,s=0;for(let n of l)o+=n.summary.total,e+=n.summary.passed,a+=n.summary.failed,i+=n.summary.flaky,m+=n.summary.skipped,s+=n.summary.timedout??0;return {total:o,passed:e,failed:a,flaky:i,skipped:m,timedout:s}}exports.mergeReports=k;//# sourceMappingURL=merge.cjs.map
117
2
  //# sourceMappingURL=merge.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/merge.ts"],"sourcesContent":["/**\n * @testrelic/playwright-analytics/merge\n *\n * Merges multiple shard report files into a single unified timeline.\n * Tree-shakeable: separate entry point from the main reporter.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type {\n TestRunReport,\n MergeOptions,\n Summary,\n TimelineEntry,\n} from '@testrelic/core';\nimport { isValidTestRunReport, createError, ErrorCode } from '@testrelic/core';\n\nexport async function mergeReports(\n files: string[],\n options: MergeOptions,\n): Promise<TestRunReport> {\n const reports: TestRunReport[] = [];\n\n for (const file of files) {\n let raw: string;\n try {\n raw = readFileSync(file, 'utf-8');\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_READ_FAILED,\n `Failed to read file: ${file}`,\n err,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid JSON in file: ${file}`,\n err,\n );\n }\n\n if (!isValidTestRunReport(parsed)) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid report schema in file: ${file}`,\n );\n }\n\n reports.push(parsed);\n }\n\n // Collect shard IDs\n const shardRunIds = reports.map((r) => r.testRunId);\n\n // Merge timelines chronologically\n const allTimelines: TimelineEntry[] = [];\n for (const report of reports) {\n allTimelines.push(...report.timeline);\n }\n allTimelines.sort((a, b) =>\n new Date(a.visitedAt).getTime() - new Date(b.visitedAt).getTime(),\n );\n\n // Recalculate summary across all shards\n const summary = recalculateSummary(reports);\n\n // Compute timing\n const startedAt = reports.reduce(\n (earliest, r) => (r.startedAt < earliest ? r.startedAt : earliest),\n reports[0]?.startedAt ?? new Date().toISOString(),\n );\n const completedAt = reports.reduce(\n (latest, r) => (r.completedAt > latest ? r.completedAt : latest),\n reports[0]?.completedAt ?? new Date().toISOString(),\n );\n const totalDuration = new Date(completedAt).getTime() - new Date(startedAt).getTime();\n\n const merged: TestRunReport = {\n schemaVersion: reports[0]?.schemaVersion ?? '1.0.0',\n testRunId: options.testRunId ?? randomUUID(),\n startedAt,\n completedAt,\n totalDuration,\n summary,\n ci: reports.find((r) => r.ci !== null)?.ci ?? null,\n metadata: reports.find((r) => r.metadata !== null)?.metadata ?? null,\n timeline: allTimelines,\n shardRunIds,\n };\n\n // Write to disk\n const dir = dirname(options.output);\n mkdirSync(dir, { recursive: true });\n writeFileSync(options.output, JSON.stringify(merged, null, 2), 'utf-8');\n\n return merged;\n}\n\nfunction recalculateSummary(reports: TestRunReport[]): Summary {\n let total = 0;\n let passed = 0;\n let failed = 0;\n let flaky = 0;\n let skipped = 0;\n let timedout = 0;\n\n for (const report of reports) {\n total += report.summary.total;\n passed += report.summary.passed;\n failed += report.summary.failed;\n flaky += report.summary.flaky;\n skipped += report.summary.skipped;\n timedout += report.summary.timedout ?? 0;\n }\n\n return { total, passed, failed, flaky, skipped, timedout };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,yBAA2B;AAC3B,qBAAuD;AACvD,uBAAwB;AAOxB,kBAA6D;AAE7D,eAAsB,aACpB,OACA,SACwB;AACxB,QAAM,UAA2B,CAAC;AAElC,aAAW,QAAQ,OAAO;AACxB,QAAI;AACJ,QAAI;AACF,gBAAM,6BAAa,MAAM,OAAO;AAAA,IAClC,SAAS,KAAK;AACZ,gBAAM;AAAA,QACJ,sBAAU;AAAA,QACV,wBAAwB,IAAI;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,GAAG;AAAA,IACzB,SAAS,KAAK;AACZ,gBAAM;AAAA,QACJ,sBAAU;AAAA,QACV,yBAAyB,IAAI;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAC,kCAAqB,MAAM,GAAG;AACjC,gBAAM;AAAA,QACJ,sBAAU;AAAA,QACV,kCAAkC,IAAI;AAAA,MACxC;AAAA,IACF;AAEA,YAAQ,KAAK,MAAM;AAAA,EACrB;AAGA,QAAM,cAAc,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS;AAGlD,QAAM,eAAgC,CAAC;AACvC,aAAW,UAAU,SAAS;AAC5B,iBAAa,KAAK,GAAG,OAAO,QAAQ;AAAA,EACtC;AACA,eAAa;AAAA,IAAK,CAAC,GAAG,MACpB,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AAAA,EAClE;AAGA,QAAM,UAAU,mBAAmB,OAAO;AAG1C,QAAM,YAAY,QAAQ;AAAA,IACxB,CAAC,UAAU,MAAO,EAAE,YAAY,WAAW,EAAE,YAAY;AAAA,IACzD,QAAQ,CAAC,GAAG,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EAClD;AACA,QAAM,cAAc,QAAQ;AAAA,IAC1B,CAAC,QAAQ,MAAO,EAAE,cAAc,SAAS,EAAE,cAAc;AAAA,IACzD,QAAQ,CAAC,GAAG,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpD;AACA,QAAM,gBAAgB,IAAI,KAAK,WAAW,EAAE,QAAQ,IAAI,IAAI,KAAK,SAAS,EAAE,QAAQ;AAEpF,QAAM,SAAwB;AAAA,IAC5B,eAAe,QAAQ,CAAC,GAAG,iBAAiB;AAAA,IAC5C,WAAW,QAAQ,iBAAa,+BAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,GAAG,MAAM;AAAA,IAC9C,UAAU,QAAQ,KAAK,CAAC,MAAM,EAAE,aAAa,IAAI,GAAG,YAAY;AAAA,IAChE,UAAU;AAAA,IACV;AAAA,EACF;AAGA,QAAM,UAAM,0BAAQ,QAAQ,MAAM;AAClC,gCAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,oCAAc,QAAQ,QAAQ,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AAEtE,SAAO;AACT;AAEA,SAAS,mBAAmB,SAAmC;AAC7D,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,MAAI,WAAW;AAEf,aAAW,UAAU,SAAS;AAC5B,aAAS,OAAO,QAAQ;AACxB,cAAU,OAAO,QAAQ;AACzB,cAAU,OAAO,QAAQ;AACzB,aAAS,OAAO,QAAQ;AACxB,eAAW,OAAO,QAAQ;AAC1B,gBAAY,OAAO,QAAQ,YAAY;AAAA,EACzC;AAEA,SAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO,SAAS,SAAS;AAC3D;","names":[]}
1
+ {"version":3,"sources":["../src/merge.ts"],"names":["mergeReports","files","options","reports","file","raw","readFileSync","err","createError","ErrorCode","parsed","isValidTestRunReport","shardRunIds","r","allTimelines","report","a","b","summary","recalculateSummary","startedAt","earliest","completedAt","latest","totalDuration","merged","randomUUID","dir","dirname","mkdirSync","writeFileSync","total","passed","failed","flaky","skipped","timedout"],"mappings":"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","file":"merge.cjs","sourcesContent":["/**\n * @testrelic/playwright-analytics/merge\n *\n * Merges multiple shard report files into a single unified timeline.\n * Tree-shakeable: separate entry point from the main reporter.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type {\n TestRunReport,\n MergeOptions,\n Summary,\n TimelineEntry,\n} from '@testrelic/core';\nimport { isValidTestRunReport, createError, ErrorCode } from '@testrelic/core';\n\nexport async function mergeReports(\n files: string[],\n options: MergeOptions,\n): Promise<TestRunReport> {\n const reports: TestRunReport[] = [];\n\n for (const file of files) {\n let raw: string;\n try {\n raw = readFileSync(file, 'utf-8');\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_READ_FAILED,\n `Failed to read file: ${file}`,\n err,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid JSON in file: ${file}`,\n err,\n );\n }\n\n if (!isValidTestRunReport(parsed)) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid report schema in file: ${file}`,\n );\n }\n\n reports.push(parsed);\n }\n\n // Collect shard IDs\n const shardRunIds = reports.map((r) => r.testRunId);\n\n // Merge timelines chronologically\n const allTimelines: TimelineEntry[] = [];\n for (const report of reports) {\n allTimelines.push(...report.timeline);\n }\n allTimelines.sort((a, b) =>\n new Date(a.visitedAt).getTime() - new Date(b.visitedAt).getTime(),\n );\n\n // Recalculate summary across all shards\n const summary = recalculateSummary(reports);\n\n // Compute timing\n const startedAt = reports.reduce(\n (earliest, r) => (r.startedAt < earliest ? r.startedAt : earliest),\n reports[0]?.startedAt ?? new Date().toISOString(),\n );\n const completedAt = reports.reduce(\n (latest, r) => (r.completedAt > latest ? r.completedAt : latest),\n reports[0]?.completedAt ?? new Date().toISOString(),\n );\n const totalDuration = new Date(completedAt).getTime() - new Date(startedAt).getTime();\n\n const merged: TestRunReport = {\n schemaVersion: reports[0]?.schemaVersion ?? '1.0.0',\n testRunId: options.testRunId ?? randomUUID(),\n startedAt,\n completedAt,\n totalDuration,\n summary,\n ci: reports.find((r) => r.ci !== null)?.ci ?? null,\n metadata: reports.find((r) => r.metadata !== null)?.metadata ?? null,\n timeline: allTimelines,\n shardRunIds,\n };\n\n // Write to disk\n const dir = dirname(options.output);\n mkdirSync(dir, { recursive: true });\n writeFileSync(options.output, JSON.stringify(merged, null, 2), 'utf-8');\n\n return merged;\n}\n\nfunction recalculateSummary(reports: TestRunReport[]): Summary {\n let total = 0;\n let passed = 0;\n let failed = 0;\n let flaky = 0;\n let skipped = 0;\n let timedout = 0;\n\n for (const report of reports) {\n total += report.summary.total;\n passed += report.summary.passed;\n failed += report.summary.failed;\n flaky += report.summary.flaky;\n skipped += report.summary.skipped;\n timedout += report.summary.timedout ?? 0;\n }\n\n return { total, passed, failed, flaky, skipped, timedout };\n}\n"]}
package/dist/merge.js CHANGED
@@ -1,92 +1,2 @@
1
- // src/merge.ts
2
- import { randomUUID } from "crypto";
3
- import { readFileSync, writeFileSync, mkdirSync } from "fs";
4
- import { dirname } from "path";
5
- import { isValidTestRunReport, createError, ErrorCode } from "@testrelic/core";
6
- async function mergeReports(files, options) {
7
- const reports = [];
8
- for (const file of files) {
9
- let raw;
10
- try {
11
- raw = readFileSync(file, "utf-8");
12
- } catch (err) {
13
- throw createError(
14
- ErrorCode.MERGE_READ_FAILED,
15
- `Failed to read file: ${file}`,
16
- err
17
- );
18
- }
19
- let parsed;
20
- try {
21
- parsed = JSON.parse(raw);
22
- } catch (err) {
23
- throw createError(
24
- ErrorCode.MERGE_INVALID_SCHEMA,
25
- `Invalid JSON in file: ${file}`,
26
- err
27
- );
28
- }
29
- if (!isValidTestRunReport(parsed)) {
30
- throw createError(
31
- ErrorCode.MERGE_INVALID_SCHEMA,
32
- `Invalid report schema in file: ${file}`
33
- );
34
- }
35
- reports.push(parsed);
36
- }
37
- const shardRunIds = reports.map((r) => r.testRunId);
38
- const allTimelines = [];
39
- for (const report of reports) {
40
- allTimelines.push(...report.timeline);
41
- }
42
- allTimelines.sort(
43
- (a, b) => new Date(a.visitedAt).getTime() - new Date(b.visitedAt).getTime()
44
- );
45
- const summary = recalculateSummary(reports);
46
- const startedAt = reports.reduce(
47
- (earliest, r) => r.startedAt < earliest ? r.startedAt : earliest,
48
- reports[0]?.startedAt ?? (/* @__PURE__ */ new Date()).toISOString()
49
- );
50
- const completedAt = reports.reduce(
51
- (latest, r) => r.completedAt > latest ? r.completedAt : latest,
52
- reports[0]?.completedAt ?? (/* @__PURE__ */ new Date()).toISOString()
53
- );
54
- const totalDuration = new Date(completedAt).getTime() - new Date(startedAt).getTime();
55
- const merged = {
56
- schemaVersion: reports[0]?.schemaVersion ?? "1.0.0",
57
- testRunId: options.testRunId ?? randomUUID(),
58
- startedAt,
59
- completedAt,
60
- totalDuration,
61
- summary,
62
- ci: reports.find((r) => r.ci !== null)?.ci ?? null,
63
- metadata: reports.find((r) => r.metadata !== null)?.metadata ?? null,
64
- timeline: allTimelines,
65
- shardRunIds
66
- };
67
- const dir = dirname(options.output);
68
- mkdirSync(dir, { recursive: true });
69
- writeFileSync(options.output, JSON.stringify(merged, null, 2), "utf-8");
70
- return merged;
71
- }
72
- function recalculateSummary(reports) {
73
- let total = 0;
74
- let passed = 0;
75
- let failed = 0;
76
- let flaky = 0;
77
- let skipped = 0;
78
- let timedout = 0;
79
- for (const report of reports) {
80
- total += report.summary.total;
81
- passed += report.summary.passed;
82
- failed += report.summary.failed;
83
- flaky += report.summary.flaky;
84
- skipped += report.summary.skipped;
85
- timedout += report.summary.timedout ?? 0;
86
- }
87
- return { total, passed, failed, flaky, skipped, timedout };
88
- }
89
- export {
90
- mergeReports
91
- };
1
+ import {randomUUID}from'crypto';import {readFileSync,mkdirSync,writeFileSync}from'fs';import {dirname}from'path';import {createError,ErrorCode,isValidTestRunReport}from'@testrelic/core';async function k(l,o){let e=[];for(let t of l){let r;try{r=readFileSync(t,"utf-8");}catch(d){throw createError(ErrorCode.MERGE_READ_FAILED,`Failed to read file: ${t}`,d)}let u;try{u=JSON.parse(r);}catch(d){throw createError(ErrorCode.MERGE_INVALID_SCHEMA,`Invalid JSON in file: ${t}`,d)}if(!isValidTestRunReport(u))throw createError(ErrorCode.MERGE_INVALID_SCHEMA,`Invalid report schema in file: ${t}`);e.push(u);}let a=e.map(t=>t.testRunId),i=[];for(let t of e)i.push(...t.timeline);i.sort((t,r)=>new Date(t.visitedAt).getTime()-new Date(r.visitedAt).getTime());let m=w(e),s=e.reduce((t,r)=>r.startedAt<t?r.startedAt:t,e[0]?.startedAt??new Date().toISOString()),n=e.reduce((t,r)=>r.completedAt>t?r.completedAt:t,e[0]?.completedAt??new Date().toISOString()),y=new Date(n).getTime()-new Date(s).getTime(),f={schemaVersion:e[0]?.schemaVersion??"1.0.0",testRunId:o.testRunId??randomUUID(),startedAt:s,completedAt:n,totalDuration:y,summary:m,ci:e.find(t=>t.ci!==null)?.ci??null,metadata:e.find(t=>t.metadata!==null)?.metadata??null,timeline:i,shardRunIds:a},R=dirname(o.output);return mkdirSync(R,{recursive:true}),writeFileSync(o.output,JSON.stringify(f,null,2),"utf-8"),f}function w(l){let o=0,e=0,a=0,i=0,m=0,s=0;for(let n of l)o+=n.summary.total,e+=n.summary.passed,a+=n.summary.failed,i+=n.summary.flaky,m+=n.summary.skipped,s+=n.summary.timedout??0;return {total:o,passed:e,failed:a,flaky:i,skipped:m,timedout:s}}export{k as mergeReports};//# sourceMappingURL=merge.js.map
92
2
  //# sourceMappingURL=merge.js.map
package/dist/merge.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/merge.ts"],"sourcesContent":["/**\n * @testrelic/playwright-analytics/merge\n *\n * Merges multiple shard report files into a single unified timeline.\n * Tree-shakeable: separate entry point from the main reporter.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type {\n TestRunReport,\n MergeOptions,\n Summary,\n TimelineEntry,\n} from '@testrelic/core';\nimport { isValidTestRunReport, createError, ErrorCode } from '@testrelic/core';\n\nexport async function mergeReports(\n files: string[],\n options: MergeOptions,\n): Promise<TestRunReport> {\n const reports: TestRunReport[] = [];\n\n for (const file of files) {\n let raw: string;\n try {\n raw = readFileSync(file, 'utf-8');\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_READ_FAILED,\n `Failed to read file: ${file}`,\n err,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid JSON in file: ${file}`,\n err,\n );\n }\n\n if (!isValidTestRunReport(parsed)) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid report schema in file: ${file}`,\n );\n }\n\n reports.push(parsed);\n }\n\n // Collect shard IDs\n const shardRunIds = reports.map((r) => r.testRunId);\n\n // Merge timelines chronologically\n const allTimelines: TimelineEntry[] = [];\n for (const report of reports) {\n allTimelines.push(...report.timeline);\n }\n allTimelines.sort((a, b) =>\n new Date(a.visitedAt).getTime() - new Date(b.visitedAt).getTime(),\n );\n\n // Recalculate summary across all shards\n const summary = recalculateSummary(reports);\n\n // Compute timing\n const startedAt = reports.reduce(\n (earliest, r) => (r.startedAt < earliest ? r.startedAt : earliest),\n reports[0]?.startedAt ?? new Date().toISOString(),\n );\n const completedAt = reports.reduce(\n (latest, r) => (r.completedAt > latest ? r.completedAt : latest),\n reports[0]?.completedAt ?? new Date().toISOString(),\n );\n const totalDuration = new Date(completedAt).getTime() - new Date(startedAt).getTime();\n\n const merged: TestRunReport = {\n schemaVersion: reports[0]?.schemaVersion ?? '1.0.0',\n testRunId: options.testRunId ?? randomUUID(),\n startedAt,\n completedAt,\n totalDuration,\n summary,\n ci: reports.find((r) => r.ci !== null)?.ci ?? null,\n metadata: reports.find((r) => r.metadata !== null)?.metadata ?? null,\n timeline: allTimelines,\n shardRunIds,\n };\n\n // Write to disk\n const dir = dirname(options.output);\n mkdirSync(dir, { recursive: true });\n writeFileSync(options.output, JSON.stringify(merged, null, 2), 'utf-8');\n\n return merged;\n}\n\nfunction recalculateSummary(reports: TestRunReport[]): Summary {\n let total = 0;\n let passed = 0;\n let failed = 0;\n let flaky = 0;\n let skipped = 0;\n let timedout = 0;\n\n for (const report of reports) {\n total += report.summary.total;\n passed += report.summary.passed;\n failed += report.summary.failed;\n flaky += report.summary.flaky;\n skipped += report.summary.skipped;\n timedout += report.summary.timedout ?? 0;\n }\n\n return { total, passed, failed, flaky, skipped, timedout };\n}\n"],"mappings":";AAOA,SAAS,kBAAkB;AAC3B,SAAS,cAAc,eAAe,iBAAiB;AACvD,SAAS,eAAe;AAOxB,SAAS,sBAAsB,aAAa,iBAAiB;AAE7D,eAAsB,aACpB,OACA,SACwB;AACxB,QAAM,UAA2B,CAAC;AAElC,aAAW,QAAQ,OAAO;AACxB,QAAI;AACJ,QAAI;AACF,YAAM,aAAa,MAAM,OAAO;AAAA,IAClC,SAAS,KAAK;AACZ,YAAM;AAAA,QACJ,UAAU;AAAA,QACV,wBAAwB,IAAI;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,GAAG;AAAA,IACzB,SAAS,KAAK;AACZ,YAAM;AAAA,QACJ,UAAU;AAAA,QACV,yBAAyB,IAAI;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,qBAAqB,MAAM,GAAG;AACjC,YAAM;AAAA,QACJ,UAAU;AAAA,QACV,kCAAkC,IAAI;AAAA,MACxC;AAAA,IACF;AAEA,YAAQ,KAAK,MAAM;AAAA,EACrB;AAGA,QAAM,cAAc,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS;AAGlD,QAAM,eAAgC,CAAC;AACvC,aAAW,UAAU,SAAS;AAC5B,iBAAa,KAAK,GAAG,OAAO,QAAQ;AAAA,EACtC;AACA,eAAa;AAAA,IAAK,CAAC,GAAG,MACpB,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ;AAAA,EAClE;AAGA,QAAM,UAAU,mBAAmB,OAAO;AAG1C,QAAM,YAAY,QAAQ;AAAA,IACxB,CAAC,UAAU,MAAO,EAAE,YAAY,WAAW,EAAE,YAAY;AAAA,IACzD,QAAQ,CAAC,GAAG,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EAClD;AACA,QAAM,cAAc,QAAQ;AAAA,IAC1B,CAAC,QAAQ,MAAO,EAAE,cAAc,SAAS,EAAE,cAAc;AAAA,IACzD,QAAQ,CAAC,GAAG,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpD;AACA,QAAM,gBAAgB,IAAI,KAAK,WAAW,EAAE,QAAQ,IAAI,IAAI,KAAK,SAAS,EAAE,QAAQ;AAEpF,QAAM,SAAwB;AAAA,IAC5B,eAAe,QAAQ,CAAC,GAAG,iBAAiB;AAAA,IAC5C,WAAW,QAAQ,aAAa,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,IAAI,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,GAAG,MAAM;AAAA,IAC9C,UAAU,QAAQ,KAAK,CAAC,MAAM,EAAE,aAAa,IAAI,GAAG,YAAY;AAAA,IAChE,UAAU;AAAA,IACV;AAAA,EACF;AAGA,QAAM,MAAM,QAAQ,QAAQ,MAAM;AAClC,YAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,gBAAc,QAAQ,QAAQ,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AAEtE,SAAO;AACT;AAEA,SAAS,mBAAmB,SAAmC;AAC7D,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,MAAI,WAAW;AAEf,aAAW,UAAU,SAAS;AAC5B,aAAS,OAAO,QAAQ;AACxB,cAAU,OAAO,QAAQ;AACzB,cAAU,OAAO,QAAQ;AACzB,aAAS,OAAO,QAAQ;AACxB,eAAW,OAAO,QAAQ;AAC1B,gBAAY,OAAO,QAAQ,YAAY;AAAA,EACzC;AAEA,SAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO,SAAS,SAAS;AAC3D;","names":[]}
1
+ {"version":3,"sources":["../src/merge.ts"],"names":["mergeReports","files","options","reports","file","raw","readFileSync","err","createError","ErrorCode","parsed","isValidTestRunReport","shardRunIds","r","allTimelines","report","a","b","summary","recalculateSummary","startedAt","earliest","completedAt","latest","totalDuration","merged","randomUUID","dir","dirname","mkdirSync","writeFileSync","total","passed","failed","flaky","skipped","timedout"],"mappings":"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","file":"merge.js","sourcesContent":["/**\n * @testrelic/playwright-analytics/merge\n *\n * Merges multiple shard report files into a single unified timeline.\n * Tree-shakeable: separate entry point from the main reporter.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type {\n TestRunReport,\n MergeOptions,\n Summary,\n TimelineEntry,\n} from '@testrelic/core';\nimport { isValidTestRunReport, createError, ErrorCode } from '@testrelic/core';\n\nexport async function mergeReports(\n files: string[],\n options: MergeOptions,\n): Promise<TestRunReport> {\n const reports: TestRunReport[] = [];\n\n for (const file of files) {\n let raw: string;\n try {\n raw = readFileSync(file, 'utf-8');\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_READ_FAILED,\n `Failed to read file: ${file}`,\n err,\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid JSON in file: ${file}`,\n err,\n );\n }\n\n if (!isValidTestRunReport(parsed)) {\n throw createError(\n ErrorCode.MERGE_INVALID_SCHEMA,\n `Invalid report schema in file: ${file}`,\n );\n }\n\n reports.push(parsed);\n }\n\n // Collect shard IDs\n const shardRunIds = reports.map((r) => r.testRunId);\n\n // Merge timelines chronologically\n const allTimelines: TimelineEntry[] = [];\n for (const report of reports) {\n allTimelines.push(...report.timeline);\n }\n allTimelines.sort((a, b) =>\n new Date(a.visitedAt).getTime() - new Date(b.visitedAt).getTime(),\n );\n\n // Recalculate summary across all shards\n const summary = recalculateSummary(reports);\n\n // Compute timing\n const startedAt = reports.reduce(\n (earliest, r) => (r.startedAt < earliest ? r.startedAt : earliest),\n reports[0]?.startedAt ?? new Date().toISOString(),\n );\n const completedAt = reports.reduce(\n (latest, r) => (r.completedAt > latest ? r.completedAt : latest),\n reports[0]?.completedAt ?? new Date().toISOString(),\n );\n const totalDuration = new Date(completedAt).getTime() - new Date(startedAt).getTime();\n\n const merged: TestRunReport = {\n schemaVersion: reports[0]?.schemaVersion ?? '1.0.0',\n testRunId: options.testRunId ?? randomUUID(),\n startedAt,\n completedAt,\n totalDuration,\n summary,\n ci: reports.find((r) => r.ci !== null)?.ci ?? null,\n metadata: reports.find((r) => r.metadata !== null)?.metadata ?? null,\n timeline: allTimelines,\n shardRunIds,\n };\n\n // Write to disk\n const dir = dirname(options.output);\n mkdirSync(dir, { recursive: true });\n writeFileSync(options.output, JSON.stringify(merged, null, 2), 'utf-8');\n\n return merged;\n}\n\nfunction recalculateSummary(reports: TestRunReport[]): Summary {\n let total = 0;\n let passed = 0;\n let failed = 0;\n let flaky = 0;\n let skipped = 0;\n let timedout = 0;\n\n for (const report of reports) {\n total += report.summary.total;\n passed += report.summary.passed;\n failed += report.summary.failed;\n flaky += report.summary.flaky;\n skipped += report.summary.skipped;\n timedout += report.summary.timedout ?? 0;\n }\n\n return { total, passed, failed, flaky, skipped, timedout };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testrelic/playwright-analytics",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Playwright custom reporter and navigation-tracking fixture for test analytics",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -46,20 +46,11 @@
46
46
  "dist",
47
47
  "timeline-schema.json"
48
48
  ],
49
- "scripts": {
50
- "build": "tsup",
51
- "test": "vitest run --exclude '**/e2e/**'",
52
- "test:watch": "vitest",
53
- "test:integration": "vitest run --config vitest.integration.config.ts",
54
- "typecheck": "tsc --noEmit",
55
- "test:e2e": "pnpm run build && npx playwright test --config __tests__/e2e/playwright.config.ts",
56
- "test:e2e:validate": "npx tsx __tests__/e2e/validate-report.ts"
57
- },
58
49
  "peerDependencies": {
59
50
  "@playwright/test": ">=1.35.0"
60
51
  },
61
52
  "dependencies": {
62
- "@testrelic/core": "workspace:*"
53
+ "@testrelic/core": "1.3.0"
63
54
  },
64
55
  "devDependencies": {
65
56
  "@playwright/test": "^1.35.0",
@@ -72,5 +63,14 @@
72
63
  "node": ">=18"
73
64
  },
74
65
  "license": "MIT",
75
- "homepage": "https://testrelic.co"
76
- }
66
+ "homepage": "https://testrelic.co",
67
+ "scripts": {
68
+ "build": "tsup",
69
+ "test": "vitest run --exclude '**/e2e/**'",
70
+ "test:watch": "vitest",
71
+ "test:integration": "vitest run --config vitest.integration.config.ts",
72
+ "typecheck": "tsc --noEmit",
73
+ "test:e2e": "pnpm run build && npx playwright test --config __tests__/e2e/playwright.config.ts",
74
+ "test:e2e:validate": "npx tsx __tests__/e2e/validate-report.ts"
75
+ }
76
+ }