@jterrazz/test 15.3.0 → 16.0.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 +120 -427
- package/dist/ambiguity.js +7 -6
- package/dist/appium.adapter.js +12 -11
- package/dist/artifacts.js +25 -1735
- package/dist/browser/index.js +256 -233
- package/dist/checker.d.ts +1 -1
- package/dist/checker.js +870 -73
- package/dist/fixtures.js +110 -0
- package/dist/index.d.ts +927 -971
- package/dist/index.js +2116 -2261
- package/dist/literate.js +1747 -0
- package/dist/match.js +625 -84
- package/dist/oxlint.cjs +3515 -1483
- package/dist/oxlint.d.cts +60 -48
- package/dist/oxlint.d.ts +60 -48
- package/dist/oxlint.js +3515 -1483
- package/dist/playwright.adapter.js +100 -6
- package/dist/{intercept.js → server.js} +2 -2
- package/dist/stream.js +6 -6
- package/dist/vitest.d.ts +67 -48
- package/dist/vitest.js +161 -85
- package/package.json +31 -11
- package/dist/spec-document.js +0 -651
package/dist/ambiguity.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/
|
|
1
|
+
//#region src/model/elements/ambiguity.ts
|
|
2
2
|
/**
|
|
3
3
|
* The ambiguity refusal — CONVENTIONS W3.
|
|
4
4
|
*
|
|
@@ -52,8 +52,9 @@ const CONTEXT_LANDMARKS = {
|
|
|
52
52
|
};
|
|
53
53
|
/**
|
|
54
54
|
* Render a descriptor as the source that would build it — `link('Articles')`,
|
|
55
|
-
* `within(navigation(), link('Articles', { exact:
|
|
56
|
-
* the vocabulary the author wrote, never playwright's
|
|
55
|
+
* `within(navigation(), link('Articles', { exact: false }))`. The error speaks
|
|
56
|
+
* the vocabulary the author wrote, never playwright's — so the option appears
|
|
57
|
+
* only when the AUTHOR stated one, whichever way.
|
|
57
58
|
*/
|
|
58
59
|
function formatElement(element) {
|
|
59
60
|
const bare = formatBare(element);
|
|
@@ -62,7 +63,7 @@ function formatElement(element) {
|
|
|
62
63
|
function formatBare(element) {
|
|
63
64
|
const args = [];
|
|
64
65
|
if (element.name !== void 0) args.push(JSON.stringify(element.name));
|
|
65
|
-
if (element.exact) args.push(
|
|
66
|
+
if (element.exact !== void 0) args.push(`{ exact: ${String(element.exact)} }`);
|
|
66
67
|
return `${CONSTRUCTORS[element.kind]}(${args.join(", ")})`;
|
|
67
68
|
}
|
|
68
69
|
/** `1. <a href="/articles">Articles</a> in <nav>` — one evidence line per candidate. */
|
|
@@ -98,7 +99,7 @@ function formatFixes(element, matches) {
|
|
|
98
99
|
const alsoHere = rest.length > 0 ? ` [also here: ${rest.map(([name]) => name).join(", ")}]` : "";
|
|
99
100
|
fixes.push(first === void 0 ? `scope it within(<a container holding only this one>, ${formatBare(element)})` : `scope it within(${first[0]}, ${formatBare(element)}) [leaves ${first[1]} of ${matches.length}]${alsoHere}`);
|
|
100
101
|
}
|
|
101
|
-
if (
|
|
102
|
+
if (element.exact === false && element.name !== void 0) {
|
|
102
103
|
const remaining = matches.filter((match) => match.text === element.name).length;
|
|
103
104
|
if (remaining > 0 && remaining < matches.length) fixes.push(`exact name ${formatBare({
|
|
104
105
|
...element,
|
|
@@ -138,7 +139,7 @@ function describeAmbiguity(options) {
|
|
|
138
139
|
"Disambiguate with one of:",
|
|
139
140
|
...fixes,
|
|
140
141
|
"",
|
|
141
|
-
"Docs: docs/
|
|
142
|
+
"Docs: docs/13-elements.md#designating-exactly-one-element (CONVENTIONS W3)"
|
|
142
143
|
].join("\n");
|
|
143
144
|
}
|
|
144
145
|
//#endregion
|
package/dist/appium.adapter.js
CHANGED
|
@@ -2,7 +2,7 @@ import { r as formatElement, t as AmbiguousElementError } from "./ambiguity.js";
|
|
|
2
2
|
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/facets/mobile/ambiguity.ts
|
|
6
6
|
/**
|
|
7
7
|
* The ambiguity refusal, mobile edition — CONVENTIONS W3.
|
|
8
8
|
*
|
|
@@ -28,15 +28,15 @@ function formatMatch(match, index) {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* The rewrites worth offering, in the order they should be tried. Scoping is
|
|
31
|
-
* always available; `exact` only
|
|
32
|
-
* the count it would leave is stated so a
|
|
33
|
-
* reads as a fix; distinct identifiers make
|
|
34
|
-
* rather than a guess.
|
|
31
|
+
* always available; `exact` only to a descriptor that opted OUT of it (exact
|
|
32
|
+
* is the default), and the count it would leave is stated so a
|
|
33
|
+
* still-ambiguous suggestion never reads as a fix; distinct identifiers make
|
|
34
|
+
* `testId()` a concrete rewrite rather than a guess.
|
|
35
35
|
*/
|
|
36
36
|
function formatFixes(element, matches) {
|
|
37
37
|
const fixes = [];
|
|
38
38
|
if (!element.scope) fixes.push(`scope it within(testId('…'), ${formatElement(element)}) — a screen has no landmarks; any descriptor works as the scope`);
|
|
39
|
-
if (
|
|
39
|
+
if (element.exact === false && element.name !== void 0) {
|
|
40
40
|
const remaining = matches.filter((match) => match.label === element.name).length;
|
|
41
41
|
if (remaining > 0 && remaining < matches.length) fixes.push(`exact name ${formatElement({
|
|
42
42
|
exact: true,
|
|
@@ -71,11 +71,11 @@ function describeMobileAmbiguity(options) {
|
|
|
71
71
|
"Disambiguate with one of:",
|
|
72
72
|
...fixes,
|
|
73
73
|
"",
|
|
74
|
-
"Docs: docs/
|
|
74
|
+
"Docs: docs/13-elements.md#designating-exactly-one-element (CONVENTIONS W3)"
|
|
75
75
|
].join("\n");
|
|
76
76
|
}
|
|
77
77
|
//#endregion
|
|
78
|
-
//#region src/
|
|
78
|
+
//#region src/facets/mobile/projection.ts
|
|
79
79
|
const TAG_PATTERN = /<(?<openTag>[A-Za-z][\w.]*)(?<rawAttributes>(?:\s+[\w:.-]+="[^"]*")*)\s*(?<selfClosing>\/?)>|<\/(?<closeTag>[\w.]*)\s*>/gu;
|
|
80
80
|
const ATTRIBUTE_PATTERN = /(?<key>[\w:.-]+)="(?<value>[^"]*)"/gu;
|
|
81
81
|
const NAMED_ENTITIES = {
|
|
@@ -180,7 +180,7 @@ function projectScreen(xml) {
|
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
//#endregion
|
|
183
|
-
//#region src/
|
|
183
|
+
//#region src/seams/appium/appium.adapter.ts
|
|
184
184
|
const DEFAULT_ACTION_TIMEOUT_MS = 3e4;
|
|
185
185
|
const POLL_INTERVAL_MS = 500;
|
|
186
186
|
/** How many candidates the ambiguity error enumerates before truncating. */
|
|
@@ -201,7 +201,7 @@ function escapePredicate(value) {
|
|
|
201
201
|
*/
|
|
202
202
|
function compilePredicate(element, options) {
|
|
203
203
|
const name = escapePredicate(element.name ?? "");
|
|
204
|
-
const contains = (attribute) => element.exact ? `${attribute}
|
|
204
|
+
const contains = (attribute) => element.exact === false ? `${attribute} CONTAINS '${name}'` : `${attribute} == '${name}'`;
|
|
205
205
|
const visible = options?.anyVisibility ? "1 == 1" : "visible == 1";
|
|
206
206
|
switch (element.kind) {
|
|
207
207
|
case "button": return `type == 'XCUIElementTypeButton' AND ${contains("label")} AND ${visible}`;
|
|
@@ -391,7 +391,8 @@ var AppiumAdapter = class {
|
|
|
391
391
|
/** Screenshot the failing state into a temp file; never masks the original error. */
|
|
392
392
|
async captureEvidence(driver) {
|
|
393
393
|
try {
|
|
394
|
-
const
|
|
394
|
+
const dir = mkdtempSync(resolve(tmpdir(), "spec-mobile-"));
|
|
395
|
+
const path = resolve(dir, "failure.png");
|
|
395
396
|
writeFileSync(path, Buffer.from(await driver.takeScreenshot(), "base64"));
|
|
396
397
|
return path;
|
|
397
398
|
} catch {
|