@piwitests/reporter 0.43.0 → 0.45.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/cli/index.js +89 -15
- package/dist/global-setup-module.js +6 -0
- package/dist/index.d.ts +55 -1
- package/dist/index.js +2481 -323
- package/dist/internal/capture/attachments.d.ts +1 -0
- package/dist/internal/capture/attachments.js +2 -1
- package/dist/internal/capture/capture-fixtures.d.ts +374 -5
- package/dist/internal/capture/capture-fixtures.js +949 -36
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1752,8 +1752,12 @@ function samePage(a, b) {
|
|
|
1752
1752
|
const kb = pageKey(b);
|
|
1753
1753
|
return ka === null || kb === null || ka === kb;
|
|
1754
1754
|
}
|
|
1755
|
+
function viewportLine(viewport) {
|
|
1756
|
+
return ` await page.setViewportSize({ width: ${Math.round(viewport.width)}, height: ${Math.round(viewport.height)} });`;
|
|
1757
|
+
}
|
|
1755
1758
|
function renderSpec(session, options = {}) {
|
|
1756
1759
|
const { steps } = session;
|
|
1760
|
+
const viewportAt = new Map((session.viewports ?? []).map((v) => [v.step, v]));
|
|
1757
1761
|
const title = options.title ?? "recorded flow";
|
|
1758
1762
|
const catalog = (options.catalog ?? []).filter(callIdentifiersAreSafe);
|
|
1759
1763
|
const ctx = {
|
|
@@ -1781,6 +1785,8 @@ function renderSpec(session, options = {}) {
|
|
|
1781
1785
|
let sawGoto = false;
|
|
1782
1786
|
while (pos < steps.length) {
|
|
1783
1787
|
const step = steps[pos];
|
|
1788
|
+
const viewport = pos > 0 ? viewportAt.get(pos) : void 0;
|
|
1789
|
+
if (viewport) bodyLines.push(viewportLine(viewport));
|
|
1784
1790
|
stepStarts[pos] = bodyLines.length;
|
|
1785
1791
|
if (step.action === "goto") {
|
|
1786
1792
|
bodyLines.push(...renderRawStep(step, pos, ctx));
|
|
@@ -1788,7 +1794,8 @@ function renderSpec(session, options = {}) {
|
|
|
1788
1794
|
pos++;
|
|
1789
1795
|
continue;
|
|
1790
1796
|
}
|
|
1791
|
-
const
|
|
1797
|
+
const found = catalog.length > 0 ? matchFunctionAt(steps, pos, catalog) : null;
|
|
1798
|
+
const match = found && ![...viewportAt.keys()].some((at) => at > pos && at <= Math.max(...found.matchedIndices)) ? found : null;
|
|
1792
1799
|
if (match) {
|
|
1793
1800
|
bodyLines.push(renderFunctionCall(match));
|
|
1794
1801
|
usedEntries.push(match.entry);
|
|
@@ -1803,11 +1810,13 @@ function renderSpec(session, options = {}) {
|
|
|
1803
1810
|
checkNextPage(pos);
|
|
1804
1811
|
pos++;
|
|
1805
1812
|
}
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1813
|
+
const start = viewportAt.get(0);
|
|
1814
|
+
const opening = [
|
|
1815
|
+
...start ? [viewportLine(start)] : [],
|
|
1816
|
+
...!sawGoto && session.startUrl ? [` await page.goto(${quote2(urlForCode(session.startUrl, ctx))});`] : []
|
|
1817
|
+
];
|
|
1818
|
+
bodyLines.unshift(...opening);
|
|
1819
|
+
const bodyOffset = opening.length;
|
|
1811
1820
|
const importLines = renderImports(usedEntries);
|
|
1812
1821
|
const instantiationLines = renderInstantiations(usedEntries);
|
|
1813
1822
|
const failLine = expectFailLine(options);
|
|
@@ -1825,7 +1834,7 @@ function renderSpec(session, options = {}) {
|
|
|
1825
1834
|
};
|
|
1826
1835
|
}
|
|
1827
1836
|
const details = renderDetails(options);
|
|
1828
|
-
const
|
|
1837
|
+
const testOpening = details.length > 0 ? [`test(${quote2(title)}, {`, ...details, `}, async ({ page }) => {`] : [`test(${quote2(title)}, async ({ page }) => {`];
|
|
1829
1838
|
const lines = [
|
|
1830
1839
|
// Package name interpolated rather than adjoining the preceding keyword
|
|
1831
1840
|
// directly, so this generated-code line does not itself look like a real
|
|
@@ -1833,12 +1842,12 @@ function renderSpec(session, options = {}) {
|
|
|
1833
1842
|
`import { test, expect } from ${quote2(options.testImport?.trim() || "@playwright/test")};`,
|
|
1834
1843
|
...importLines,
|
|
1835
1844
|
``,
|
|
1836
|
-
...
|
|
1845
|
+
...testOpening,
|
|
1837
1846
|
...testBody,
|
|
1838
1847
|
`});`,
|
|
1839
1848
|
``
|
|
1840
1849
|
];
|
|
1841
|
-
const header = 1 + importLines.length + 1 +
|
|
1850
|
+
const header = 1 + importLines.length + 1 + testOpening.length;
|
|
1842
1851
|
return { code: lines.join("\n"), matchedSpans, warnings: ctx.warnings, stepLines: linesFrom(header) };
|
|
1843
1852
|
}
|
|
1844
1853
|
|
|
@@ -1850,7 +1859,12 @@ var STEPS_LIMITS = {
|
|
|
1850
1859
|
/** Typed values, expected values, URLs, notes. */
|
|
1851
1860
|
valueLength: 2e3,
|
|
1852
1861
|
/** Titles, names, texts, locators. */
|
|
1853
|
-
textLength: 500
|
|
1862
|
+
textLength: 500,
|
|
1863
|
+
viewports: 50,
|
|
1864
|
+
/** The widest and tallest viewport, in CSS pixels. */
|
|
1865
|
+
viewportSize: 1e4,
|
|
1866
|
+
/** The browser's zoom factors a viewport may name, as browsers allow them. */
|
|
1867
|
+
zoom: { min: 0.25, max: 5 }
|
|
1854
1868
|
};
|
|
1855
1869
|
var ACTIONS = /* @__PURE__ */ new Set([
|
|
1856
1870
|
"goto",
|
|
@@ -1895,13 +1909,14 @@ function toStepsDocument(session, meta = {}) {
|
|
|
1895
1909
|
origin,
|
|
1896
1910
|
recordedAt: session.startedAt,
|
|
1897
1911
|
note: meta.note ?? null,
|
|
1898
|
-
steps: session.steps.map((step) => ({
|
|
1912
|
+
steps: session.steps.map(({ view: _view, ...step }) => ({
|
|
1899
1913
|
...step,
|
|
1900
1914
|
target: step.target ? withoutElementKey(step.target) : null,
|
|
1901
1915
|
...step.dropTarget ? { dropTarget: withoutElementKey(step.dropTarget) } : {},
|
|
1902
1916
|
pageUrl: toPath(step.pageUrl, origin),
|
|
1903
1917
|
value: step.action === "goto" && step.value ? toPath(step.value, origin) : step.value
|
|
1904
|
-
}))
|
|
1918
|
+
})),
|
|
1919
|
+
...session.viewports?.length ? { viewports: session.viewports.map((v) => ({ ...v })) } : {}
|
|
1905
1920
|
};
|
|
1906
1921
|
}
|
|
1907
1922
|
function withoutElementKey(target) {
|
|
@@ -1915,7 +1930,12 @@ function sessionFromSteps(doc, origin = doc.origin) {
|
|
|
1915
1930
|
value: step.action === "goto" && step.value ? toAbsolute(step.value, origin) : step.value
|
|
1916
1931
|
}));
|
|
1917
1932
|
const firstGoto = steps.find((s) => s.action === "goto");
|
|
1918
|
-
return {
|
|
1933
|
+
return {
|
|
1934
|
+
steps,
|
|
1935
|
+
startedAt: doc.recordedAt,
|
|
1936
|
+
startUrl: firstGoto?.value ?? steps[0]?.pageUrl ?? origin ?? "",
|
|
1937
|
+
...doc.viewports?.length ? { viewports: doc.viewports } : {}
|
|
1938
|
+
};
|
|
1919
1939
|
}
|
|
1920
1940
|
function isObject(v) {
|
|
1921
1941
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -2001,6 +2021,44 @@ function checkAssertion(c, v, path19) {
|
|
|
2001
2021
|
note: c.text(v.note, `${path19}.note`, STEPS_LIMITS.valueLength, true)
|
|
2002
2022
|
};
|
|
2003
2023
|
}
|
|
2024
|
+
function checkViewports(c, v, stepCount) {
|
|
2025
|
+
if (v == null) return [];
|
|
2026
|
+
if (!Array.isArray(v)) {
|
|
2027
|
+
c.fail("viewports", "must be a list");
|
|
2028
|
+
return [];
|
|
2029
|
+
}
|
|
2030
|
+
if (v.length > STEPS_LIMITS.viewports) {
|
|
2031
|
+
c.fail("viewports", `holds more than ${STEPS_LIMITS.viewports}`);
|
|
2032
|
+
return [];
|
|
2033
|
+
}
|
|
2034
|
+
const out = [];
|
|
2035
|
+
v.forEach((entry, i) => {
|
|
2036
|
+
const at = `viewports[${i}]`;
|
|
2037
|
+
if (!isObject(entry)) return c.fail(at, "must be an object");
|
|
2038
|
+
const { step, width, height } = entry;
|
|
2039
|
+
if (!Number.isInteger(step) || step < 0 || step >= stepCount)
|
|
2040
|
+
return c.fail(`${at}.step`, "must be the index of a step");
|
|
2041
|
+
for (const [name, size] of [
|
|
2042
|
+
["width", width],
|
|
2043
|
+
["height", height]
|
|
2044
|
+
]) {
|
|
2045
|
+
if (!Number.isInteger(size) || size < 1 || size > STEPS_LIMITS.viewportSize)
|
|
2046
|
+
return c.fail(`${at}.${name}`, `must be a whole number of pixels from 1 to ${STEPS_LIMITS.viewportSize}`);
|
|
2047
|
+
}
|
|
2048
|
+
const { zoom } = entry;
|
|
2049
|
+
if (zoom != null && (typeof zoom !== "number" || !(zoom >= STEPS_LIMITS.zoom.min && zoom <= STEPS_LIMITS.zoom.max)))
|
|
2050
|
+
return c.fail(`${at}.zoom`, `must be a zoom factor from ${STEPS_LIMITS.zoom.min} to ${STEPS_LIMITS.zoom.max}`);
|
|
2051
|
+
const last = out[out.length - 1];
|
|
2052
|
+
if (last && last.step >= step) return c.fail(`${at}.step`, "must come after the step before it");
|
|
2053
|
+
out.push({
|
|
2054
|
+
step,
|
|
2055
|
+
width,
|
|
2056
|
+
height,
|
|
2057
|
+
...zoom != null && zoom !== 1 ? { zoom } : {}
|
|
2058
|
+
});
|
|
2059
|
+
});
|
|
2060
|
+
return out;
|
|
2061
|
+
}
|
|
2004
2062
|
function checkStep(c, v, path19) {
|
|
2005
2063
|
if (!isObject(v)) {
|
|
2006
2064
|
c.fail(path19, "must be an object");
|
|
@@ -2072,13 +2130,15 @@ function parseSteps(input) {
|
|
|
2072
2130
|
const originText = c.text(value.origin, "origin", STEPS_LIMITS.textLength, true);
|
|
2073
2131
|
const origin = originText ? originOf2(originText) : null;
|
|
2074
2132
|
if (originText && !origin) c.fail("origin", "must be an http(s) origin");
|
|
2133
|
+
const viewports = checkViewports(c, value.viewports, steps.length);
|
|
2075
2134
|
doc = {
|
|
2076
2135
|
v: STEPS_VERSION,
|
|
2077
2136
|
title: c.text(value.title, "title", STEPS_LIMITS.textLength, true),
|
|
2078
2137
|
origin,
|
|
2079
2138
|
recordedAt: value.recordedAt == null ? 0 : c.number(value.recordedAt, "recordedAt"),
|
|
2080
2139
|
note: c.text(value.note, "note", STEPS_LIMITS.valueLength, true),
|
|
2081
|
-
steps
|
|
2140
|
+
steps,
|
|
2141
|
+
...viewports.length > 0 ? { viewports } : {}
|
|
2082
2142
|
};
|
|
2083
2143
|
}
|
|
2084
2144
|
return c.errors.length > 0 ? { ok: false, errors: c.errors } : { ok: true, steps: doc };
|
|
@@ -2454,6 +2514,8 @@ var DEFAULTS = {
|
|
|
2454
2514
|
// Off by default: JavaScript coverage slows the page, so a scheduled job opts in.
|
|
2455
2515
|
captureCodeReach: false,
|
|
2456
2516
|
captureServerTraces: true,
|
|
2517
|
+
captureResources: true,
|
|
2518
|
+
leakCheck: "report",
|
|
2457
2519
|
sampleAriaOnPass: true,
|
|
2458
2520
|
uploadManifest: true,
|
|
2459
2521
|
defaultCapture: true,
|
|
@@ -2494,6 +2556,8 @@ var PIWI_ENV_KEYS = {
|
|
|
2494
2556
|
captureCodeReach: "PIWI_CAPTURE_CODE_REACH",
|
|
2495
2557
|
codeReachRoots: "PIWI_CODE_REACH_ROOTS",
|
|
2496
2558
|
captureServerTraces: "PIWI_CAPTURE_SERVER_TRACES",
|
|
2559
|
+
captureResources: "PIWI_CAPTURE_RESOURCES",
|
|
2560
|
+
leakCheck: "PIWI_LEAK_CHECK",
|
|
2497
2561
|
sampleAriaOnPass: "PIWI_SAMPLE_ARIA_ON_PASS",
|
|
2498
2562
|
uploadManifest: "PIWI_UPLOAD_MANIFEST",
|
|
2499
2563
|
defaultCapture: "PIWI_DEFAULT_CAPTURE",
|
|
@@ -2545,6 +2609,8 @@ var ENV_FALLBACK_SPECS = [
|
|
|
2545
2609
|
{ option: "capturePageInventory", env: PIWI_ENV_KEYS.capturePageInventory, kind: "bool" },
|
|
2546
2610
|
{ option: "captureCodeReach", env: PIWI_ENV_KEYS.captureCodeReach, kind: "bool" },
|
|
2547
2611
|
{ option: "captureServerTraces", env: PIWI_ENV_KEYS.captureServerTraces, kind: "bool" },
|
|
2612
|
+
{ option: "captureResources", env: PIWI_ENV_KEYS.captureResources, kind: "bool" },
|
|
2613
|
+
{ option: "leakCheck", env: PIWI_ENV_KEYS.leakCheck, kind: "string" },
|
|
2548
2614
|
{ option: "sampleAriaOnPass", env: PIWI_ENV_KEYS.sampleAriaOnPass, kind: "bool" },
|
|
2549
2615
|
{ option: "uploadManifest", env: PIWI_ENV_KEYS.uploadManifest, kind: "bool" },
|
|
2550
2616
|
{ option: "defaultCapture", env: PIWI_ENV_KEYS.defaultCapture, kind: "bool" },
|
|
@@ -3404,6 +3470,10 @@ function formatGateResult(result) {
|
|
|
3404
3470
|
` ${facts.quarantinedFailures} failing ${facts.quarantinedFailures === 1 ? "test is" : "tests are"} quarantined and did not count`
|
|
3405
3471
|
);
|
|
3406
3472
|
}
|
|
3473
|
+
if (facts.resources?.reported) {
|
|
3474
|
+
const { leaks, newLeaks } = facts.resources;
|
|
3475
|
+
lines.push(` ${leaks.length} ${leaks.length === 1 ? "leak" : "leaks"}, ${newLeaks.length} new`);
|
|
3476
|
+
}
|
|
3407
3477
|
for (const violation of result.violations) lines.push(` \u2716 ${violation.message}`);
|
|
3408
3478
|
for (const warning of result.warnings ?? []) lines.push(` \u26A0 ${warning}`);
|
|
3409
3479
|
lines.push(` ${facts.runUrl}`);
|
|
@@ -3439,6 +3509,8 @@ Policy (at least one is required):
|
|
|
3439
3509
|
--fail-on-new-cluster Fail when this run introduced a new failure cluster
|
|
3440
3510
|
--fail-on-flaky Fail when this run contains any flaky test
|
|
3441
3511
|
--require-selection <key> Fail when a test the named selection matches did not run or failed
|
|
3512
|
+
--max-leaks <n> Fail when the run left more than n browsers, contexts or pages open (per opening line)
|
|
3513
|
+
--max-new-leaks <n> Fail when more than n of those were never seen on the base branch
|
|
3442
3514
|
|
|
3443
3515
|
Warn-only (reported, never fails the build):
|
|
3444
3516
|
--max-uncovered-changes <n> Warn when more than n changed files have no observed test reach
|
|
@@ -3495,7 +3567,9 @@ function parseGateArgs(argv, env) {
|
|
|
3495
3567
|
maxQuarantined: readCount(argv, "--max-quarantined"),
|
|
3496
3568
|
failOnNewCluster: argv.includes("--fail-on-new-cluster"),
|
|
3497
3569
|
failOnFlaky: argv.includes("--fail-on-flaky"),
|
|
3498
|
-
requireSelection: readOption4(argv, "--require-selection")
|
|
3570
|
+
requireSelection: readOption4(argv, "--require-selection"),
|
|
3571
|
+
maxLeaks: readCount(argv, "--max-leaks"),
|
|
3572
|
+
maxNewLeaks: readCount(argv, "--max-new-leaks")
|
|
3499
3573
|
};
|
|
3500
3574
|
return {
|
|
3501
3575
|
serverUrl,
|
|
@@ -83,6 +83,8 @@ var DEFAULTS = {
|
|
|
83
83
|
// Off by default: JavaScript coverage slows the page, so a scheduled job opts in.
|
|
84
84
|
captureCodeReach: false,
|
|
85
85
|
captureServerTraces: true,
|
|
86
|
+
captureResources: true,
|
|
87
|
+
leakCheck: "report",
|
|
86
88
|
sampleAriaOnPass: true,
|
|
87
89
|
uploadManifest: true,
|
|
88
90
|
defaultCapture: true,
|
|
@@ -123,6 +125,8 @@ var PIWI_ENV_KEYS = {
|
|
|
123
125
|
captureCodeReach: "PIWI_CAPTURE_CODE_REACH",
|
|
124
126
|
codeReachRoots: "PIWI_CODE_REACH_ROOTS",
|
|
125
127
|
captureServerTraces: "PIWI_CAPTURE_SERVER_TRACES",
|
|
128
|
+
captureResources: "PIWI_CAPTURE_RESOURCES",
|
|
129
|
+
leakCheck: "PIWI_LEAK_CHECK",
|
|
126
130
|
sampleAriaOnPass: "PIWI_SAMPLE_ARIA_ON_PASS",
|
|
127
131
|
uploadManifest: "PIWI_UPLOAD_MANIFEST",
|
|
128
132
|
defaultCapture: "PIWI_DEFAULT_CAPTURE",
|
|
@@ -168,6 +172,8 @@ var ENV_FALLBACK_SPECS = [
|
|
|
168
172
|
{ option: "capturePageInventory", env: PIWI_ENV_KEYS.capturePageInventory, kind: "bool" },
|
|
169
173
|
{ option: "captureCodeReach", env: PIWI_ENV_KEYS.captureCodeReach, kind: "bool" },
|
|
170
174
|
{ option: "captureServerTraces", env: PIWI_ENV_KEYS.captureServerTraces, kind: "bool" },
|
|
175
|
+
{ option: "captureResources", env: PIWI_ENV_KEYS.captureResources, kind: "bool" },
|
|
176
|
+
{ option: "leakCheck", env: PIWI_ENV_KEYS.leakCheck, kind: "string" },
|
|
171
177
|
{ option: "sampleAriaOnPass", env: PIWI_ENV_KEYS.sampleAriaOnPass, kind: "bool" },
|
|
172
178
|
{ option: "uploadManifest", env: PIWI_ENV_KEYS.uploadManifest, kind: "bool" },
|
|
173
179
|
{ option: "defaultCapture", env: PIWI_ENV_KEYS.defaultCapture, kind: "bool" },
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
|
2
2
|
import { PlaywrightTestConfig, Locator, TestType, Page, Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions } from '@playwright/test';
|
|
3
3
|
export { PlaywrightTestConfig } from '@playwright/test';
|
|
4
|
-
export { PiwiFixtures, extendPiwiFixtures, piwiFixtures } from './internal/capture/capture-fixtures.js';
|
|
4
|
+
export { PiwiFixtures, PiwiWorkerFixtures, extendPiwiFixtures, piwiFixtures } from './internal/capture/capture-fixtures.js';
|
|
5
5
|
import '@piwitests/picker-dom';
|
|
6
6
|
import '@piwitests/core/wire';
|
|
7
7
|
import '@piwitests/core/code-reach';
|
|
@@ -100,6 +100,35 @@ interface PiwiDashboardOptions {
|
|
|
100
100
|
* `false`. Can also be forced off with `PIWI_CAPTURE_SERVER_TRACES=false`.
|
|
101
101
|
*/
|
|
102
102
|
captureServerTraces?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Keep a ledger of the browsers, contexts, pages and API request contexts each
|
|
105
|
+
* test opens, and list at the end of the run the ones left open after the
|
|
106
|
+
* scope that created them ended (a context a test never closed, a `beforeAll`
|
|
107
|
+
* context no `afterAll` closes, a browser a test launched itself), the pages
|
|
108
|
+
* opened and never used, and the pages, listeners and route handlers piling up
|
|
109
|
+
* on a page or context that lives across tests. Each finding names the line or
|
|
110
|
+
* the fixture that opened the object. Rides the capture fixtures and costs a
|
|
111
|
+
* few bookkeeping steps per test. Also samples the run's processes and the
|
|
112
|
+
* machine, with or without the fixtures, and prints what the run cost: CPU by
|
|
113
|
+
* process, time spent waiting for a CPU, peak memory and disk. The findings,
|
|
114
|
+
* the run's cost and each test's go to the dashboard with the run, on its
|
|
115
|
+
* Resources tab. Defaults to `true`. Set to `false` (or
|
|
116
|
+
* `PIWI_CAPTURE_RESOURCES=false`) to turn both off.
|
|
117
|
+
*/
|
|
118
|
+
captureResources?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* What the capture fixtures do when a test leaves open a browser, context,
|
|
121
|
+
* page or API request context that the test itself opened (its body or its
|
|
122
|
+
* `beforeEach`/`afterEach` hooks; a fixture's objects are the fixture's):
|
|
123
|
+
* `'report'` lists it in the end-of-run summary, `'fail'` also fails the test
|
|
124
|
+
* with the line that opened it, and `'close'` closes it when the test ends and
|
|
125
|
+
* still lists it. A `beforeAll` object left open is only ever reported. Each
|
|
126
|
+
* test is judged when it ends, so a test that hands what it opened to the next
|
|
127
|
+
* one fails under `'fail'` and loses it under `'close'`: open such objects in
|
|
128
|
+
* `beforeAll` and close them in `afterAll`. Defaults to `'report'`. Can also
|
|
129
|
+
* be set with `PIWI_LEAK_CHECK`.
|
|
130
|
+
*/
|
|
131
|
+
leakCheck?: 'report' | 'fail' | 'close';
|
|
103
132
|
/**
|
|
104
133
|
* Sample the ARIA snapshot at the end of a *passing* test, so a later failure
|
|
105
134
|
* can be diffed against the page as it last looked when green. Rate-limited by
|
|
@@ -375,6 +404,20 @@ declare class PiwiDashboardReporter {
|
|
|
375
404
|
private filterDetails;
|
|
376
405
|
/** Configured `maxFailures` (0 = unlimited) — disambiguates an interrupted run's unrun reason. */
|
|
377
406
|
private maxFailures;
|
|
407
|
+
/** The resource censuses the capture fixtures attached, one per test attempt. */
|
|
408
|
+
private resourceCensuses;
|
|
409
|
+
/** Lifecycle steps of the tests that ran without the fixtures. */
|
|
410
|
+
private lifecycleTallies;
|
|
411
|
+
/** The user fixtures set up by the tests that left a page unused, by test id. */
|
|
412
|
+
private fixturesByTest;
|
|
413
|
+
/** The file workers append their shutdown census to, set in `onBegin`. */
|
|
414
|
+
private resourcesFile;
|
|
415
|
+
/** Samples the run's processes and the machine from `onBegin` to `onEnd`. */
|
|
416
|
+
private sampler;
|
|
417
|
+
/** Bytes of the files the tests attached, by kind. */
|
|
418
|
+
private artifactBytes;
|
|
419
|
+
/** The run's resource report for the dashboard, built in `onEnd`. */
|
|
420
|
+
private resourceReport;
|
|
378
421
|
private httpClient;
|
|
379
422
|
private uploader;
|
|
380
423
|
private fileHandler;
|
|
@@ -408,6 +451,17 @@ declare class PiwiDashboardReporter {
|
|
|
408
451
|
onStepEnd(test: TestCase | undefined, _result: TestResult | undefined, step: any): void;
|
|
409
452
|
/** Playwright reporter hook: called when an individual test finishes */
|
|
410
453
|
onTestEnd(test: TestCase, result: TestResult): void;
|
|
454
|
+
/**
|
|
455
|
+
* Add up the files a test attached, and keep its resource census; for a test
|
|
456
|
+
* that ran without the capture fixtures, tally the browsers and contexts its
|
|
457
|
+
* steps opened and closed.
|
|
458
|
+
*/
|
|
459
|
+
private collectResources;
|
|
460
|
+
/**
|
|
461
|
+
* Print what the run left open or opened for nothing, from the censuses and
|
|
462
|
+
* the workers' shutdown file, then what the run cost the machine.
|
|
463
|
+
*/
|
|
464
|
+
private reportResources;
|
|
411
465
|
/**
|
|
412
466
|
* Synthesize `didnotrun` cases for tests Playwright planned but never reported
|
|
413
467
|
* (no `onTestEnd`) — typically because `maxFailures` cut the run short. These
|