obsidian-integration-testing 12.1.0 → 12.1.2

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 (51) hide show
  1. package/dist/lib/cjs/adb.cjs +61 -0
  2. package/dist/lib/cjs/adb.d.cts +61 -0
  3. package/dist/lib/cjs/device-screenshot.cjs +42 -0
  4. package/dist/lib/cjs/device-screenshot.d.cts +36 -0
  5. package/dist/lib/cjs/device-setting-restore.cjs +45 -0
  6. package/dist/lib/cjs/device-setting-restore.d.cts +60 -0
  7. package/dist/lib/cjs/device-settings-command.cjs +49 -0
  8. package/dist/lib/cjs/device-settings-command.d.cts +76 -0
  9. package/dist/lib/cjs/device-settings.cjs +88 -0
  10. package/dist/lib/cjs/device-settings.d.cts +94 -0
  11. package/dist/lib/cjs/emulator-device-id.cjs +32 -0
  12. package/dist/lib/cjs/emulator-device-id.d.cts +49 -0
  13. package/dist/lib/cjs/index.cjs +56 -3
  14. package/dist/lib/cjs/index.d.cts +18 -0
  15. package/dist/lib/cjs/library.cjs +1 -1
  16. package/dist/lib/cjs/mobile-input.cjs +14 -1
  17. package/dist/lib/cjs/mobile-input.d.cts +30 -0
  18. package/dist/lib/cjs/namespace-bootstrap.cjs +9 -1
  19. package/dist/lib/cjs/resolve-emulator-device-id.cjs +54 -0
  20. package/dist/lib/cjs/resolve-emulator-device-id.d.cts +28 -0
  21. package/dist/lib/cjs/soft-keyboard-geometry.cjs +75 -0
  22. package/dist/lib/cjs/soft-keyboard-geometry.d.cts +156 -0
  23. package/dist/lib/cjs/soft-keyboard.cjs +118 -0
  24. package/dist/lib/cjs/soft-keyboard.d.cts +82 -0
  25. package/dist/lib/cjs/transport-appium.cjs +5 -1
  26. package/dist/lib/esm/adb.d.mts +61 -0
  27. package/dist/lib/esm/adb.mjs +35 -0
  28. package/dist/lib/esm/device-screenshot.d.mts +36 -0
  29. package/dist/lib/esm/device-screenshot.mjs +18 -0
  30. package/dist/lib/esm/device-setting-restore.d.mts +60 -0
  31. package/dist/lib/esm/device-setting-restore.mjs +20 -0
  32. package/dist/lib/esm/device-settings-command.d.mts +76 -0
  33. package/dist/lib/esm/device-settings-command.mjs +23 -0
  34. package/dist/lib/esm/device-settings.d.mts +94 -0
  35. package/dist/lib/esm/device-settings.mjs +67 -0
  36. package/dist/lib/esm/emulator-device-id.d.mts +49 -0
  37. package/dist/lib/esm/emulator-device-id.mjs +8 -0
  38. package/dist/lib/esm/index.d.mts +18 -0
  39. package/dist/lib/esm/index.mjs +58 -2
  40. package/dist/lib/esm/library.mjs +1 -1
  41. package/dist/lib/esm/mobile-input.d.mts +30 -0
  42. package/dist/lib/esm/mobile-input.mjs +12 -1
  43. package/dist/lib/esm/namespace-bootstrap.mjs +9 -1
  44. package/dist/lib/esm/resolve-emulator-device-id.d.mts +28 -0
  45. package/dist/lib/esm/resolve-emulator-device-id.mjs +33 -0
  46. package/dist/lib/esm/soft-keyboard-geometry.d.mts +156 -0
  47. package/dist/lib/esm/soft-keyboard-geometry.mjs +47 -0
  48. package/dist/lib/esm/soft-keyboard.d.mts +82 -0
  49. package/dist/lib/esm/soft-keyboard.mjs +91 -0
  50. package/dist/lib/esm/transport-appium.mjs +7 -1
  51. package/package.json +4 -3
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Decides whether the Android soft keyboard is up, and where to touch to raise
5
+ * it — from geometry alone.
6
+ *
7
+ * **Nothing in the page reports the keyboard.** `innerHeight`, `visualViewport`
8
+ * and the modal container all stay at their full height with the keyboard shown
9
+ * and `dumpsys input_method` reporting `mInputShown=true` — Obsidian Mobile keeps
10
+ * a full-screen container and lifts its contents inside it. The only signal is
11
+ * the field's own offset from the bottom, which is why the detection here is
12
+ * geometric rather than an API call. Two runs failed on that before a framebuffer
13
+ * dump said so, which is also why the diagnostic below exists.
14
+ *
15
+ * Pure and unit-tested; the touching and the capture live in `soft-keyboard`.
16
+ */
17
+ /**
18
+ * Parameters for {@link buildSoftKeyboardDiagnosticMessage}.
19
+ */
20
+ export interface BuildSoftKeyboardDiagnosticMessageParams {
21
+ /**
22
+ * The lines of `dumpsys input_method` worth reading, as {@link parseInputMethodState} returned them.
23
+ */
24
+ readonly inputMethodState: string;
25
+ /**
26
+ * Where the device framebuffer was written, so the reader can look at what the device was showing.
27
+ */
28
+ readonly screenshotPath: string;
29
+ /**
30
+ * The geometry read after the last touch.
31
+ */
32
+ readonly snapshot: SoftKeyboardViewportSnapshot;
33
+ }
34
+ /**
35
+ * Parameters for {@link checkIsSoftKeyboardUp}.
36
+ */
37
+ export interface CheckIsSoftKeyboardUpParams {
38
+ /**
39
+ * The least a raised keyboard lifts the field by, so a stray rounding pixel is not read as one.
40
+ *
41
+ * @default {@link DEFAULT_MINIMUM_KEYBOARD_HEIGHT_IN_PIXELS}
42
+ */
43
+ readonly minimumKeyboardHeightInPixels?: number;
44
+ /**
45
+ * The geometry to judge.
46
+ */
47
+ readonly snapshot: SoftKeyboardViewportSnapshot;
48
+ }
49
+ /**
50
+ * A rectangle as the renderer reports it, in CSS pixels.
51
+ */
52
+ export interface ElementRect {
53
+ /**
54
+ * The rectangle's height.
55
+ */
56
+ readonly height: number;
57
+ /**
58
+ * The distance from the viewport's left edge.
59
+ */
60
+ readonly left: number;
61
+ /**
62
+ * The distance from the viewport's top edge.
63
+ */
64
+ readonly top: number;
65
+ /**
66
+ * The rectangle's width.
67
+ */
68
+ readonly width: number;
69
+ }
70
+ /**
71
+ * Parameters for {@link resolveSoftKeyboardTapPoints}.
72
+ */
73
+ export interface ResolveSoftKeyboardTapPointsParams {
74
+ /**
75
+ * The geometry the tap is aimed from.
76
+ */
77
+ readonly snapshot: SoftKeyboardViewportSnapshot;
78
+ }
79
+ /**
80
+ * A point on the device's screen, in device pixels.
81
+ */
82
+ export interface SoftKeyboardTapPoint {
83
+ /**
84
+ * The distance from the screen's left edge.
85
+ */
86
+ readonly xInPixels: number;
87
+ /**
88
+ * The distance from the screen's top edge.
89
+ */
90
+ readonly yInPixels: number;
91
+ }
92
+ /**
93
+ * What the renderer knows about its own geometry.
94
+ */
95
+ export interface SoftKeyboardViewportSnapshot {
96
+ /**
97
+ * The ratio between CSS pixels and the device pixels `adb shell input tap` speaks in.
98
+ */
99
+ readonly devicePixelRatio: number;
100
+ /**
101
+ * The viewport's height in CSS pixels.
102
+ *
103
+ * Kept for the diagnostic as much as the decision: it does **not** shrink when the keyboard comes up.
104
+ */
105
+ readonly innerHeight: number;
106
+ /**
107
+ * The field's rect, which is what says whether the keyboard is up, or `null` when it is not on screen.
108
+ */
109
+ readonly inputRect: ElementRect | null;
110
+ /**
111
+ * The window's offset from the top of the screen, as the page understands it.
112
+ */
113
+ readonly screenY: number;
114
+ }
115
+ /**
116
+ * The least a raised keyboard lifts the field by, so a stray rounding pixel is not read as one.
117
+ *
118
+ * Exported because it is the number both {@link checkIsSoftKeyboardUp} and `raiseSoftKeyboard` default to,
119
+ * and a suite tightening it wants to say so relative to this rather than in the abstract.
120
+ */
121
+ export declare const DEFAULT_MINIMUM_KEYBOARD_HEIGHT_IN_PIXELS = 100;
122
+ /**
123
+ * Builds the message a failed raise reports.
124
+ *
125
+ * A bare "the keyboard did not come up" is unreadable — what the reader needs is what the page saw and what
126
+ * the device thought, side by side, because the two disagreeing is the whole diagnosis.
127
+ *
128
+ * @param params - The evidence gathered after the last touch.
129
+ * @returns The message, ready to throw.
130
+ */
131
+ export declare function buildSoftKeyboardDiagnosticMessage(params: BuildSoftKeyboardDiagnosticMessageParams): string;
132
+ /**
133
+ * Decides whether the IME is up, from the page's own geometry.
134
+ *
135
+ * @param params - The geometry to judge, and how far the field must have lifted.
136
+ * @returns Whether the field has stopped short of the bottom to make room for a keyboard.
137
+ */
138
+ export declare function checkIsSoftKeyboardUp(params: CheckIsSoftKeyboardUpParams): boolean;
139
+ /**
140
+ * Reduces `dumpsys input_method` to the handful of fields that say whether the IME is showing.
141
+ *
142
+ * @param dumpsysOutput - Raw stdout of `adb shell dumpsys input_method`.
143
+ * @returns The interesting fields, trimmed and joined, or an empty string when none were reported.
144
+ */
145
+ export declare function parseInputMethodState(dumpsysOutput: string): string;
146
+ /**
147
+ * Works out where to touch, in the device pixels `adb shell input tap` speaks.
148
+ *
149
+ * Two candidates, not one: the WebView may or may not start at the top of the screen, and the page cannot
150
+ * tell which. Both land inside the field — it is taller than the offset — so a wrong guess costs one touch
151
+ * rather than a mis-tap on whatever sits below.
152
+ *
153
+ * @param params - The geometry the tap is aimed from.
154
+ * @returns The points to try, in order, or an empty array when the field is not on screen.
155
+ */
156
+ export declare function resolveSoftKeyboardTapPoints(params: ResolveSoftKeyboardTapPointsParams): SoftKeyboardTapPoint[];
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var soft_keyboard_exports = {};
30
+ __export(soft_keyboard_exports, {
31
+ raiseSoftKeyboard: () => raiseSoftKeyboard,
32
+ tapDevice: () => tapDevice
33
+ });
34
+ module.exports = __toCommonJS(soft_keyboard_exports);
35
+ var import_node_fs = require("node:fs");
36
+ var import_node_path = require("node:path");
37
+ var import_node_process = __toESM(require("node:process"), 1);
38
+ var import_promises = require("node:timers/promises");
39
+ var import_adb = require("./adb.cjs");
40
+ var import_device_screenshot = require("./device-screenshot.cjs");
41
+ var import_eval_in_obsidian = require("./eval-in-obsidian.cjs");
42
+ var import_soft_keyboard_geometry = require("./soft-keyboard-geometry.cjs");
43
+ const DEFAULT_DIAGNOSTICS_DIRECTORY = (0, import_node_path.join)(import_node_process.default.cwd(), "dist", "screenshots");
44
+ const KEYBOARD_SETTLE_DELAY_IN_MILLISECONDS = 1500;
45
+ async function raiseSoftKeyboard(params) {
46
+ let snapshot = await readSoftKeyboardViewport(params);
47
+ if (!snapshot.inputRect) {
48
+ throw new Error(`raiseSoftKeyboard: nothing matches "${params.inputSelector}", so there is no field to touch.`);
49
+ }
50
+ for (const point of (0, import_soft_keyboard_geometry.resolveSoftKeyboardTapPoints)({ snapshot })) {
51
+ if (checkIsUp(snapshot)) {
52
+ break;
53
+ }
54
+ await tapDevice({ deviceId: params.deviceId, point });
55
+ await (0, import_promises.setTimeout)(KEYBOARD_SETTLE_DELAY_IN_MILLISECONDS);
56
+ snapshot = await readSoftKeyboardViewport(params);
57
+ }
58
+ if (!checkIsUp(snapshot)) {
59
+ throw new Error(await buildFailureMessage(params, snapshot));
60
+ }
61
+ return snapshot;
62
+ function checkIsUp(current) {
63
+ return (0, import_soft_keyboard_geometry.checkIsSoftKeyboardUp)({
64
+ ...params.minimumKeyboardHeightInPixels !== void 0 && { minimumKeyboardHeightInPixels: params.minimumKeyboardHeightInPixels },
65
+ snapshot: current
66
+ });
67
+ }
68
+ }
69
+ async function tapDevice(params) {
70
+ await (0, import_adb.runAdbText)({
71
+ commandArguments: ["shell", "input", "tap", String(params.point.xInPixels), String(params.point.yInPixels)],
72
+ deviceId: params.deviceId
73
+ });
74
+ }
75
+ async function buildFailureMessage(params, snapshot) {
76
+ const diagnosticsDirectory = params.diagnosticsDirectory ?? DEFAULT_DIAGNOSTICS_DIRECTORY;
77
+ (0, import_node_fs.mkdirSync)(diagnosticsDirectory, { recursive: true });
78
+ const screenshotPath = (0, import_node_path.join)(diagnosticsDirectory, "keyboard-not-raised.png");
79
+ (0, import_node_fs.writeFileSync)(screenshotPath, await (0, import_device_screenshot.captureDeviceScreenshot)({ deviceId: params.deviceId }));
80
+ const dumpsysOutput = await (0, import_adb.runAdbText)({
81
+ commandArguments: ["shell", "dumpsys", "input_method"],
82
+ deviceId: params.deviceId
83
+ });
84
+ return (0, import_soft_keyboard_geometry.buildSoftKeyboardDiagnosticMessage)({
85
+ inputMethodState: (0, import_soft_keyboard_geometry.parseInputMethodState)(dumpsysOutput),
86
+ screenshotPath,
87
+ snapshot
88
+ });
89
+ }
90
+ async function readSoftKeyboardViewport(params) {
91
+ return await (0, import_eval_in_obsidian.evalInObsidian)({
92
+ callback({ inputSelector }) {
93
+ const inputEl = document.querySelector(inputSelector);
94
+ function toRect(rect) {
95
+ return {
96
+ height: rect.height,
97
+ left: rect.left,
98
+ top: rect.top,
99
+ width: rect.width
100
+ };
101
+ }
102
+ return {
103
+ devicePixelRatio: window.devicePixelRatio,
104
+ innerHeight: window.innerHeight,
105
+ inputRect: inputEl ? toRect(inputEl.getBoundingClientRect()) : null,
106
+ screenY: window.screenY
107
+ };
108
+ },
109
+ input: { inputSelector: params.inputSelector },
110
+ ...params.vaultPath !== void 0 && { vaultPath: params.vaultPath }
111
+ });
112
+ }
113
+ // Annotate the CommonJS export names for ESM import in node:
114
+ 0 && (module.exports = {
115
+ raiseSoftKeyboard,
116
+ tapDevice
117
+ });
118
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3NvZnQta2V5Ym9hcmQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBSYWlzZXMgdGhlIEFuZHJvaWQgc29mdCBrZXlib2FyZCBmb3IgYSBzY3JlZW5zaG90LCBhbmQgcHJvdmVzIGl0IGNhbWUgdXAuXG4gKlxuICogVHdvIHRoaW5ncyBoYXZlIHRvIGJlIHRydWUsIGFuZCB0aGUgc2Vjb25kIGlzIHRoZSBvbmUgdGhhdCBpcyBlYXN5IHRvIG1pc3M6XG4gKlxuICogMS4gVGhlIGRldmljZSBtdXN0IGJlIGFsbG93ZWQgdG8gZHJhdyBhIGtleWJvYXJkIGF0IGFsbC4gVGhlIHNjcmVlbnNob3QgQVZEc1xuICogICAgYXJlIGJ1aWx0IGBody5rZXlib2FyZD15ZXNgLCBzbyBBbmRyb2lkIHN1cHByZXNzZXMgdGhlIG9uLXNjcmVlbiBvbmUgXHUyMDE0XG4gKiAgICBgd2l0aFNvZnRLZXlib2FyZEVuYWJsZWRgIGluIGBkZXZpY2Utc2V0dGluZ3NgIGlzIHdoYXQgbGlmdHMgdGhhdC5cbiAqIDIuIFRoZSBJTUUgbXVzdCBiZSAqYXNrZWQqIGZvciBieSBhIGdlc3R1cmUuIEEgZmllbGQgdGhhdCB0YWtlcyBmb2N1c1xuICogICAgcHJvZ3JhbW1hdGljYWxseSBkb2VzIG5vdCBnZXQgb25lOiBhbiBBbmRyb2lkIFdlYlZpZXcgcmFpc2VzIHRoZSBJTUUgb24gYVxuICogICAgcmVhbCB0b3VjaCwgYW5kIGEgcnVuIHdpdGggdGhlIHNldHRpbmcgZmxpcHBlZCBhbmQgbm8gdG91Y2ggY29tZXMgYmFjayB3aXRoXG4gKiAgICBleGFjdGx5IHRoZSBlbXB0eSBiYW5kIGl0IGhhZCBiZWZvcmUuIGBhZGIgc2hlbGwgaW5wdXQgdGFwYCBpcyB0aGF0IGdlc3R1cmUuXG4gKlxuICogVGhlIGdlb21ldHJ5IHRoYXQgZGVjaWRlcyB3aGV0aGVyIGl0IHdvcmtlZCBpcyB1bml0LXRlc3RlZCBpblxuICogYHNvZnQta2V5Ym9hcmQtZ2VvbWV0cnlgOyBldmVyeXRoaW5nIGhlcmUgZHJpdmVzIGEgcmVhbCBkZXZpY2UsIHNvIHRoZSB3aG9sZVxuICogbW9kdWxlIGlzIGludGVncmF0aW9uLXRpbWUgY29kZS5cbiAqL1xuXG4vKiB2OCBpZ25vcmUgc3RhcnQgLS0gSW50ZWdyYXRpb24tdGltZSBjb2RlIChkcml2ZXMgYSBsaXZlIE9ic2lkaWFuIG9uIGEgcmVhbCBkZXZpY2UpIGNvdmVyZWQgYnkgaW50ZWdyYXRpb24gdGVzdHMsIG5vdCB1bml0IHRlc3RzLiAqL1xuXG5pbXBvcnQge1xuICBta2RpclN5bmMsXG4gIHdyaXRlRmlsZVN5bmNcbn0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCBwcm9jZXNzIGZyb20gJ25vZGU6cHJvY2Vzcyc7XG5pbXBvcnQgeyBzZXRUaW1lb3V0IGFzIHNsZWVwIH0gZnJvbSAnbm9kZTp0aW1lcnMvcHJvbWlzZXMnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIEVsZW1lbnRSZWN0LFxuICBTb2Z0S2V5Ym9hcmRUYXBQb2ludCxcbiAgU29mdEtleWJvYXJkVmlld3BvcnRTbmFwc2hvdFxufSBmcm9tICcuL3NvZnQta2V5Ym9hcmQtZ2VvbWV0cnkuY2pzJztcblxuaW1wb3J0IHsgcnVuQWRiVGV4dCB9IGZyb20gJy4vYWRiLmNqcyc7XG5pbXBvcnQgeyBjYXB0dXJlRGV2aWNlU2NyZWVuc2hvdCB9IGZyb20gJy4vZGV2aWNlLXNjcmVlbnNob3QuY2pzJztcbmltcG9ydCB7IGV2YWxJbk9ic2lkaWFuIH0gZnJvbSAnLi9ldmFsLWluLW9ic2lkaWFuLmNqcyc7XG5pbXBvcnQge1xuICBidWlsZFNvZnRLZXlib2FyZERpYWdub3N0aWNNZXNzYWdlLFxuICBjaGVja0lzU29mdEtleWJvYXJkVXAsXG4gIHBhcnNlSW5wdXRNZXRob2RTdGF0ZSxcbiAgcmVzb2x2ZVNvZnRLZXlib2FyZFRhcFBvaW50c1xufSBmcm9tICcuL3NvZnQta2V5Ym9hcmQtZ2VvbWV0cnkuY2pzJztcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgcmFpc2VTb2Z0S2V5Ym9hcmR9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJhaXNlU29mdEtleWJvYXJkUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBkZXZpY2UgdG8gdG91Y2guXG4gICAqL1xuICByZWFkb25seSBkZXZpY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVyZSBhIGZhaWxlZCBhdHRlbXB0IHdyaXRlcyB0aGUgZGV2aWNlIGZyYW1lYnVmZmVyLlxuICAgKlxuICAgKiBXaGVuIG9taXR0ZWQsIGl0IGlzIGBkaXN0L3NjcmVlbnNob3RzYCB1bmRlciB0aGUgd29ya2luZyBkaXJlY3RvcnkgXHUyMDE0IHJlc29sdmVkIGF0IGxvYWQsIHNvIHRoZXJlIGlzIG5vXG4gICAqIGxpdGVyYWwgZGVmYXVsdCB0byBzdGF0ZSBoZXJlLlxuICAgKi9cbiAgcmVhZG9ubHkgZGlhZ25vc3RpY3NEaXJlY3Rvcnk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBDU1Mgc2VsZWN0b3Igb2YgdGhlIGZpZWxkIHRvIHRvdWNoLCBlLmcuIGAucHJvbXB0LWlucHV0YC5cbiAgICovXG4gIHJlYWRvbmx5IGlucHV0U2VsZWN0b3I6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGxlYXN0IGEgcmFpc2VkIGtleWJvYXJkIGxpZnRzIHRoZSBmaWVsZCBieS5cbiAgICpcbiAgICogV2hlbiBvbWl0dGVkLCBgREVGQVVMVF9NSU5JTVVNX0tFWUJPQVJEX0hFSUdIVF9JTl9QSVhFTFNgIGZyb20gYHNvZnQta2V5Ym9hcmQtZ2VvbWV0cnlgIGFwcGxpZXMuXG4gICAqL1xuICByZWFkb25seSBtaW5pbXVtS2V5Ym9hcmRIZWlnaHRJblBpeGVscz86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIHZhdWx0IHRvIHJlYWQgdGhlIGdlb21ldHJ5IGZyb20uIFdoZW4gb21pdHRlZCwgdGhlIGN1cnJlbnQgdGVzdCBjb250ZXh0J3MgdmF1bHQgaXMgdXNlZC5cbiAgICovXG4gIHJlYWRvbmx5IHZhdWx0UGF0aD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgdGFwRGV2aWNlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYXBEZXZpY2VQYXJhbXMge1xuICAvKipcbiAgICogVGhlIGRldmljZSB0byB0b3VjaC5cbiAgICovXG4gIHJlYWRvbmx5IGRldmljZUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXJlIHRvIHRvdWNoIGl0LlxuICAgKi9cbiAgcmVhZG9ubHkgcG9pbnQ6IFNvZnRLZXlib2FyZFRhcFBvaW50O1xufVxuXG4vKipcbiAqIFdoZXJlIGEgZmFpbGVkIGF0dGVtcHQgbGVhdmVzIGl0cyBldmlkZW5jZSBcdTIwMTQgZ2l0aWdub3JlZCBhY3Jvc3MgdGhlIGZsZWV0LCBsaWtlIHRoZSBjYXB0dXJlIHNjcmF0Y2ggZmlsZXMuXG4gKi9cbmNvbnN0IERFRkFVTFRfRElBR05PU1RJQ1NfRElSRUNUT1JZID0gam9pbihwcm9jZXNzLmN3ZCgpLCAnZGlzdCcsICdzY3JlZW5zaG90cycpO1xuXG4vKipcbiAqIEhvdyBsb25nIHRoZSBJTUUgdGFrZXMgdG8gZmluaXNoIGFuaW1hdGluZyBpbiwgYWZ0ZXIgd2hpY2ggdGhlIGxheW91dCBoYXMgc2V0dGxlZC5cbiAqL1xuY29uc3QgS0VZQk9BUkRfU0VUVExFX0RFTEFZX0lOX01JTExJU0VDT05EUyA9IDE1MDA7XG5cbi8qKlxuICogUmFpc2VzIHRoZSBvbi1zY3JlZW4ga2V5Ym9hcmQgd2l0aCBhIHJlYWwgdG91Y2ggb24gYSBmaWVsZCwgYW5kIGNvbmZpcm1zIGl0IGNhbWUgdXAuXG4gKlxuICogQ2FsbCBpdCBpbnNpZGUgYHdpdGhTb2Z0S2V5Ym9hcmRFbmFibGVkYCBcdTIwMTQgdGhlIGRldmljZSBzZXR0aW5nIGFsb25lIGRvZXMgbm90IHJhaXNlIHRoZSBrZXlib2FyZCwgYW5kIHRoaXNcbiAqIHRvdWNoIGFsb25lIGNhbm5vdCB3aGlsZSB0aGUgc2V0dGluZyBzdXBwcmVzc2VzIGl0LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgZGV2aWNlLCB0aGUgZmllbGQgdG8gdG91Y2gsIGFuZCBob3cgZmFyIGl0IG11c3QgbGlmdC5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGdlb21ldHJ5IHJlYWQgb25jZSB0aGUga2V5Ym9hcmQgaXMgdXAuXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBrZXlib2FyZCBuZXZlciBjYW1lIHVwLCBhZnRlciB3cml0aW5nIHRoZSBkZXZpY2UgZnJhbWVidWZmZXIgYW5kIHRoZSBkZXZpY2UncyBvd25cbiAqICAgYGlucHV0X21ldGhvZGAgc3RhdGUgdG8gdGhlIGRpYWdub3N0aWNzIGRpcmVjdG9yeS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJhaXNlU29mdEtleWJvYXJkKHBhcmFtczogUmFpc2VTb2Z0S2V5Ym9hcmRQYXJhbXMpOiBQcm9taXNlPFNvZnRLZXlib2FyZFZpZXdwb3J0U25hcHNob3Q+IHtcbiAgbGV0IHNuYXBzaG90ID0gYXdhaXQgcmVhZFNvZnRLZXlib2FyZFZpZXdwb3J0KHBhcmFtcyk7XG5cbiAgaWYgKCFzbmFwc2hvdC5pbnB1dFJlY3QpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHJhaXNlU29mdEtleWJvYXJkOiBub3RoaW5nIG1hdGNoZXMgXCIke3BhcmFtcy5pbnB1dFNlbGVjdG9yfVwiLCBzbyB0aGVyZSBpcyBubyBmaWVsZCB0byB0b3VjaC5gKTtcbiAgfVxuXG4gIGZvciAoY29uc3QgcG9pbnQgb2YgcmVzb2x2ZVNvZnRLZXlib2FyZFRhcFBvaW50cyh7IHNuYXBzaG90IH0pKSB7XG4gICAgaWYgKGNoZWNrSXNVcChzbmFwc2hvdCkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGF3YWl0IHRhcERldmljZSh7IGRldmljZUlkOiBwYXJhbXMuZGV2aWNlSWQsIHBvaW50IH0pO1xuICAgIGF3YWl0IHNsZWVwKEtFWUJPQVJEX1NFVFRMRV9ERUxBWV9JTl9NSUxMSVNFQ09ORFMpO1xuICAgIHNuYXBzaG90ID0gYXdhaXQgcmVhZFNvZnRLZXlib2FyZFZpZXdwb3J0KHBhcmFtcyk7XG4gIH1cblxuICBpZiAoIWNoZWNrSXNVcChzbmFwc2hvdCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYXdhaXQgYnVpbGRGYWlsdXJlTWVzc2FnZShwYXJhbXMsIHNuYXBzaG90KSk7XG4gIH1cblxuICByZXR1cm4gc25hcHNob3Q7XG5cbiAgZnVuY3Rpb24gY2hlY2tJc1VwKGN1cnJlbnQ6IFNvZnRLZXlib2FyZFZpZXdwb3J0U25hcHNob3QpOiBib29sZWFuIHtcbiAgICByZXR1cm4gY2hlY2tJc1NvZnRLZXlib2FyZFVwKHtcbiAgICAgIC4uLihwYXJhbXMubWluaW11bUtleWJvYXJkSGVpZ2h0SW5QaXhlbHMgIT09IHVuZGVmaW5lZCAmJiB7IG1pbmltdW1LZXlib2FyZEhlaWdodEluUGl4ZWxzOiBwYXJhbXMubWluaW11bUtleWJvYXJkSGVpZ2h0SW5QaXhlbHMgfSksXG4gICAgICBzbmFwc2hvdDogY3VycmVudFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogVG91Y2hlcyB0aGUgZGV2aWNlIGF0IGEgcG9pbnQsIHRoZSB3YXkgYSB0aHVtYiB3b3VsZC5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIGRldmljZSBhbmQgd2hlcmUgdG8gdG91Y2ggaXQuXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIG9uY2UgdGhlIHRvdWNoIGhhcyBiZWVuIGRpc3BhdGNoZWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0YXBEZXZpY2UocGFyYW1zOiBUYXBEZXZpY2VQYXJhbXMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgcnVuQWRiVGV4dCh7XG4gICAgY29tbWFuZEFyZ3VtZW50czogWydzaGVsbCcsICdpbnB1dCcsICd0YXAnLCBTdHJpbmcocGFyYW1zLnBvaW50LnhJblBpeGVscyksIFN0cmluZyhwYXJhbXMucG9pbnQueUluUGl4ZWxzKV0sXG4gICAgZGV2aWNlSWQ6IHBhcmFtcy5kZXZpY2VJZFxuICB9KTtcbn1cblxuLyoqXG4gKiBXcml0ZXMgdGhlIGRldmljZSBmcmFtZWJ1ZmZlciBhbmQgcmVhZHMgdGhlIGRldmljZSdzIGBpbnB1dF9tZXRob2RgIHN0YXRlLCB0aGVuIGNvbXBvc2VzIHRoZSBmYWlsdXJlLlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgZGV2aWNlIGFuZCB0aGUgZGlhZ25vc3RpY3MgZGlyZWN0b3J5LlxuICogQHBhcmFtIHNuYXBzaG90IC0gVGhlIGdlb21ldHJ5IHJlYWQgYWZ0ZXIgdGhlIGxhc3QgdG91Y2guXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHRvIHRoZSBtZXNzYWdlIHRvIHRocm93LlxuICovXG5hc3luYyBmdW5jdGlvbiBidWlsZEZhaWx1cmVNZXNzYWdlKHBhcmFtczogUmFpc2VTb2Z0S2V5Ym9hcmRQYXJhbXMsIHNuYXBzaG90OiBTb2Z0S2V5Ym9hcmRWaWV3cG9ydFNuYXBzaG90KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgZGlhZ25vc3RpY3NEaXJlY3RvcnkgPSBwYXJhbXMuZGlhZ25vc3RpY3NEaXJlY3RvcnkgPz8gREVGQVVMVF9ESUFHTk9TVElDU19ESVJFQ1RPUlk7XG4gIG1rZGlyU3luYyhkaWFnbm9zdGljc0RpcmVjdG9yeSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgY29uc3Qgc2NyZWVuc2hvdFBhdGggPSBqb2luKGRpYWdub3N0aWNzRGlyZWN0b3J5LCAna2V5Ym9hcmQtbm90LXJhaXNlZC5wbmcnKTtcbiAgd3JpdGVGaWxlU3luYyhzY3JlZW5zaG90UGF0aCwgYXdhaXQgY2FwdHVyZURldmljZVNjcmVlbnNob3QoeyBkZXZpY2VJZDogcGFyYW1zLmRldmljZUlkIH0pKTtcblxuICBjb25zdCBkdW1wc3lzT3V0cHV0ID0gYXdhaXQgcnVuQWRiVGV4dCh7XG4gICAgY29tbWFuZEFyZ3VtZW50czogWydzaGVsbCcsICdkdW1wc3lzJywgJ2lucHV0X21ldGhvZCddLFxuICAgIGRldmljZUlkOiBwYXJhbXMuZGV2aWNlSWRcbiAgfSk7XG5cbiAgcmV0dXJuIGJ1aWxkU29mdEtleWJvYXJkRGlhZ25vc3RpY01lc3NhZ2Uoe1xuICAgIGlucHV0TWV0aG9kU3RhdGU6IHBhcnNlSW5wdXRNZXRob2RTdGF0ZShkdW1wc3lzT3V0cHV0KSxcbiAgICBzY3JlZW5zaG90UGF0aCxcbiAgICBzbmFwc2hvdFxuICB9KTtcbn1cblxuLyoqXG4gKiBSZWFkcyB3aGF0IHRoZSByZW5kZXJlciBrbm93cyBhYm91dCBpdHMgb3duIGdlb21ldHJ5LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgZmllbGQgdG8gbWVhc3VyZSBhbmQgdGhlIHZhdWx0IHRvIHJlYWQgaXQgZnJvbS5cbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHZpZXdwb3J0IGFuZCB0aGUgZmllbGQncyByZWN0LCBpbiBDU1MgcGl4ZWxzLlxuICovXG5hc3luYyBmdW5jdGlvbiByZWFkU29mdEtleWJvYXJkVmlld3BvcnQocGFyYW1zOiBSYWlzZVNvZnRLZXlib2FyZFBhcmFtcyk6IFByb21pc2U8U29mdEtleWJvYXJkVmlld3BvcnRTbmFwc2hvdD4ge1xuICByZXR1cm4gYXdhaXQgZXZhbEluT2JzaWRpYW4oe1xuICAgIGNhbGxiYWNrKHsgaW5wdXRTZWxlY3RvciB9KTogU29mdEtleWJvYXJkVmlld3BvcnRTbmFwc2hvdCB7XG4gICAgICBjb25zdCBpbnB1dEVsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihpbnB1dFNlbGVjdG9yKTtcblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vY29uc2lzdGVudC1mdW5jdGlvbi1zY29waW5nIC0tIFRoaXMgY2xvc3VyZSBpcyBzZXJpYWxpemVkIGFuZCBldmFsdWF0ZWQgaW4gdGhlIHJlbmRlcmVyLCBzbyBhIGhlbHBlciBob2lzdGVkIHRvIG1vZHVsZSBzY29wZSB3b3VsZCBub3QgZXhpc3QgdGhlcmUuXG4gICAgICBmdW5jdGlvbiB0b1JlY3QocmVjdDogRE9NUmVjdCk6IEVsZW1lbnRSZWN0IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBoZWlnaHQ6IHJlY3QuaGVpZ2h0LFxuICAgICAgICAgIGxlZnQ6IHJlY3QubGVmdCxcbiAgICAgICAgICB0b3A6IHJlY3QudG9wLFxuICAgICAgICAgIHdpZHRoOiByZWN0LndpZHRoXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGRldmljZVBpeGVsUmF0aW86IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvLFxuICAgICAgICBpbm5lckhlaWdodDogd2luZG93LmlubmVySGVpZ2h0LFxuICAgICAgICBpbnB1dFJlY3Q6IGlucHV0RWwgPyB0b1JlY3QoaW5wdXRFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSkgOiBudWxsLFxuICAgICAgICBzY3JlZW5ZOiB3aW5kb3cuc2NyZWVuWVxuICAgICAgfTtcbiAgICB9LFxuICAgIGlucHV0OiB7IGlucHV0U2VsZWN0b3I6IHBhcmFtcy5pbnB1dFNlbGVjdG9yIH0sXG4gICAgLi4uKHBhcmFtcy52YXVsdFBhdGggIT09IHVuZGVmaW5lZCAmJiB7IHZhdWx0UGF0aDogcGFyYW1zLnZhdWx0UGF0aCB9KVxuICB9KTtcbn1cblxuLyogdjggaWdub3JlIHN0b3AgKi9cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFzQkEscUJBR087QUFDUCx1QkFBcUI7QUFDckIsMEJBQW9CO0FBQ3BCLHNCQUFvQztBQVFwQyxpQkFBMkI7QUFDM0IsK0JBQXdDO0FBQ3hDLDhCQUErQjtBQUMvQixvQ0FLTztBQXVEUCxNQUFNLG9DQUFn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
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Raises the Android soft keyboard for a screenshot, and proves it came up.
5
+ *
6
+ * Two things have to be true, and the second is the one that is easy to miss:
7
+ *
8
+ * 1. The device must be allowed to draw a keyboard at all. The screenshot AVDs
9
+ * are built `hw.keyboard=yes`, so Android suppresses the on-screen one —
10
+ * `withSoftKeyboardEnabled` in `device-settings` is what lifts that.
11
+ * 2. The IME must be *asked* for by a gesture. A field that takes focus
12
+ * programmatically does not get one: an Android WebView raises the IME on a
13
+ * real touch, and a run with the setting flipped and no touch comes back with
14
+ * exactly the empty band it had before. `adb shell input tap` is that gesture.
15
+ *
16
+ * The geometry that decides whether it worked is unit-tested in
17
+ * `soft-keyboard-geometry`; everything here drives a real device, so the whole
18
+ * module is integration-time code.
19
+ */
20
+ import type { SoftKeyboardTapPoint, SoftKeyboardViewportSnapshot } from './soft-keyboard-geometry.cjs';
21
+ /**
22
+ * Parameters for {@link raiseSoftKeyboard}.
23
+ */
24
+ export interface RaiseSoftKeyboardParams {
25
+ /**
26
+ * The device to touch.
27
+ */
28
+ readonly deviceId: string;
29
+ /**
30
+ * Where a failed attempt writes the device framebuffer.
31
+ *
32
+ * When omitted, it is `dist/screenshots` under the working directory — resolved at load, so there is no
33
+ * literal default to state here.
34
+ */
35
+ readonly diagnosticsDirectory?: string;
36
+ /**
37
+ * The CSS selector of the field to touch, e.g. `.prompt-input`.
38
+ */
39
+ readonly inputSelector: string;
40
+ /**
41
+ * The least a raised keyboard lifts the field by.
42
+ *
43
+ * When omitted, `DEFAULT_MINIMUM_KEYBOARD_HEIGHT_IN_PIXELS` from `soft-keyboard-geometry` applies.
44
+ */
45
+ readonly minimumKeyboardHeightInPixels?: number;
46
+ /**
47
+ * The vault to read the geometry from. When omitted, the current test context's vault is used.
48
+ */
49
+ readonly vaultPath?: string;
50
+ }
51
+ /**
52
+ * Parameters for {@link tapDevice}.
53
+ */
54
+ export interface TapDeviceParams {
55
+ /**
56
+ * The device to touch.
57
+ */
58
+ readonly deviceId: string;
59
+ /**
60
+ * Where to touch it.
61
+ */
62
+ readonly point: SoftKeyboardTapPoint;
63
+ }
64
+ /**
65
+ * Raises the on-screen keyboard with a real touch on a field, and confirms it came up.
66
+ *
67
+ * Call it inside `withSoftKeyboardEnabled` — the device setting alone does not raise the keyboard, and this
68
+ * touch alone cannot while the setting suppresses it.
69
+ *
70
+ * @param params - The device, the field to touch, and how far it must lift.
71
+ * @returns A {@link Promise} that resolves to the geometry read once the keyboard is up.
72
+ * @throws Error if the keyboard never came up, after writing the device framebuffer and the device's own
73
+ * `input_method` state to the diagnostics directory.
74
+ */
75
+ export declare function raiseSoftKeyboard(params: RaiseSoftKeyboardParams): Promise<SoftKeyboardViewportSnapshot>;
76
+ /**
77
+ * Touches the device at a point, the way a thumb would.
78
+ *
79
+ * @param params - The device and where to touch it.
80
+ * @returns A {@link Promise} that resolves once the touch has been dispatched.
81
+ */
82
+ export declare function tapDevice(params: TapDeviceParams): Promise<void>;