Skip to content

Testing

Terminal window
cargo test --workspace # All Rust tests
cargo check --workspace # Compile check only
flutter test # Dart tests
flutter test --coverage # With coverage

Tests construct a modality directly with state and services, then exercise compilation and dispatch:

#[test]
fn test_compile() {
let state = State {
synced: WhiteboardSynced::default(),
ephemeral: Default::default(),
};
let services = Arc::new(ModalityServices::new(AgentService::noop()));
let modality = Whiteboard::new(state, services);
let result = modality.compile(
&WhiteboardMetadata::default(),
&HashMap::new(),
);
assert!(result.is_ok());
}
  • AgentService::noop() — creates a no-op agent service for tests (no AI channel)
  • State { synced, ephemeral: Default::default() } — minimal state construction
  • ModalityServices::new(agent) — wraps an AgentService for modalities without extra domain services

Test reduce() directly (it’s static — no instance needed):

#[test]
fn test_reduce_add_placement() {
let mut state = State {
synced: WhiteboardSynced::default(),
ephemeral: Default::default(),
};
let services = Arc::new(ModalityServices::new(AgentService::noop()));
let (send_tx, _) = mpsc::channel();
let (spawn_tx, _) = mpsc::channel();
let mut fx = Effects::new(services, send_tx, spawn_tx);
Whiteboard::reduce(
Command::Intent(WhiteboardIntent::AddPlacement { /* ... */ }),
&mut state,
&mut fx,
);
assert_eq!(state.synced.placements.len(), 1);
}

Session tests need a Doc, backend, and sinks:

#[test]
fn test_session_dispatch() {
let session = Session::new(/* modality, doc, services, sinks */);
session.dispatch(Command::Intent(
SessionIntent::Modality(WhiteboardIntent::AddPlacement { /* ... */ })
));
assert_eq!(session.modality.state().synced.placements.len(), 1);
}