@piwitests/reporter 0.39.0 → 0.41.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.
@@ -259,8 +259,9 @@ function isAutoGenerated(value) {
259
259
  }
260
260
  if (/^(emotion-|styled-|css-|sc-)/.test(value)) return true;
261
261
  if (value.startsWith("ng-")) return true;
262
- if (/^(radix-|headlessui-|mui-|mantine-|chakra-)/i.test(value)) return true;
262
+ if (/^(radix-|headlessui-|mui-|mantine-|chakra-|reka-|bits-|downshift-|react-aria|el-id-)/i.test(value)) return true;
263
263
  if (/^:r[0-9a-z]+:$/i.test(value) || /^«r[0-9a-z]+»$/i.test(value)) return true;
264
+ if (/(^|[-_:])v-\d+(-\d+)+$/.test(value) || /(^|[-_:])v-\d+(-\d+)+[-_:]/.test(value)) return true;
264
265
  return false;
265
266
  }
266
267
  var TEST_DATA_ATTRS = /* @__PURE__ */ new Set(["data-test", "data-test-id", "data-qa", "data-qa-id", "data-cy", "data-e2e"]);
@@ -477,9 +478,15 @@ function generateAlternatives(attrs) {
477
478
  }
478
479
  function approximateAccessibleName(attrs) {
479
480
  const a = attrs.attributes;
481
+ const labelText = attrs.labelText || null;
482
+ if (a["aria-labelledby"] && labelText) return labelText;
480
483
  const ariaLabel = a["aria-label"];
481
484
  if (ariaLabel) return ariaLabel;
482
- if (attrs.textContent) return attrs.textContent;
485
+ if (["input", "select", "textarea"].includes(attrs.tagName)) {
486
+ if (labelText) return labelText;
487
+ } else if (attrs.textContent) {
488
+ return attrs.textContent;
489
+ }
483
490
  const title = a["title"];
484
491
  if (title) return title;
485
492
  const placeholder = a["placeholder"];
@@ -472,6 +472,11 @@ function installPickerOverlay(arg) {
472
472
  placeLabel(r);
473
473
  foot.textContent = "click to pick \xB7 \u2191 parent \xB7 \u2193 child \xB7 Esc skip";
474
474
  };
475
+ const redescribe = () => {
476
+ labeled = null;
477
+ if (current()) refresh();
478
+ };
479
+ g.__piwiRedescribe = redescribe;
475
480
  const stop = (e) => {
476
481
  e.preventDefault();
477
482
  e.stopImmediatePropagation();
@@ -526,6 +531,7 @@ function installPickerOverlay(arg) {
526
531
  highlight.remove();
527
532
  label.remove();
528
533
  banner.remove();
534
+ if (g.__piwiRedescribe === redescribe) delete g.__piwiRedescribe;
529
535
  };
530
536
  const reportPicked = (el) => {
531
537
  removePickingListeners();
@@ -1056,8 +1062,9 @@ function isAutoGenerated(value) {
1056
1062
  }
1057
1063
  if (/^(emotion-|styled-|css-|sc-)/.test(value)) return true;
1058
1064
  if (value.startsWith("ng-")) return true;
1059
- if (/^(radix-|headlessui-|mui-|mantine-|chakra-)/i.test(value)) return true;
1065
+ if (/^(radix-|headlessui-|mui-|mantine-|chakra-|reka-|bits-|downshift-|react-aria|el-id-)/i.test(value)) return true;
1060
1066
  if (/^:r[0-9a-z]+:$/i.test(value) || /^«r[0-9a-z]+»$/i.test(value)) return true;
1067
+ if (/(^|[-_:])v-\d+(-\d+)+$/.test(value) || /(^|[-_:])v-\d+(-\d+)+[-_:]/.test(value)) return true;
1061
1068
  return false;
1062
1069
  }
1063
1070
  var TEST_DATA_ATTRS = /* @__PURE__ */ new Set(["data-test", "data-test-id", "data-qa", "data-qa-id", "data-cy", "data-e2e"]);
@@ -1274,9 +1281,15 @@ function generateAlternatives(attrs) {
1274
1281
  }
1275
1282
  function approximateAccessibleName(attrs) {
1276
1283
  const a = attrs.attributes;
1284
+ const labelText = attrs.labelText || null;
1285
+ if (a["aria-labelledby"] && labelText) return labelText;
1277
1286
  const ariaLabel = a["aria-label"];
1278
1287
  if (ariaLabel) return ariaLabel;
1279
- if (attrs.textContent) return attrs.textContent;
1288
+ if (["input", "select", "textarea"].includes(attrs.tagName)) {
1289
+ if (labelText) return labelText;
1290
+ } else if (attrs.textContent) {
1291
+ return attrs.textContent;
1292
+ }
1280
1293
  const title = a["title"];
1281
1294
  if (title) return title;
1282
1295
  const placeholder = a["placeholder"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piwitests/reporter",
3
- "version": "0.39.0",
3
+ "version": "0.41.0",
4
4
  "description": "Playwright reporter that streams results, traces and HTML reports to a Piwi Dashboard instance",
5
5
  "url": "https://github.com/PiwiTests/platform",
6
6
  "homepage": "https://piwitests.dev",
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: fix-a-reported-bug
3
+ description: Fix a bug someone reported from Piwi Picker, starting from its failing test. Use when the user names a Piwi bug report ("bug #37"), asks to "fix the reported bug", "reproduce this bug report", or pastes a link to /bug-reports/<id>.
4
+ ---
5
+
6
+ # Fix a reported bug
7
+
8
+ A bug report sent from Piwi Picker is already a test: the steps someone took, the assertion that says what the page
9
+ should show, and the value it showed instead. This skill turns it into a committed failing test, reproduces the bug,
10
+ fixes it, and proves the fix with that same test.
11
+
12
+ ## How you reach Piwi
13
+
14
+ Prefer the **Piwi MCP server** if it is connected: `get_bug_report` (the steps in words, what was expected, the
15
+ evidence, the reproductions, the tests that visit the page) and `render_steps` with `bugReportId` (the failing test).
16
+ Without it, the CLI does the same with the dashboard's URL and an API key: `npx @piwitests/reporter bug <id>`.
17
+
18
+ ## Steps
19
+
20
+ 1. **Read the report.** `get_bug_report { id }`. Note the page, each expected result with the value the page showed,
21
+ the reporter's note, the failed requests and console errors. The evidence often names the cause (a `POST … 500`).
22
+
23
+ 2. **Write the failing test.** `npx @piwitests/reporter bug <id> --write` writes the spec to the project's bugs folder
24
+ (`tests/bugs` unless the project names another) and runs it once. It is marked `test.fail()` and annotated
25
+ `piwi:bug <id>`, so it passes while the bug exists. Exit code 0 means the bug reproduces here. Exit code 1 means it
26
+ does not: read the output. A step that finds no element means the page or the data differ here (a user, a cart, a
27
+ flag the report assumed): make the test's setup provide them, in the project's style, rather than deleting steps.
28
+
29
+ 3. **Look at the tests that already visit the page** (`missedBy` in `get_bug_report`). If one of them reaches the
30
+ element, the missing piece is often one assertion in that test; say so in your report, and keep the bug's own spec
31
+ as the regression test.
32
+
33
+ 4. **Fix the bug** in the application code. Keep the change to what the evidence and the expected result point at.
34
+
35
+ 5. **Prove the fix.** Remove the `test.fail()` line from the bug's spec and run it: it must pass. Run the tests that
36
+ visit the page too (`npx playwright test <their files>`), so the fix breaks nothing around it.
37
+
38
+ 6. **Report.** The cause, the fix, the spec file, and the two runs. Once the spec runs in CI without `test.fail()`, Piwi
39
+ closes the report on its own; before that, a run where the spec still carries `test.fail()` and passes marks it
40
+ "looks fixed".
41
+
42
+ ## Guardrails
43
+
44
+ - Never change the expected value in the spec to make it pass: it is what the reporter said the page should show. If
45
+ you believe the reporter was wrong, stop and ask.
46
+ - Keep `piwi:bug <id>` on the test: it is how the report follows the fix.
47
+ - One bug, one spec. Do not fold the reproduction into an unrelated test.
@@ -9,10 +9,22 @@ Running the whole suite for every change is slow, and hand-maintained grep patte
9
9
 
10
10
  ## How you reach Piwi
11
11
 
12
- Prefer the **Piwi MCP server** if it is connected (`list_selections`, `resolve_selection`, `preview_selection`). Otherwise use the reporter CLI (`npx @piwitests/reporter select|run`) with `PIWI_DASHBOARD_URL` / `PIWI_API_KEY` / `PIWI_PROJECT_NAME` set, or the dashboard's **Selections** tab.
12
+ Prefer the **Piwi MCP server** if it is connected (`list_selections`, `resolve_selection`, `preview_selection`,
13
+ `predict_locator_breaks`). Otherwise use the reporter CLI (`npx @piwitests/reporter select|run|preflight`) with `PIWI_DASHBOARD_URL` / `PIWI_API_KEY` / `PIWI_PROJECT_NAME` set, or the dashboard's **Selections** tab.
13
14
 
14
15
  ## Steps
15
16
 
17
+ 0. **After a UI change, check the locators it breaks first.** Renaming a label, an `aria-label`, a test id, a
18
+ placeholder or a translation breaks every test that finds the element by it. Run
19
+ ```
20
+ npx @piwitests/reporter preflight --fix
21
+ ```
22
+ It diffs the working tree against `HEAD`, lists the locators the change breaks with their tests, and rewrites the
23
+ ones whose call site holds the string (keeping the quotes). Edit the ones it lists as "edit by hand" yourself, then
24
+ run the tests it names with `npx @piwitests/reporter preflight --run`. Over MCP, `predict_locator_breaks` takes
25
+ your `git diff` and returns the same breaks and edits. A prediction is not a failure: say which breaks you fixed and
26
+ which you left, and why.
27
+
16
28
  1. **See what selections exist.** Call `list_selections` for the project. Every project has the built-ins `failed` (tests whose latest run failed) and `quarantine-free`, plus any the team saved (often `smoke`). Pick the one that matches the intent:
17
29
  - About to make a broad change, or want a quick confidence check → `smoke` (or `preview_selection` with `{ "include": [{ "tags": ["smoke"] }] }`).
18
30
  - Iterating on a fix → `failed`, or a `{ "include": [{ "failedInLastRuns": 5 }] }` preview.