harness_loop/
profile_guide.rs1use async_trait::async_trait;
16use harness_core::{Block, Context, Execution, Guide, GuideError, GuideId, GuideScope, World};
17use std::sync::OnceLock;
18
19pub struct ProfileGuide;
22
23static PROFILE_GUIDE_ID: OnceLock<GuideId> = OnceLock::new();
24static PROFILE_GUIDE_SCOPE: OnceLock<GuideScope> = OnceLock::new();
25
26#[async_trait]
27impl Guide for ProfileGuide {
28 fn id(&self) -> &GuideId {
29 PROFILE_GUIDE_ID.get_or_init(|| "user-profile".into())
30 }
31 fn kind(&self) -> Execution {
32 Execution::Inferential
33 }
34 fn scope(&self) -> &GuideScope {
35 PROFILE_GUIDE_SCOPE.get_or_init(|| GuideScope::Always)
36 }
37 async fn apply(&self, ctx: &mut Context, w: &World) -> Result<(), GuideError> {
38 let p = &w.profile;
39 if p.name.is_none() && p.tz.is_none() && p.locale.is_none() && p.extra.is_empty() {
40 return Ok(()); }
42 ctx.guides
43 .push(Block::Text(format!("User profile: {}", p.summary_line())));
44 Ok(())
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use harness_core::UserProfile;
51
52 #[test]
53 fn empty_profile_is_empty() {
54 let p = UserProfile::default();
55 assert!(p.name.is_none() && p.tz.is_none() && p.locale.is_none() && p.extra.is_empty());
56 }
57
58 #[test]
59 fn populated_profile_renders_line() {
60 let p = UserProfile {
61 name: Some("李亮".into()),
62 tz: Some("Asia/Shanghai".into()),
63 locale: Some("zh-CN".into()),
64 ..Default::default()
65 };
66 let s = p.summary_line();
67 assert!(s.contains("李亮"));
68 assert!(s.contains("Asia/Shanghai"));
69 assert!(s.contains("zh-CN"));
70 }
71}