pub struct TestHarness<S, A: Action> {
pub state: S,
/* private fields */
}Expand description
Generic test harness for tui-dispatch applications.
Provides:
- State management with a simple
statefield - Action channel for capturing emitted actions
- Helper methods for dispatching and draining actions
§Type Parameters
S: The state typeA: The action type (must implementAction)
§Example
use tui_dispatch::testing::TestHarness;
#[derive(Clone, Debug, PartialEq)]
enum MyAction { Foo, Bar(i32) }
let mut harness = TestHarness::<MyState, MyAction>::new(MyState::default());
// Emit actions (simulating what handlers would do)
harness.emit(MyAction::Foo);
harness.emit(MyAction::Bar(42));
// Drain and verify
let actions = harness.drain_emitted();
assert_eq!(actions.len(), 2);Fields§
§state: SThe application state under test
Implementations§
Source§impl<S, A: Action> TestHarness<S, A>
impl<S, A: Action> TestHarness<S, A>
Sourcepub fn sender(&self) -> UnboundedSender<A>
pub fn sender(&self) -> UnboundedSender<A>
Get a clone of the action sender for passing to handlers.
Sourcepub fn drain_emitted(&mut self) -> Vec<A>
pub fn drain_emitted(&mut self) -> Vec<A>
Drain all emitted actions from the channel.
Sourcepub fn has_emitted(&mut self) -> bool
pub fn has_emitted(&mut self) -> bool
Check if any actions were emitted.
Sourcepub fn complete_action(&self, action: A)
pub fn complete_action(&self, action: A)
Simulate async action completion (semantic alias for Self::emit).
Use this when simulating backend responses or async operation results.
§Example
use tui_dispatch::testing::TestHarness;
harness.complete_action(Action::DidConnect { id: "conn-1", .. });
harness.complete_action(Action::DidScanKeys { keys: vec!["foo", "bar"] });Sourcepub fn complete_actions(&self, actions: impl IntoIterator<Item = A>)
pub fn complete_actions(&self, actions: impl IntoIterator<Item = A>)
Sourcepub fn send_keys<C, H>(&mut self, keys: &str, handler: H) -> Vec<A>
pub fn send_keys<C, H>(&mut self, keys: &str, handler: H) -> Vec<A>
Send a sequence of key events and collect actions from a handler.
Parses the space-separated key string and calls the handler for each event, collecting all returned actions.
§Example
use tui_dispatch::testing::TestHarness;
let mut harness = TestHarness::<AppState, Action>::new(AppState::default());
// Send key sequence and collect actions
let actions = harness.send_keys("ctrl+p down down enter", |state, event| {
component.handle_event(&event.kind, ComponentProps { state })
});
actions.assert_contains(Action::SelectItem(2));Sourcepub fn send_keys_emit<C, H>(&mut self, keys: &str, handler: H)
pub fn send_keys_emit<C, H>(&mut self, keys: &str, handler: H)
Send a sequence of key events, calling handler and emitting returned actions.
Unlike Self::send_keys, this method emits returned actions to the harness channel,
allowing you to drain them later.
§Example
harness.send_keys_emit("ctrl+p down enter", |state, event| {
component.handle_event(&event.kind, props)
});
let actions = harness.drain_emitted();
actions.assert_contains(Action::Confirm);Source§impl<S, A: ActionCategory> TestHarness<S, A>
Category-aware methods for TestHarness.
impl<S, A: ActionCategory> TestHarness<S, A>
Category-aware methods for TestHarness.
These methods are available when the action type implements ActionCategory,
enabling filtering and assertions by action category.
Sourcepub fn drain_category(&mut self, category: &str) -> Vec<A>
pub fn drain_category(&mut self, category: &str) -> Vec<A>
Drain all emitted actions that belong to a specific category.
Actions not matching the category remain in the channel for later draining.
§Example
use tui_dispatch::testing::TestHarness;
let mut harness = TestHarness::<MyState, MyAction>::new(MyState::default());
// Emit various actions
harness.emit(MyAction::SearchStart);
harness.emit(MyAction::ConnectionFormOpen);
harness.emit(MyAction::SearchClear);
// Drain only search-related actions
let search_actions = harness.drain_category("search");
assert_eq!(search_actions.len(), 2);
// Other actions remain
let remaining = harness.drain_emitted();
assert_eq!(remaining.len(), 1);Sourcepub fn has_category(&mut self, category: &str) -> bool
pub fn has_category(&mut self, category: &str) -> bool
Check if any action of the given category was emitted.
This drains only the matching category, leaving other actions in the channel.
Trait Implementations§
Auto Trait Implementations§
impl<S, A> Freeze for TestHarness<S, A>where
S: Freeze,
impl<S, A> RefUnwindSafe for TestHarness<S, A>where
S: RefUnwindSafe,
impl<S, A> Send for TestHarness<S, A>where
S: Send,
impl<S, A> Sync for TestHarness<S, A>where
S: Sync,
impl<S, A> Unpin for TestHarness<S, A>where
S: Unpin,
impl<S, A> UnwindSafe for TestHarness<S, A>where
S: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more