super-stt-shared/src/models/notification_method.rs
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-3.0-only |
2 | | |
3 | | use super_engine_protocol::wire_enum_strings; |
4 | | |
5 | | /// How the daemon surfaces a recording failure to the user. |
6 | | /// |
7 | | /// The caller always learns about a failure through the response and the |
8 | | /// `error` event; this controls the additional human-facing notice. |
9 | | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] |
10 | | pub enum NotificationMethod { |
11 | | /// Desktop notification, falling back to typing the notice if it cannot |
12 | | /// be delivered. |
13 | | #[default] |
14 | | Auto, |
15 | | /// Desktop notification only; log if it cannot be delivered. |
16 | | /// |
17 | | /// Named for what the user sees rather than for the transport, which is |
18 | | /// not the same on every platform: a freedesktop notification server over |
19 | | /// the session bus on Linux, Notification Center on macOS. |
20 | | Desktop, |
21 | | /// Type a fixed notice into the focused window. |
22 | | Typed, |
23 | | /// Log only; never surface. |
24 | | Off, |
25 | | } |
26 | | |
27 | | wire_enum_strings!(NotificationMethod { |
28 | | Auto => "auto", |
29 | | Desktop => "desktop", |
30 | | Typed => "typed", |
31 | | Off => "off", |
32 | | }); |
33 | | |
34 | | impl NotificationMethod { |
35 | | #[must_use] |
36 | 0 | pub fn pretty_name(self) -> &'static str { |
37 | 0 | match self { |
38 | 0 | Self::Auto => "Auto (recommended)", |
39 | 0 | Self::Desktop => "Desktop notification", |
40 | 0 | Self::Typed => "Type into window", |
41 | 0 | Self::Off => "Off", |
42 | | } |
43 | 0 | } |
44 | | } |
45 | | |
46 | | #[cfg(test)] |
47 | | mod tests { |
48 | | use super::*; |
49 | | |
50 | | #[test] |
51 | 1 | fn default_is_auto() { |
52 | 1 | assert_eq!(NotificationMethod::default(), NotificationMethod::Auto); |
53 | 1 | } |
54 | | |
55 | | #[test] |
56 | 1 | fn display_roundtrip() { |
57 | 4 | for method in [ |
58 | 1 | NotificationMethod::Auto, |
59 | 1 | NotificationMethod::Desktop, |
60 | 1 | NotificationMethod::Typed, |
61 | 1 | NotificationMethod::Off, |
62 | 1 | ] { |
63 | 4 | let s = method.to_string(); |
64 | 4 | let parsed: NotificationMethod = s.parse().unwrap(); |
65 | 4 | assert_eq!(parsed, method); |
66 | | } |
67 | 1 | } |
68 | | |
69 | | #[test] |
70 | 1 | fn wire_tokens_are_snake_case() { |
71 | 1 | assert_eq!(NotificationMethod::Auto.to_string(), "auto"); |
72 | 1 | assert_eq!(NotificationMethod::Desktop.to_string(), "desktop"); |
73 | 1 | assert_eq!(NotificationMethod::Typed.to_string(), "typed"); |
74 | 1 | assert_eq!(NotificationMethod::Off.to_string(), "off"); |
75 | 1 | } |
76 | | |
77 | | #[test] |
78 | 1 | fn from_str_rejects_unknown_and_plausible_aliases() { |
79 | 1 | assert!("nonsense".parse::<NotificationMethod>().is_err()); |
80 | | // No aliases: exactly one token maps to each variant. |
81 | 8 | for dropped in [ |
82 | 1 | "notification", |
83 | 1 | "notify", |
84 | 1 | "d-bus", |
85 | 1 | "freedesktop", |
86 | 1 | "none", |
87 | 1 | "disabled", |
88 | 1 | "Auto", |
89 | 1 | // `Desktop`'s former token. Only the daemon's config loader |
90 | 1 | // still reads it, so a choice stored before the rename survives. |
91 | 1 | "dbus", |
92 | 1 | ] { |
93 | 8 | assert!( |
94 | 8 | dropped.parse::<NotificationMethod>().is_err(), |
95 | | "`{dropped}` must not parse" |
96 | | ); |
97 | | } |
98 | 1 | } |
99 | | |
100 | | #[test] |
101 | 1 | fn serde_roundtrip() { |
102 | 1 | let method = NotificationMethod::Desktop; |
103 | 1 | let json = serde_json::to_string(&method).unwrap(); |
104 | 1 | assert_eq!(json, "\"desktop\""); |
105 | 1 | let parsed: NotificationMethod = serde_json::from_str(&json).unwrap(); |
106 | 1 | assert_eq!(parsed, method); |
107 | 1 | } |
108 | | |
109 | | #[test] |
110 | 1 | fn wire_variants_lists_every_token() { |
111 | 1 | assert_eq!( |
112 | | NotificationMethod::WIRE_VARIANTS, |
113 | | &["auto", "desktop", "typed", "off"] |
114 | | ); |
115 | 1 | } |
116 | | } |