# Inlay Testing

> Write widget tests for Flutter screens that use inlay's InlayNavigator or KeyValueStorage singletons, using the in-memory fakes from package:inlay/testing.dart. Use when testing screens in an inlay add-to-app module that navigate, use generated stores or InlayCubit, or read/write shared state.

- Skill: `leancodepl/inlay-testing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add leancodepl/inlay-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/leancodepl/inlay-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: leancodepl (https://skillmd.com/u/leancodepl)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/leancodepl/inlay-testing

---


# Testing inlay screens

Screens in an inlay module depend on two singletons that talk to the native host over platform
channels: `InlayNavigator` and `KeyValueStorage`. In plain widget tests there is no host, so
those calls throw `MissingPluginException`. `package:inlay/testing.dart` ships in-memory fakes,
and both singletons expose a `@visibleForTesting` instance setter.

Canonical docs: https://github.com/leancodepl/inlay/blob/main/docs/testing.md
Reference tests (use both fakes):
https://github.com/leancodepl/inlay/tree/main/example/example_module/test

## 1. Install the fakes in `setUp`

```dart
import 'package:inlay/inlay.dart';
import 'package:inlay/testing.dart';

setUp(() {
  KeyValueStorage.instance = FakeKeyValueStorage();
  InlayNavigator.instance = FakeInlayNavigator();
});
```

Keep local references when the test needs to assert on them:

```dart
late FakeInlayNavigator navigator;
late FakeKeyValueStorage storage;

setUp(() {
  navigator = FakeInlayNavigator();
  storage = FakeKeyValueStorage();
  InlayNavigator.instance = navigator;
  KeyValueStorage.instance = storage;
});
```

## 2. Assert navigation with `FakeInlayNavigator`

It records instead of navigating:

- `pushedRoutes` — typed routes passed to `push()`, in call order. Assert with
  `expect(navigator.pushedRoutes, [isA<ContactDetailsPage>()])` and check fields on the typed
  route.
- `pushedPages` — raw `PageSettings` from all dispatch methods, including those produced by
  `push()`.
- `popCount` — container pops; `maybePop` still pops an in-Flutter route when it can.
- `nativePopGestureEnabled` — last value passed to `setNativePopGestureEnabled`.

## 3. Seed and assert state with `FakeKeyValueStorage`

An in-memory map with the real storage's semantics:

- **Seed through the generated store wrapper**, not by writing raw keys — the wrapper uses the
  production key encoding:
  ```dart
  await SoundsNotificationsStore(storage, contactId: 'abc').setMute(true);
  ```
  The raw backing map `storage.data` is available for inspection.
- Writes do **not** fire `stream` (matching the platform's self-notification suppression), so
  seeding in `setUp` won't trigger listeners.
- `simulateExternalChange(entries)` applies entries **and** fires `stream` — this is what a
  write from another engine or native code looks like to the widget under test. Use it to
  cover the full store → `InlayCubit` → widget rebuild chain, then `await tester.pump()`.

## 4. Shape of a full test

Per screen: pump the widget with its store/cubit built from the fakes, assert the initial
render (remember `InlayCubit` starts in `InlayStateLoading` — pump until ready), interact and
assert writes landed in `storage.data` / navigation landed in `navigator.pushedRoutes`, and use
`simulateExternalChange` to assert the screen reacts to changes from elsewhere. The reference
tests `greeting_screen_test.dart` and `profile_screen_test.dart` in the example module
demonstrate all of these patterns — mirror them.

## Gotchas

- Reset singletons per test (`setUp` runs per test — fresh fakes each time prevent state
  leaking between tests).
- Store getters/setters are async; `await` them in tests or you'll assert before the write.
- These fakes cover widget tests only. Real cross-boundary behavior (plugin registration,
  typed results delivered to native, appearance propagation) is host-side territory — the
  example repo has XCUITest and UiAutomator suites to mirror if you need that:
  https://github.com/leancodepl/inlay/blob/main/docs/testing.md#reference-tests

