# Keyboard (/docs/sims/conditions/keyboard)



Two modes:

| Mode       | What the device does                                                                              |
| ---------- | ------------------------------------------------------------------------------------------------- |
| `software` | the on-screen keyboard always shows, although warden types with hardware key events (the default) |
| `hardware` | the on-screen keyboard stays hidden, as with a connected keyboard                                 |

Every warden-leased simulator and emulator starts on `software`, and release puts it back. Switch live to watch a bottom sheet or a sticky footer ride the keyboard up and down.

With the software keyboard up, a tap on a target the keyboard covers first scrolls it into view (inside a scroll container) or dismisses the keyboard (the injected library resigns the first responder; it never presses Return, which could submit a form), then taps. This is iOS only: an Android snapshot carries the app's window, not the keyboard, so there is no frame to test against (use `device.hideKeyboard()`).

## In a spec [#in-a-spec]

```ts
import { expect, test } from "@delacour/warden-e2e";

test("the footer stays above the keyboard", async ({ app, device, screen }) => {
	await app.open();
	await screen.getByTestId("open-sheet").tap();
	await screen.getByTestId("sheet-input").fill("buy milk");
	await expect(device).toHaveKeyboard();
	await expect(screen.getByTestId("sheet-save")).toBeVisible();

	await device.keyboard("hardware");
	await expect(device).not.toHaveKeyboard();
});
```

| Member                                                  | Does                                                               |
| ------------------------------------------------------- | ------------------------------------------------------------------ |
| `device.keyboard("software" \| "hardware" \| "toggle")` | sets the mode live; `toggle` flips the mode this spec has in place |
| `device.keyboardVisible()`                              | whether a keyboard is up now                                       |
| `expect(device).toHaveKeyboard({ timeout? })`           | polls until a keyboard is up; `.not` until it is gone              |

`device.hideKeyboard()` dismisses a keyboard that is up: iOS resigns the first responder through the injected library (never Return, so no form is submitted; an app running without the library falls back to Enter), Android presses back.

The mode goes back to the suite's `conditions.keyboard` (else `software`) when the test ends.

## In a suite [#in-a-suite]

```ts title="warden.config.ts"
conditions: { keyboard: "hardware" },
```

Applied at the start of each spec and put back when it ends. Values: `"software"` or `"hardware"`.

## By hand [#by-hand]

```bash
warden ui keyboard hardware
warden ui keyboard toggle
warden ui keyboard status   # keyboard  software  visible
warden ui keyboard reset
```

With `--json` the answer is `result.mode` (and `result.visible` for `status`). When the running iOS app was launched without warden's library, `software` / `hardware` answer `appliesOnLaunch: true` with a warning: relaunch it with `warden ui open <bundle> --relaunch`. `software` and `reset` drop the record on your lease; `hardware` is put back on release.

## Per platform [#per-platform]

|              | iOS simulator                                                                                     | Android emulator                                                                                                                                                                                                                                                                                                        | Physical device                                      |
| ------------ | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| How          | the injected library keeps the software keyboard from minimising; live, no relaunch               | `hardware` disables every input method (`ime disable`; `input text` still types); the originals are saved on the device and your lease. `software` puts the saved `enabled_input_methods` and `default_input_method` back, and release does too. After `software` the keyboard reappears at the next field focus or tap | `E_UNSUPPORTED` on an iPhone and on an Android phone |
| Reaches      | an app launched by warden; for an app warden did not launch the mode applies from its next launch | the whole device                                                                                                                                                                                                                                                                                                        |                                                      |
| Visible read | the accessibility tree                                                                            | the input method window (`dumpsys window InputMethod`)                                                                                                                                                                                                                                                                  |                                                      |
