1use chrono::{DateTime, Local};
6
7#[derive(Debug, Clone)]
9pub struct CompareCommit {
10 pub hash: String,
12 pub message: String,
14 pub author: String,
16 pub date: DateTime<Local>,
18}
19
20#[derive(Debug, Clone)]
22pub struct BranchCompare {
23 pub base_branch: String,
25 pub target_branch: String,
27 pub ahead_commits: Vec<CompareCommit>,
29 pub behind_commits: Vec<CompareCommit>,
31 pub merge_base: String,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Default)]
37pub enum CompareTab {
38 #[default]
39 Ahead,
40 Behind,
41}
42
43impl CompareTab {
44 pub fn toggle(&self) -> Self {
46 match self {
47 CompareTab::Ahead => CompareTab::Behind,
48 CompareTab::Behind => CompareTab::Ahead,
49 }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use chrono::Local;
57
58 #[test]
59 fn compare_tab_default_is_ahead() {
60 let tab = CompareTab::default();
61 assert_eq!(tab, CompareTab::Ahead);
62 }
63
64 #[test]
65 fn compare_tab_toggle_ahead_to_behind() {
66 let tab = CompareTab::Ahead;
67 assert_eq!(tab.toggle(), CompareTab::Behind);
68 }
69
70 #[test]
71 fn compare_tab_toggle_behind_to_ahead() {
72 let tab = CompareTab::Behind;
73 assert_eq!(tab.toggle(), CompareTab::Ahead);
74 }
75
76 #[test]
77 fn compare_tab_toggle_roundtrip() {
78 let tab = CompareTab::Ahead;
79 assert_eq!(tab.toggle().toggle(), CompareTab::Ahead);
80 }
81
82 #[test]
83 fn compare_tab_clone() {
84 let tab = CompareTab::Ahead;
85 let cloned = tab;
86 assert_eq!(tab, cloned);
87 }
88
89 #[test]
90 fn compare_tab_debug() {
91 let ahead = format!("{:?}", CompareTab::Ahead);
92 let behind = format!("{:?}", CompareTab::Behind);
93 assert_eq!(ahead, "Ahead");
94 assert_eq!(behind, "Behind");
95 }
96
97 #[test]
98 fn compare_commit_fields() {
99 let commit = CompareCommit {
100 hash: "abc1234".to_string(),
101 message: "fix: some bug".to_string(),
102 author: "Test User".to_string(),
103 date: Local::now(),
104 };
105 assert_eq!(commit.hash, "abc1234");
106 assert_eq!(commit.message, "fix: some bug");
107 assert_eq!(commit.author, "Test User");
108 }
109
110 #[test]
111 fn branch_compare_empty_commits() {
112 let compare = BranchCompare {
113 base_branch: "main".to_string(),
114 target_branch: "feature".to_string(),
115 ahead_commits: vec![],
116 behind_commits: vec![],
117 merge_base: "deadbeef".to_string(),
118 };
119 assert_eq!(compare.base_branch, "main");
120 assert_eq!(compare.target_branch, "feature");
121 assert!(compare.ahead_commits.is_empty());
122 assert!(compare.behind_commits.is_empty());
123 assert_eq!(compare.merge_base, "deadbeef");
124 }
125
126 #[test]
127 fn branch_compare_with_commits() {
128 let now = Local::now();
129 let compare = BranchCompare {
130 base_branch: "main".to_string(),
131 target_branch: "feature/test".to_string(),
132 ahead_commits: vec![
133 CompareCommit {
134 hash: "aaa1111".to_string(),
135 message: "feat: add feature".to_string(),
136 author: "Alice".to_string(),
137 date: now,
138 },
139 CompareCommit {
140 hash: "bbb2222".to_string(),
141 message: "test: add tests".to_string(),
142 author: "Bob".to_string(),
143 date: now,
144 },
145 ],
146 behind_commits: vec![CompareCommit {
147 hash: "ccc3333".to_string(),
148 message: "fix: hotfix".to_string(),
149 author: "Charlie".to_string(),
150 date: now,
151 }],
152 merge_base: "000abcd".to_string(),
153 };
154 assert_eq!(compare.ahead_commits.len(), 2);
155 assert_eq!(compare.behind_commits.len(), 1);
156 assert_eq!(compare.ahead_commits[0].author, "Alice");
157 assert_eq!(compare.behind_commits[0].hash, "ccc3333");
158 }
159
160 #[test]
161 fn compare_commit_clone() {
162 let commit = CompareCommit {
163 hash: "abc".to_string(),
164 message: "msg".to_string(),
165 author: "author".to_string(),
166 date: Local::now(),
167 };
168 let cloned = commit.clone();
169 assert_eq!(commit.hash, cloned.hash);
170 assert_eq!(commit.message, cloned.message);
171 assert_eq!(commit.author, cloned.author);
172 }
173}