executable-stories-formatters 0.9.0 → 0.10.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/adapters.d.cts +1 -1
- package/dist/adapters.d.ts +1 -1
- package/dist/cli.js +418 -96
- package/dist/cli.js.map +1 -1
- package/dist/{index-it3Pkmqv.d.cts → index-CbWFyoTx.d.cts} +2 -0
- package/dist/{index-it3Pkmqv.d.ts → index-CbWFyoTx.d.ts} +2 -0
- package/dist/index.cjs +485 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +201 -4
- package/dist/index.d.ts +201 -4
- package/dist/index.js +475 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/behavior-manifest-v1.json +65 -0
- package/schemas/examples/dotnet.json +84 -20
- package/schemas/examples/go.json +77 -20
- package/schemas/examples/junit5.json +84 -20
- package/schemas/examples/pytest.json +92 -20
- package/schemas/examples/rust.json +84 -20
- package/schemas/scenario-index-v1.json +88 -0
- package/schemas/story-report-v1.json +5 -0
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
AstroFormatter: () => AstroFormatter,
|
|
34
|
+
BehaviorManifestJsonFormatter: () => BehaviorManifestJsonFormatter,
|
|
34
35
|
ConfluenceFormatter: () => ConfluenceFormatter,
|
|
35
36
|
CucumberHtmlFormatter: () => CucumberHtmlFormatter,
|
|
36
37
|
CucumberJsonFormatter: () => CucumberJsonFormatter,
|
|
@@ -51,6 +52,7 @@ __export(src_exports, {
|
|
|
51
52
|
STORY_META_KEY: () => STORY_META_KEY,
|
|
52
53
|
STORY_REPORT_SCHEMA_MAJOR: () => STORY_REPORT_SCHEMA_MAJOR,
|
|
53
54
|
STORY_REPORT_SCHEMA_VERSION: () => STORY_REPORT_SCHEMA_VERSION,
|
|
55
|
+
ScenarioIndexJsonFormatter: () => ScenarioIndexJsonFormatter,
|
|
54
56
|
StoryReportJsonFormatter: () => StoryReportJsonFormatter,
|
|
55
57
|
adaptJestRun: () => adaptJestRun,
|
|
56
58
|
adaptPlaywrightRun: () => adaptPlaywrightRun,
|
|
@@ -61,6 +63,7 @@ __export(src_exports, {
|
|
|
61
63
|
calculateFlakiness: () => calculateFlakiness,
|
|
62
64
|
calculateStability: () => calculateStability,
|
|
63
65
|
canonicalizeRun: () => canonicalizeRun,
|
|
66
|
+
classifyStatusChange: () => classifyStatusChange,
|
|
64
67
|
clearVersionCache: () => clearVersionCache,
|
|
65
68
|
computeTestMetrics: () => computeTestMetrics,
|
|
66
69
|
copyMarkdownAssets: () => copyMarkdownAssets,
|
|
@@ -72,6 +75,7 @@ __export(src_exports, {
|
|
|
72
75
|
detectCI: () => detectCI4,
|
|
73
76
|
detectPerformanceTrend: () => detectPerformanceTrend,
|
|
74
77
|
diffRuns: () => diffRuns,
|
|
78
|
+
diffStoryReports: () => diffStoryReports,
|
|
75
79
|
findGitDir: () => findGitDir,
|
|
76
80
|
formatDuration: () => formatDuration3,
|
|
77
81
|
generateRunComparison: () => generateRunComparison,
|
|
@@ -99,29 +103,34 @@ __export(src_exports, {
|
|
|
99
103
|
readBranchName: () => readBranchName,
|
|
100
104
|
readGitSha: () => readGitSha,
|
|
101
105
|
readPackageVersion: () => readPackageVersion,
|
|
106
|
+
regenerateArtifacts: () => regenerateArtifacts,
|
|
102
107
|
resolveAttachment: () => resolveAttachment,
|
|
103
108
|
resolveAttachments: () => resolveAttachments,
|
|
104
109
|
resolveTheme: () => resolveTheme,
|
|
105
110
|
resolveTraceUrl: () => resolveTraceUrl,
|
|
106
111
|
rewriteAssetPaths: () => rewriteAssetPaths,
|
|
107
112
|
saveHistory: () => saveHistory,
|
|
113
|
+
scenariosCoveringPaths: () => scenariosCoveringPaths,
|
|
108
114
|
sendNotifications: () => sendNotifications,
|
|
109
115
|
sendSlackNotification: () => sendSlackNotification,
|
|
110
116
|
sendTeamsNotification: () => sendTeamsNotification,
|
|
111
117
|
sendWebhookNotification: () => sendWebhookNotification,
|
|
112
118
|
signBody: () => signBody,
|
|
113
119
|
slugify: () => slugify,
|
|
120
|
+
startWatch: () => startWatch,
|
|
114
121
|
stripAnsi: () => stripAnsi,
|
|
122
|
+
toBehaviorManifest: () => toBehaviorManifest,
|
|
115
123
|
toCIInfo: () => toCIInfo,
|
|
116
124
|
toRawCIInfo: () => toRawCIInfo,
|
|
125
|
+
toScenarioIndex: () => toScenarioIndex,
|
|
117
126
|
toStoryReport: () => toStoryReport,
|
|
118
127
|
tryGetActiveOtelContext: () => tryGetActiveOtelContext,
|
|
119
128
|
updateHistory: () => updateHistory,
|
|
120
129
|
validateCanonicalRun: () => validateCanonicalRun
|
|
121
130
|
});
|
|
122
131
|
module.exports = __toCommonJS(src_exports);
|
|
123
|
-
var
|
|
124
|
-
var
|
|
132
|
+
var fs9 = require("fs");
|
|
133
|
+
var path10 = __toESM(require("path"), 1);
|
|
125
134
|
var fsPromises = __toESM(require("fs/promises"), 1);
|
|
126
135
|
|
|
127
136
|
// src/converters/acl/status.ts
|
|
@@ -967,6 +976,9 @@ function buildScenario(tc, featureId) {
|
|
|
967
976
|
if (tickets && tickets.length > 0) {
|
|
968
977
|
scenario.tickets = tickets.map((t) => t.url ? { id: t.id, url: t.url } : { id: t.id });
|
|
969
978
|
}
|
|
979
|
+
if (tc.story.covers && tc.story.covers.length > 0) {
|
|
980
|
+
scenario.covers = [...tc.story.covers];
|
|
981
|
+
}
|
|
970
982
|
return scenario;
|
|
971
983
|
}
|
|
972
984
|
function deriveFeatureTitle(group, relSourceFile) {
|
|
@@ -1090,6 +1102,181 @@ var StoryReportJsonFormatter = class {
|
|
|
1090
1102
|
}
|
|
1091
1103
|
};
|
|
1092
1104
|
|
|
1105
|
+
// src/formatters/scenario-index-json.ts
|
|
1106
|
+
var ScenarioIndexJsonFormatter = class {
|
|
1107
|
+
options;
|
|
1108
|
+
constructor(options = {}) {
|
|
1109
|
+
this.options = {
|
|
1110
|
+
pretty: options.pretty ?? true,
|
|
1111
|
+
filters: options.filters
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
toIndex(run) {
|
|
1115
|
+
return toScenarioIndex(toStoryReport(run), this.options.filters);
|
|
1116
|
+
}
|
|
1117
|
+
format(run) {
|
|
1118
|
+
const index = this.toIndex(run);
|
|
1119
|
+
return this.options.pretty ? JSON.stringify(index, null, 2) : JSON.stringify(index);
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
function toScenarioIndex(report, filters = {}) {
|
|
1123
|
+
const scenarios = report.features.flatMap(
|
|
1124
|
+
(feature) => feature.scenarios.map((scenario) => toScenarioIndexItem(feature, scenario))
|
|
1125
|
+
).filter((scenario) => matchesFilters(scenario, filters));
|
|
1126
|
+
return {
|
|
1127
|
+
schemaVersion: "1.0",
|
|
1128
|
+
runId: report.runId,
|
|
1129
|
+
generatedAtMs: report.finishedAtMs,
|
|
1130
|
+
summary: summarize(scenarios),
|
|
1131
|
+
scenarios
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
function toScenarioIndexItem(feature, scenario) {
|
|
1135
|
+
return {
|
|
1136
|
+
id: scenario.id,
|
|
1137
|
+
title: scenario.title,
|
|
1138
|
+
status: scenario.status,
|
|
1139
|
+
feature: feature.title,
|
|
1140
|
+
sourceFile: feature.sourceFile,
|
|
1141
|
+
sourceLine: scenario.sourceLine,
|
|
1142
|
+
tags: scenario.tags,
|
|
1143
|
+
tickets: scenario.tickets ?? [],
|
|
1144
|
+
covers: scenario.covers ?? [],
|
|
1145
|
+
durationMs: scenario.durationMs,
|
|
1146
|
+
steps: scenario.steps.map((step) => ({
|
|
1147
|
+
id: step.id,
|
|
1148
|
+
index: step.index,
|
|
1149
|
+
keyword: step.keyword,
|
|
1150
|
+
text: step.text,
|
|
1151
|
+
status: step.status,
|
|
1152
|
+
durationMs: step.durationMs,
|
|
1153
|
+
errorMessage: step.errorMessage,
|
|
1154
|
+
docKinds: step.docEntries.map((entry) => entry.kind)
|
|
1155
|
+
})),
|
|
1156
|
+
docKinds: scenario.docEntries.map((entry) => entry.kind),
|
|
1157
|
+
error: scenario.errorMessage ? { message: scenario.errorMessage, stack: scenario.errorStack } : void 0
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function matchesFilters(scenario, filters) {
|
|
1161
|
+
if (filters.statuses?.length && !filters.statuses.includes(scenario.status)) {
|
|
1162
|
+
return false;
|
|
1163
|
+
}
|
|
1164
|
+
if (filters.tags?.length && !filters.tags.some((tag) => scenario.tags.includes(tag))) {
|
|
1165
|
+
return false;
|
|
1166
|
+
}
|
|
1167
|
+
if (filters.sourceFiles?.length && !filters.sourceFiles.some((sourceFile) => scenario.sourceFile.includes(sourceFile))) {
|
|
1168
|
+
return false;
|
|
1169
|
+
}
|
|
1170
|
+
return true;
|
|
1171
|
+
}
|
|
1172
|
+
function summarize(scenarios) {
|
|
1173
|
+
return {
|
|
1174
|
+
total: scenarios.length,
|
|
1175
|
+
passed: scenarios.filter((scenario) => scenario.status === "passed").length,
|
|
1176
|
+
failed: scenarios.filter((scenario) => scenario.status === "failed").length,
|
|
1177
|
+
skipped: scenarios.filter((scenario) => scenario.status === "skipped").length,
|
|
1178
|
+
pending: scenarios.filter((scenario) => scenario.status === "pending").length,
|
|
1179
|
+
durationMs: scenarios.reduce((total, scenario) => total + scenario.durationMs, 0)
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// src/formatters/behavior-manifest-json.ts
|
|
1184
|
+
var BehaviorManifestJsonFormatter = class {
|
|
1185
|
+
pretty;
|
|
1186
|
+
constructor(options = {}) {
|
|
1187
|
+
this.pretty = options.pretty ?? true;
|
|
1188
|
+
}
|
|
1189
|
+
toManifest(run) {
|
|
1190
|
+
return toBehaviorManifest(toStoryReport(run));
|
|
1191
|
+
}
|
|
1192
|
+
format(run) {
|
|
1193
|
+
const manifest = this.toManifest(run);
|
|
1194
|
+
return this.pretty ? JSON.stringify(manifest, null, 2) : JSON.stringify(manifest);
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
function toBehaviorManifest(report) {
|
|
1198
|
+
const index = toScenarioIndex(report);
|
|
1199
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
1200
|
+
const byTag = /* @__PURE__ */ new Map();
|
|
1201
|
+
const docKinds = /* @__PURE__ */ new Set();
|
|
1202
|
+
const debuggerIssues = [];
|
|
1203
|
+
for (const scenario of index.scenarios) {
|
|
1204
|
+
const source = bySource.get(scenario.sourceFile) ?? {
|
|
1205
|
+
path: scenario.sourceFile,
|
|
1206
|
+
scenarioCount: 0,
|
|
1207
|
+
failed: 0,
|
|
1208
|
+
tags: []
|
|
1209
|
+
};
|
|
1210
|
+
source.scenarioCount += 1;
|
|
1211
|
+
if (scenario.status === "failed") source.failed += 1;
|
|
1212
|
+
source.tags = [.../* @__PURE__ */ new Set([...source.tags, ...scenario.tags])].sort();
|
|
1213
|
+
bySource.set(scenario.sourceFile, source);
|
|
1214
|
+
for (const tag of scenario.tags) {
|
|
1215
|
+
const tagEntry = byTag.get(tag) ?? { name: tag, scenarioCount: 0 };
|
|
1216
|
+
tagEntry.scenarioCount += 1;
|
|
1217
|
+
byTag.set(tag, tagEntry);
|
|
1218
|
+
}
|
|
1219
|
+
for (const kind of scenario.docKinds) docKinds.add(kind);
|
|
1220
|
+
for (const step of scenario.steps) {
|
|
1221
|
+
for (const kind of step.docKinds) docKinds.add(kind);
|
|
1222
|
+
}
|
|
1223
|
+
if (!scenarioHasDocs(scenario)) {
|
|
1224
|
+
debuggerIssues.push({
|
|
1225
|
+
severity: "warning",
|
|
1226
|
+
code: "missing-docs",
|
|
1227
|
+
scenarioId: scenario.id,
|
|
1228
|
+
title: scenario.title,
|
|
1229
|
+
message: "Scenario has no doc entries."
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
if (scenario.tags.length === 0) {
|
|
1233
|
+
debuggerIssues.push({
|
|
1234
|
+
severity: "warning",
|
|
1235
|
+
code: "missing-tags",
|
|
1236
|
+
scenarioId: scenario.id,
|
|
1237
|
+
title: scenario.title,
|
|
1238
|
+
message: "Scenario has no tags."
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
if (scenario.covers.length === 0) {
|
|
1242
|
+
debuggerIssues.push({
|
|
1243
|
+
severity: "warning",
|
|
1244
|
+
code: "missing-covers",
|
|
1245
|
+
scenarioId: scenario.id,
|
|
1246
|
+
title: scenario.title,
|
|
1247
|
+
message: "Scenario declares no covers (product-code paths), so code\u2192scenario lookup cannot find it."
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1250
|
+
if (scenario.sourceLine === void 0) {
|
|
1251
|
+
debuggerIssues.push({
|
|
1252
|
+
severity: "warning",
|
|
1253
|
+
code: "missing-source-line",
|
|
1254
|
+
scenarioId: scenario.id,
|
|
1255
|
+
title: scenario.title,
|
|
1256
|
+
message: "Scenario has no source line."
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
const scenariosWithDocs = index.scenarios.filter(scenarioHasDocs).length;
|
|
1261
|
+
return {
|
|
1262
|
+
schemaVersion: "1.0",
|
|
1263
|
+
runId: report.runId,
|
|
1264
|
+
generatedAtMs: report.finishedAtMs,
|
|
1265
|
+
summary: index.summary,
|
|
1266
|
+
sourceFiles: [...bySource.values()].sort((a, b) => a.path.localeCompare(b.path)),
|
|
1267
|
+
tags: [...byTag.values()].sort((a, b) => a.name.localeCompare(b.name)),
|
|
1268
|
+
docCoverage: {
|
|
1269
|
+
scenariosWithDocs,
|
|
1270
|
+
scenariosWithoutDocs: index.scenarios.length - scenariosWithDocs,
|
|
1271
|
+
docKinds: [...docKinds].sort()
|
|
1272
|
+
},
|
|
1273
|
+
debugger: debuggerIssues
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
function scenarioHasDocs(scenario) {
|
|
1277
|
+
return scenario.docKinds.length > 0 || scenario.steps.some((step) => step.docKinds.length > 0);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1093
1280
|
// src/formatters/html/renderers/index.ts
|
|
1094
1281
|
var fs2 = __toESM(require("fs"), 1);
|
|
1095
1282
|
var path3 = __toESM(require("path"), 1);
|
|
@@ -15958,8 +16145,8 @@ function extractDocAttachments(step) {
|
|
|
15958
16145
|
}
|
|
15959
16146
|
return attachments;
|
|
15960
16147
|
}
|
|
15961
|
-
function guessMediaType(
|
|
15962
|
-
const lower =
|
|
16148
|
+
function guessMediaType(path11) {
|
|
16149
|
+
const lower = path11.toLowerCase();
|
|
15963
16150
|
if (lower.endsWith(".png")) return "image/png";
|
|
15964
16151
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
|
15965
16152
|
if (lower.endsWith(".gif")) return "image/gif";
|
|
@@ -16100,11 +16287,11 @@ var CucumberHtmlFormatter = class {
|
|
|
16100
16287
|
for (const envelope of envelopes) {
|
|
16101
16288
|
const accepted = htmlStream.write(envelope);
|
|
16102
16289
|
if (!accepted) {
|
|
16103
|
-
await new Promise((
|
|
16290
|
+
await new Promise((resolve8) => htmlStream.once("drain", resolve8));
|
|
16104
16291
|
}
|
|
16105
16292
|
}
|
|
16106
|
-
await new Promise((
|
|
16107
|
-
collector.on("finish",
|
|
16293
|
+
await new Promise((resolve8, reject) => {
|
|
16294
|
+
collector.on("finish", resolve8);
|
|
16108
16295
|
collector.on("error", reject);
|
|
16109
16296
|
htmlStream.end();
|
|
16110
16297
|
});
|
|
@@ -18093,6 +18280,184 @@ ${result.errors.join("\n")}`);
|
|
|
18093
18280
|
}
|
|
18094
18281
|
}
|
|
18095
18282
|
|
|
18283
|
+
// src/coverage-index.ts
|
|
18284
|
+
function normalizePath(path11) {
|
|
18285
|
+
return path11.replace(/^\.\//, "");
|
|
18286
|
+
}
|
|
18287
|
+
function scenariosCoveringPaths(index, paths) {
|
|
18288
|
+
const queries = paths.map(normalizePath);
|
|
18289
|
+
return index.scenarios.filter(
|
|
18290
|
+
(scenario) => scenario.covers.some(
|
|
18291
|
+
(glob) => queries.some((path11) => matchesPattern(normalizePath(glob), path11))
|
|
18292
|
+
)
|
|
18293
|
+
);
|
|
18294
|
+
}
|
|
18295
|
+
|
|
18296
|
+
// src/watch.ts
|
|
18297
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
18298
|
+
var path7 = __toESM(require("path"), 1);
|
|
18299
|
+
|
|
18300
|
+
// src/converters/synthesize.ts
|
|
18301
|
+
var KEYWORD_MAP = {
|
|
18302
|
+
given: "Given",
|
|
18303
|
+
when: "When",
|
|
18304
|
+
then: "Then",
|
|
18305
|
+
and: "And",
|
|
18306
|
+
but: "But"
|
|
18307
|
+
};
|
|
18308
|
+
function normalizeKeyword(keyword) {
|
|
18309
|
+
return KEYWORD_MAP[keyword.toLowerCase()] ?? keyword;
|
|
18310
|
+
}
|
|
18311
|
+
function normalizeStepKeywords(steps) {
|
|
18312
|
+
return steps.map((step) => ({
|
|
18313
|
+
...step,
|
|
18314
|
+
keyword: normalizeKeyword(step.keyword)
|
|
18315
|
+
}));
|
|
18316
|
+
}
|
|
18317
|
+
function deriveScenarioName(tc) {
|
|
18318
|
+
if (tc.title) return tc.title;
|
|
18319
|
+
if (tc.titlePath && tc.titlePath.length > 0) {
|
|
18320
|
+
return tc.titlePath[tc.titlePath.length - 1];
|
|
18321
|
+
}
|
|
18322
|
+
return "Untitled";
|
|
18323
|
+
}
|
|
18324
|
+
function synthesizeStories(raw) {
|
|
18325
|
+
return {
|
|
18326
|
+
...raw,
|
|
18327
|
+
testCases: raw.testCases.map(synthesizeTestCase)
|
|
18328
|
+
};
|
|
18329
|
+
}
|
|
18330
|
+
function synthesizeTestCase(tc) {
|
|
18331
|
+
if (tc.story == null) {
|
|
18332
|
+
const scenario = deriveScenarioName(tc);
|
|
18333
|
+
return {
|
|
18334
|
+
...tc,
|
|
18335
|
+
story: {
|
|
18336
|
+
scenario,
|
|
18337
|
+
steps: [{ keyword: "Then", text: scenario }]
|
|
18338
|
+
}
|
|
18339
|
+
};
|
|
18340
|
+
}
|
|
18341
|
+
const steps = tc.story.steps;
|
|
18342
|
+
if (!steps || steps.length === 0) {
|
|
18343
|
+
return {
|
|
18344
|
+
...tc,
|
|
18345
|
+
story: {
|
|
18346
|
+
...tc.story,
|
|
18347
|
+
steps: [{ keyword: "Then", text: tc.story.scenario }]
|
|
18348
|
+
}
|
|
18349
|
+
};
|
|
18350
|
+
}
|
|
18351
|
+
return {
|
|
18352
|
+
...tc,
|
|
18353
|
+
story: {
|
|
18354
|
+
...tc.story,
|
|
18355
|
+
steps: normalizeStepKeywords(steps)
|
|
18356
|
+
}
|
|
18357
|
+
};
|
|
18358
|
+
}
|
|
18359
|
+
|
|
18360
|
+
// src/watch.ts
|
|
18361
|
+
function toRun(data, inputType, synthesize) {
|
|
18362
|
+
if (inputType === "canonical") return data;
|
|
18363
|
+
let raw = data;
|
|
18364
|
+
if (synthesize) raw = synthesizeStories(raw);
|
|
18365
|
+
return canonicalizeRun(raw);
|
|
18366
|
+
}
|
|
18367
|
+
async function regenerateArtifacts(options, deps = {}) {
|
|
18368
|
+
const read = deps.readFile ?? ((filePath) => fs6.readFileSync(filePath, "utf8"));
|
|
18369
|
+
const data = JSON.parse(read(path7.resolve(options.input)));
|
|
18370
|
+
const run = toRun(data, options.inputType ?? "raw", options.synthesize !== false);
|
|
18371
|
+
const generator = new ReportGenerator({
|
|
18372
|
+
formats: options.formats,
|
|
18373
|
+
outputDir: options.outputDir,
|
|
18374
|
+
outputName: options.outputName
|
|
18375
|
+
});
|
|
18376
|
+
const result = await generator.generate(run);
|
|
18377
|
+
return [...result.values()].flat();
|
|
18378
|
+
}
|
|
18379
|
+
function startWatch(options, deps = {}) {
|
|
18380
|
+
const log = deps.log ?? ((message) => console.log(message));
|
|
18381
|
+
const regenerate = deps.regenerate ?? ((input) => regenerateArtifacts({ ...options, input }, deps));
|
|
18382
|
+
const watchFn = deps.watch ?? ((filePath, listener) => fs6.watch(filePath, listener));
|
|
18383
|
+
const debounceMs = options.debounceMs ?? 150;
|
|
18384
|
+
let timer;
|
|
18385
|
+
let running = false;
|
|
18386
|
+
let pending = false;
|
|
18387
|
+
const run = async () => {
|
|
18388
|
+
if (running) {
|
|
18389
|
+
pending = true;
|
|
18390
|
+
return;
|
|
18391
|
+
}
|
|
18392
|
+
running = true;
|
|
18393
|
+
try {
|
|
18394
|
+
const files = await regenerate(options.input);
|
|
18395
|
+
log(`Regenerated ${files.length} artifact file(s) from ${options.input}`);
|
|
18396
|
+
} catch (error) {
|
|
18397
|
+
log(`Watch regeneration failed: ${error.message}`);
|
|
18398
|
+
} finally {
|
|
18399
|
+
running = false;
|
|
18400
|
+
if (pending) {
|
|
18401
|
+
pending = false;
|
|
18402
|
+
trigger();
|
|
18403
|
+
}
|
|
18404
|
+
}
|
|
18405
|
+
};
|
|
18406
|
+
const trigger = () => {
|
|
18407
|
+
if (timer) clearTimeout(timer);
|
|
18408
|
+
timer = setTimeout(() => void run(), debounceMs);
|
|
18409
|
+
};
|
|
18410
|
+
trigger();
|
|
18411
|
+
const watcher = watchFn(path7.resolve(options.input), trigger);
|
|
18412
|
+
return {
|
|
18413
|
+
close: () => {
|
|
18414
|
+
if (timer) clearTimeout(timer);
|
|
18415
|
+
watcher.close();
|
|
18416
|
+
}
|
|
18417
|
+
};
|
|
18418
|
+
}
|
|
18419
|
+
|
|
18420
|
+
// src/behavior-diff.ts
|
|
18421
|
+
function classifyStatusChange(baseline, current) {
|
|
18422
|
+
if (baseline === void 0) return "added";
|
|
18423
|
+
if (current === void 0) return "removed";
|
|
18424
|
+
if (baseline === current) return "unchanged";
|
|
18425
|
+
if (baseline === "passed" && current === "failed") return "regressed";
|
|
18426
|
+
if (baseline === "failed" && current === "passed") return "fixed";
|
|
18427
|
+
return "changed";
|
|
18428
|
+
}
|
|
18429
|
+
function scenarioMap(report) {
|
|
18430
|
+
const map = /* @__PURE__ */ new Map();
|
|
18431
|
+
for (const feature of report.features) {
|
|
18432
|
+
for (const scenario of feature.scenarios) {
|
|
18433
|
+
map.set(scenario.id, { scenario, sourceFile: feature.sourceFile });
|
|
18434
|
+
}
|
|
18435
|
+
}
|
|
18436
|
+
return map;
|
|
18437
|
+
}
|
|
18438
|
+
function diffStoryReports(baseline, current) {
|
|
18439
|
+
const base = scenarioMap(baseline);
|
|
18440
|
+
const curr = scenarioMap(current);
|
|
18441
|
+
const ids = [.../* @__PURE__ */ new Set([...base.keys(), ...curr.keys()])];
|
|
18442
|
+
const scenarios = ids.map((id) => {
|
|
18443
|
+
const b = base.get(id);
|
|
18444
|
+
const c = curr.get(id);
|
|
18445
|
+
const kind = classifyStatusChange(b?.scenario.status, c?.scenario.status);
|
|
18446
|
+
const meta = c ?? b;
|
|
18447
|
+
return {
|
|
18448
|
+
id,
|
|
18449
|
+
title: meta.scenario.title,
|
|
18450
|
+
sourceFile: meta.sourceFile,
|
|
18451
|
+
kind,
|
|
18452
|
+
baselineStatus: b?.scenario.status,
|
|
18453
|
+
currentStatus: c?.scenario.status
|
|
18454
|
+
};
|
|
18455
|
+
});
|
|
18456
|
+
const summary = { added: 0, removed: 0, regressed: 0, fixed: 0, changed: 0, unchanged: 0 };
|
|
18457
|
+
for (const s of scenarios) summary[s.kind] += 1;
|
|
18458
|
+
return { schemaVersion: "1.0", summary, scenarios };
|
|
18459
|
+
}
|
|
18460
|
+
|
|
18096
18461
|
// src/publishers/confluence.ts
|
|
18097
18462
|
function parseAdf(adf) {
|
|
18098
18463
|
let parsed;
|
|
@@ -18688,27 +19053,27 @@ function pickleStepArgumentToDocs(ps) {
|
|
|
18688
19053
|
}
|
|
18689
19054
|
|
|
18690
19055
|
// src/utils/git-info.ts
|
|
18691
|
-
var
|
|
18692
|
-
var
|
|
19056
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
19057
|
+
var path8 = __toESM(require("path"), 1);
|
|
18693
19058
|
function readGitSha(cwd = process.cwd()) {
|
|
18694
19059
|
const envSha = process.env.GITHUB_SHA || process.env.GIT_COMMIT || process.env.CI_COMMIT_SHA;
|
|
18695
19060
|
if (envSha) return envSha;
|
|
18696
19061
|
const gitDir = findGitDir(cwd);
|
|
18697
19062
|
if (!gitDir) return void 0;
|
|
18698
19063
|
try {
|
|
18699
|
-
const headPath =
|
|
18700
|
-
const head =
|
|
19064
|
+
const headPath = path8.join(gitDir, "HEAD");
|
|
19065
|
+
const head = fs7.readFileSync(headPath, "utf8").trim();
|
|
18701
19066
|
if (!head.startsWith("ref:")) {
|
|
18702
19067
|
return head;
|
|
18703
19068
|
}
|
|
18704
19069
|
const refPath = head.replace("ref:", "").trim();
|
|
18705
|
-
const refFile =
|
|
18706
|
-
if (
|
|
18707
|
-
return
|
|
19070
|
+
const refFile = path8.join(gitDir, refPath);
|
|
19071
|
+
if (fs7.existsSync(refFile)) {
|
|
19072
|
+
return fs7.readFileSync(refFile, "utf8").trim();
|
|
18708
19073
|
}
|
|
18709
|
-
const packedRefs =
|
|
18710
|
-
if (
|
|
18711
|
-
const content =
|
|
19074
|
+
const packedRefs = path8.join(gitDir, "packed-refs");
|
|
19075
|
+
if (fs7.existsSync(packedRefs)) {
|
|
19076
|
+
const content = fs7.readFileSync(packedRefs, "utf8");
|
|
18712
19077
|
for (const line of content.split("\n")) {
|
|
18713
19078
|
if (!line || line.startsWith("#") || line.startsWith("^")) continue;
|
|
18714
19079
|
const [sha, ref] = line.split(" ");
|
|
@@ -18723,19 +19088,19 @@ function readGitSha(cwd = process.cwd()) {
|
|
|
18723
19088
|
function findGitDir(start) {
|
|
18724
19089
|
let current = start;
|
|
18725
19090
|
while (true) {
|
|
18726
|
-
const candidate =
|
|
18727
|
-
if (
|
|
18728
|
-
const stat =
|
|
19091
|
+
const candidate = path8.join(current, ".git");
|
|
19092
|
+
if (fs7.existsSync(candidate)) {
|
|
19093
|
+
const stat = fs7.statSync(candidate);
|
|
18729
19094
|
if (stat.isFile()) {
|
|
18730
|
-
const content =
|
|
19095
|
+
const content = fs7.readFileSync(candidate, "utf8").trim();
|
|
18731
19096
|
const match = content.match(/^gitdir: (.+)$/);
|
|
18732
19097
|
if (match) {
|
|
18733
|
-
return
|
|
19098
|
+
return path8.resolve(current, match[1]);
|
|
18734
19099
|
}
|
|
18735
19100
|
}
|
|
18736
19101
|
return candidate;
|
|
18737
19102
|
}
|
|
18738
|
-
const parent =
|
|
19103
|
+
const parent = path8.dirname(current);
|
|
18739
19104
|
if (parent === current) return void 0;
|
|
18740
19105
|
current = parent;
|
|
18741
19106
|
}
|
|
@@ -18746,8 +19111,8 @@ function readBranchName(cwd = process.cwd()) {
|
|
|
18746
19111
|
const gitDir = findGitDir(cwd);
|
|
18747
19112
|
if (!gitDir) return void 0;
|
|
18748
19113
|
try {
|
|
18749
|
-
const headPath =
|
|
18750
|
-
const head =
|
|
19114
|
+
const headPath = path8.join(gitDir, "HEAD");
|
|
19115
|
+
const head = fs7.readFileSync(headPath, "utf8").trim();
|
|
18751
19116
|
if (head.startsWith("ref:")) {
|
|
18752
19117
|
const refPath = head.replace("ref:", "").trim();
|
|
18753
19118
|
const match = refPath.match(/^refs\/heads\/(.+)$/);
|
|
@@ -18784,8 +19149,8 @@ function nanosecondsToMs(ns) {
|
|
|
18784
19149
|
}
|
|
18785
19150
|
|
|
18786
19151
|
// src/utils/metadata.ts
|
|
18787
|
-
var
|
|
18788
|
-
var
|
|
19152
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
19153
|
+
var path9 = __toESM(require("path"), 1);
|
|
18789
19154
|
var versionCache = /* @__PURE__ */ new Map();
|
|
18790
19155
|
function readPackageVersion(root) {
|
|
18791
19156
|
if (versionCache.has(root)) {
|
|
@@ -18796,18 +19161,18 @@ function readPackageVersion(root) {
|
|
|
18796
19161
|
return version;
|
|
18797
19162
|
}
|
|
18798
19163
|
function findPackageVersion(startDir) {
|
|
18799
|
-
let current =
|
|
19164
|
+
let current = path9.resolve(startDir);
|
|
18800
19165
|
while (true) {
|
|
18801
|
-
const pkgPath =
|
|
19166
|
+
const pkgPath = path9.join(current, "package.json");
|
|
18802
19167
|
try {
|
|
18803
|
-
if (
|
|
18804
|
-
const raw =
|
|
19168
|
+
if (fs8.existsSync(pkgPath)) {
|
|
19169
|
+
const raw = fs8.readFileSync(pkgPath, "utf8");
|
|
18805
19170
|
const parsed = JSON.parse(raw);
|
|
18806
19171
|
return parsed.version;
|
|
18807
19172
|
}
|
|
18808
19173
|
} catch {
|
|
18809
19174
|
}
|
|
18810
|
-
const parent =
|
|
19175
|
+
const parent = path9.dirname(current);
|
|
18811
19176
|
if (parent === current) {
|
|
18812
19177
|
return void 0;
|
|
18813
19178
|
}
|
|
@@ -19678,12 +20043,22 @@ function listScenarios(args, _deps) {
|
|
|
19678
20043
|
const { testCases, format } = args;
|
|
19679
20044
|
if (format === "json") {
|
|
19680
20045
|
const items = testCases.map((tc) => ({
|
|
20046
|
+
id: tc.id,
|
|
19681
20047
|
scenario: tc.story.scenario,
|
|
19682
20048
|
status: tc.status,
|
|
19683
20049
|
sourceFile: tc.sourceFile,
|
|
19684
20050
|
sourceLine: tc.sourceLine,
|
|
20051
|
+
suitePath: tc.story.suitePath ?? tc.titlePath.slice(0, -1),
|
|
19685
20052
|
tags: tc.tags,
|
|
19686
|
-
|
|
20053
|
+
tickets: tc.story.tickets ?? [],
|
|
20054
|
+
covers: tc.story.covers ?? [],
|
|
20055
|
+
durationMs: tc.durationMs,
|
|
20056
|
+
error: tc.errorMessage ? {
|
|
20057
|
+
message: tc.errorMessage,
|
|
20058
|
+
stack: tc.errorStack
|
|
20059
|
+
} : void 0,
|
|
20060
|
+
steps: tc.story.steps.map((step, index) => toScenarioStep(step, index, tc)),
|
|
20061
|
+
docKinds: collectDocKinds(tc)
|
|
19687
20062
|
}));
|
|
19688
20063
|
return JSON.stringify(items, null, 2);
|
|
19689
20064
|
}
|
|
@@ -19756,6 +20131,34 @@ function listScenarios(args, _deps) {
|
|
|
19756
20131
|
];
|
|
19757
20132
|
return lines.join("\n");
|
|
19758
20133
|
}
|
|
20134
|
+
function toScenarioStep(step, index, testCase) {
|
|
20135
|
+
const result = testCase.stepResults.find(
|
|
20136
|
+
(candidate) => candidate.index === index || candidate.stepId === step.id
|
|
20137
|
+
);
|
|
20138
|
+
return {
|
|
20139
|
+
id: step.id,
|
|
20140
|
+
index,
|
|
20141
|
+
keyword: step.keyword,
|
|
20142
|
+
text: step.text,
|
|
20143
|
+
status: result?.status ?? testCase.status,
|
|
20144
|
+
durationMs: result?.durationMs ?? step.durationMs ?? 0,
|
|
20145
|
+
errorMessage: result?.errorMessage,
|
|
20146
|
+
mode: step.mode,
|
|
20147
|
+
docKinds: (step.docs ?? []).map((doc) => doc.kind)
|
|
20148
|
+
};
|
|
20149
|
+
}
|
|
20150
|
+
function collectDocKinds(testCase) {
|
|
20151
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
20152
|
+
for (const doc of testCase.story.docs ?? []) {
|
|
20153
|
+
kinds.add(doc.kind);
|
|
20154
|
+
}
|
|
20155
|
+
for (const step of testCase.story.steps) {
|
|
20156
|
+
for (const doc of step.docs ?? []) {
|
|
20157
|
+
kinds.add(doc.kind);
|
|
20158
|
+
}
|
|
20159
|
+
}
|
|
20160
|
+
return [...kinds].sort();
|
|
20161
|
+
}
|
|
19759
20162
|
|
|
19760
20163
|
// src/review/conventions.ts
|
|
19761
20164
|
var CHANGE_TAG_PREFIX = "change:";
|
|
@@ -19803,18 +20206,18 @@ function deriveChangeType(tags) {
|
|
|
19803
20206
|
}
|
|
19804
20207
|
return "unknown";
|
|
19805
20208
|
}
|
|
19806
|
-
function extensionOf(
|
|
19807
|
-
const base =
|
|
20209
|
+
function extensionOf(path11) {
|
|
20210
|
+
const base = path11.split("/").pop() ?? path11;
|
|
19808
20211
|
const dot = base.lastIndexOf(".");
|
|
19809
20212
|
return dot === -1 ? "" : base.slice(dot + 1).toLowerCase();
|
|
19810
20213
|
}
|
|
19811
|
-
function isTestFile(
|
|
19812
|
-
return TEST_INFIX.test(
|
|
20214
|
+
function isTestFile(path11) {
|
|
20215
|
+
return TEST_INFIX.test(path11);
|
|
19813
20216
|
}
|
|
19814
|
-
function isReviewableSource(
|
|
19815
|
-
if (isTestFile(
|
|
19816
|
-
if (
|
|
19817
|
-
return CODE_EXTENSIONS.has(extensionOf(
|
|
20217
|
+
function isReviewableSource(path11) {
|
|
20218
|
+
if (isTestFile(path11)) return false;
|
|
20219
|
+
if (path11.endsWith(".d.ts")) return false;
|
|
20220
|
+
return CODE_EXTENSIONS.has(extensionOf(path11));
|
|
19818
20221
|
}
|
|
19819
20222
|
function testBaseKey(testFile) {
|
|
19820
20223
|
return testFile.replace(TEST_INFIX, "");
|
|
@@ -19918,7 +20321,7 @@ function toClaim(testCase, changedSourcePaths) {
|
|
|
19918
20321
|
const { strength, reasons } = gradeEvidence(testCase, audience);
|
|
19919
20322
|
const key = testBaseKey(testCase.sourceFile);
|
|
19920
20323
|
const coversFiles = changedSourcePaths.filter(
|
|
19921
|
-
(
|
|
20324
|
+
(path11) => sourceBaseKey(path11) === key
|
|
19922
20325
|
);
|
|
19923
20326
|
return {
|
|
19924
20327
|
id: testCase.id,
|
|
@@ -20451,6 +20854,7 @@ applyTheme(getEffectiveTheme());` : "";
|
|
|
20451
20854
|
// src/index.ts
|
|
20452
20855
|
var FORMAT_EXTENSIONS = {
|
|
20453
20856
|
astro: ".md",
|
|
20857
|
+
"behavior-manifest-json": ".behavior-manifest.json",
|
|
20454
20858
|
markdown: ".md",
|
|
20455
20859
|
html: ".html",
|
|
20456
20860
|
"cucumber-html": ".cucumber.html",
|
|
@@ -20458,6 +20862,7 @@ var FORMAT_EXTENSIONS = {
|
|
|
20458
20862
|
"cucumber-json": ".cucumber.json",
|
|
20459
20863
|
"cucumber-messages": ".ndjson",
|
|
20460
20864
|
confluence: ".adf.json",
|
|
20865
|
+
"scenario-index-json": ".scenarios-index.json",
|
|
20461
20866
|
"story-report-json": ".story-report.json"
|
|
20462
20867
|
};
|
|
20463
20868
|
var TEST_EXTENSIONS = [
|
|
@@ -20485,11 +20890,11 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
20485
20890
|
const ext = FORMAT_EXTENSIONS[format];
|
|
20486
20891
|
const effectiveName = outputName + (outputNameSuffix ?? "");
|
|
20487
20892
|
if (mode === "aggregated") {
|
|
20488
|
-
return toPosix(
|
|
20893
|
+
return toPosix(path10.join(baseOutputDir, `${effectiveName}${ext}`));
|
|
20489
20894
|
}
|
|
20490
20895
|
const normalizedSource = toPosix(sourceFile);
|
|
20491
|
-
const dirOfSource =
|
|
20492
|
-
let baseName =
|
|
20896
|
+
const dirOfSource = path10.posix.dirname(normalizedSource);
|
|
20897
|
+
let baseName = path10.posix.basename(normalizedSource);
|
|
20493
20898
|
for (const testExt of TEST_EXTENSIONS) {
|
|
20494
20899
|
if (baseName.endsWith(testExt)) {
|
|
20495
20900
|
baseName = baseName.slice(0, -testExt.length);
|
|
@@ -20498,9 +20903,9 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
20498
20903
|
}
|
|
20499
20904
|
const fileName = `${baseName}.${effectiveName}${ext}`;
|
|
20500
20905
|
if (colocatedStyle === "adjacent") {
|
|
20501
|
-
return toPosix(
|
|
20906
|
+
return toPosix(path10.posix.join(dirOfSource, fileName));
|
|
20502
20907
|
}
|
|
20503
|
-
return toPosix(
|
|
20908
|
+
return toPosix(path10.posix.join(baseOutputDir, dirOfSource, fileName));
|
|
20504
20909
|
}
|
|
20505
20910
|
function groupTestCasesByOutput(testCases, format, options, logger, outputNameSuffix) {
|
|
20506
20911
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -20586,6 +20991,12 @@ var ReportGenerator = class {
|
|
|
20586
20991
|
storyReportJson: {
|
|
20587
20992
|
pretty: options.storyReportJson?.pretty ?? true
|
|
20588
20993
|
},
|
|
20994
|
+
scenarioIndexJson: {
|
|
20995
|
+
pretty: options.scenarioIndexJson?.pretty ?? true
|
|
20996
|
+
},
|
|
20997
|
+
behaviorManifestJson: {
|
|
20998
|
+
pretty: options.behaviorManifestJson?.pretty ?? true
|
|
20999
|
+
},
|
|
20589
21000
|
cucumberMessages: {
|
|
20590
21001
|
uriStrategy: options.cucumberMessages?.uriStrategy ?? "sourceFile",
|
|
20591
21002
|
includeSynthetics: options.cucumberMessages?.includeSynthetics ?? true,
|
|
@@ -20701,8 +21112,8 @@ var ReportGenerator = class {
|
|
|
20701
21112
|
if (astroPaths) {
|
|
20702
21113
|
for (const mdPath of astroPaths) {
|
|
20703
21114
|
const content = await fsPromises.readFile(mdPath, "utf8");
|
|
20704
|
-
const mdDir =
|
|
20705
|
-
const assetsDir =
|
|
21115
|
+
const mdDir = path10.dirname(mdPath);
|
|
21116
|
+
const assetsDir = path10.resolve(this.options.astro.assetsDir);
|
|
20706
21117
|
const result = copyMarkdownAssets({
|
|
20707
21118
|
markdown: content,
|
|
20708
21119
|
markdownDir: mdDir,
|
|
@@ -20733,9 +21144,9 @@ var ReportGenerator = class {
|
|
|
20733
21144
|
if (groups.size === 0 && this.options.output.mode === "aggregated") {
|
|
20734
21145
|
const ext = FORMAT_EXTENSIONS[format];
|
|
20735
21146
|
const effectiveName = this.options.outputName + (outputNameSuffix ?? "");
|
|
20736
|
-
const outputPath = toPosix(
|
|
21147
|
+
const outputPath = toPosix(path10.join(this.options.outputDir, `${effectiveName}${ext}`));
|
|
20737
21148
|
const content = await this.formatContent(run, format);
|
|
20738
|
-
const dir =
|
|
21149
|
+
const dir = path10.dirname(outputPath);
|
|
20739
21150
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
20740
21151
|
await this.deps.writeFile(outputPath, content);
|
|
20741
21152
|
return [outputPath];
|
|
@@ -20747,7 +21158,7 @@ var ReportGenerator = class {
|
|
|
20747
21158
|
testCases
|
|
20748
21159
|
};
|
|
20749
21160
|
const content = await this.formatContent(groupRun, format);
|
|
20750
|
-
const dir =
|
|
21161
|
+
const dir = path10.dirname(outputPath);
|
|
20751
21162
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
20752
21163
|
await this.deps.writeFile(outputPath, content);
|
|
20753
21164
|
writtenPaths.push(outputPath);
|
|
@@ -20860,6 +21271,18 @@ var ReportGenerator = class {
|
|
|
20860
21271
|
});
|
|
20861
21272
|
return formatter.format(run);
|
|
20862
21273
|
}
|
|
21274
|
+
case "scenario-index-json": {
|
|
21275
|
+
const formatter = new ScenarioIndexJsonFormatter({
|
|
21276
|
+
pretty: this.options.scenarioIndexJson.pretty
|
|
21277
|
+
});
|
|
21278
|
+
return formatter.format(run);
|
|
21279
|
+
}
|
|
21280
|
+
case "behavior-manifest-json": {
|
|
21281
|
+
const formatter = new BehaviorManifestJsonFormatter({
|
|
21282
|
+
pretty: this.options.behaviorManifestJson.pretty
|
|
21283
|
+
});
|
|
21284
|
+
return formatter.format(run);
|
|
21285
|
+
}
|
|
20863
21286
|
default:
|
|
20864
21287
|
throw new Error(`Unknown format: ${format}`);
|
|
20865
21288
|
}
|
|
@@ -20876,7 +21299,7 @@ async function generateRunComparison(args) {
|
|
|
20876
21299
|
await fsPromises.mkdir(outputDir, { recursive: true });
|
|
20877
21300
|
for (const format of args.formats) {
|
|
20878
21301
|
const ext = format === "html" ? ".html" : ".md";
|
|
20879
|
-
const outputPath = toPosix(
|
|
21302
|
+
const outputPath = toPosix(path10.join(outputDir, `${outputName}${ext}`));
|
|
20880
21303
|
const content = format === "html" ? new RunDiffHtmlFormatter({ title: args.title }).format(diff) : new RunDiffMarkdownFormatter({ title: args.title }).format(diff);
|
|
20881
21304
|
await fsPromises.writeFile(outputPath, content, "utf8");
|
|
20882
21305
|
files.push(outputPath);
|
|
@@ -20898,6 +21321,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
|
|
|
20898
21321
|
// Annotate the CommonJS export names for ESM import in node:
|
|
20899
21322
|
0 && (module.exports = {
|
|
20900
21323
|
AstroFormatter,
|
|
21324
|
+
BehaviorManifestJsonFormatter,
|
|
20901
21325
|
ConfluenceFormatter,
|
|
20902
21326
|
CucumberHtmlFormatter,
|
|
20903
21327
|
CucumberJsonFormatter,
|
|
@@ -20918,6 +21342,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
|
|
|
20918
21342
|
STORY_META_KEY,
|
|
20919
21343
|
STORY_REPORT_SCHEMA_MAJOR,
|
|
20920
21344
|
STORY_REPORT_SCHEMA_VERSION,
|
|
21345
|
+
ScenarioIndexJsonFormatter,
|
|
20921
21346
|
StoryReportJsonFormatter,
|
|
20922
21347
|
adaptJestRun,
|
|
20923
21348
|
adaptPlaywrightRun,
|
|
@@ -20928,6 +21353,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
|
|
|
20928
21353
|
calculateFlakiness,
|
|
20929
21354
|
calculateStability,
|
|
20930
21355
|
canonicalizeRun,
|
|
21356
|
+
classifyStatusChange,
|
|
20931
21357
|
clearVersionCache,
|
|
20932
21358
|
computeTestMetrics,
|
|
20933
21359
|
copyMarkdownAssets,
|
|
@@ -20939,6 +21365,7 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
|
|
|
20939
21365
|
detectCI,
|
|
20940
21366
|
detectPerformanceTrend,
|
|
20941
21367
|
diffRuns,
|
|
21368
|
+
diffStoryReports,
|
|
20942
21369
|
findGitDir,
|
|
20943
21370
|
formatDuration,
|
|
20944
21371
|
generateRunComparison,
|
|
@@ -20966,21 +21393,26 @@ function normalizePlaywrightResults(testResults, adapterOptions, canonicalizeOpt
|
|
|
20966
21393
|
readBranchName,
|
|
20967
21394
|
readGitSha,
|
|
20968
21395
|
readPackageVersion,
|
|
21396
|
+
regenerateArtifacts,
|
|
20969
21397
|
resolveAttachment,
|
|
20970
21398
|
resolveAttachments,
|
|
20971
21399
|
resolveTheme,
|
|
20972
21400
|
resolveTraceUrl,
|
|
20973
21401
|
rewriteAssetPaths,
|
|
20974
21402
|
saveHistory,
|
|
21403
|
+
scenariosCoveringPaths,
|
|
20975
21404
|
sendNotifications,
|
|
20976
21405
|
sendSlackNotification,
|
|
20977
21406
|
sendTeamsNotification,
|
|
20978
21407
|
sendWebhookNotification,
|
|
20979
21408
|
signBody,
|
|
20980
21409
|
slugify,
|
|
21410
|
+
startWatch,
|
|
20981
21411
|
stripAnsi,
|
|
21412
|
+
toBehaviorManifest,
|
|
20982
21413
|
toCIInfo,
|
|
20983
21414
|
toRawCIInfo,
|
|
21415
|
+
toScenarioIndex,
|
|
20984
21416
|
toStoryReport,
|
|
20985
21417
|
tryGetActiveOtelContext,
|
|
20986
21418
|
updateHistory,
|