test_context.rs

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