/** * @file * * Raises the Android soft keyboard for a screenshot, and proves it came up. * * Two things have to be true, and the second is the one that is easy to miss: * * 1. The device must be allowed to draw a keyboard at all. The screenshot AVDs * are built `hw.keyboard=yes`, so Android suppresses the on-screen one — * `withSoftKeyboardEnabled` in `device-settings` is what lifts that. * 2. The IME must be *asked* for by a gesture. A field that takes focus * programmatically does not get one: an Android WebView raises the IME on a * real touch, and a run with the setting flipped and no touch comes back with * exactly the empty band it had before. `adb shell input tap` is that gesture. * * 3. The proof that it arrived is that the field **moved**, measured against a * baseline read here before the first touch. An absolute offset from the * viewport bottom is the same test only for a bottom-anchored field; for a * centred modal it is already true with no keyboard, which used to break the * loop below before it had dispatched a single touch and return success * having done nothing. Reading the baseline first also makes that shape * unrepresentable rather than merely corrected: the delta of the baseline * against itself is zero, so the first iteration always taps. * * The geometry that decides whether it worked is unit-tested in * `soft-keyboard-geometry`; everything here drives a real device, so the whole * module is integration-time code. */ import type { SoftKeyboardTapPoint, SoftKeyboardViewportSnapshot } from './soft-keyboard-geometry.mjs'; /** * Parameters for {@link raiseSoftKeyboard}. */ export interface RaiseSoftKeyboardParams { /** * The device to touch. */ readonly deviceId: string; /** * Where a failed attempt writes the device framebuffer. * * When omitted, it is `dist/screenshots` under the working directory — resolved at load, so there is no * literal default to state here. */ readonly diagnosticsDirectory?: string; /** * The CSS selector of the field to touch, e.g. `.prompt-input`. */ readonly inputSelector: string; /** * The least a raised keyboard lifts the field by. * * When omitted, `DEFAULT_MINIMUM_KEYBOARD_HEIGHT_IN_PIXELS` from `soft-keyboard-geometry` applies. */ readonly minimumKeyboardHeightInPixels?: number; /** * The vault to read the geometry from. When omitted, the current test context's vault is used. */ readonly vaultPath?: string; } /** * Parameters for {@link tapDevice}. */ export interface TapDeviceParams { /** * The device to touch. */ readonly deviceId: string; /** * Where to touch it. */ readonly point: SoftKeyboardTapPoint; } /** * Raises the on-screen keyboard with a real touch on a field, and confirms it came up. * * Call it inside `withSoftKeyboardEnabled` — the device setting alone does not raise the keyboard, and this * touch alone cannot while the setting suppresses it. * * **Call it with the keyboard DOWN.** The first read is the baseline every later read is compared against, * so a keyboard that is already up leaves the field nothing to lift by and this throws. That is the * deliberate trade for working on a centred modal as well as a bottom-anchored one — see * {@link checkIsSoftKeyboardUp}. * * @param params - The device, the field to touch, and how far it must lift. * @returns A {@link Promise} that resolves to the geometry read once the keyboard is up. * @throws Error if the field never matched, or if it never lifted, the latter after writing the device * framebuffer and the device's own `input_method` state to the diagnostics directory. */ export declare function raiseSoftKeyboard(params: RaiseSoftKeyboardParams): Promise; /** * Touches the device at a point, the way a thumb would. * * @param params - The device and where to touch it. * @returns A {@link Promise} that resolves once the touch has been dispatched. */ export declare function tapDevice(params: TapDeviceParams): Promise;