pub struct TestApp { /* private fields */ }Expand description
A headless app for tests.
TestApp runs a real App on a deterministic scheduler. Its platform keeps
the clipboard, opened URLs and prompts in memory, so you can assert on them
instead of seeing them on screen. Each TestApp is independent: state set in
one doesn’t appear in another.
See the testing guide.
Implementations§
Source§impl TestApp
impl TestApp
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a test app with scheduler seed 0.
Text is shaped by the test text system, not by real fonts. Use
TestApp::with_text_system when a test measures real glyphs.
Sourcepub fn with_seed(seed: u64) -> Self
pub fn with_seed(seed: u64) -> Self
Creates a test app whose scheduler orders ready tasks by seed.
The seed decides which ready task runs first. The same seed gives the same order every time, so a failing seed can be replayed.
Sourcepub fn with_text_system(text_system: Arc<dyn PlatformTextSystem>) -> Self
pub fn with_text_system(text_system: Arc<dyn PlatformTextSystem>) -> Self
Creates a test app that shapes text with text_system. Uses seed 0.
Pass a real text system to measure glyphs as the app would on a platform.
Sourcepub fn with_text_system_and_assets(
text_system: Arc<dyn PlatformTextSystem>,
asset_source: Arc<dyn AssetSource>,
) -> Self
pub fn with_text_system_and_assets( text_system: Arc<dyn PlatformTextSystem>, asset_source: Arc<dyn AssetSource>, ) -> Self
Creates a test app with the given text system and asset source.
This is TestApp::with_text_system plus an AssetSource,
so views can load icons and other assets. Uses seed 0.
Sourcepub fn update<R>(&mut self, f: impl FnOnce(&mut App) -> R) -> R
pub fn update<R>(&mut self, f: impl FnOnce(&mut App) -> R) -> R
Runs f with mutable access to the App, then runs pending tasks until none can make progress.
Effects such as observers and subscriptions run when f returns, before the
pending tasks run. Timers that haven’t expired stay pending; use
TestApp::advance_clock to fire them.
§Example
let mut app = TestApp::new();
let finished = Rc::new(Cell::new(false));
let flag = finished.clone();
app.spawn(|_| async move { flag.set(true) }).detach();
// Any update runs the task that was spawned above.
app.update(|_| ());
assert!(finished.get());Sourcepub fn read<R>(&self, f: impl FnOnce(&App) -> R) -> R
pub fn read<R>(&self, f: impl FnOnce(&App) -> R) -> R
Runs f with read-only access to the App.
This doesn’t run pending tasks. A task that is still waiting to run doesn’t
run before f is called.
Sourcepub fn new_entity<T: 'static>(
&mut self,
build: impl FnOnce(&mut Context<'_, T>) -> T,
) -> Entity<T>
pub fn new_entity<T: 'static>( &mut self, build: impl FnOnce(&mut Context<'_, T>) -> T, ) -> Entity<T>
Creates an entity from build and runs pending tasks until parked.
This is cx.new(build) inside TestApp::update.
Sourcepub fn update_entity<T: 'static, R>(
&mut self,
entity: &Entity<T>,
f: impl FnOnce(&mut T, &mut Context<'_, T>) -> R,
) -> R
pub fn update_entity<T: 'static, R>( &mut self, entity: &Entity<T>, f: impl FnOnce(&mut T, &mut Context<'_, T>) -> R, ) -> R
Updates an entity and runs pending tasks until parked.
Sourcepub fn read_entity<T: 'static, R>(
&self,
entity: &Entity<T>,
f: impl FnOnce(&T, &App) -> R,
) -> R
pub fn read_entity<T: 'static, R>( &self, entity: &Entity<T>, f: impl FnOnce(&T, &App) -> R, ) -> R
Reads an entity without running pending tasks.
Sourcepub fn open_window<V: Render + 'static>(
&mut self,
build_view: impl FnOnce(&mut Window, &mut Context<'_, V>) -> V,
) -> TestAppWindow<V>
pub fn open_window<V: Render + 'static>( &mut self, build_view: impl FnOnce(&mut Window, &mut Context<'_, V>) -> V, ) -> TestAppWindow<V>
Opens a window sized to the test display and returns a TestAppWindow for its root view.
The window’s bounds are the maximized bounds of the test display. Use
TestApp::open_window_with_options to choose other bounds.
§Panics
Panics if the window can’t be opened.
Sourcepub fn open_window_with_options<V: Render + 'static>(
&mut self,
options: WindowOptions,
build_view: impl FnOnce(&mut Window, &mut Context<'_, V>) -> V,
) -> TestAppWindow<V>
pub fn open_window_with_options<V: Render + 'static>( &mut self, options: WindowOptions, build_view: impl FnOnce(&mut Window, &mut Context<'_, V>) -> V, ) -> TestAppWindow<V>
Opens a window with options and returns a TestAppWindow for its root view.
§Panics
Panics if the window can’t be opened.
Sourcepub fn run_until_parked(&self)
pub fn run_until_parked(&self)
Runs tasks until none can make progress.
This doesn’t move the simulated clock. A timer that hasn’t expired stays
pending until TestApp::advance_clock moves time past it.
§Example
let mut app = TestApp::new();
let fired = Rc::new(Cell::new(false));
let flag = fired.clone();
app.spawn(|cx| async move {
cx.background_executor().timer(Duration::from_secs(1)).await;
flag.set(true);
})
.detach();
app.run_until_parked();
assert!(!fired.get(), "the timer hasn't expired yet");
app.advance_clock(Duration::from_secs(1));
app.run_until_parked();
assert!(fired.get());Sourcepub fn advance_clock(&self, duration: Duration)
pub fn advance_clock(&self, duration: Duration)
Moves the simulated clock forward by duration.
Tasks that become ready run during the call, including timers that expire
within the window. Use this to test timeouts and delays, as in the example for
TestApp::run_until_parked.
Sourcepub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncApp) -> Fut) -> Task<R> ⓘwhere
Fut: Future<Output = R> + 'static,
R: 'static,
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncApp) -> Fut) -> Task<R> ⓘwhere
Fut: Future<Output = R> + 'static,
R: 'static,
Spawns a future on the foreground executor, given an AsyncApp for this app.
The future runs when the app runs tasks: during TestApp::run_until_parked,
TestApp::advance_clock or the next update. Await, store or detach the
returned Task, as in a real app. See async work.
Sourcepub fn background_spawn<R>(
&self,
future: impl Future<Output = R> + Send + 'static,
) -> Task<R> ⓘwhere
R: Send + 'static,
pub fn background_spawn<R>(
&self,
future: impl Future<Output = R> + Send + 'static,
) -> Task<R> ⓘwhere
R: Send + 'static,
Spawns a Send future on the background executor.
Like TestApp::spawn, the future runs when the app runs tasks.
Sourcepub fn to_async(&self) -> AsyncApp
pub fn to_async(&self) -> AsyncApp
Returns an AsyncApp for this app.
The handle holds a weak reference, so it can’t keep the app alive.
Sourcepub fn background_executor(&self) -> &BackgroundExecutor
pub fn background_executor(&self) -> &BackgroundExecutor
Returns the test background executor.
Sourcepub fn foreground_executor(&self) -> &ForegroundExecutor
pub fn foreground_executor(&self) -> &ForegroundExecutor
Returns the test foreground executor.
Sourcepub fn text_system(&self) -> &Arc<TextSystem> ⓘ
pub fn text_system(&self) -> &Arc<TextSystem> ⓘ
Returns the text system the app uses to shape and measure text.
Sourcepub fn has_global<G: Global>(&self) -> bool
pub fn has_global<G: Global>(&self) -> bool
Returns whether a global of type G is set.
Sourcepub fn set_global<G: Global>(&mut self, global: G)
pub fn set_global<G: Global>(&mut self, global: G)
Sets the global of type G, replacing any previous value, then runs pending tasks.
Sourcepub fn read_global<G: Global, R>(&self, f: impl FnOnce(&G, &App) -> R) -> R
pub fn read_global<G: Global, R>(&self, f: impl FnOnce(&G, &App) -> R) -> R
Runs f with the global of type G.
§Panics
Panics if no global of type G is set. Check with TestApp::has_global first.
Sourcepub fn update_global<G: Global, R>(
&mut self,
f: impl FnOnce(&mut G, &mut App) -> R,
) -> R
pub fn update_global<G: Global, R>( &mut self, f: impl FnOnce(&mut G, &mut App) -> R, ) -> R
Runs f with mutable access to the global of type G, then runs pending tasks.
§Panics
Panics if no global of type G is set.
Sourcepub fn write_to_clipboard(&self, item: ClipboardItem)
pub fn write_to_clipboard(&self, item: ClipboardItem)
Writes item to the test clipboard.
TestApp::read_from_clipboard returns the item until something else is written.
Sourcepub fn read_from_clipboard(&self) -> Option<ClipboardItem>
pub fn read_from_clipboard(&self) -> Option<ClipboardItem>
Returns the item most recently written to the test clipboard, or None if nothing was written.
Sourcepub fn opened_url(&self) -> Option<String>
pub fn opened_url(&self) -> Option<String>
Returns the URL most recently passed to App::open_url, or None.
Nothing is launched. Only the last URL is kept, so open a second URL and the first is no longer reported.
§Example
let mut app = TestApp::new();
app.update(|cx| cx.open_url("https://example.com"));
assert_eq!(app.opened_url().as_deref(), Some("https://example.com"));Sourcepub fn did_prompt_for_new_path(&self) -> bool
pub fn did_prompt_for_new_path(&self) -> bool
Returns whether a App::prompt_for_new_path request is waiting for an answer.
Answer it with TestApp::simulate_new_path_selection.
Sourcepub fn simulate_new_path_selection(
&self,
select: impl FnOnce(&Path) -> Option<PathBuf>,
)
pub fn simulate_new_path_selection( &self, select: impl FnOnce(&Path) -> Option<PathBuf>, )
Answers the oldest pending App::prompt_for_new_path request.
select receives the directory the app asked about and returns the chosen
path, or None to cancel the request.
§Panics
Panics if no new-path request is pending.
Sourcepub fn has_pending_prompt(&self) -> bool
pub fn has_pending_prompt(&self) -> bool
Returns whether a prompt from Window::prompt is waiting for an answer.
Sourcepub fn simulate_prompt_answer(&self, button: &str)
pub fn simulate_prompt_answer(&self, button: &str)
Answers the oldest pending prompt by pressing the button labelled button.
The prompt is removed before the label is checked, so a wrong label still consumes it.
§Panics
Panics if no prompt is pending, or if no button has the label button.
Sourcepub fn windows(&self) -> Vec<AnyWindowHandle>
pub fn windows(&self) -> Vec<AnyWindowHandle>
Returns the handles of all open windows.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for TestApp
impl !Send for TestApp
impl !Sync for TestApp
impl !UnwindSafe for TestApp
impl Freeze for TestApp
impl Unpin for TestApp
impl UnsafeUnpin for TestApp
Blanket Implementations§
Source§impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for Swhere
T: Real + Zero + Arithmetics + Clone,
Swp: WhitePoint<T>,
Dwp: WhitePoint<T>,
D: AdaptFrom<S, Swp, Dwp, T>,
Source§fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
fn adapt_into_using<M>(self, method: M) -> Dwhere
M: TransformMatrix<T>,
replaced by palette::chromatic_adaptation::AdaptIntoUnclamped
Source§fn adapt_into(self) -> D
fn adapt_into(self) -> D
replaced by palette::chromatic_adaptation::AdaptIntoUnclamped
Source§impl<T, C> AdaptIntoUnclamped<T> for Cwhere
T: AdaptFromUnclamped<C>,
impl<T, C> AdaptIntoUnclamped<T> for Cwhere
T: AdaptFromUnclamped<C>,
Source§type Scalar = <T as AdaptFromUnclamped<C>>::Scalar
type Scalar = <T as AdaptFromUnclamped<C>>::Scalar
Source§fn adapt_into_unclamped_with<M>(self) -> Twhere
M: LmsToXyz<<C as AdaptIntoUnclamped<T>>::Scalar> + XyzToLms<<C as AdaptIntoUnclamped<T>>::Scalar>,
fn adapt_into_unclamped_with<M>(self) -> Twhere
M: LmsToXyz<<C as AdaptIntoUnclamped<T>>::Scalar> + XyzToLms<<C as AdaptIntoUnclamped<T>>::Scalar>,
Source§impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
impl<T, C> ArraysFrom<C> for Twhere
C: IntoArrays<T>,
Source§fn arrays_from(colors: C) -> T
fn arrays_from(colors: C) -> T
Source§impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
impl<T, C> ArraysInto<C> for Twhere
C: FromArrays<T>,
Source§fn arrays_into(self) -> C
fn arrays_into(self) -> C
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<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for Uwhere
T: FromCam16Unclamped<WpParam, U>,
Source§type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar
parameters when converting.Source§fn cam16_into_unclamped(
self,
parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>,
) -> T
fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T
self into C, using the provided parameters.impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
impl<T, C> ComponentsFrom<C> for Twhere
C: IntoComponents<T>,
Source§fn components_from(colors: C) -> T
fn components_from(colors: C) -> T
Source§impl<T, C> ComponentsInto<C> for T
impl<T, C> ComponentsInto<C> for T
Source§fn components_into(self) -> C
fn components_into(self) -> C
Source§impl<T> FromAngle<T> for T
impl<T> FromAngle<T> for T
Source§fn from_angle(angle: T) -> T
fn from_angle(angle: T) -> T
angle.Source§impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
impl<T, U> FromStimulus<U> for Twhere
U: IntoStimulus<T>,
Source§fn from_stimulus(other: U) -> T
fn from_stimulus(other: U) -> T
other into Self, while performing the appropriate scaling,
rounding and clamping.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, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
impl<T, U> IntoAngle<U> for Twhere
U: FromAngle<T>,
Source§fn into_angle(self) -> U
fn into_angle(self) -> U
T.Source§impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for Uwhere
T: Cam16FromUnclamped<WpParam, U>,
Source§type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar
parameters when converting.Source§fn into_cam16_unclamped(
self,
parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>,
) -> T
fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T
self into C, using the provided parameters.Source§impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
impl<T, U> IntoColor<U> for Twhere
U: FromColor<T>,
Source§fn into_color(self) -> U
fn into_color(self) -> U
Source§impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
impl<T, U> IntoColorUnclamped<U> for Twhere
U: FromColorUnclamped<T>,
Source§fn into_color_unclamped(self) -> U
fn into_color_unclamped(self) -> U
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 moreSource§impl<T> IntoStimulus<T> for T
impl<T> IntoStimulus<T> for T
Source§fn into_stimulus(self) -> T
fn into_stimulus(self) -> T
self into T, while performing the appropriate scaling,
rounding and clamping.Source§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian().Source§impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
impl<T, C> TryComponentsInto<C> for Twhere
C: TryFromComponents<T>,
Source§type Error = <C as TryFromComponents<T>>::Error
type Error = <C as TryFromComponents<T>>::Error
try_into_colors fails to cast.Source§fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>
Source§impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
impl<T, U> TryIntoColor<U> for Twhere
U: TryFromColor<T>,
Source§fn try_into_color(self) -> Result<U, OutOfBounds<U>>
fn try_into_color(self) -> Result<U, OutOfBounds<U>>
OutOfBounds error is returned which contains
the unclamped color. Read more