Skip to main content

telar_services_core/
lib.rs

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