@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.
- package/README.md +3 -3
- package/dist/cli/index.js +3794 -511
- package/dist/global-setup-module.js +5 -0
- package/dist/index.d.ts +24 -2
- package/dist/index.js +3675 -2155
- package/dist/internal/capture/attachments.d.ts +2 -0
- package/dist/internal/capture/attachments.js +2 -0
- package/dist/internal/capture/capture-fixtures.d.ts +75 -2
- package/dist/internal/capture/capture-fixtures.js +1453 -144
- package/dist/internal/capture/locator-healing.js +9 -2
- package/dist/internal/capture/pick-on-failure.js +15 -2
- package/package.json +1 -1
- package/templates/skills/fix-a-reported-bug/SKILL.md +47 -0
- package/templates/skills/run-the-right-tests/SKILL.md +13 -1
|
@@ -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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|