@piwitests/reporter 0.44.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 CHANGED
@@ -2514,6 +2514,8 @@ var DEFAULTS = {
2514
2514
  // Off by default: JavaScript coverage slows the page, so a scheduled job opts in.
2515
2515
  captureCodeReach: false,
2516
2516
  captureServerTraces: true,
2517
+ captureResources: true,
2518
+ leakCheck: "report",
2517
2519
  sampleAriaOnPass: true,
2518
2520
  uploadManifest: true,
2519
2521
  defaultCapture: true,
@@ -2554,6 +2556,8 @@ var PIWI_ENV_KEYS = {
2554
2556
  captureCodeReach: "PIWI_CAPTURE_CODE_REACH",
2555
2557
  codeReachRoots: "PIWI_CODE_REACH_ROOTS",
2556
2558
  captureServerTraces: "PIWI_CAPTURE_SERVER_TRACES",
2559
+ captureResources: "PIWI_CAPTURE_RESOURCES",
2560
+ leakCheck: "PIWI_LEAK_CHECK",
2557
2561
  sampleAriaOnPass: "PIWI_SAMPLE_ARIA_ON_PASS",
2558
2562
  uploadManifest: "PIWI_UPLOAD_MANIFEST",
2559
2563
  defaultCapture: "PIWI_DEFAULT_CAPTURE",
@@ -2605,6 +2609,8 @@ var ENV_FALLBACK_SPECS = [
2605
2609
  { option: "capturePageInventory", env: PIWI_ENV_KEYS.capturePageInventory, kind: "bool" },
2606
2610
  { option: "captureCodeReach", env: PIWI_ENV_KEYS.captureCodeReach, kind: "bool" },
2607
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" },
2608
2614
  { option: "sampleAriaOnPass", env: PIWI_ENV_KEYS.sampleAriaOnPass, kind: "bool" },
2609
2615
  { option: "uploadManifest", env: PIWI_ENV_KEYS.uploadManifest, kind: "bool" },
2610
2616
  { option: "defaultCapture", env: PIWI_ENV_KEYS.defaultCapture, kind: "bool" },
@@ -3464,6 +3470,10 @@ function formatGateResult(result) {
3464
3470
  ` ${facts.quarantinedFailures} failing ${facts.quarantinedFailures === 1 ? "test is" : "tests are"} quarantined and did not count`
3465
3471
  );
3466
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
+ }
3467
3477
  for (const violation of result.violations) lines.push(` \u2716 ${violation.message}`);
3468
3478
  for (const warning of result.warnings ?? []) lines.push(` \u26A0 ${warning}`);
3469
3479
  lines.push(` ${facts.runUrl}`);
@@ -3499,6 +3509,8 @@ Policy (at least one is required):
3499
3509
  --fail-on-new-cluster Fail when this run introduced a new failure cluster
3500
3510
  --fail-on-flaky Fail when this run contains any flaky test
3501
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
3502
3514
 
3503
3515
  Warn-only (reported, never fails the build):
3504
3516
  --max-uncovered-changes <n> Warn when more than n changed files have no observed test reach
@@ -3555,7 +3567,9 @@ function parseGateArgs(argv, env) {
3555
3567
  maxQuarantined: readCount(argv, "--max-quarantined"),
3556
3568
  failOnNewCluster: argv.includes("--fail-on-new-cluster"),
3557
3569
  failOnFlaky: argv.includes("--fail-on-flaky"),
3558
- requireSelection: readOption4(argv, "--require-selection")
3570
+ requireSelection: readOption4(argv, "--require-selection"),
3571
+ maxLeaks: readCount(argv, "--max-leaks"),
3572
+ maxNewLeaks: readCount(argv, "--max-new-leaks")
3559
3573
  };
3560
3574
  return {
3561
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