Testing
Two halves, one element model. Both describe elements identically because
both descriptors come from one Rust implementation in
slint-dart-interpreter.
Headless: slint_testing
A component on Slint's testing backend — no window, renderer, or event loop — wrapped in its generated wrapper like any other backend's instance:
final ui = SlintTestApp.compile(TodoApp.slintSource,
component: TodoApp.componentName, files: TodoApp.slintFiles);
final app = TodoApp(ui);
addTearDown(app.dispose);
final added = <String>[];
app.onAddTodo(added.add);
ui.findById('TodoView::edit').single.setValue('buy milk');
ui.findByLabel('Add').single.click();
expect(added, ['buy milk']);
Elements are found through the test app; properties and callbacks go
through the wrapper, so nothing names a Slint property. No device, no
window. Reach for it to check a component's logic fast.
examples/todo/test/todo_headless_test.dart drives TodoApp this way. See
the testing package.
Live: slint_patrol
Patrol finders over the live component in a real widget tree, tapping and typing through real Flutter gestures:
await $.slintById('TodoView::edit').enterText('buy milk');
await $.slint('Add').tap();
await $.slintSettle();
expect(TodoApp($.slintComponent()).todoModel.last.title, 'buy milk');
Elements are found by label or id — accessibility queries — and state is read
through the generated wrapper, which takes the live component from any
backend; nothing names a Slint property. examples/todo/test/todo_patrol_test.dart
drives the real TodoPage this way.
SlintView renders on a Ticker every frame, so the tree never settles —
use slintSettle() (a bounded handful of frames) where a Flutter-only test
would call pumpAndSettle. Element queries need the interpreter backend
(debug builds, including flutter test and patrol test). See the
Patrol package.