use chrono::{DateTime, Local};
#[derive(Debug, Clone)]
pub struct CompareCommit {
pub hash: String,
pub message: String,
pub author: String,
pub date: DateTime<Local>,
}
#[derive(Debug, Clone)]
pub struct BranchCompare {
pub base_branch: String,
pub target_branch: String,
pub ahead_commits: Vec<CompareCommit>,
pub behind_commits: Vec<CompareCommit>,
pub merge_base: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum CompareTab {
#[default]
Ahead,
Behind,
}
impl CompareTab {
pub fn toggle(&self) -> Self {
match self {
CompareTab::Ahead => CompareTab::Behind,
CompareTab::Behind => CompareTab::Ahead,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Local;
#[test]
fn compare_tab_default_is_ahead() {
let tab = CompareTab::default();
assert_eq!(tab, CompareTab::Ahead);
}
#[test]
fn compare_tab_toggle_ahead_to_behind() {
let tab = CompareTab::Ahead;
assert_eq!(tab.toggle(), CompareTab::Behind);
}
#[test]
fn compare_tab_toggle_behind_to_ahead() {
let tab = CompareTab::Behind;
assert_eq!(tab.toggle(), CompareTab::Ahead);
}
#[test]
fn compare_tab_toggle_roundtrip() {
let tab = CompareTab::Ahead;
assert_eq!(tab.toggle().toggle(), CompareTab::Ahead);
}
#[test]
fn compare_tab_clone() {
let tab = CompareTab::Ahead;
let cloned = tab;
assert_eq!(tab, cloned);
}
#[test]
fn compare_tab_debug() {
let ahead = format!("{:?}", CompareTab::Ahead);
let behind = format!("{:?}", CompareTab::Behind);
assert_eq!(ahead, "Ahead");
assert_eq!(behind, "Behind");
}
#[test]
fn compare_commit_fields() {
let commit = CompareCommit {
hash: "abc1234".to_string(),
message: "fix: some bug".to_string(),
author: "Test User".to_string(),
date: Local::now(),
};
assert_eq!(commit.hash, "abc1234");
assert_eq!(commit.message, "fix: some bug");
assert_eq!(commit.author, "Test User");
}
#[test]
fn branch_compare_empty_commits() {
let compare = BranchCompare {
base_branch: "main".to_string(),
target_branch: "feature".to_string(),
ahead_commits: vec![],
behind_commits: vec![],
merge_base: "deadbeef".to_string(),
};
assert_eq!(compare.base_branch, "main");
assert_eq!(compare.target_branch, "feature");
assert!(compare.ahead_commits.is_empty());
assert!(compare.behind_commits.is_empty());
assert_eq!(compare.merge_base, "deadbeef");
}
#[test]
fn branch_compare_with_commits() {
let now = Local::now();
let compare = BranchCompare {
base_branch: "main".to_string(),
target_branch: "feature/test".to_string(),
ahead_commits: vec![
CompareCommit {
hash: "aaa1111".to_string(),
message: "feat: add feature".to_string(),
author: "Alice".to_string(),
date: now,
},
CompareCommit {
hash: "bbb2222".to_string(),
message: "test: add tests".to_string(),
author: "Bob".to_string(),
date: now,
},
],
behind_commits: vec![CompareCommit {
hash: "ccc3333".to_string(),
message: "fix: hotfix".to_string(),
author: "Charlie".to_string(),
date: now,
}],
merge_base: "000abcd".to_string(),
};
assert_eq!(compare.ahead_commits.len(), 2);
assert_eq!(compare.behind_commits.len(), 1);
assert_eq!(compare.ahead_commits[0].author, "Alice");
assert_eq!(compare.behind_commits[0].hash, "ccc3333");
}
#[test]
fn compare_commit_clone() {
let commit = CompareCommit {
hash: "abc".to_string(),
message: "msg".to_string(),
author: "author".to_string(),
date: Local::now(),
};
let cloned = commit.clone();
assert_eq!(commit.hash, cloned.hash);
assert_eq!(commit.message, cloned.message);
assert_eq!(commit.author, cloned.author);
}
}