touchpress 0.2.0 → 0.2.1
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/core/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as normalizeText, C as parseScreen, D as deviceNameForSlot, E as TOUCHPRESS_DEFAULTS, M as TouchpressError, O as parseDeviceOptions, S as silentSink, T as resolve, a as sizeOf, d as createScrollSearch, f as directionToward, g as evaluate, h as describeCheck, i as relativeTo, j as textMatch, k as describeQuery, l as captureEvidence, m as probe, n as compareScreenshot, o as toPixelBox, p as formatFailure, r as cropScreenshot, t as preflight, u as createDevice, v as openSession, w as renderScreen, x as renderTitle, y as sessionName } from "../preflight-
|
|
1
|
+
import { A as normalizeText, C as parseScreen, D as deviceNameForSlot, E as TOUCHPRESS_DEFAULTS, M as TouchpressError, O as parseDeviceOptions, S as silentSink, T as resolve, a as sizeOf, d as createScrollSearch, f as directionToward, g as evaluate, h as describeCheck, i as relativeTo, j as textMatch, k as describeQuery, l as captureEvidence, m as probe, n as compareScreenshot, o as toPixelBox, p as formatFailure, r as cropScreenshot, t as preflight, u as createDevice, v as openSession, w as renderScreen, x as renderTitle, y as sessionName } from "../preflight-D1aux7ic.mjs";
|
|
2
2
|
export { TOUCHPRESS_DEFAULTS, TouchpressError, captureEvidence, compareScreenshot, createDevice, createScrollSearch, cropScreenshot, describeCheck, describeQuery, deviceNameForSlot, directionToward, evaluate, formatFailure, normalizeText, openSession, parseDeviceOptions, parseScreen, preflight, probe, relativeTo, renderScreen, renderTitle, resolve, sessionName, silentSink, sizeOf, textMatch, toPixelBox };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as parseScreen, E as TOUCHPRESS_DEFAULTS, M as TouchpressError, O as parseDeviceOptions, S as silentSink, T as resolve, _ as createQueue, a as sizeOf, b as sleep, c as createClient, i as relativeTo, j as textMatch, l as captureEvidence, n as compareScreenshot, o as toPixelBox, r as cropScreenshot, s as createAgentDeviceDriver, t as preflight, u as createDevice, v as openSession, w as renderScreen, x as renderTitle } from "./preflight-
|
|
1
|
+
import { C as parseScreen, E as TOUCHPRESS_DEFAULTS, M as TouchpressError, O as parseDeviceOptions, S as silentSink, T as resolve, _ as createQueue, a as sizeOf, b as sleep, c as createClient, i as relativeTo, j as textMatch, l as captureEvidence, n as compareScreenshot, o as toPixelBox, r as cropScreenshot, s as createAgentDeviceDriver, t as preflight, u as createDevice, v as openSession, w as renderScreen, x as renderTitle } from "./preflight-D1aux7ic.mjs";
|
|
2
2
|
import { expect as expect$1, test as test$1 } from "@playwright/test";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname } from "node:path";
|
|
@@ -51,11 +51,11 @@ function formatError(info) {
|
|
|
51
51
|
info.screen
|
|
52
52
|
].join("\n");
|
|
53
53
|
case "fill-unconfirmed": return [
|
|
54
|
-
`fill left the field holding something else after ${String(info.attempts)} attempts in ${String(info.timeoutMs)}ms.`,
|
|
54
|
+
info.actual === null ? `fill lost the field after ${String(info.attempts)} attempts in ${String(info.timeoutMs)}ms.` : `fill left the field holding something else after ${String(info.attempts)} attempts in ${String(info.timeoutMs)}ms.`,
|
|
55
55
|
``,
|
|
56
56
|
`Locator: ${info.locator}`,
|
|
57
57
|
`Expected value: ${describeValue(info.expected)}${info.expected.kind === "masked" ? " (a secure field reports a mask, not its contents)" : ""}`,
|
|
58
|
-
`Actual value: ${info.actual === null ? "the
|
|
58
|
+
`Actual value: ${info.actual === null ? "unknown, the field no longer resolved after the write" : describeValue(info.actual)}`,
|
|
59
59
|
``,
|
|
60
60
|
`Screen:`,
|
|
61
61
|
info.screen
|
|
@@ -1388,6 +1388,7 @@ function perform(session, sink, record, options, dispatch, write) {
|
|
|
1388
1388
|
let retriedStaleRef = false;
|
|
1389
1389
|
let attempts = 0;
|
|
1390
1390
|
let target = record.query;
|
|
1391
|
+
let written = null;
|
|
1391
1392
|
let lastActual = null;
|
|
1392
1393
|
let screen = await device.capture();
|
|
1393
1394
|
const unconfirmed = (expected) => new TouchpressError({
|
|
@@ -1426,6 +1427,7 @@ function perform(session, sink, record, options, dispatch, write) {
|
|
|
1426
1427
|
typed: typedOf(resolution.node.role, write)
|
|
1427
1428
|
}), () => Promise.resolve(), { box: true });
|
|
1428
1429
|
target = identityOf(screen, resolution.node);
|
|
1430
|
+
written = confirmation;
|
|
1429
1431
|
screen = await device.capture();
|
|
1430
1432
|
lastActual = valueAt(screen, target);
|
|
1431
1433
|
if (lastActual !== null && holds(confirmation, lastActual)) {
|
|
@@ -1442,13 +1444,16 @@ function perform(session, sink, record, options, dispatch, write) {
|
|
|
1442
1444
|
continue;
|
|
1443
1445
|
}
|
|
1444
1446
|
const remaining = deadline - Date.now();
|
|
1445
|
-
if (remaining <= 0)
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1447
|
+
if (remaining <= 0) {
|
|
1448
|
+
if (written !== null) throw unconfirmed(expectedOf(written));
|
|
1449
|
+
throw new TouchpressError({
|
|
1450
|
+
kind: "not-found",
|
|
1451
|
+
locator,
|
|
1452
|
+
timeoutMs: timeout,
|
|
1453
|
+
screen: renderScreen(screen),
|
|
1454
|
+
scrolled: search.trail()
|
|
1455
|
+
});
|
|
1456
|
+
}
|
|
1452
1457
|
if (attempts === 0 && await search.step(screen, target, remaining)) {
|
|
1453
1458
|
screen = await device.capture();
|
|
1454
1459
|
continue;
|
|
@@ -1630,18 +1635,29 @@ function valueAt(screen, target) {
|
|
|
1630
1635
|
/**
|
|
1631
1636
|
* How the written node is found again on the next snapshot.
|
|
1632
1637
|
*
|
|
1633
|
-
*
|
|
1634
|
-
*
|
|
1635
|
-
*
|
|
1636
|
-
*
|
|
1638
|
+
* A testId rarely names one node. SwiftUI puts one identifier on a field, its
|
|
1639
|
+
* placeholder, and the button under it, and the driver copies an ancestor's
|
|
1640
|
+
* identifier onto every inheriting descendant. The role narrows those to the
|
|
1641
|
+
* field, and failing that the field's position among nodes of its role stands
|
|
1642
|
+
* in. Never the raw tree index: the software keyboard inserts its windows at the
|
|
1643
|
+
* top of the tree, which shifts every index but adds no text field.
|
|
1637
1644
|
*/
|
|
1638
1645
|
function identityOf(screen, node) {
|
|
1639
1646
|
if (node.testId !== null) {
|
|
1640
|
-
const byTestId = {
|
|
1647
|
+
const byTestId = {
|
|
1648
|
+
role: node.role,
|
|
1649
|
+
testId: textMatch(node.testId, true)
|
|
1650
|
+
};
|
|
1641
1651
|
const resolution = resolve(screen, byTestId);
|
|
1642
1652
|
if (resolution.outcome === "one" && resolution.node === node) return byTestId;
|
|
1643
1653
|
}
|
|
1644
|
-
|
|
1654
|
+
const byRole = { role: node.role };
|
|
1655
|
+
const index = matchesOf(screen, byRole).indexOf(node);
|
|
1656
|
+
if (index === -1) throw new Error(`${node.ref} does not resolve under its own role`);
|
|
1657
|
+
return {
|
|
1658
|
+
...byRole,
|
|
1659
|
+
index
|
|
1660
|
+
};
|
|
1645
1661
|
}
|
|
1646
1662
|
//#endregion
|
|
1647
1663
|
//#region src/core/evidence.ts
|