Class TestNavigator
An in-memory NavigatorCore for unit testing view models without a UI framework. It runs the real navigation and dialog engine against placeholder views, records everything that happens in Events, and lets tests script dialog outcomes.
Inherited Members
Namespace: Singulink.UI.Navigation.Testing
Assembly: Singulink.UI.Navigation.Testing.dll
Syntax
public sealed class TestNavigator : NavigatorCore, INavigator, IDialogPresenter, INotifyPropertyChanged
Remarks
Instances must be created and used inside Run(Func<Task>), which provides the single-threaded synchronization context the navigator and its task runners require.
Constructors
| Name | Description |
|---|---|
| TestNavigator(Action<TestNavigatorBuilder>) | Initializes a new instance of the TestNavigator class using the specified build action to map view models and add routes. |
Properties
| Name | Description |
|---|---|
| ActiveViewModels | Gets the active view models from the root of the view hierarchy down to the leaf. |
| AutoAcceptMessageDialogs | Gets or sets a value indicating whether message dialogs without a scripted response (see OnMessageDialog(Func<MessageDialogViewModel, int>)) are automatically answered with their default button (or the first button if there is no default). When false (the default), an unscripted message dialog fails the test, since it usually indicates an unexpected code path or a missing script. |
| Events | Gets everything that happened in this navigator, in order: navigations, redirects, view model creation and activation, lifecycle method invocations, dialogs and busy state changes. Use ClearEvents() to start a fresh slice before the part of a test being asserted on. |
| LastNavigationResult | Gets the result of the most recently completed navigation, or null if no navigation has completed yet. |
| ShowingDialogs | Gets the dialogs currently showing, from the bottom of the dialog stack to the top. |
| TopDialog | Gets the top showing dialog, or null if no dialog is showing. |
Methods
| Name | Description |
|---|---|
| ActiveViewModel<TViewModel>() | Gets the active view model of the specified type, searching from the leaf of the view hierarchy upwards. |
| ClearEvents() | Removes all recorded events. |
| CloseLightDismissPopups() | Closes any light-dismiss popups that are currently open. |
| CreateDefaultDialog(Type) | Creates a framework dialog object for a dialog view model type that has no registered dialog mapping, or returns null if no default is available (in which case showing the dialog throws). The default implementation returns null. |
| EnsureThreadAccess() | Ensures that the current call is happening on the required thread. |
| HideDialog(object) | Hides the specified framework dialog object. |
| OnDialogShown<TViewModel>(Action<TViewModel>) | Registers a script that runs whenever a dialog with the specified view model type is shown. The script typically sets state on the view model and closes it through its navigator. Scripts run asynchronously after the dialog has been shown, so the code that showed the dialog is already awaiting it. Dialogs without a script stay open so the test can drive them through TopDialog. |
| OnDialogShown<TViewModel>(Func<TViewModel, Task>) | Registers a script that runs whenever a dialog with the specified view model type is shown. The script typically sets state on the view model and closes it through its navigator. Scripts run asynchronously after the dialog has been shown, so the code that showed the dialog is already awaiting it. Dialogs without a script stay open so the test can drive them through TopDialog. |
| OnLayerCoveredChanged(object?, bool) | Called when a layer (the root view or a dialog) becomes covered by a child dialog, or is uncovered again when the child dialog closes. Implementations can use this to adjust how the layer is presented while it is covered (e.g. to avoid showing it as disabled underneath the child dialog while it is busy, since the child dialog is what blocks interaction with it). The default implementation does nothing. |
| OnMessageDialog(Func<MessageDialogViewModel, int>) | Registers a script that chooses the button index to answer message dialogs with. Runs whenever a message dialog is shown. |
| OnNavigationCompleted(NavigationType, NavigatorRoute, NavigationResult, object?) | Called when a navigation completes, either successfully or due to cancellation. This is always called if OnNavigationStarting(NavigationType, NavigatorRoute) was called for the same navigation. |
| OnNavigationRedirecting(IRoutedViewModelBase, Redirect) | Called when a routed view model requested a redirect during navigation, immediately before the redirect is executed. The default implementation does nothing. |
| OnNavigationStarting(NavigationType, NavigatorRoute) | Called synchronously at the start of a navigation, before any view model lifecycle methods are invoked and before any awaits occur. Implementations should perform any synchronous work required at the start of a navigation, such as updating browser history state on WebAssembly platforms (which must happen synchronously while user activation is still valid). |
| OnViewModelLifecycleInvoking(IRoutedViewModelBase, ViewModelLifecycleStage) | Called immediately before a lifecycle method is invoked on a routed view model during navigation. The default implementation does nothing. |
| RequestDismissTop() | Delivers a dismiss request to the top dialog, equivalent to the user pressing the escape key or the system back button. The request is only honoured if the dialog view model implements IDismissibleDialogViewModel and the dialog is not busy, matching the application navigator's behaviour. |
| RestoreDialogFocusState(object, object?) | Restores focus into the specified framework dialog object after a child dialog closes. Implementations should defer the restoration until after any
focus handling the framework performs when a dialog closes, and should ensure focus ends up inside the dialog even if |
| SetActiveView(object, object?) | Sets the active view in the specified view navigator. |
| StartShowingDialog(object) | Starts showing the specified framework dialog object. This is invoked in a fire-and-forget manner; awaiting completion of the dialog is handled by the core orchestration via the dialog's TaskCompletionSource. |
| WaitUntilIdleAsync() | Waits until the navigator and all dialogs are idle: no busy tasks, no fire-and-forget work and no pending continuations. Use this after invoking commands that start work without returning a task before asserting on the outcome. |
| WireDialog(object, IDialogViewModel, out ITaskRunner) | Wires up a newly created framework-specific dialog object with the specified view model. The implementation should attach the view model as the dialog's data context, hook up any framework-specific bindings/event handlers, and produce a task runner used to run dialog operations. |
| WireView(object, IRoutedViewModelBase, out object?) | Wires up a newly materialized view with the specified view model. The implementation should attach the view model as the view's data context, hook up any framework-specific bindings/event handlers, and produce the child view navigator if the view is a parent view. |