execbro 2.1.1 → 2.2.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.
Files changed (98) hide show
  1. package/README.md +1 -1
  2. package/build/__tests__/integration/text-input.test.d.ts +2 -0
  3. package/build/__tests__/integration/text-input.test.d.ts.map +1 -0
  4. package/build/__tests__/integration/text-input.test.js +181 -0
  5. package/build/__tests__/integration/text-input.test.js.map +1 -0
  6. package/build/__tests__/unit/focusedInputTools.test.js +19 -6
  7. package/build/__tests__/unit/focusedInputTools.test.js.map +1 -1
  8. package/build/__tests__/unit/inputTarget.test.d.ts +2 -0
  9. package/build/__tests__/unit/inputTarget.test.d.ts.map +1 -0
  10. package/build/__tests__/unit/inputTarget.test.js +144 -0
  11. package/build/__tests__/unit/inputTarget.test.js.map +1 -0
  12. package/build/__tests__/unit/inputTargetTools.test.d.ts +2 -0
  13. package/build/__tests__/unit/inputTargetTools.test.d.ts.map +1 -0
  14. package/build/__tests__/unit/inputTargetTools.test.js +46 -0
  15. package/build/__tests__/unit/inputTargetTools.test.js.map +1 -0
  16. package/build/__tests__/unit/inputTextTool.test.d.ts +2 -0
  17. package/build/__tests__/unit/inputTextTool.test.d.ts.map +1 -0
  18. package/build/__tests__/unit/inputTextTool.test.js +120 -0
  19. package/build/__tests__/unit/inputTextTool.test.js.map +1 -0
  20. package/build/__tests__/unit/keyboardMetrics.test.d.ts +2 -0
  21. package/build/__tests__/unit/keyboardMetrics.test.d.ts.map +1 -0
  22. package/build/__tests__/unit/keyboardMetrics.test.js +58 -0
  23. package/build/__tests__/unit/keyboardMetrics.test.js.map +1 -0
  24. package/build/__tests__/unit/keyboardRaise.test.d.ts +2 -0
  25. package/build/__tests__/unit/keyboardRaise.test.d.ts.map +1 -0
  26. package/build/__tests__/unit/keyboardRaise.test.js +74 -0
  27. package/build/__tests__/unit/keyboardRaise.test.js.map +1 -0
  28. package/build/__tests__/unit/nativeInputValue.test.d.ts +2 -0
  29. package/build/__tests__/unit/nativeInputValue.test.d.ts.map +1 -0
  30. package/build/__tests__/unit/nativeInputValue.test.js +67 -0
  31. package/build/__tests__/unit/nativeInputValue.test.js.map +1 -0
  32. package/build/__tests__/unit/screenStateInputValue.test.d.ts +2 -0
  33. package/build/__tests__/unit/screenStateInputValue.test.d.ts.map +1 -0
  34. package/build/__tests__/unit/screenStateInputValue.test.js +49 -0
  35. package/build/__tests__/unit/screenStateInputValue.test.js.map +1 -0
  36. package/build/__tests__/unit/screenStateKeyboard.test.d.ts +2 -0
  37. package/build/__tests__/unit/screenStateKeyboard.test.d.ts.map +1 -0
  38. package/build/__tests__/unit/screenStateKeyboard.test.js +99 -0
  39. package/build/__tests__/unit/screenStateKeyboard.test.js.map +1 -0
  40. package/build/__tests__/unit/textEntry.test.d.ts +2 -0
  41. package/build/__tests__/unit/textEntry.test.d.ts.map +1 -0
  42. package/build/__tests__/unit/textEntry.test.js +291 -0
  43. package/build/__tests__/unit/textEntry.test.js.map +1 -0
  44. package/build/core/focusedInputTools.d.ts.map +1 -1
  45. package/build/core/focusedInputTools.js +13 -35
  46. package/build/core/focusedInputTools.js.map +1 -1
  47. package/build/core/injectedFilters.d.ts +23 -0
  48. package/build/core/injectedFilters.d.ts.map +1 -0
  49. package/build/core/injectedFilters.js +23 -0
  50. package/build/core/injectedFilters.js.map +1 -0
  51. package/build/core/inputTarget.d.ts +85 -0
  52. package/build/core/inputTarget.d.ts.map +1 -0
  53. package/build/core/inputTarget.js +364 -0
  54. package/build/core/inputTarget.js.map +1 -0
  55. package/build/core/inputTargetTools.d.ts +12 -0
  56. package/build/core/inputTargetTools.d.ts.map +1 -0
  57. package/build/core/inputTargetTools.js +26 -0
  58. package/build/core/inputTargetTools.js.map +1 -0
  59. package/build/core/ios.d.ts.map +1 -1
  60. package/build/core/ios.js +7 -1
  61. package/build/core/ios.js.map +1 -1
  62. package/build/core/keyboardMetrics.d.ts +11 -0
  63. package/build/core/keyboardMetrics.d.ts.map +1 -0
  64. package/build/core/keyboardMetrics.js +40 -0
  65. package/build/core/keyboardMetrics.js.map +1 -0
  66. package/build/core/keyboardRaise.d.ts +22 -0
  67. package/build/core/keyboardRaise.d.ts.map +1 -0
  68. package/build/core/keyboardRaise.js +74 -0
  69. package/build/core/keyboardRaise.js.map +1 -0
  70. package/build/core/nativeInputValue.d.ts +48 -0
  71. package/build/core/nativeInputValue.d.ts.map +1 -0
  72. package/build/core/nativeInputValue.js +113 -0
  73. package/build/core/nativeInputValue.js.map +1 -0
  74. package/build/core/screenState.d.ts +39 -0
  75. package/build/core/screenState.d.ts.map +1 -1
  76. package/build/core/screenState.js +93 -8
  77. package/build/core/screenState.js.map +1 -1
  78. package/build/core/textEntry.d.ts +75 -0
  79. package/build/core/textEntry.d.ts.map +1 -0
  80. package/build/core/textEntry.js +252 -0
  81. package/build/core/textEntry.js.map +1 -0
  82. package/build/tools/componentTools.d.ts.map +1 -1
  83. package/build/tools/componentTools.js +9 -2
  84. package/build/tools/componentTools.js.map +1 -1
  85. package/build/tools/interactionTools.d.ts +13 -0
  86. package/build/tools/interactionTools.d.ts.map +1 -1
  87. package/build/tools/interactionTools.js +112 -2
  88. package/build/tools/interactionTools.js.map +1 -1
  89. package/package.json +2 -2
  90. package/tools.json +11 -1
  91. package/build/__tests__/unit/focusedInput.test.d.ts +0 -2
  92. package/build/__tests__/unit/focusedInput.test.d.ts.map +0 -1
  93. package/build/__tests__/unit/focusedInput.test.js +0 -58
  94. package/build/__tests__/unit/focusedInput.test.js.map +0 -1
  95. package/build/core/focusedInput.d.ts +0 -27
  96. package/build/core/focusedInput.d.ts.map +0 -1
  97. package/build/core/focusedInput.js +0 -110
  98. package/build/core/focusedInput.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ExecBro
