@reportforge/playwright-pdf 0.5.1 → 0.6.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/CHANGELOG.md +12 -0
- package/README.md +35 -0
- package/dist/demo/cli.js +154 -49
- package/dist/index.d.mts +40 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +155 -50
- package/dist/index.mjs +155 -50
- package/dist/templates/layouts/detailed.hbs +14 -10
- package/dist/templates/layouts/executive.hbs +16 -8
- package/dist/templates/layouts/minimal.hbs +19 -5
- package/dist/templates/styles/base.css +198 -1
- package/dist/templates/styles/detailed.css +3 -104
- package/dist/templates/styles/executive.css +4 -99
- package/dist/templates/styles/minimal.css +4 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10332,6 +10332,113 @@ var DEFAULT_OPTIONS = {
|
|
|
10332
10332
|
flakinessTopN: 5
|
|
10333
10333
|
};
|
|
10334
10334
|
|
|
10335
|
+
// src/templates/sections.ts
|
|
10336
|
+
init_cjs_shims();
|
|
10337
|
+
var SECTION_KEYS = [
|
|
10338
|
+
// block toggles
|
|
10339
|
+
"coverPage",
|
|
10340
|
+
"analysisOneliner",
|
|
10341
|
+
"releaseGate",
|
|
10342
|
+
"summary",
|
|
10343
|
+
"charts",
|
|
10344
|
+
"trend",
|
|
10345
|
+
"requirementsMatrix",
|
|
10346
|
+
"ciEnvironment",
|
|
10347
|
+
"suiteBreakdown",
|
|
10348
|
+
"failureDeepDive",
|
|
10349
|
+
"failureAnalysis",
|
|
10350
|
+
"slowTests",
|
|
10351
|
+
"defectLog",
|
|
10352
|
+
// display modifiers
|
|
10353
|
+
"passRate",
|
|
10354
|
+
"fullEnvironment",
|
|
10355
|
+
"retries",
|
|
10356
|
+
"fullFailures",
|
|
10357
|
+
"stackTraces"
|
|
10358
|
+
];
|
|
10359
|
+
var SECTION_DEFAULTS = {
|
|
10360
|
+
minimal: {
|
|
10361
|
+
coverPage: false,
|
|
10362
|
+
analysisOneliner: false,
|
|
10363
|
+
releaseGate: true,
|
|
10364
|
+
summary: true,
|
|
10365
|
+
charts: false,
|
|
10366
|
+
trend: false,
|
|
10367
|
+
requirementsMatrix: false,
|
|
10368
|
+
ciEnvironment: true,
|
|
10369
|
+
suiteBreakdown: true,
|
|
10370
|
+
failureDeepDive: true,
|
|
10371
|
+
failureAnalysis: false,
|
|
10372
|
+
slowTests: false,
|
|
10373
|
+
defectLog: false,
|
|
10374
|
+
passRate: true,
|
|
10375
|
+
fullEnvironment: false,
|
|
10376
|
+
retries: true,
|
|
10377
|
+
fullFailures: true,
|
|
10378
|
+
stackTraces: true
|
|
10379
|
+
},
|
|
10380
|
+
detailed: {
|
|
10381
|
+
coverPage: false,
|
|
10382
|
+
analysisOneliner: false,
|
|
10383
|
+
releaseGate: true,
|
|
10384
|
+
summary: true,
|
|
10385
|
+
charts: true,
|
|
10386
|
+
trend: true,
|
|
10387
|
+
requirementsMatrix: true,
|
|
10388
|
+
ciEnvironment: true,
|
|
10389
|
+
suiteBreakdown: true,
|
|
10390
|
+
failureDeepDive: true,
|
|
10391
|
+
failureAnalysis: true,
|
|
10392
|
+
slowTests: true,
|
|
10393
|
+
defectLog: true,
|
|
10394
|
+
passRate: true,
|
|
10395
|
+
fullEnvironment: true,
|
|
10396
|
+
retries: true,
|
|
10397
|
+
fullFailures: true,
|
|
10398
|
+
stackTraces: true
|
|
10399
|
+
},
|
|
10400
|
+
executive: {
|
|
10401
|
+
coverPage: true,
|
|
10402
|
+
analysisOneliner: true,
|
|
10403
|
+
releaseGate: true,
|
|
10404
|
+
summary: true,
|
|
10405
|
+
charts: true,
|
|
10406
|
+
trend: true,
|
|
10407
|
+
requirementsMatrix: false,
|
|
10408
|
+
ciEnvironment: true,
|
|
10409
|
+
suiteBreakdown: false,
|
|
10410
|
+
failureDeepDive: true,
|
|
10411
|
+
failureAnalysis: false,
|
|
10412
|
+
slowTests: true,
|
|
10413
|
+
defectLog: false,
|
|
10414
|
+
passRate: true,
|
|
10415
|
+
fullEnvironment: false,
|
|
10416
|
+
retries: false,
|
|
10417
|
+
fullFailures: false,
|
|
10418
|
+
stackTraces: false
|
|
10419
|
+
}
|
|
10420
|
+
};
|
|
10421
|
+
var SECTION_KEY_SET = new Set(SECTION_KEYS);
|
|
10422
|
+
function resolveSections(template, userSections) {
|
|
10423
|
+
const base = SECTION_DEFAULTS[template];
|
|
10424
|
+
if (!userSections) return { ...base };
|
|
10425
|
+
const flat = {};
|
|
10426
|
+
for (const [k, v] of Object.entries(userSections)) {
|
|
10427
|
+
if (v !== void 0 && SECTION_KEY_SET.has(k)) flat[k] = v;
|
|
10428
|
+
}
|
|
10429
|
+
const perTemplateRaw = userSections[template] ?? {};
|
|
10430
|
+
const perTemplate = {};
|
|
10431
|
+
for (const [k, v] of Object.entries(perTemplateRaw)) {
|
|
10432
|
+
if (v !== void 0) perTemplate[k] = v;
|
|
10433
|
+
}
|
|
10434
|
+
const result = { ...base, ...flat, ...perTemplate };
|
|
10435
|
+
if (!result.charts) result.trend = false;
|
|
10436
|
+
return result;
|
|
10437
|
+
}
|
|
10438
|
+
function allSectionsOn() {
|
|
10439
|
+
return Object.fromEntries(SECTION_KEYS.map((k) => [k, true]));
|
|
10440
|
+
}
|
|
10441
|
+
|
|
10335
10442
|
// src/config/schema.ts
|
|
10336
10443
|
var hexColor = external_exports.string().regex(
|
|
10337
10444
|
/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/,
|
|
@@ -10364,6 +10471,15 @@ var failureAnalysisConfigSchema = external_exports.object({
|
|
|
10364
10471
|
collectUnclassified: external_exports.boolean().default(true),
|
|
10365
10472
|
autoUpdateModel: external_exports.boolean().default(true)
|
|
10366
10473
|
}).default({});
|
|
10474
|
+
var sectionFlagsShape = Object.fromEntries(
|
|
10475
|
+
SECTION_KEYS.map((k) => [k, external_exports.boolean().optional()])
|
|
10476
|
+
);
|
|
10477
|
+
var sectionFlagsSchema = external_exports.object(sectionFlagsShape).strict();
|
|
10478
|
+
var sectionsSchema = sectionFlagsSchema.extend({
|
|
10479
|
+
minimal: sectionFlagsSchema.optional(),
|
|
10480
|
+
detailed: sectionFlagsSchema.optional(),
|
|
10481
|
+
executive: sectionFlagsSchema.optional()
|
|
10482
|
+
}).strict();
|
|
10367
10483
|
var ReporterOptionsSchema = external_exports.object({
|
|
10368
10484
|
outputFile: external_exports.string().optional().default(DEFAULT_OPTIONS.outputFile),
|
|
10369
10485
|
template: external_exports.union([
|
|
@@ -10401,7 +10517,8 @@ var ReporterOptionsSchema = external_exports.object({
|
|
|
10401
10517
|
).min(1, "templatePath array must not be empty")
|
|
10402
10518
|
]).optional().transform(
|
|
10403
10519
|
(v) => v === void 0 ? void 0 : Array.isArray(v) ? v : [v]
|
|
10404
|
-
)
|
|
10520
|
+
),
|
|
10521
|
+
sections: sectionsSchema.optional()
|
|
10405
10522
|
});
|
|
10406
10523
|
function parseOptions(raw) {
|
|
10407
10524
|
const result = ReporterOptionsSchema.safeParse(raw ?? {});
|
|
@@ -11913,11 +12030,23 @@ function formatDuration(ms) {
|
|
|
11913
12030
|
function jsonForInlineScript(value) {
|
|
11914
12031
|
return JSON.stringify(value).replace(/<\//g, "<\\/");
|
|
11915
12032
|
}
|
|
12033
|
+
function deriveOptions(s) {
|
|
12034
|
+
return {
|
|
12035
|
+
showCharts: s.charts,
|
|
12036
|
+
showTrend: s.trend,
|
|
12037
|
+
showStackTraces: s.stackTraces,
|
|
12038
|
+
showFullEnvironment: s.fullEnvironment,
|
|
12039
|
+
showPassRate: s.passRate,
|
|
12040
|
+
showRetries: s.retries,
|
|
12041
|
+
showFullFailures: s.fullFailures
|
|
12042
|
+
};
|
|
12043
|
+
}
|
|
11916
12044
|
var TemplateEngine = class {
|
|
11917
12045
|
constructor() {
|
|
11918
12046
|
this.chartjsInline = "";
|
|
11919
12047
|
this.fontsBundleCss = "";
|
|
11920
12048
|
this.customTemplateCache = /* @__PURE__ */ new Map();
|
|
12049
|
+
this.styleCache = /* @__PURE__ */ new Map();
|
|
11921
12050
|
this.handlebars = import_handlebars.default.create();
|
|
11922
12051
|
this.templatesDir = import_path3.default.resolve(__dirname, "templates");
|
|
11923
12052
|
if (!import_fs4.default.existsSync(this.templatesDir)) {
|
|
@@ -11937,14 +12066,14 @@ var TemplateEngine = class {
|
|
|
11937
12066
|
setChartjsBundle(inline) {
|
|
11938
12067
|
this.chartjsInline = inline;
|
|
11939
12068
|
}
|
|
11940
|
-
render(data, template) {
|
|
12069
|
+
render(data, template, userSections) {
|
|
11941
12070
|
const layoutPath = import_path3.default.join(this.templatesDir, "layouts", `${template}.hbs`);
|
|
11942
12071
|
if (!import_fs4.default.existsSync(layoutPath)) {
|
|
11943
12072
|
throw new Error(`[reportforge] Template layout not found: ${layoutPath}`);
|
|
11944
12073
|
}
|
|
11945
12074
|
const layoutSource = import_fs4.default.readFileSync(layoutPath, "utf8");
|
|
11946
12075
|
const compiledLayout = this.handlebars.compile(layoutSource);
|
|
11947
|
-
const ctx = this.buildContext(data, template);
|
|
12076
|
+
const ctx = this.buildContext(data, template, userSections);
|
|
11948
12077
|
return compiledLayout(ctx);
|
|
11949
12078
|
}
|
|
11950
12079
|
renderFromPath(data, filePath) {
|
|
@@ -11959,17 +12088,11 @@ var TemplateEngine = class {
|
|
|
11959
12088
|
return compiledFn(this.buildCustomContext(data));
|
|
11960
12089
|
}
|
|
11961
12090
|
buildCustomContext(data) {
|
|
12091
|
+
const sections = allSectionsOn();
|
|
11962
12092
|
return {
|
|
11963
12093
|
...data,
|
|
11964
|
-
options:
|
|
11965
|
-
|
|
11966
|
-
showTrend: true,
|
|
11967
|
-
showStackTraces: true,
|
|
11968
|
-
showFullEnvironment: true,
|
|
11969
|
-
showPassRate: true,
|
|
11970
|
-
showRetries: true,
|
|
11971
|
-
showFullFailures: true
|
|
11972
|
-
},
|
|
12094
|
+
options: deriveOptions(sections),
|
|
12095
|
+
sections,
|
|
11973
12096
|
tagGroups: this.buildTagGroups(data),
|
|
11974
12097
|
slowTests: this.buildSlowTests(data),
|
|
11975
12098
|
baseCSS: this.fontsBundleCss + "\n" + this.readStyle("base.css"),
|
|
@@ -11977,47 +12100,20 @@ var TemplateEngine = class {
|
|
|
11977
12100
|
chartjsScript: this.buildChartjsScript()
|
|
11978
12101
|
};
|
|
11979
12102
|
}
|
|
11980
|
-
buildContext(data, template) {
|
|
12103
|
+
buildContext(data, template, userSections) {
|
|
11981
12104
|
const baseCSS = this.fontsBundleCss + "\n" + this.readStyle("base.css");
|
|
11982
12105
|
const templateCSS = this.readStyle(`${template}.css`);
|
|
11983
|
-
const
|
|
11984
|
-
|
|
11985
|
-
showCharts: false,
|
|
11986
|
-
showTrend: false,
|
|
11987
|
-
showStackTraces: true,
|
|
11988
|
-
showFullEnvironment: false,
|
|
11989
|
-
showPassRate: true,
|
|
11990
|
-
showRetries: true,
|
|
11991
|
-
showFullFailures: true
|
|
11992
|
-
},
|
|
11993
|
-
detailed: {
|
|
11994
|
-
showCharts: true,
|
|
11995
|
-
showTrend: true,
|
|
11996
|
-
showStackTraces: true,
|
|
11997
|
-
showFullEnvironment: true,
|
|
11998
|
-
showPassRate: true,
|
|
11999
|
-
showRetries: true,
|
|
12000
|
-
showFullFailures: true
|
|
12001
|
-
},
|
|
12002
|
-
executive: {
|
|
12003
|
-
showCharts: true,
|
|
12004
|
-
showTrend: true,
|
|
12005
|
-
showStackTraces: false,
|
|
12006
|
-
showFullEnvironment: false,
|
|
12007
|
-
showPassRate: true,
|
|
12008
|
-
showRetries: false,
|
|
12009
|
-
showFullFailures: false
|
|
12010
|
-
}
|
|
12011
|
-
};
|
|
12012
|
-
const chartjsScript = this.buildChartjsScript();
|
|
12106
|
+
const sections = resolveSections(template, userSections);
|
|
12107
|
+
const options = deriveOptions(sections);
|
|
12013
12108
|
return {
|
|
12014
12109
|
...data,
|
|
12015
|
-
options
|
|
12110
|
+
options,
|
|
12111
|
+
sections,
|
|
12016
12112
|
tagGroups: this.buildTagGroups(data),
|
|
12017
12113
|
slowTests: this.buildSlowTests(data),
|
|
12018
12114
|
baseCSS,
|
|
12019
12115
|
templateCSS,
|
|
12020
|
-
chartjsScript
|
|
12116
|
+
chartjsScript: this.buildChartjsScript()
|
|
12021
12117
|
};
|
|
12022
12118
|
}
|
|
12023
12119
|
buildChartjsScript() {
|
|
@@ -12065,9 +12161,12 @@ var TemplateEngine = class {
|
|
|
12065
12161
|
return tests.sort((a, b) => b.durationMs - a.durationMs).slice(0, 10);
|
|
12066
12162
|
}
|
|
12067
12163
|
readStyle(filename) {
|
|
12164
|
+
const cached = this.styleCache.get(filename);
|
|
12165
|
+
if (cached !== void 0) return cached;
|
|
12068
12166
|
const stylePath = import_path3.default.join(this.templatesDir, "styles", filename);
|
|
12069
|
-
|
|
12070
|
-
|
|
12167
|
+
const css = import_fs4.default.existsSync(stylePath) ? import_fs4.default.readFileSync(stylePath, "utf8") : "";
|
|
12168
|
+
this.styleCache.set(filename, css);
|
|
12169
|
+
return css;
|
|
12071
12170
|
}
|
|
12072
12171
|
registerPartials() {
|
|
12073
12172
|
const partialsDir = import_path3.default.join(this.templatesDir, "partials");
|
|
@@ -12622,6 +12721,12 @@ var PdfGenerator = class {
|
|
|
12622
12721
|
`Compression: level=${compression.effective} jpeg-q=${compression.quality} max-w=${compression.maxWidth}px inline-failures\u2264${compression.maxInlineFailures}`
|
|
12623
12722
|
);
|
|
12624
12723
|
const outputPaths = [];
|
|
12724
|
+
if (options.sections !== void 0) {
|
|
12725
|
+
const hasCustom = sources.some((s) => s.kind !== "builtin");
|
|
12726
|
+
if (hasCustom) {
|
|
12727
|
+
logger.warn('[reportforge] "sections" applies to built-in templates only; it is ignored for custom templatePath templates.');
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12625
12730
|
const { page } = await this.browserManager.launch(options.puppeteerExecutablePath);
|
|
12626
12731
|
try {
|
|
12627
12732
|
for (const source of sources) {
|
|
@@ -12729,13 +12834,13 @@ var PdfGenerator = class {
|
|
|
12729
12834
|
}
|
|
12730
12835
|
const templateLabel = source.kind === "builtin" ? source.id : source.label;
|
|
12731
12836
|
logger.info(`Rendering template: ${templateLabel}`);
|
|
12732
|
-
const html = source.kind === "builtin" ? this.templateEngine.render(renderData, source.id) : this.templateEngine.renderFromPath(renderData, source.absolutePath);
|
|
12837
|
+
const html = source.kind === "builtin" ? this.templateEngine.render(renderData, source.id, options.sections) : this.templateEngine.renderFromPath(renderData, source.absolutePath);
|
|
12733
12838
|
const tempHtmlPath = await this.htmlWriter.write(html);
|
|
12734
12839
|
const fileUrl = this.htmlWriter.toFileUrl(tempHtmlPath);
|
|
12735
12840
|
try {
|
|
12736
12841
|
logger.info(`Navigating to temp HTML (${Math.round(html.length / 1024)} KB)...`);
|
|
12737
12842
|
await page.goto(fileUrl, { waitUntil: "domcontentloaded", timeout: 6e4 });
|
|
12738
|
-
const showCharts = source.kind === "builtin" ? source.id
|
|
12843
|
+
const showCharts = source.kind === "builtin" ? resolveSections(source.id, options.sections).charts : true;
|
|
12739
12844
|
await this.chartRenderer.waitForCharts(page, showCharts);
|
|
12740
12845
|
logger.info(`Generating PDF \u2192 ${import_path8.default.relative(process.cwd(), outputPath)}`);
|
|
12741
12846
|
await page.pdf({
|
|
@@ -13126,7 +13231,7 @@ var PdfReporter = class {
|
|
|
13126
13231
|
this.dataCollector = new DataCollector();
|
|
13127
13232
|
this.pdfGenerator = new PdfGenerator();
|
|
13128
13233
|
this.options = parseOptions(rawOptions);
|
|
13129
|
-
const version = true ? "0.
|
|
13234
|
+
const version = true ? "0.6.0" : "0.x";
|
|
13130
13235
|
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
13131
13236
|
this.licenseClient = new LicenseClient({
|
|
13132
13237
|
licenseKey: this.options.licenseKey,
|
package/dist/index.mjs
CHANGED
|
@@ -10333,6 +10333,113 @@ var DEFAULT_OPTIONS = {
|
|
|
10333
10333
|
flakinessTopN: 5
|
|
10334
10334
|
};
|
|
10335
10335
|
|
|
10336
|
+
// src/templates/sections.ts
|
|
10337
|
+
init_esm_shims();
|
|
10338
|
+
var SECTION_KEYS = [
|
|
10339
|
+
// block toggles
|
|
10340
|
+
"coverPage",
|
|
10341
|
+
"analysisOneliner",
|
|
10342
|
+
"releaseGate",
|
|
10343
|
+
"summary",
|
|
10344
|
+
"charts",
|
|
10345
|
+
"trend",
|
|
10346
|
+
"requirementsMatrix",
|
|
10347
|
+
"ciEnvironment",
|
|
10348
|
+
"suiteBreakdown",
|
|
10349
|
+
"failureDeepDive",
|
|
10350
|
+
"failureAnalysis",
|
|
10351
|
+
"slowTests",
|
|
10352
|
+
"defectLog",
|
|
10353
|
+
// display modifiers
|
|
10354
|
+
"passRate",
|
|
10355
|
+
"fullEnvironment",
|
|
10356
|
+
"retries",
|
|
10357
|
+
"fullFailures",
|
|
10358
|
+
"stackTraces"
|
|
10359
|
+
];
|
|
10360
|
+
var SECTION_DEFAULTS = {
|
|
10361
|
+
minimal: {
|
|
10362
|
+
coverPage: false,
|
|
10363
|
+
analysisOneliner: false,
|
|
10364
|
+
releaseGate: true,
|
|
10365
|
+
summary: true,
|
|
10366
|
+
charts: false,
|
|
10367
|
+
trend: false,
|
|
10368
|
+
requirementsMatrix: false,
|
|
10369
|
+
ciEnvironment: true,
|
|
10370
|
+
suiteBreakdown: true,
|
|
10371
|
+
failureDeepDive: true,
|
|
10372
|
+
failureAnalysis: false,
|
|
10373
|
+
slowTests: false,
|
|
10374
|
+
defectLog: false,
|
|
10375
|
+
passRate: true,
|
|
10376
|
+
fullEnvironment: false,
|
|
10377
|
+
retries: true,
|
|
10378
|
+
fullFailures: true,
|
|
10379
|
+
stackTraces: true
|
|
10380
|
+
},
|
|
10381
|
+
detailed: {
|
|
10382
|
+
coverPage: false,
|
|
10383
|
+
analysisOneliner: false,
|
|
10384
|
+
releaseGate: true,
|
|
10385
|
+
summary: true,
|
|
10386
|
+
charts: true,
|
|
10387
|
+
trend: true,
|
|
10388
|
+
requirementsMatrix: true,
|
|
10389
|
+
ciEnvironment: true,
|
|
10390
|
+
suiteBreakdown: true,
|
|
10391
|
+
failureDeepDive: true,
|
|
10392
|
+
failureAnalysis: true,
|
|
10393
|
+
slowTests: true,
|
|
10394
|
+
defectLog: true,
|
|
10395
|
+
passRate: true,
|
|
10396
|
+
fullEnvironment: true,
|
|
10397
|
+
retries: true,
|
|
10398
|
+
fullFailures: true,
|
|
10399
|
+
stackTraces: true
|
|
10400
|
+
},
|
|
10401
|
+
executive: {
|
|
10402
|
+
coverPage: true,
|
|
10403
|
+
analysisOneliner: true,
|
|
10404
|
+
releaseGate: true,
|
|
10405
|
+
summary: true,
|
|
10406
|
+
charts: true,
|
|
10407
|
+
trend: true,
|
|
10408
|
+
requirementsMatrix: false,
|
|
10409
|
+
ciEnvironment: true,
|
|
10410
|
+
suiteBreakdown: false,
|
|
10411
|
+
failureDeepDive: true,
|
|
10412
|
+
failureAnalysis: false,
|
|
10413
|
+
slowTests: true,
|
|
10414
|
+
defectLog: false,
|
|
10415
|
+
passRate: true,
|
|
10416
|
+
fullEnvironment: false,
|
|
10417
|
+
retries: false,
|
|
10418
|
+
fullFailures: false,
|
|
10419
|
+
stackTraces: false
|
|
10420
|
+
}
|
|
10421
|
+
};
|
|
10422
|
+
var SECTION_KEY_SET = new Set(SECTION_KEYS);
|
|
10423
|
+
function resolveSections(template, userSections) {
|
|
10424
|
+
const base = SECTION_DEFAULTS[template];
|
|
10425
|
+
if (!userSections) return { ...base };
|
|
10426
|
+
const flat = {};
|
|
10427
|
+
for (const [k, v] of Object.entries(userSections)) {
|
|
10428
|
+
if (v !== void 0 && SECTION_KEY_SET.has(k)) flat[k] = v;
|
|
10429
|
+
}
|
|
10430
|
+
const perTemplateRaw = userSections[template] ?? {};
|
|
10431
|
+
const perTemplate = {};
|
|
10432
|
+
for (const [k, v] of Object.entries(perTemplateRaw)) {
|
|
10433
|
+
if (v !== void 0) perTemplate[k] = v;
|
|
10434
|
+
}
|
|
10435
|
+
const result = { ...base, ...flat, ...perTemplate };
|
|
10436
|
+
if (!result.charts) result.trend = false;
|
|
10437
|
+
return result;
|
|
10438
|
+
}
|
|
10439
|
+
function allSectionsOn() {
|
|
10440
|
+
return Object.fromEntries(SECTION_KEYS.map((k) => [k, true]));
|
|
10441
|
+
}
|
|
10442
|
+
|
|
10336
10443
|
// src/config/schema.ts
|
|
10337
10444
|
var hexColor = external_exports.string().regex(
|
|
10338
10445
|
/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/,
|
|
@@ -10365,6 +10472,15 @@ var failureAnalysisConfigSchema = external_exports.object({
|
|
|
10365
10472
|
collectUnclassified: external_exports.boolean().default(true),
|
|
10366
10473
|
autoUpdateModel: external_exports.boolean().default(true)
|
|
10367
10474
|
}).default({});
|
|
10475
|
+
var sectionFlagsShape = Object.fromEntries(
|
|
10476
|
+
SECTION_KEYS.map((k) => [k, external_exports.boolean().optional()])
|
|
10477
|
+
);
|
|
10478
|
+
var sectionFlagsSchema = external_exports.object(sectionFlagsShape).strict();
|
|
10479
|
+
var sectionsSchema = sectionFlagsSchema.extend({
|
|
10480
|
+
minimal: sectionFlagsSchema.optional(),
|
|
10481
|
+
detailed: sectionFlagsSchema.optional(),
|
|
10482
|
+
executive: sectionFlagsSchema.optional()
|
|
10483
|
+
}).strict();
|
|
10368
10484
|
var ReporterOptionsSchema = external_exports.object({
|
|
10369
10485
|
outputFile: external_exports.string().optional().default(DEFAULT_OPTIONS.outputFile),
|
|
10370
10486
|
template: external_exports.union([
|
|
@@ -10402,7 +10518,8 @@ var ReporterOptionsSchema = external_exports.object({
|
|
|
10402
10518
|
).min(1, "templatePath array must not be empty")
|
|
10403
10519
|
]).optional().transform(
|
|
10404
10520
|
(v) => v === void 0 ? void 0 : Array.isArray(v) ? v : [v]
|
|
10405
|
-
)
|
|
10521
|
+
),
|
|
10522
|
+
sections: sectionsSchema.optional()
|
|
10406
10523
|
});
|
|
10407
10524
|
function parseOptions(raw) {
|
|
10408
10525
|
const result = ReporterOptionsSchema.safeParse(raw ?? {});
|
|
@@ -11914,11 +12031,23 @@ function formatDuration(ms) {
|
|
|
11914
12031
|
function jsonForInlineScript(value) {
|
|
11915
12032
|
return JSON.stringify(value).replace(/<\//g, "<\\/");
|
|
11916
12033
|
}
|
|
12034
|
+
function deriveOptions(s) {
|
|
12035
|
+
return {
|
|
12036
|
+
showCharts: s.charts,
|
|
12037
|
+
showTrend: s.trend,
|
|
12038
|
+
showStackTraces: s.stackTraces,
|
|
12039
|
+
showFullEnvironment: s.fullEnvironment,
|
|
12040
|
+
showPassRate: s.passRate,
|
|
12041
|
+
showRetries: s.retries,
|
|
12042
|
+
showFullFailures: s.fullFailures
|
|
12043
|
+
};
|
|
12044
|
+
}
|
|
11917
12045
|
var TemplateEngine = class {
|
|
11918
12046
|
constructor() {
|
|
11919
12047
|
this.chartjsInline = "";
|
|
11920
12048
|
this.fontsBundleCss = "";
|
|
11921
12049
|
this.customTemplateCache = /* @__PURE__ */ new Map();
|
|
12050
|
+
this.styleCache = /* @__PURE__ */ new Map();
|
|
11922
12051
|
this.handlebars = import_handlebars.default.create();
|
|
11923
12052
|
this.templatesDir = path7.resolve(__dirname, "templates");
|
|
11924
12053
|
if (!fs5.existsSync(this.templatesDir)) {
|
|
@@ -11938,14 +12067,14 @@ var TemplateEngine = class {
|
|
|
11938
12067
|
setChartjsBundle(inline) {
|
|
11939
12068
|
this.chartjsInline = inline;
|
|
11940
12069
|
}
|
|
11941
|
-
render(data, template) {
|
|
12070
|
+
render(data, template, userSections) {
|
|
11942
12071
|
const layoutPath = path7.join(this.templatesDir, "layouts", `${template}.hbs`);
|
|
11943
12072
|
if (!fs5.existsSync(layoutPath)) {
|
|
11944
12073
|
throw new Error(`[reportforge] Template layout not found: ${layoutPath}`);
|
|
11945
12074
|
}
|
|
11946
12075
|
const layoutSource = fs5.readFileSync(layoutPath, "utf8");
|
|
11947
12076
|
const compiledLayout = this.handlebars.compile(layoutSource);
|
|
11948
|
-
const ctx = this.buildContext(data, template);
|
|
12077
|
+
const ctx = this.buildContext(data, template, userSections);
|
|
11949
12078
|
return compiledLayout(ctx);
|
|
11950
12079
|
}
|
|
11951
12080
|
renderFromPath(data, filePath) {
|
|
@@ -11960,17 +12089,11 @@ var TemplateEngine = class {
|
|
|
11960
12089
|
return compiledFn(this.buildCustomContext(data));
|
|
11961
12090
|
}
|
|
11962
12091
|
buildCustomContext(data) {
|
|
12092
|
+
const sections = allSectionsOn();
|
|
11963
12093
|
return {
|
|
11964
12094
|
...data,
|
|
11965
|
-
options:
|
|
11966
|
-
|
|
11967
|
-
showTrend: true,
|
|
11968
|
-
showStackTraces: true,
|
|
11969
|
-
showFullEnvironment: true,
|
|
11970
|
-
showPassRate: true,
|
|
11971
|
-
showRetries: true,
|
|
11972
|
-
showFullFailures: true
|
|
11973
|
-
},
|
|
12095
|
+
options: deriveOptions(sections),
|
|
12096
|
+
sections,
|
|
11974
12097
|
tagGroups: this.buildTagGroups(data),
|
|
11975
12098
|
slowTests: this.buildSlowTests(data),
|
|
11976
12099
|
baseCSS: this.fontsBundleCss + "\n" + this.readStyle("base.css"),
|
|
@@ -11978,47 +12101,20 @@ var TemplateEngine = class {
|
|
|
11978
12101
|
chartjsScript: this.buildChartjsScript()
|
|
11979
12102
|
};
|
|
11980
12103
|
}
|
|
11981
|
-
buildContext(data, template) {
|
|
12104
|
+
buildContext(data, template, userSections) {
|
|
11982
12105
|
const baseCSS = this.fontsBundleCss + "\n" + this.readStyle("base.css");
|
|
11983
12106
|
const templateCSS = this.readStyle(`${template}.css`);
|
|
11984
|
-
const
|
|
11985
|
-
|
|
11986
|
-
showCharts: false,
|
|
11987
|
-
showTrend: false,
|
|
11988
|
-
showStackTraces: true,
|
|
11989
|
-
showFullEnvironment: false,
|
|
11990
|
-
showPassRate: true,
|
|
11991
|
-
showRetries: true,
|
|
11992
|
-
showFullFailures: true
|
|
11993
|
-
},
|
|
11994
|
-
detailed: {
|
|
11995
|
-
showCharts: true,
|
|
11996
|
-
showTrend: true,
|
|
11997
|
-
showStackTraces: true,
|
|
11998
|
-
showFullEnvironment: true,
|
|
11999
|
-
showPassRate: true,
|
|
12000
|
-
showRetries: true,
|
|
12001
|
-
showFullFailures: true
|
|
12002
|
-
},
|
|
12003
|
-
executive: {
|
|
12004
|
-
showCharts: true,
|
|
12005
|
-
showTrend: true,
|
|
12006
|
-
showStackTraces: false,
|
|
12007
|
-
showFullEnvironment: false,
|
|
12008
|
-
showPassRate: true,
|
|
12009
|
-
showRetries: false,
|
|
12010
|
-
showFullFailures: false
|
|
12011
|
-
}
|
|
12012
|
-
};
|
|
12013
|
-
const chartjsScript = this.buildChartjsScript();
|
|
12107
|
+
const sections = resolveSections(template, userSections);
|
|
12108
|
+
const options = deriveOptions(sections);
|
|
12014
12109
|
return {
|
|
12015
12110
|
...data,
|
|
12016
|
-
options
|
|
12111
|
+
options,
|
|
12112
|
+
sections,
|
|
12017
12113
|
tagGroups: this.buildTagGroups(data),
|
|
12018
12114
|
slowTests: this.buildSlowTests(data),
|
|
12019
12115
|
baseCSS,
|
|
12020
12116
|
templateCSS,
|
|
12021
|
-
chartjsScript
|
|
12117
|
+
chartjsScript: this.buildChartjsScript()
|
|
12022
12118
|
};
|
|
12023
12119
|
}
|
|
12024
12120
|
buildChartjsScript() {
|
|
@@ -12066,9 +12162,12 @@ var TemplateEngine = class {
|
|
|
12066
12162
|
return tests.sort((a, b) => b.durationMs - a.durationMs).slice(0, 10);
|
|
12067
12163
|
}
|
|
12068
12164
|
readStyle(filename) {
|
|
12165
|
+
const cached = this.styleCache.get(filename);
|
|
12166
|
+
if (cached !== void 0) return cached;
|
|
12069
12167
|
const stylePath = path7.join(this.templatesDir, "styles", filename);
|
|
12070
|
-
|
|
12071
|
-
|
|
12168
|
+
const css = fs5.existsSync(stylePath) ? fs5.readFileSync(stylePath, "utf8") : "";
|
|
12169
|
+
this.styleCache.set(filename, css);
|
|
12170
|
+
return css;
|
|
12072
12171
|
}
|
|
12073
12172
|
registerPartials() {
|
|
12074
12173
|
const partialsDir = path7.join(this.templatesDir, "partials");
|
|
@@ -12623,6 +12722,12 @@ var PdfGenerator = class {
|
|
|
12623
12722
|
`Compression: level=${compression.effective} jpeg-q=${compression.quality} max-w=${compression.maxWidth}px inline-failures\u2264${compression.maxInlineFailures}`
|
|
12624
12723
|
);
|
|
12625
12724
|
const outputPaths = [];
|
|
12725
|
+
if (options.sections !== void 0) {
|
|
12726
|
+
const hasCustom = sources.some((s) => s.kind !== "builtin");
|
|
12727
|
+
if (hasCustom) {
|
|
12728
|
+
logger.warn('[reportforge] "sections" applies to built-in templates only; it is ignored for custom templatePath templates.');
|
|
12729
|
+
}
|
|
12730
|
+
}
|
|
12626
12731
|
const { page } = await this.browserManager.launch(options.puppeteerExecutablePath);
|
|
12627
12732
|
try {
|
|
12628
12733
|
for (const source of sources) {
|
|
@@ -12730,13 +12835,13 @@ var PdfGenerator = class {
|
|
|
12730
12835
|
}
|
|
12731
12836
|
const templateLabel = source.kind === "builtin" ? source.id : source.label;
|
|
12732
12837
|
logger.info(`Rendering template: ${templateLabel}`);
|
|
12733
|
-
const html = source.kind === "builtin" ? this.templateEngine.render(renderData, source.id) : this.templateEngine.renderFromPath(renderData, source.absolutePath);
|
|
12838
|
+
const html = source.kind === "builtin" ? this.templateEngine.render(renderData, source.id, options.sections) : this.templateEngine.renderFromPath(renderData, source.absolutePath);
|
|
12734
12839
|
const tempHtmlPath = await this.htmlWriter.write(html);
|
|
12735
12840
|
const fileUrl = this.htmlWriter.toFileUrl(tempHtmlPath);
|
|
12736
12841
|
try {
|
|
12737
12842
|
logger.info(`Navigating to temp HTML (${Math.round(html.length / 1024)} KB)...`);
|
|
12738
12843
|
await page.goto(fileUrl, { waitUntil: "domcontentloaded", timeout: 6e4 });
|
|
12739
|
-
const showCharts = source.kind === "builtin" ? source.id
|
|
12844
|
+
const showCharts = source.kind === "builtin" ? resolveSections(source.id, options.sections).charts : true;
|
|
12740
12845
|
await this.chartRenderer.waitForCharts(page, showCharts);
|
|
12741
12846
|
logger.info(`Generating PDF \u2192 ${path12.relative(process.cwd(), outputPath)}`);
|
|
12742
12847
|
await page.pdf({
|
|
@@ -13127,7 +13232,7 @@ var PdfReporter = class {
|
|
|
13127
13232
|
this.dataCollector = new DataCollector();
|
|
13128
13233
|
this.pdfGenerator = new PdfGenerator();
|
|
13129
13234
|
this.options = parseOptions(rawOptions);
|
|
13130
|
-
const version = true ? "0.
|
|
13235
|
+
const version = true ? "0.6.0" : "0.x";
|
|
13131
13236
|
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
13132
13237
|
this.licenseClient = new LicenseClient({
|
|
13133
13238
|
licenseKey: this.options.licenseKey,
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
{{> watermark}}
|
|
4
4
|
|
|
5
|
+
{{#if sections.coverPage}}{{> cover-page}}{{/if}}
|
|
6
|
+
|
|
5
7
|
<div class="report-header">
|
|
6
8
|
{{#if meta.branding.logoBase64}}
|
|
7
9
|
<img class="report-header__logo" src="{{meta.branding.logoBase64}}" alt="Logo">
|
|
@@ -12,25 +14,27 @@
|
|
|
12
14
|
</div>
|
|
13
15
|
</div>
|
|
14
16
|
|
|
15
|
-
{{>
|
|
17
|
+
{{#if sections.analysisOneliner}}{{> analysis-oneliner}}{{/if}}
|
|
18
|
+
|
|
19
|
+
{{#if sections.releaseGate}}{{> release-gate}}{{/if}}
|
|
16
20
|
|
|
17
|
-
{{> executive-summary options=(obj showPassRate=
|
|
21
|
+
{{#if sections.summary}}{{> executive-summary options=(obj showPassRate=sections.passRate) }}{{/if}}
|
|
18
22
|
|
|
19
|
-
{{> charts options=(obj showCharts=true showTrend=
|
|
23
|
+
{{#if sections.charts}}{{> charts options=(obj showCharts=true showTrend=sections.trend) }}{{/if}}
|
|
20
24
|
|
|
21
|
-
{{> requirements-matrix }}
|
|
25
|
+
{{#if sections.requirementsMatrix}}{{> requirements-matrix }}{{/if}}
|
|
22
26
|
|
|
23
|
-
{{> ci-environment options=(obj showFullEnvironment=
|
|
27
|
+
{{#if sections.ciEnvironment}}{{> ci-environment options=(obj showFullEnvironment=sections.fullEnvironment) }}{{/if}}
|
|
24
28
|
|
|
25
|
-
{{> suite-breakdown options=(obj showRetries=
|
|
29
|
+
{{#if sections.suiteBreakdown}}{{> suite-breakdown options=(obj showRetries=sections.retries) }}{{/if}}
|
|
26
30
|
|
|
27
|
-
{{> failure-deep-dive options=(obj showFullFailures=
|
|
31
|
+
{{#if sections.failureDeepDive}}{{> failure-deep-dive options=(obj showFullFailures=sections.fullFailures showStackTraces=sections.stackTraces) }}{{/if}}
|
|
28
32
|
|
|
29
|
-
{{> failure-analysis}}
|
|
33
|
+
{{#if sections.failureAnalysis}}{{> failure-analysis}}{{/if}}
|
|
30
34
|
|
|
31
|
-
{{> slow-tests limit=10 showProject=true}}
|
|
35
|
+
{{#if sections.slowTests}}{{> slow-tests limit=10 showProject=true}}{{/if}}
|
|
32
36
|
|
|
33
|
-
{{> defect-log }}
|
|
37
|
+
{{#if sections.defectLog}}{{> defect-log }}{{/if}}
|
|
34
38
|
|
|
35
39
|
<div class="report-footer">
|
|
36
40
|
<span>Generated by ReportForge</span>
|