1use serde::{Deserialize, Serialize};
2
3use crate::board::storage::{BoardSection, ColumnConfig};
4
5#[derive(Debug, Serialize, Deserialize)]
6pub struct BoardConfig {
7 pub board: BoardSection,
8 #[serde(rename = "columns")]
9 pub columns: Vec<ColumnConfig>,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct KandoToml {
16 #[serde(default = "default_kando_branch")]
17 pub branch: String,
18}
19
20fn default_kando_branch() -> String {
21 "kando".to_string()
22}
23
24#[derive(Debug, Default, Serialize, Deserialize)]
27pub struct LocalConfig {
28 #[serde(default, alias = "tutorial_shown")]
30 pub help_hint_shown: bool,
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn local_config_default_creates_empty_struct() {
39 let _cfg = LocalConfig::default();
40 }
41
42 #[test]
43 fn local_config_toml_roundtrip() {
44 let original = LocalConfig::default();
45 let serialized = toml::to_string_pretty(&original).unwrap();
46 let _loaded: LocalConfig = toml::from_str(&serialized).unwrap();
47 }
48
49 #[test]
50 fn local_config_empty_string_deserializes() {
51 let _loaded: LocalConfig = toml::from_str("").unwrap();
52 }
53
54 #[test]
55 fn local_config_ignores_unknown_fields() {
56 let _loaded: LocalConfig = toml::from_str("focus_mode = true\n").unwrap();
58 }
59
60 #[test]
61 fn local_config_default_help_hint_shown_is_false() {
62 assert!(!LocalConfig::default().help_hint_shown);
63 }
64
65 #[test]
66 fn local_config_help_hint_shown_true_roundtrip() {
67 let original = LocalConfig { help_hint_shown: true };
68 let serialized = toml::to_string_pretty(&original).unwrap();
69 let loaded: LocalConfig = toml::from_str(&serialized).unwrap();
70 assert!(loaded.help_hint_shown);
71 }
72
73 #[test]
74 fn local_config_missing_help_hint_shown_defaults_to_false() {
75 let loaded: LocalConfig = toml::from_str("").unwrap();
76 assert!(!loaded.help_hint_shown);
77 }
78
79 #[test]
80 fn local_config_legacy_tutorial_shown_deserializes_as_help_hint_shown() {
81 let loaded: LocalConfig = toml::from_str("tutorial_shown = true\n").unwrap();
82 assert!(loaded.help_hint_shown);
83 }
84
85 #[test]
86 fn local_config_serializes_with_new_field_name_not_alias() {
87 let cfg = LocalConfig { help_hint_shown: true };
88 let serialized = toml::to_string_pretty(&cfg).unwrap();
89 assert!(serialized.contains("help_hint_shown"));
90 assert!(!serialized.contains("tutorial_shown"));
91 }
92
93 #[test]
94 fn local_config_both_keys_present_is_rejected() {
95 let result = toml::from_str::<LocalConfig>(
96 "tutorial_shown = false\nhelp_hint_shown = true\n",
97 );
98 assert!(result.is_err(), "duplicate field must be rejected");
99 }
100
101 #[test]
104 fn kando_toml_roundtrip() {
105 let original = KandoToml { branch: "kando".to_string() };
106 let serialized = toml::to_string_pretty(&original).unwrap();
107 let loaded: KandoToml = toml::from_str(&serialized).unwrap();
108 assert_eq!(loaded.branch, "kando");
109 }
110
111 #[test]
112 fn kando_toml_default_branch_when_missing() {
113 let loaded: KandoToml = toml::from_str("").unwrap();
114 assert_eq!(loaded.branch, "kando");
115 }
116
117 #[test]
118 fn kando_toml_custom_branch() {
119 let loaded: KandoToml = toml::from_str("branch = \"my-board\"\n").unwrap();
120 assert_eq!(loaded.branch, "my-board");
121 }
122
123 #[test]
124 fn kando_toml_malformed_returns_err() {
125 let result = toml::from_str::<KandoToml>("branch = !!!");
126 assert!(result.is_err());
127 }
128
129 #[test]
130 fn kando_toml_ignores_unknown_fields() {
131 let loaded: KandoToml = toml::from_str("branch = \"kando\"\nextra = 42\n").unwrap();
132 assert_eq!(loaded.branch, "kando");
133 }
134
135 #[test]
136 fn kando_toml_serialization_contains_branch() {
137 let toml = KandoToml { branch: "kando".to_string() };
138 let s = toml::to_string_pretty(&toml).unwrap();
139 assert!(s.contains("branch = \"kando\""));
140 }
141
142 #[test]
143 fn kando_toml_branch_with_slashes() {
144 let loaded: KandoToml = toml::from_str("branch = \"team/board\"\n").unwrap();
145 assert_eq!(loaded.branch, "team/board");
146 }
147}