Skip to main content

torrust_tracker_deployer_lib/presentation/cli/views/messages/
detail.rs

1//! Detail message for very verbose progress output
2//!
3//! This message type is used for detailed contextual information that appears
4//! at the `VeryVerbose` (`-vv`) verbosity level and above. It uses the detail symbol
5//! (📋 in emoji theme) to visually distinguish detailed context from step headers.
6
7use super::super::channel::Channel;
8use super::super::theme::Theme;
9use super::super::traits::OutputMessage;
10use super::super::verbosity::VerbosityLevel;
11
12/// A detail message shown at `VeryVerbose` verbosity level and above
13///
14/// Detail messages provide contextual information within steps during command
15/// execution. They are emitted by the `CommandProgressListener` implementation
16/// via `on_detail()` to show results, file paths, retry attempts, etc.
17///
18/// # Examples
19///
20/// ```rust,ignore
21/// use torrust_tracker_deployer_lib::presentation::cli::views::messages::DetailMessage;
22///
23/// let message = DetailMessage {
24///     text: "     → Instance IP: 10.140.190.235".to_string(),
25/// };
26/// ```
27pub struct DetailMessage {
28    /// The detail text to display
29    pub text: String,
30}
31
32impl OutputMessage for DetailMessage {
33    fn format(&self, theme: &Theme) -> String {
34        format!("{} {}\n", theme.detail_symbol(), self.text)
35    }
36
37    fn required_verbosity(&self) -> VerbosityLevel {
38        VerbosityLevel::VeryVerbose
39    }
40
41    fn channel(&self) -> Channel {
42        Channel::Stderr
43    }
44
45    fn type_name(&self) -> &'static str {
46        "DetailMessage"
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn it_should_format_with_detail_symbol() {
56        let message = DetailMessage {
57            text: "     → Instance IP: 10.140.190.235".to_string(),
58        };
59        let theme = Theme::emoji();
60        let formatted = message.format(&theme);
61        assert_eq!(formatted, "📋      → Instance IP: 10.140.190.235\n");
62    }
63
64    #[test]
65    fn it_should_require_very_verbose_verbosity_level() {
66        let message = DetailMessage {
67            text: "test".to_string(),
68        };
69        assert_eq!(message.required_verbosity(), VerbosityLevel::VeryVerbose);
70    }
71
72    #[test]
73    fn it_should_output_to_stderr() {
74        let message = DetailMessage {
75            text: "test".to_string(),
76        };
77        assert_eq!(message.channel(), Channel::Stderr);
78    }
79
80    #[test]
81    fn it_should_have_correct_type_name() {
82        let message = DetailMessage {
83            text: "test".to_string(),
84        };
85        assert_eq!(message.type_name(), "DetailMessage");
86    }
87
88    #[test]
89    fn it_should_format_with_plain_theme() {
90        let message = DetailMessage {
91            text: "     → Instance IP: 10.140.190.235".to_string(),
92        };
93        let theme = Theme::plain();
94        let formatted = message.format(&theme);
95        assert_eq!(formatted, "[DETAIL]      → Instance IP: 10.140.190.235\n");
96    }
97}