use crate::{ AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, Handle, MainThread, ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext, }; use parking_lot::Mutex; use std::{future::Future, sync::Arc}; #[derive(Clone)] pub struct TestAppContext { pub app: Arc>, pub executor: Executor, } impl Context for TestAppContext { type EntityContext<'a, 'w, T> = ModelContext<'a, T>; type Result = T; fn entity( &mut self, build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T, ) -> Self::Result> where T: 'static + Send, { let mut lock = self.app.lock(); lock.entity(build_entity) } fn update_entity( &mut self, handle: &Handle, update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R, ) -> Self::Result { let mut lock = self.app.lock(); lock.update_entity(handle, update) } } impl TestAppContext { pub fn new(dispatcher: TestDispatcher) -> Self { let executor = Executor::new(Arc::new(dispatcher)); let platform = Arc::new(TestPlatform::new(executor.clone())); let asset_source = Arc::new(()); let http_client = util::http::FakeHttpClient::with_404_response(); Self { app: AppContext::new(platform, asset_source, http_client), executor, } } pub fn quit(&self) { self.app.lock().quit(); } pub fn refresh(&mut self) -> Result<()> { let mut lock = self.app.lock(); lock.refresh(); Ok(()) } pub fn executor(&self) -> &Executor { &self.executor } pub fn update(&self, f: impl FnOnce(&mut AppContext) -> R) -> R { let mut lock = self.app.lock(); f(&mut *lock) } pub fn read_window( &self, handle: AnyWindowHandle, read: impl FnOnce(&WindowContext) -> R, ) -> R { let mut app_context = self.app.lock(); app_context.read_window(handle.id, read).unwrap() } pub fn update_window( &self, handle: AnyWindowHandle, update: impl FnOnce(&mut WindowContext) -> R, ) -> R { let mut app = self.app.lock(); app.update_window(handle.id, update).unwrap() } pub fn spawn(&self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static) -> Task where Fut: Future + Send + 'static, R: Send + 'static, { let cx = self.to_async(); self.executor.spawn(async move { f(cx).await }) } pub fn spawn_on_main( &self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static, ) -> Task where Fut: Future + 'static, R: Send + 'static, { let cx = self.to_async(); self.executor.spawn_on_main(|| f(cx)) } pub fn run_on_main( &self, f: impl FnOnce(&mut MainThread) -> R + Send + 'static, ) -> Task where R: Send + 'static, { let mut app_context = self.app.lock(); app_context.run_on_main(f) } pub fn has_global(&self) -> bool { let lock = self.app.lock(); lock.has_global::() } pub fn read_global(&self, read: impl FnOnce(&G, &AppContext) -> R) -> R { let lock = self.app.lock(); read(lock.global(), &lock) } pub fn try_read_global( &self, read: impl FnOnce(&G, &AppContext) -> R, ) -> Option { let lock = self.app.lock(); Some(read(lock.try_global()?, &lock)) } pub fn update_global( &mut self, update: impl FnOnce(&mut G, &mut AppContext) -> R, ) -> R { let mut lock = self.app.lock(); lock.update_global(update) } pub fn to_async(&self) -> AsyncAppContext { AsyncAppContext { app: Arc::downgrade(&self.app), executor: self.executor.clone(), } } }