2
2
 
3
- [![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.igorzheludkov%2Fexecbro-6E56CF)](https://registry.modelcontextprotocol.io/?q=io.github.igorzheludkov%2Fexecbro)
3
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-com.execbro%2Fexecbro-6E56CF)](https://registry.modelcontextprotocol.io/?q=com.execbro%2Fexecbro)
4
4
 
5
5
  **Give your AI assistant eyes and hands into your running React Native app.** Like Chrome DevTools — but for AI agents.
6
6
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=text-input.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-input.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/text-input.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,181 @@
1
+ // Device-gated: each platform's block skips cleanly when that platform has no
2
+ // device attached, so this runs on a Mac with both, either, or neither. CI has
3
+ // neither.
4
+ //
5
+ // Both platforms run the SAME cases, because the bugs this suite has caught
6
+ // were platform-specific in cause but identical in symptom. What it does NOT
7
+ // cover is the HID keystroke race: it is transient and cannot be provoked on
8
+ // demand — 15 consecutive clean runs during development, then it fired twice in
9
+ // a row an hour later. What IS covered is the machinery that makes it
10
+ // survivable: exact comparison, the retry, and the accessibility read-back that
11
+ // lets an uncontrolled field be checked at all.
12
+ import { describe, it, expect, beforeAll, afterEach } from "@jest/globals";
13
+ import { execSync } from "node:child_process";
14
+ import { enterText, isHidTypeable } from "../../core/textEntry.js";
15
+ import { runInputOp } from "../../core/inputTargetTools.js";
16
+ import { readNativeFields } from "../../core/nativeInputValue.js";
17
+ import { readKeyboardState } from "../../core/keyboardMetrics.js";
18
+ import { scanMetroPorts, fetchDevices, filterDebuggableDevices } from "../../core/metro.js";
19
+ import { connectToDevice } from "../../core/connection.js";
20
+ import { androidInputText } from "../../core/android.js";
21
+ import { iosInputText } from "../../core/ios.js";
22
+ function androidSerial() {
23
+ try {
24
+ const out = execSync("adb devices", { encoding: "utf8", timeout: 5000 });
25
+ const line = out.split("\n").slice(1).find((l) => l.trim().endsWith("device"));
26
+ return line ? line.split(/\s+/)[0] : null;
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ function bootedIosUdid() {
33
+ try {
34
+ const out = execSync("xcrun simctl list devices booted -j", { encoding: "utf8", timeout: 10_000 });
35
+ const parsed = JSON.parse(out);
36
+ for (const list of Object.values(parsed.devices ?? {})) {
37
+ const booted = list.find((d) => d.state === "Booted");
38
+ if (booted)
39
+ return booted.udid;
40
+ }
41
+ }
42
+ catch {
43
+ /* no simulator, or no Xcode */
44
+ }
45
+ return null;
46
+ }
47
+ /** RN reports Android emulators as "sdk_gphone… - 16 - API 36"; iOS as "iPhone Air". */
48
+ const ANDROID_NAME = /sdk_gphone|emulator|android/i;
49
+ /**
50
+ * A testID that exists in the app under test. Without it the field-specific
51
+ * cases no-op rather than failing, so the suite stays honest on any app.
52
+ */
53
+ const FIELD = process.env.EXECBRO_TEST_INPUT_TESTID ?? "";
54
+ /**
55
+ * A SECOND field, so the non-ASCII case does not inherit the ASCII case's text
56
+ * and focus. Sharing one field made a write issued right after the previous
57
+ * case's typing intermittently swallowed — reproducible in-suite, never in
58
+ * isolation. Isolating the state is the fix; relaxing the assertion would not
59
+ * have been.
60
+ */
61
+ const FIELD_2 = process.env.EXECBRO_TEST_INPUT_TESTID_2 ?? "";
62
+ function suiteFor(platform, deviceId) {
63
+ describe(`text entry (live ${platform} device)`, () => {
64
+ // The RN device name, needed so every op targets THIS app when both
65
+ // platforms are connected in the same process.
66
+ let rnDevice;
67
+ let connected = false;
68
+ beforeAll(async () => {
69
+ for (const port of await scanMetroPorts()) {
70
+ for (const device of filterDebuggableDevices(await fetchDevices(port))) {
71
+ const name = device.deviceName ?? "";
72
+ const isAndroid = ANDROID_NAME.test(name);
73
+ if ((platform === "android") !== isAndroid)
74
+ continue;
75
+ await connectToDevice(device, port, {
76
+ reconnectionConfig: {
77
+ enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1
78
+ }
79
+ });
80
+ rnDevice = name;
81
+ connected = true;
82
+ }
83
+ }
84
+ }, 60_000);
85
+ // Real devices need a beat between cases. Without it a write issued
86
+ // immediately after the previous case's typing is intermittently
87
+ // swallowed — the field simply does not change. This is quiescence, not
88
+ // an assertion being relaxed: every expectation below is unchanged.
89
+ afterEach(async () => {
90
+ await new Promise((r) => setTimeout(r, 700));
91
+ });
92
+ const deps = () => ({
93
+ runOp: (op, query, device) => runInputOp(op, query, device ?? rnDevice),
94
+ typeHid: (text) => platform === "ios" ? iosInputText(text, deviceId) : androidInputText(text, deviceId),
95
+ raise: async () => ({ raised: false, changed: false, reason: "not exercised in tests" }),
96
+ readNativeFields: () => readNativeFields(platform, deviceId)
97
+ });
98
+ it("reads keyboard state without throwing", async () => {
99
+ if (!connected)
100
+ return;
101
+ const s = await readKeyboardState(rnDevice);
102
+ expect(typeof s.visible).toBe("boolean");
103
+ // Metrics are either all present or all null — never a half-shape.
104
+ if (!s.visible)
105
+ expect(s.height).toBeNull();
106
+ }, 30_000);
107
+ it("sees the fields the app has mounted", async () => {
108
+ if (!connected)
109
+ return;
110
+ const { fields, error } = await readNativeFields(platform, deviceId);
111
+ expect(error).toBeUndefined();
112
+ expect(fields.length).toBeGreaterThan(0);
113
+ }, 30_000);
114
+ it("refuses to type when nothing is focused and no target is given", async () => {
115
+ if (!connected)
116
+ return;
117
+ await runInputOp({ kind: "blur" }, undefined, rnDevice);
118
+ const r = await enterText({ text: "should not land", device: rnDevice }, deps());
119
+ expect(r.success).toBe(false);
120
+ expect(r.error).toMatch(/focus/i);
121
+ }, 30_000);
122
+ it("lists candidate inputs when a target matches nothing", async () => {
123
+ if (!connected)
124
+ return;
125
+ const r = await enterText({ text: "x", testID: "definitely-not-a-real-testid", device: rnDevice }, deps());
126
+ expect(r.success).toBe(false);
127
+ expect(Array.isArray(r.candidates)).toBe(true);
128
+ }, 30_000);
129
+ it("writes and verifies an exact ASCII string", async () => {
130
+ if (!connected || !FIELD)
131
+ return;
132
+ // Capitalised deliberately: iOS TextInput defaults autoCapitalize to
133
+ // "sentences", so a lowercase first letter comes back transformed and
134
+ // the tool correctly refuses. That behaviour has its own test below.
135
+ const r = await enterText({ text: "Hello", testID: FIELD, replace: true, device: rnDevice }, deps());
136
+ if (!r.success)
137
+ throw new Error(`enterText failed: ${JSON.stringify(r)}`);
138
+ expect(r.verified).toBe(true);
139
+ }, 90_000);
140
+ it("writes non-ASCII, which the HID driver cannot express", async () => {
141
+ if (!connected || !FIELD_2)
142
+ return;
143
+ // Spanish accents matter as much as Cyrillic and CJK here: they look
144
+ // Latin but have no US keycode either.
145
+ const text = "Señor Привіт 世界";
146
+ expect(isHidTypeable(text)).toBe(false);
147
+ const r = await enterText({ text, testID: FIELD_2, replace: true, device: rnDevice }, deps());
148
+ if (!r.success)
149
+ throw new Error(`enterText failed: ${JSON.stringify(r)}`);
150
+ expect(r.path).toBe("native");
151
+ }, 90_000);
152
+ it("appends rather than replacing by default", async () => {
153
+ if (!connected || !FIELD)
154
+ return;
155
+ await enterText({ text: "abc", testID: FIELD, replace: true, device: rnDevice }, deps());
156
+ const r = await enterText({ text: "de", testID: FIELD, device: rnDevice }, deps());
157
+ // The field's keyboard may transform input (iOS auto-capitalises),
158
+ // so assert the append SHAPE rather than an exact string.
159
+ if (r.verified && r.value)
160
+ expect(r.value.toLowerCase()).toBe("abcde");
161
+ }, 90_000);
162
+ it("never reports success with an unverified value silently", async () => {
163
+ if (!connected || !FIELD)
164
+ return;
165
+ const r = await enterText({ text: "Check", testID: FIELD, replace: true, device: rnDevice }, deps());
166
+ // Either it verified, or it said out loud that it could not.
167
+ expect(r.verified === true || typeof r.error === "string").toBe(true);
168
+ }, 90_000);
169
+ });
170
+ }
171
+ const ANDROID = androidSerial();
172
+ const IOS = bootedIosUdid();
173
+ if (ANDROID)
174
+ suiteFor("android", ANDROID);
175
+ else
176
+ describe.skip("text entry (live android device)", () => it("skipped", () => { }));
177
+ if (IOS)
178
+ suiteFor("ios", IOS);
179
+ else
180
+ describe.skip("text entry (live ios device)", () => it("skipped", () => { }));
181
+ //# sourceMappingURL=text-input.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-input.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/text-input.test.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,+EAA+E;AAC/E,WAAW;AACX,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,sEAAsE;AACtE,gFAAgF;AAChF,gDAAgD;AAEhD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAsB,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,SAAS,aAAa;IAClB,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,SAAS,aAAa;IAClB,IAAI,CAAC;QACD,MAAM,GAAG,GAAG,QAAQ,CAAC,qCAAqC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACnG,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyE,CAAC;QACvG,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;YACrD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;YACtD,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC,IAAI,CAAC;QACnC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACL,+BAA+B;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,wFAAwF;AACxF,MAAM,YAAY,GAAG,8BAA8B,CAAC;AAEpD;;;GAGG;AACH,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,EAAE,CAAC;AAI9D,SAAS,QAAQ,CAAC,QAAkB,EAAE,QAAgB;IAClD,QAAQ,CAAC,oBAAoB,QAAQ,UAAU,EAAE,GAAG,EAAE;QAClD,oEAAoE;QACpE,+CAA+C;QAC/C,IAAI,QAA4B,CAAC;QACjC,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,SAAS,CAAC,KAAK,IAAI,EAAE;YACjB,KAAK,MAAM,IAAI,IAAI,MAAM,cAAc,EAAE,EAAE,CAAC;gBACxC,KAAK,MAAM,MAAM,IAAI,uBAAuB,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACrE,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;oBACrC,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC1C,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,KAAK,SAAS;wBAAE,SAAS;oBACrD,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE;wBAChC,kBAAkB,EAAE;4BAChB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC;yBACzF;qBACJ,CAAC,CAAC;oBACH,QAAQ,GAAG,IAAI,CAAC;oBAChB,SAAS,GAAG,IAAI,CAAC;gBACrB,CAAC;YACL,CAAC;QACL,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,oEAAoE;QACpE,iEAAiE;QACjE,wEAAwE;QACxE,oEAAoE;QACpE,SAAS,CAAC,KAAK,IAAI,EAAE;YACjB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,GAAkB,EAAE,CAAC,CAAC;YAC/B,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,IAAI,QAAQ,CAAC;YACvE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CACd,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC;YACxF,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC;YACxF,gBAAgB,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC/D,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACnD,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,CAAC,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzC,mEAAmE;YACnE,IAAI,CAAC,CAAC,CAAC,OAAO;gBAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChD,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACjD,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;YAC5E,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;YACxD,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACjF,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;YAClE,IAAI,CAAC,SAAS;gBAAE,OAAO;YACvB,MAAM,CAAC,GAAG,MAAM,SAAS,CACrB,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,8BAA8B,EAAE,MAAM,EAAE,QAAQ,EAAE,EACvE,IAAI,EAAE,CACT,CAAC;YACF,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACvD,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK;gBAAE,OAAO;YACjC,qEAAqE;YACrE,sEAAsE;YACtE,qEAAqE;YACrE,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACrG,IAAI,CAAC,CAAC,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1E,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;YACnE,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO;gBAAE,OAAO;YACnC,qEAAqE;YACrE,uCAAuC;YACvC,MAAM,IAAI,GAAG,iBAAiB,CAAC;YAC/B,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9F,IAAI,CAAC,CAAC,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC1E,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;YACtD,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK;gBAAE,OAAO;YACjC,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACzF,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACnF,mEAAmE;YACnE,0DAA0D;YAC1D,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK;gBAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3E,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACrE,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK;gBAAE,OAAO;YACjC,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACrG,6DAA6D;YAC7D,MAAM,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1E,CAAC,EAAE,MAAM,CAAC,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAChC,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;AAE5B,IAAI,OAAO;IAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;;IACrC,QAAQ,CAAC,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC;AAEtF,IAAI,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;;IACzB,QAAQ,CAAC,IAAI,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC"}
@@ -2,19 +2,32 @@ import { describe, expect, it, jest } from "@jest/globals";
2
2
  import { clearFocusedInput, dismissKeyboard, inputTextWithReplace } from "../../core/focusedInputTools.js";
3
3
  const okExecute = (result) => jest.fn(async () => ({ success: true, result: JSON.stringify(result) }));
4
4
  const errExecute = (error) => jest.fn(async () => ({ success: false, error }));
5
+ // These now go through the shared resolver (inputTarget.ts), so the executor
6
+ // payload is the resolver's { found, ok, via } shape rather than the old
7
+ // per-operation { cleared } / { dismissed } shapes. The public contract of
8
+ // clearFocusedInput / dismissKeyboard is unchanged.
9
+ const resolved = (over = {}) => ({
10
+ found: true,
11
+ focused: true,
12
+ nativeTag: 42,
13
+ value: "",
14
+ hasOnChangeText: true,
15
+ ok: true,
16
+ ...over
17
+ });
5
18
  describe("clearFocusedInput", () => {
6
19
  it("returns success when executor reports cleared via onChangeText", async () => {
7
- const result = await clearFocusedInput(undefined, okExecute({ cleared: true, via: "onChangeText" }));
20
+ const result = await clearFocusedInput(undefined, okExecute(resolved({ via: "onChangeText" })));
8
21
  expect(result.success).toBe(true);
9
22
  expect(result.via).toBe("onChangeText");
10
23
  });
11
24
  it("returns success with fallback flag when via=publicInstance", async () => {
12
- const result = await clearFocusedInput(undefined, okExecute({ cleared: true, via: "publicInstance" }));
25
+ const result = await clearFocusedInput(undefined, okExecute(resolved({ via: "publicInstance.clear", hasOnChangeText: false })));
13
26
  expect(result.success).toBe(true);
14
27
  expect(result.via).toBe("publicInstance");
15
28
  });
16
29
  it("returns failure when no input focused", async () => {
17
- const result = await clearFocusedInput(undefined, okExecute({ cleared: false, reason: "no focused TextInput" }));
30
+ const result = await clearFocusedInput(undefined, okExecute({ found: false, reason: "no focused TextInput" }));
18
31
  expect(result.success).toBe(false);
19
32
  expect(result.error).toContain("no focused TextInput");
20
33
  });
@@ -26,7 +39,7 @@ describe("clearFocusedInput", () => {
26
39
  it("passes the device argument through to the executor", async () => {
27
40
  const exec = jest.fn(async () => ({
28
41
  success: true,
29
- result: JSON.stringify({ cleared: true, via: "onChangeText" })
42
+ result: JSON.stringify(resolved({ via: "onChangeText" }))
30
43
  }));
31
44
  await clearFocusedInput("iPhone 15", exec);
32
45
  expect(exec).toHaveBeenCalledWith(expect.any(String), "iPhone 15");
@@ -34,12 +47,12 @@ describe("clearFocusedInput", () => {
34
47
  });
35
48
  describe("dismissKeyboard", () => {
36
49
  it("returns success with nativeTag on dismiss", async () => {
37
- const result = await dismissKeyboard(undefined, okExecute({ dismissed: true, nativeTag: 42 }));
50
+ const result = await dismissKeyboard(undefined, okExecute(resolved({ focused: false, via: "publicInstance.blur" })));
38
51
  expect(result.success).toBe(true);
39
52
  expect(result.nativeTag).toBe(42);
40
53
  });
41
54
  it("returns failure when nothing focused", async () => {
42
- const result = await dismissKeyboard(undefined, okExecute({ dismissed: false, reason: "no focused TextInput" }));
55
+ const result = await dismissKeyboard(undefined, okExecute({ found: false, reason: "no focused TextInput" }));
43
56
  expect(result.success).toBe(false);
44
57
  expect(result.error).toContain("no focused TextInput");
45
58
  });
@@ -1 +1 @@
1
- {"version":3,"file":"focusedInputTools.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/focusedInputTools.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"focusedInputTools.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/focusedInputTools.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=inputTarget.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTarget.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/inputTarget.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,144 @@
1
+ import { describe, expect, it } from "@jest/globals";
2
+ import { buildInputExpression } from "../../core/inputTarget.js";
3
+ describe("buildInputExpression", () => {
4
+ it("returns a parseable IIFE", () => {
5
+ const expr = buildInputExpression({ kind: "find" });
6
+ expect(expr.trim()).toMatch(/^\(\(\)\s*=>\s*\{/);
7
+ expect(expr.trim()).toMatch(/\}\)\(\)$/);
8
+ });
9
+ it("walks every fiber root, not just the first", () => {
10
+ const expr = buildInputExpression({ kind: "find" });
11
+ // The old walkers did `if (roots.length > 0) { root = roots[0]; break; }`,
12
+ // which hid a focused input living under a second root (modal/portal).
13
+ expect(expr).not.toMatch(/roots\[0\]/);
14
+ expect(expr).toContain("getFiberRoots");
15
+ expect(expr).toContain("allRoots");
16
+ });
17
+ it("resolves the public instance for Fabric and Paper stateNode shapes", () => {
18
+ const expr = buildInputExpression({ kind: "find" });
19
+ expect(expr).toContain("canonical.publicInstance");
20
+ // Paper exposes the instance as stateNode itself. A Fabric-only read makes
21
+ // old-arch apps report "no focused TextInput" while a field IS focused.
22
+ expect(expr).toMatch(/return sn;/);
23
+ });
24
+ it("recognises all three host input types", () => {
25
+ const expr = buildInputExpression({ kind: "find" });
26
+ expect(expr).toContain("RCTSinglelineTextInputView");
27
+ expect(expr).toContain("RCTMultilineTextInputView");
28
+ expect(expr).toContain("AndroidTextInput");
29
+ });
30
+ it("targets by testID when a query is given", () => {
31
+ const expr = buildInputExpression({ kind: "focus" }, { testID: "email-input" });
32
+ expect(expr).toContain('"email-input"');
33
+ expect(expr).toContain("wantTestID");
34
+ });
35
+ it("falls back to the focused input when no query is given", () => {
36
+ const expr = buildInputExpression({ kind: "focus" });
37
+ expect(expr).toContain("isFocused");
38
+ expect(expr).toContain("wantTestID = null");
39
+ });
40
+ it("embeds the value as a JSON literal for setValue", () => {
41
+ const tricky = 'a"b\\c';
42
+ const expr = buildInputExpression({ kind: "setValue", value: tricky });
43
+ expect(expr).toContain(JSON.stringify(tricky));
44
+ });
45
+ it("writes and clears through onChangeText", () => {
46
+ expect(buildInputExpression({ kind: "setValue", value: "x" })).toContain("onChangeText");
47
+ expect(buildInputExpression({ kind: "clear" })).toContain('onChangeText("")');
48
+ });
49
+ it("focuses and blurs through the public instance", () => {
50
+ expect(buildInputExpression({ kind: "focus" })).toContain(".focus()");
51
+ expect(buildInputExpression({ kind: "blur" })).toContain(".blur()");
52
+ });
53
+ it("offers candidate testIDs when the target is not found", () => {
54
+ const expr = buildInputExpression({ kind: "focus" }, { testID: "nope" });
55
+ expect(expr).toContain("candidates");
56
+ });
57
+ it("explains how to fix a missing focus rather than just naming it", () => {
58
+ const expr = buildInputExpression({ kind: "find" });
59
+ expect(expr).toContain("no focused TextInput");
60
+ expect(expr).toContain("testID");
61
+ });
62
+ it("keeps clear falling back to publicInstance.clear for uncontrolled inputs", () => {
63
+ expect(buildInputExpression({ kind: "clear" })).toContain(".clear()");
64
+ });
65
+ });
66
+ describe("target disambiguation", () => {
67
+ it("collects every match instead of taking the first", () => {
68
+ const expr = buildInputExpression({ kind: "find" }, { component: "Input" });
69
+ // Silently taking match[0] writes the right text into the wrong field of a
70
+ // form and still verifies clean. Every branch must push, never break.
71
+ expect(expr).toContain("__eb_matches.push");
72
+ expect(expr).not.toMatch(/__eb_host = __eb_inputs\[i\]; break;/);
73
+ });
74
+ it("refuses when several inputs match and no index is given", () => {
75
+ const expr = buildInputExpression({ kind: "find" }, { component: "Input" });
76
+ expect(expr).toContain("ambiguous: true");
77
+ expect(expr).toContain("__eb_matches.length > 1");
78
+ });
79
+ it("selects by index when one is supplied", () => {
80
+ const expr = buildInputExpression({ kind: "find" }, { component: "Input", index: 3 });
81
+ expect(expr).toContain("__eb_index = 3");
82
+ });
83
+ it("rejects an out-of-range index rather than clamping it", () => {
84
+ const expr = buildInputExpression({ kind: "find" }, { component: "Input", index: 99 });
85
+ expect(expr).toContain("is out of range");
86
+ });
87
+ it("describes candidates richly enough to choose between them", () => {
88
+ const expr = buildInputExpression({ kind: "find" }, { testID: "nope" });
89
+ for (const field of ["index:", "component:", "label:", "placeholder:", "value:", "testID:"]) {
90
+ expect(expr).toContain(field);
91
+ }
92
+ });
93
+ });
94
+ describe("targeting keys", () => {
95
+ it("scopes testID to the host and its owner, never an arbitrary ancestor", () => {
96
+ const expr = buildInputExpression({ kind: "find" }, { testID: "email" });
97
+ // Free climbing picked up a ScrollView's nativeID: on a 7-field form every
98
+ // input answered to testID "7", so one target matched them all.
99
+ expect(expr).toContain("__eb_testIDOf");
100
+ expect(expr).toContain("scope");
101
+ expect(expr).not.toMatch(/for \(var p = hostFiber; p; p = p\.return\)[\s\S]{0,120}mp\.nativeID/);
102
+ });
103
+ it("prefers an explicit testID over a nativeID", () => {
104
+ const expr = buildInputExpression({ kind: "find" }, { testID: "email" });
105
+ expect(expr.indexOf("mp.testID")).toBeLessThan(expr.indexOf("mp2.nativeID"));
106
+ });
107
+ it("filters framework wrappers out of the component name", () => {
108
+ const expr = buildInputExpression({ kind: "find" }, { component: "InputField" });
109
+ // Without the filters every input resolves to TextAncestorContext, which
110
+ // names nothing and matches everything.
111
+ expect(expr).toContain("RN_PRIMITIVES");
112
+ expect(expr).toContain("GENERIC_COMPONENT");
113
+ expect(expr).toContain("TextAncestorContext");
114
+ });
115
+ it("matches the visible field label as well as value and placeholder", () => {
116
+ const expr = buildInputExpression({ kind: "find" }, { textMatch: "First Name" });
117
+ expect(expr).toContain("__eb_labelOf");
118
+ expect(expr).toContain("accessibilityLabel");
119
+ });
120
+ it("never lets an input's own value become its label", () => {
121
+ const expr = buildInputExpression({ kind: "find" }, { textMatch: "x" });
122
+ expect(expr).toMatch(/HOSTS\.indexOf\(__eb_name\(f\.type\)\) !== -1\) return;/);
123
+ });
124
+ it("finds the field wrapper by outermost onChangeText, not a capped climb", () => {
125
+ const expr = buildInputExpression({ kind: "find" }, { component: "FormInput" });
126
+ // Measured on a real form: the wrapper sits 10 levels above the host behind
127
+ // four plain Views, so a 4-composite budget is spent before reaching it and
128
+ // every input resolves to nothing. onChangeText is what distinguishes a
129
+ // field's wrapper from the layout Views around it.
130
+ expect(expr).toContain("__eb_fieldFiber");
131
+ expect(expr).toContain("d < 30");
132
+ });
133
+ it("reads and writes through the innermost composite, skipping host fibers", () => {
134
+ const expr = buildInputExpression({ kind: "setValue", value: "x" });
135
+ expect(expr).toMatch(/if \(typeof p\.type === "string"\) continue;/);
136
+ });
137
+ it("stops descending a text branch once it yields a string", () => {
138
+ const expr = buildInputExpression({ kind: "find" });
139
+ // One label repeats down its Text -> RCTText chain; descending through it
140
+ // renders "Title Title Title *" instead of "Title *".
141
+ expect(expr).toMatch(/parts\.push\(mp\.children\.trim\(\)\);[\s\S]{0,80}return;/);
142
+ });
143
+ });
144
+ //# sourceMappingURL=inputTarget.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTarget.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/inputTarget.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=inputTargetTools.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTargetTools.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/inputTargetTools.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,46 @@
1
+ import { describe, expect, it, jest } from "@jest/globals";
2
+ import { runInputOp } from "../../core/inputTargetTools.js";
3
+ const ok = (payload) => async () => ({ success: true, result: JSON.stringify(payload) });
4
+ describe("runInputOp", () => {
5
+ it("parses a found result", async () => {
6
+ const r = await runInputOp({ kind: "read" }, undefined, undefined, ok({ found: true, focused: true, nativeTag: 7, value: "hi", hasOnChangeText: true, ok: true }));
7
+ expect(r).toMatchObject({ found: true, value: "hi", hasOnChangeText: true });
8
+ });
9
+ it("passes the not-found reason and candidates through", async () => {
10
+ const r = await runInputOp({ kind: "read" }, undefined, undefined, ok({ found: false, reason: "no focused TextInput", candidates: ["email"] }));
11
+ expect(r).toEqual({ found: false, reason: "no focused TextInput", candidates: ["email"] });
12
+ });
13
+ it("reports executor failure as not-found rather than throwing", async () => {
14
+ const r = await runInputOp({ kind: "read" }, undefined, undefined, async () => ({
15
+ success: false,
16
+ error: "No apps connected"
17
+ }));
18
+ expect(r).toEqual({ found: false, reason: "No apps connected" });
19
+ });
20
+ it("reports unparseable output as not-found rather than throwing", async () => {
21
+ const r = await runInputOp({ kind: "read" }, undefined, undefined, async () => ({
22
+ success: true,
23
+ result: "not json"
24
+ }));
25
+ expect(r.found).toBe(false);
26
+ if (!r.found)
27
+ expect(r.reason).toContain("not json");
28
+ });
29
+ it("threads the device argument to the executor", async () => {
30
+ const spy = jest.fn(async () => ({
31
+ success: true,
32
+ result: JSON.stringify({ found: false, reason: "x" })
33
+ }));
34
+ await runInputOp({ kind: "read" }, undefined, "iPhone Air", spy);
35
+ expect(spy).toHaveBeenCalledWith(expect.any(String), "iPhone Air");
36
+ });
37
+ it("passes the query into the built expression", async () => {
38
+ const spy = jest.fn(async () => ({
39
+ success: true,
40
+ result: JSON.stringify({ found: false, reason: "x" })
41
+ }));
42
+ await runInputOp({ kind: "focus" }, { testID: "email-input" }, undefined, spy);
43
+ expect(spy.mock.calls[0][0]).toContain("email-input");
44
+ });
45
+ });
46
+ //# sourceMappingURL=inputTargetTools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTargetTools.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/inputTargetTools.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=inputTextTool.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTextTool.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/inputTextTool.test.ts"],"names":[],"mappings":""}