test_context.rs

  1use crate::{
  2    AnyView, AnyWindowHandle, AppContext, AsyncAppContext, Context, Executor, MainThread, Model,
  3    ModelContext, Result, Task, TestDispatcher, TestPlatform, WindowContext,
  4};
  5use parking_lot::Mutex;
  6use std::{future::Future, sync::Arc};
  7
  8#[derive(Clone)]
  9pub struct TestAppContext {
 10    pub app: Arc<Mutex<AppContext>>,
 11    pub executor: Executor,
 12}
 13
 14impl Context for TestAppContext {
 15    type WindowContext<'a> = WindowContext<'a>;
 16    type ModelContext<'a, T> = ModelContext<'a, T>;
 17    type Result<T> = T;
 18
 19    fn build_model<T: 'static>(
 20        &mut self,
 21        build_model: impl FnOnce(&mut Self::ModelContext<'_, T>) -> T,
 22    ) -> Self::Result<Model<T>>
 23    where
 24        T: 'static + Send,
 25    {
 26        let mut lock = self.app.lock();
 27        lock.build_model(build_model)
 28    }
 29
 30    fn update_model<T: 'static, R>(
 31        &mut self,
 32        handle: &Model<T>,
 33        update: impl FnOnce(&mut T, &mut Self::ModelContext<'_, T>) -> R,
 34    ) -> Self::Result<R> {
 35        let mut lock = self.app.lock();
 36        lock.update_model(handle, update)
 37    }
 38
 39    fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Result<T>
 40    where
 41        F: FnOnce(AnyView, &mut Self::WindowContext<'_>) -> T,
 42    {
 43        let mut lock = self.app.lock();
 44        lock.update_window(window, f)
 45    }
 46}
 47
 48impl TestAppContext {
 49    pub fn new(dispatcher: TestDispatcher) -> Self {
 50        let executor = Executor::new(Arc::new(dispatcher));
 51        let platform = Arc::new(TestPlatform::new(executor.clone()));
 52        let asset_source = Arc::new(());
 53        let http_client = util::http::FakeHttpClient::with_404_response();
 54        Self {
 55            app: AppContext::new(platform, asset_source, http_client),
 56            executor,
 57        }
 58    }
 59
 60    pub fn quit(&self) {
 61        self.app.lock().quit();
 62    }
 63
 64    pub fn refresh(&mut self) -> Result<()> {
 65        let mut lock = self.app.lock();
 66        lock.refresh();
 67        Ok(())
 68    }
 69
 70    pub fn executor(&self) -> &Executor {
 71        &self.executor
 72    }
 73
 74    pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> R {
 75        let mut lock = self.app.lock();
 76        f(&mut *lock)
 77    }
 78
 79    pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static) -> Task<R>
 80    where
 81        Fut: Future<Output = R> + Send + 'static,
 82        R: Send + 'static,
 83    {
 84        let cx = self.to_async();
 85        self.executor.spawn(async move { f(cx).await })
 86    }
 87
 88    pub fn spawn_on_main<Fut, R>(
 89        &self,
 90        f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static,
 91    ) -> Task<R>
 92    where
 93        Fut: Future<Output = R> + 'static,
 94        R: Send + 'static,
 95    {
 96        let cx = self.to_async();
 97        self.executor.spawn_on_main(|| f(cx))
 98    }
 99
100    pub fn run_on_main<R>(
101        &self,
102        f: impl FnOnce(&mut MainThread<AppContext>) -> R + Send + 'static,
103    ) -> Task<R>
104    where
105        R: Send + 'static,
106    {
107        let mut app_context = self.app.lock();
108        app_context.run_on_main(f)
109    }
110
111    pub fn has_global<G: 'static>(&self) -> bool {
112        let lock = self.app.lock();
113        lock.has_global::<G>()
114    }
115
116    pub fn read_global<G: 'static, R>(&self, read: impl FnOnce(&G, &AppContext) -> R) -> R {
117        let lock = self.app.lock();
118        read(lock.global(), &lock)
119    }
120
121    pub fn try_read_global<G: 'static, R>(
122        &self,
123        read: impl FnOnce(&G, &AppContext) -> R,
124    ) -> Option<R> {
125        let lock = self.app.lock();
126        Some(read(lock.try_global()?, &lock))
127    }
128
129    pub fn update_global<G: 'static, R>(
130        &mut self,
131        update: impl FnOnce(&mut G, &mut AppContext) -> R,
132    ) -> R {
133        let mut lock = self.app.lock();
134        lock.update_global(update)
135    }
136
137    pub fn to_async(&self) -> AsyncAppContext {
138        AsyncAppContext {
139            app: Arc::downgrade(&self.app),
140            executor: self.executor.clone(),
141        }
142    }
143}