Skip to main content

telar_services_core/
lib.rs

1pub mod dialogs;
2pub mod paths;
3#[cfg(feature = "di")]
4mod registry;
5#[cfg(feature = "di")]
6mod scope;
7
8pub use dialogs::{FileDialog, FileDialogs, FileFilter, file_dialogs, set_file_dialogs};
9pub use paths::{AppPathsProvider, NoPaths};
10#[cfg(feature = "di")]
11pub use registry::ServiceError;
12#[cfg(feature = "di")]
13pub use scope::{Scope, ServiceContext, ServiceGuard, provide, try_inject, with_service};
14
15#[cfg(all(test, feature = "di"))]
16mod tests {
17    use std::cell::RefCell;
18    use std::rc::Rc;
19
20    use super::*;
21    use crate::registry::ServiceRegistry;
22
23    #[test]
24    fn registry_insert_get() {
25        let mut reg = ServiceRegistry::new();
26        reg.insert(42u32).unwrap();
27        assert_eq!(reg.get::<u32>(), Some(&42));
28    }
29
30    #[test]
31    fn registry_insert_duplicate_returns_error() {
32        let mut reg = ServiceRegistry::new();
33        assert!(reg.insert(1u32).is_ok());
34        assert_eq!(reg.insert(2u32), Err(ServiceError::AlreadyRegistered));
35        assert_eq!(reg.get::<u32>(), Some(&1));
36    }
37
38    #[test]
39    fn registry_missing_type() {
40        let reg = ServiceRegistry::new();
41        assert_eq!(reg.get::<u32>(), None);
42    }
43
44    #[test]
45    fn scope_provide_inject() {
46        Scope::with(|| {
47            provide(99u32).unwrap();
48            assert_eq!(try_inject::<u32>(), Some(99));
49        });
50    }
51
52    #[test]
53    fn scope_child_inherits_parent() {
54        Scope::with(|| {
55            provide(String::from("from-parent")).unwrap();
56            Scope::with(|| {
57                assert_eq!(try_inject::<String>(), Some(String::from("from-parent")));
58            });
59        });
60    }
61
62    #[test]
63    fn scope_child_shadows_parent() {
64        Scope::with(|| {
65            provide(1u32).unwrap();
66            Scope::with(|| {
67                provide(2u32).unwrap();
68                assert_eq!(try_inject::<u32>(), Some(2));
69            });
70        });
71    }
72
73    #[test]
74    fn scope_drop_restores_parent() {
75        Scope::with(|| {
76            provide(String::from("parent")).unwrap();
77            Scope::with(|| {
78                provide(String::from("child")).unwrap();
79                assert_eq!(try_inject::<String>().as_deref(), Some("child"));
80            });
81            assert_eq!(try_inject::<String>().as_deref(), Some("parent"));
82        });
83    }
84
85    #[test]
86    fn with_service_non_clone() {
87        Scope::with(|| {
88            provide(Rc::new(RefCell::new(vec![1, 2, 3]))).unwrap();
89            let len = with_service(|v: &Rc<RefCell<Vec<i32>>>| v.borrow().len());
90            assert_eq!(len, Some(3));
91        });
92    }
93
94    #[test]
95    fn try_inject_missing_returns_none() {
96        Scope::with(|| {
97            assert_eq!(try_inject::<u64>(), None);
98        });
99    }
100
101    #[test]
102    fn scope_with_provides_service() {
103        Scope::with(|| {
104            provide(42u32).unwrap();
105            assert_eq!(try_inject::<u32>(), Some(42));
106        });
107        assert_eq!(try_inject::<u32>(), None);
108    }
109
110    #[test]
111    fn scope_with_cleans_up_after_closure_returns() {
112        Scope::with(|| {
113            provide(String::from("ephemeral")).unwrap();
114            assert!(try_inject::<String>().is_some());
115        });
116        assert_eq!(
117            try_inject::<String>(),
118            None,
119            "service must not be visible after Scope::with returns"
120        );
121    }
122
123    #[test]
124    fn scope_with_nested() {
125        Scope::with(|| {
126            provide(String::from("outer")).unwrap();
127            Scope::with(|| {
128                provide(String::from("inner")).unwrap();
129                assert_eq!(try_inject::<String>().as_deref(), Some("inner"));
130            });
131            assert_eq!(try_inject::<String>().as_deref(), Some("outer"));
132        });
133    }
134}