@piwitests/reporter 0.62.0 → 0.63.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 +14 -13
- package/dist/global-setup-module.js +27 -12
- package/dist/index.d.ts +8 -0
- package/dist/index.js +16258 -13784
- package/dist/internal/capture/capture-fixtures.d.ts +13 -1
- package/dist/internal/capture/capture-fixtures.js +2791 -560
- package/dist/internal/capture/locator-healing.d.ts +11 -1
- package/dist/internal/capture/locator-healing.js +22 -10
- package/dist/internal/capture/pick-on-failure.js +29 -5
- package/package.json +1 -1
|
@@ -131,6 +131,16 @@ declare function renderFailing(failed: FailedLocatorInfo): string;
|
|
|
131
131
|
* present (so the failure wasn't a rename), or when no candidate is confident.
|
|
132
132
|
*/
|
|
133
133
|
declare function suggestLocatorsFromAria(failed: FailedLocatorInfo, ariaSnapshot: string | null): LocatorSuggestion | null;
|
|
134
|
+
/**
|
|
135
|
+
* The local path a stack frame's file names: a `file://` URL (an ES-module suite's frames) through `fileURLToPath`,
|
|
136
|
+
* any other path as it is. `windows` reads the URL as Windows does. Null for a URL that names no local file.
|
|
137
|
+
*/
|
|
138
|
+
declare function framePath(file: string, windows?: boolean): string | null;
|
|
139
|
+
/**
|
|
140
|
+
* A stack frame's file relative to `cwd`, with forward slashes: the form Playwright writes a location in its error
|
|
141
|
+
* messages. A file on another drive stays absolute. Null for a URL that names no local file.
|
|
142
|
+
*/
|
|
143
|
+
declare function callSitePath(file: string, cwd?: string, windows?: boolean): string | null;
|
|
134
144
|
/**
|
|
135
145
|
* Capture the calling test's source location (`file:line:col`) from the current
|
|
136
146
|
* stack, for stamping onto a locator snapshot. The path is made cwd-relative so
|
|
@@ -147,4 +157,4 @@ declare function suggestLocatorsFromAria(failed: FailedLocatorInfo, ariaSnapshot
|
|
|
147
157
|
*/
|
|
148
158
|
declare function captureCallerLocation(stack?: string): string | null;
|
|
149
159
|
|
|
150
|
-
export { ACTION_METHODS, CHAIN_METHODS, EXPECT_CAPTURE_EXPRESSIONS, EXPECT_METHOD, FORM_FIELD_TAGS, type FailedLocatorInfo, LOCATOR_CREATING_CHAINS, LOCATOR_METHODS, type LocatorSuggestion, type NameSource, captureCallerLocation, dedupeSnapshotsByLocation, exactAccessibleName, extractAccessibleName, renderFailing, suggestLocatorsFromAria };
|
|
160
|
+
export { ACTION_METHODS, CHAIN_METHODS, EXPECT_CAPTURE_EXPRESSIONS, EXPECT_METHOD, FORM_FIELD_TAGS, type FailedLocatorInfo, LOCATOR_CREATING_CHAINS, LOCATOR_METHODS, type LocatorSuggestion, type NameSource, callSitePath, captureCallerLocation, dedupeSnapshotsByLocation, exactAccessibleName, extractAccessibleName, framePath, renderFailing, suggestLocatorsFromAria };
|
|
@@ -41,11 +41,13 @@ __export(locator_healing_exports, {
|
|
|
41
41
|
LOCATOR_METHODS: () => LOCATOR_METHODS,
|
|
42
42
|
TAG_TO_ROLE: () => TAG_TO_ROLE,
|
|
43
43
|
approximateAccessibleName: () => approximateAccessibleName,
|
|
44
|
+
callSitePath: () => callSitePath,
|
|
44
45
|
captureCallerLocation: () => captureCallerLocation,
|
|
45
46
|
classifyCssStability: () => classifyCssStability,
|
|
46
47
|
dedupeSnapshotsByLocation: () => dedupeSnapshotsByLocation,
|
|
47
48
|
exactAccessibleName: () => exactAccessibleName,
|
|
48
49
|
extractAccessibleName: () => extractAccessibleName,
|
|
50
|
+
framePath: () => framePath,
|
|
49
51
|
generateAlternatives: () => generateAlternatives,
|
|
50
52
|
headingLevel: () => headingLevel,
|
|
51
53
|
isAutoGenerated: () => isAutoGenerated,
|
|
@@ -55,6 +57,7 @@ __export(locator_healing_exports, {
|
|
|
55
57
|
});
|
|
56
58
|
module.exports = __toCommonJS(locator_healing_exports);
|
|
57
59
|
var path = __toESM(require("path"));
|
|
60
|
+
var import_node_url = require("url");
|
|
58
61
|
|
|
59
62
|
// ../core/src/locator-chain.ts
|
|
60
63
|
var LOCATING_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -744,6 +747,20 @@ function suggestLocatorsFromAria(failed, ariaSnapshot) {
|
|
|
744
747
|
if (suggestions.length === 0) return null;
|
|
745
748
|
return { failing: renderFailing(failed), suggestions };
|
|
746
749
|
}
|
|
750
|
+
function framePath(file, windows = process.platform === "win32") {
|
|
751
|
+
if (!file.startsWith("file://")) return file;
|
|
752
|
+
try {
|
|
753
|
+
return (0, import_node_url.fileURLToPath)(file, { windows });
|
|
754
|
+
} catch {
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
function callSitePath(file, cwd = process.cwd(), windows = process.platform === "win32") {
|
|
759
|
+
const local = framePath(file, windows);
|
|
760
|
+
if (local === null) return null;
|
|
761
|
+
const paths = windows ? path.win32 : path.posix;
|
|
762
|
+
return paths.relative(cwd, local).split(paths.sep).join("/");
|
|
763
|
+
}
|
|
747
764
|
function captureCallerLocation(stack = new Error().stack ?? "") {
|
|
748
765
|
const lines = stack.split("\n");
|
|
749
766
|
let prevWasCaptureModule = false;
|
|
@@ -756,13 +773,8 @@ function captureCallerLocation(stack = new Error().stack ?? "") {
|
|
|
756
773
|
prevWasCaptureModule = false;
|
|
757
774
|
continue;
|
|
758
775
|
}
|
|
759
|
-
|
|
760
|
-
if (!file || file.startsWith("node:")) {
|
|
761
|
-
prevWasCaptureModule = false;
|
|
762
|
-
continue;
|
|
763
|
-
}
|
|
764
|
-
file = file.replace(/^file:\/\/\/?/, "");
|
|
765
|
-
if (!/\.[a-z]+$/i.test(file)) {
|
|
776
|
+
const file = m[2] ? framePath(m[2]) : null;
|
|
777
|
+
if (!file || file.startsWith("node:") || !/\.[a-z]+$/i.test(file)) {
|
|
766
778
|
prevWasCaptureModule = false;
|
|
767
779
|
continue;
|
|
768
780
|
}
|
|
@@ -785,11 +797,9 @@ function captureCallerLocation(stack = new Error().stack ?? "") {
|
|
|
785
797
|
}
|
|
786
798
|
let rel = file;
|
|
787
799
|
try {
|
|
788
|
-
rel =
|
|
800
|
+
rel = callSitePath(file) ?? file;
|
|
789
801
|
} catch {
|
|
790
802
|
}
|
|
791
|
-
rel = rel.split(path.sep).join("/");
|
|
792
|
-
if (rel.startsWith("./")) rel = rel.slice(2);
|
|
793
803
|
return `${rel}:${m[3]}:${m[4]}`;
|
|
794
804
|
}
|
|
795
805
|
return null;
|
|
@@ -807,11 +817,13 @@ function captureCallerLocation(stack = new Error().stack ?? "") {
|
|
|
807
817
|
LOCATOR_METHODS,
|
|
808
818
|
TAG_TO_ROLE,
|
|
809
819
|
approximateAccessibleName,
|
|
820
|
+
callSitePath,
|
|
810
821
|
captureCallerLocation,
|
|
811
822
|
classifyCssStability,
|
|
812
823
|
dedupeSnapshotsByLocation,
|
|
813
824
|
exactAccessibleName,
|
|
814
825
|
extractAccessibleName,
|
|
826
|
+
framePath,
|
|
815
827
|
generateAlternatives,
|
|
816
828
|
headingLevel,
|
|
817
829
|
isAutoGenerated,
|
|
@@ -880,13 +880,17 @@ function showAnchorPicker(arg) {
|
|
|
880
880
|
}
|
|
881
881
|
const MONO = "ui-monospace,SFMono-Regular,Menlo,Consolas,monospace";
|
|
882
882
|
const outline = doc.createElement("div");
|
|
883
|
+
outline.id = "__piwi_anchor_outline";
|
|
883
884
|
outline.style.cssText = `position:fixed;pointer-events:none;z-index:${Z};box-sizing:border-box;border:2px solid #22c55e;background:rgba(34,197,94,.10);border-radius:4px;display:none;box-shadow:0 0 0 1px rgba(255,255,255,.9),0 0 0 3px rgba(5,46,22,.5);`;
|
|
884
885
|
const outlineLabel = doc.createElement("div");
|
|
886
|
+
outlineLabel.id = "__piwi_anchor_label";
|
|
885
887
|
outlineLabel.style.cssText = `position:fixed;pointer-events:none;z-index:${Z + 1};display:none;box-sizing:border-box;max-width:min(420px,90vw);background:#0b1120;color:#f9fafb;border:1px solid #22c55e;border-radius:6px;padding:3px 7px;font:12px/1.45 ${MONO};white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-shadow:0 4px 18px rgba(0,0,0,.5);`;
|
|
886
888
|
const pickedOutline = doc.createElement("div");
|
|
889
|
+
pickedOutline.id = "__piwi_anchor_picked";
|
|
887
890
|
const pr = el.getBoundingClientRect();
|
|
888
891
|
pickedOutline.style.cssText = `position:fixed;pointer-events:none;z-index:${Z};box-sizing:border-box;border:2px solid #a855f7;background:rgba(168,85,247,.14);border-radius:4px;box-shadow:0 0 0 1px rgba(255,255,255,.9),0 0 0 3px rgba(59,7,100,.55);left:${pr.left}px;top:${pr.top}px;width:${pr.width}px;height:${pr.height}px;`;
|
|
889
892
|
const panel = doc.createElement("div");
|
|
893
|
+
panel.id = "__piwi_anchor_panel";
|
|
890
894
|
panel.style.cssText = `position:fixed;top:12px;right:12px;z-index:${Z + 3};width:min(340px,calc(100vw - 56px));max-height:82vh;overflow:auto;background:#111827;color:#f9fafb;border-radius:10px;padding:16px;font:12px/1.5 system-ui,sans-serif;box-shadow:0 8px 40px rgba(0,0,0,.5);`;
|
|
891
895
|
const title = doc.createElement("div");
|
|
892
896
|
title.style.cssText = "font-weight:600;font-size:13px;margin-bottom:2px;";
|
|
@@ -1075,6 +1079,7 @@ function showPickerChoices(arg) {
|
|
|
1075
1079
|
}
|
|
1076
1080
|
const Z = 2147483600;
|
|
1077
1081
|
const wrap = doc.createElement("div");
|
|
1082
|
+
wrap.id = "__piwi_picker_choices";
|
|
1078
1083
|
wrap.style.cssText = `position:fixed;inset:0;z-index:${Z + 3};background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;font:13px/1.5 system-ui,sans-serif;`;
|
|
1079
1084
|
const panel = doc.createElement("div");
|
|
1080
1085
|
panel.style.cssText = "background:#111827;color:#f9fafb;border-radius:10px;padding:20px;max-width:640px;width:90vw;max-height:70vh;overflow:auto;box-shadow:0 8px 40px rgba(0,0,0,.5);";
|
|
@@ -1105,10 +1110,14 @@ function showPickerChoices(arg) {
|
|
|
1105
1110
|
}
|
|
1106
1111
|
panel.appendChild(title);
|
|
1107
1112
|
panel.appendChild(sub);
|
|
1108
|
-
const
|
|
1109
|
-
g.__piwiPickChoice = choice;
|
|
1113
|
+
const cleanup = () => {
|
|
1110
1114
|
doc.removeEventListener("keydown", onKey, true);
|
|
1111
1115
|
wrap.remove();
|
|
1116
|
+
if (g.__piwiChoiceCleanup === cleanup) delete g.__piwiChoiceCleanup;
|
|
1117
|
+
};
|
|
1118
|
+
const done = (choice) => {
|
|
1119
|
+
g.__piwiPickChoice = choice;
|
|
1120
|
+
cleanup();
|
|
1112
1121
|
};
|
|
1113
1122
|
const onKey = (e) => {
|
|
1114
1123
|
if (e.key !== "Escape") return;
|
|
@@ -1144,6 +1153,7 @@ function showPickerChoices(arg) {
|
|
|
1144
1153
|
});
|
|
1145
1154
|
panel.appendChild(skip);
|
|
1146
1155
|
doc.addEventListener("keydown", onKey, true);
|
|
1156
|
+
g.__piwiChoiceCleanup = cleanup;
|
|
1147
1157
|
wrap.appendChild(panel);
|
|
1148
1158
|
doc.body.appendChild(wrap);
|
|
1149
1159
|
}
|
|
@@ -1569,6 +1579,7 @@ function mergeCandidates(base, extra) {
|
|
|
1569
1579
|
|
|
1570
1580
|
// src/internal/capture/locator-healing.ts
|
|
1571
1581
|
var path = __toESM(require("path"));
|
|
1582
|
+
var import_node_url = require("url");
|
|
1572
1583
|
|
|
1573
1584
|
// ../core/src/locator-fingerprint.ts
|
|
1574
1585
|
var FUNCTION_WORDS = new Set(
|
|
@@ -1625,8 +1636,10 @@ async function cleanupPicker(page, ended = false) {
|
|
|
1625
1636
|
const g = globalThis;
|
|
1626
1637
|
if (typeof g.__piwiPickCleanup === "function") g.__piwiPickCleanup();
|
|
1627
1638
|
if (typeof g.__piwiAnchorCleanup === "function") g.__piwiAnchorCleanup();
|
|
1639
|
+
if (typeof g.__piwiChoiceCleanup === "function") g.__piwiChoiceCleanup();
|
|
1628
1640
|
delete g.__piwiPickCleanup;
|
|
1629
1641
|
delete g.__piwiAnchorCleanup;
|
|
1642
|
+
delete g.__piwiChoiceCleanup;
|
|
1630
1643
|
delete g.__piwiPickState;
|
|
1631
1644
|
delete g.__piwiPickChoice;
|
|
1632
1645
|
delete g.__piwiPickedElement;
|
|
@@ -1652,13 +1665,24 @@ function unlessEnded(run, ended) {
|
|
|
1652
1665
|
]);
|
|
1653
1666
|
}
|
|
1654
1667
|
async function pickLocator(page, probe, failing, ended) {
|
|
1668
|
+
let polling = false;
|
|
1655
1669
|
const answered = async (name) => {
|
|
1656
1670
|
const wait = page.waitForFunction(
|
|
1657
|
-
([key, endedKey]) =>
|
|
1671
|
+
([key, endedKey]) => {
|
|
1672
|
+
const g = globalThis;
|
|
1673
|
+
if (g[endedKey] !== true) return g[key] !== void 0;
|
|
1674
|
+
delete g[endedKey];
|
|
1675
|
+
return true;
|
|
1676
|
+
},
|
|
1658
1677
|
[name, PICK_ENDED],
|
|
1659
1678
|
{ timeout: 0, polling: 250 }
|
|
1660
1679
|
);
|
|
1661
|
-
|
|
1680
|
+
polling = true;
|
|
1681
|
+
const done = await unlessEnded(
|
|
1682
|
+
wait.then(() => true),
|
|
1683
|
+
ended
|
|
1684
|
+
);
|
|
1685
|
+
if (done) polling = false;
|
|
1662
1686
|
return !ended?.aborted;
|
|
1663
1687
|
};
|
|
1664
1688
|
try {
|
|
@@ -1727,7 +1751,7 @@ async function pickLocator(page, probe, failing, ended) {
|
|
|
1727
1751
|
...anchors.length > 0 ? { anchors } : {}
|
|
1728
1752
|
};
|
|
1729
1753
|
} finally {
|
|
1730
|
-
await cleanupPicker(page,
|
|
1754
|
+
await cleanupPicker(page, polling);
|
|
1731
1755
|
}
|
|
1732
1756
|
}
|
|
1733
1757
|
async function runLocatorPicker(page, testInfo, failed, probe) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piwitests/reporter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.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/piwi",
|
|
6
6
|
"homepage": "https://piwitests.dev",
|