375 lines
11 KiB
Rust
375 lines
11 KiB
Rust
//! Tests for MR transformer module.
|
|
|
|
use lore::gitlab::transformers::merge_request::transform_merge_request;
|
|
use lore::gitlab::types::{GitLabAuthor, GitLabMergeRequest, GitLabReferences, GitLabReviewer};
|
|
|
|
fn make_test_mr() -> GitLabMergeRequest {
|
|
GitLabMergeRequest {
|
|
id: 12345,
|
|
iid: 42,
|
|
project_id: 100,
|
|
title: "Add user authentication".to_string(),
|
|
description: Some("Implements JWT auth flow".to_string()),
|
|
state: "merged".to_string(),
|
|
draft: false,
|
|
work_in_progress: false,
|
|
source_branch: "feature/auth".to_string(),
|
|
target_branch: "main".to_string(),
|
|
sha: Some("abc123def456".to_string()),
|
|
references: Some(GitLabReferences {
|
|
short: "!42".to_string(),
|
|
full: "group/project!42".to_string(),
|
|
}),
|
|
detailed_merge_status: Some("mergeable".to_string()),
|
|
merge_status_legacy: Some("can_be_merged".to_string()),
|
|
created_at: "2024-01-15T10:00:00.000Z".to_string(),
|
|
updated_at: "2024-01-20T14:30:00.000Z".to_string(),
|
|
merged_at: Some("2024-01-20T14:30:00.000Z".to_string()),
|
|
closed_at: None,
|
|
author: GitLabAuthor {
|
|
id: 1,
|
|
username: "johndoe".to_string(),
|
|
name: "John Doe".to_string(),
|
|
},
|
|
merge_user: Some(GitLabAuthor {
|
|
id: 2,
|
|
username: "janedoe".to_string(),
|
|
name: "Jane Doe".to_string(),
|
|
}),
|
|
merged_by: Some(GitLabAuthor {
|
|
id: 2,
|
|
username: "janedoe".to_string(),
|
|
name: "Jane Doe".to_string(),
|
|
}),
|
|
labels: vec!["enhancement".to_string(), "auth".to_string()],
|
|
assignees: vec![GitLabAuthor {
|
|
id: 3,
|
|
username: "bob".to_string(),
|
|
name: "Bob Smith".to_string(),
|
|
}],
|
|
reviewers: vec![GitLabReviewer {
|
|
id: 4,
|
|
username: "alice".to_string(),
|
|
name: "Alice Wong".to_string(),
|
|
}],
|
|
web_url: "https://gitlab.example.com/group/project/-/merge_requests/42".to_string(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn transforms_mr_with_all_fields() {
|
|
let mr = make_test_mr();
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
|
|
assert_eq!(result.merge_request.gitlab_id, 12345);
|
|
assert_eq!(result.merge_request.iid, 42);
|
|
assert_eq!(result.merge_request.project_id, 200); // Local project ID, not GitLab's
|
|
assert_eq!(result.merge_request.title, "Add user authentication");
|
|
assert_eq!(
|
|
result.merge_request.description,
|
|
Some("Implements JWT auth flow".to_string())
|
|
);
|
|
assert_eq!(result.merge_request.state, "merged");
|
|
assert!(!result.merge_request.draft);
|
|
assert_eq!(result.merge_request.author_username, "johndoe");
|
|
assert_eq!(result.merge_request.source_branch, "feature/auth");
|
|
assert_eq!(result.merge_request.target_branch, "main");
|
|
assert_eq!(
|
|
result.merge_request.head_sha,
|
|
Some("abc123def456".to_string())
|
|
);
|
|
assert_eq!(
|
|
result.merge_request.references_short,
|
|
Some("!42".to_string())
|
|
);
|
|
assert_eq!(
|
|
result.merge_request.references_full,
|
|
Some("group/project!42".to_string())
|
|
);
|
|
assert_eq!(
|
|
result.merge_request.detailed_merge_status,
|
|
Some("mergeable".to_string())
|
|
);
|
|
assert_eq!(
|
|
result.merge_request.merge_user_username,
|
|
Some("janedoe".to_string())
|
|
);
|
|
assert_eq!(
|
|
result.merge_request.web_url,
|
|
"https://gitlab.example.com/group/project/-/merge_requests/42"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parses_timestamps_to_ms_epoch() {
|
|
let mr = make_test_mr();
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
|
|
// 2024-01-15T10:00:00.000Z = 1705312800000 ms
|
|
assert_eq!(result.merge_request.created_at, 1705312800000);
|
|
// 2024-01-20T14:30:00.000Z = 1705761000000 ms
|
|
assert_eq!(result.merge_request.updated_at, 1705761000000);
|
|
// merged_at should also be parsed
|
|
assert_eq!(result.merge_request.merged_at, Some(1705761000000));
|
|
}
|
|
|
|
#[test]
|
|
fn handles_timezone_offset_timestamps() {
|
|
let mut mr = make_test_mr();
|
|
// GitLab can return timestamps with timezone offset
|
|
mr.created_at = "2024-01-15T05:00:00-05:00".to_string();
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
// 05:00 EST = 10:00 UTC = same as original test
|
|
assert_eq!(result.merge_request.created_at, 1705312800000);
|
|
}
|
|
|
|
#[test]
|
|
fn sets_last_seen_at_to_current_time() {
|
|
let mr = make_test_mr();
|
|
let before = std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_millis() as i64;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
|
|
let after = std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_millis() as i64;
|
|
|
|
assert!(result.merge_request.last_seen_at >= before);
|
|
assert!(result.merge_request.last_seen_at <= after);
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_label_names() {
|
|
let mr = make_test_mr();
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
|
|
assert_eq!(result.label_names.len(), 2);
|
|
assert_eq!(result.label_names[0], "enhancement");
|
|
assert_eq!(result.label_names[1], "auth");
|
|
}
|
|
|
|
#[test]
|
|
fn handles_empty_labels() {
|
|
let mut mr = make_test_mr();
|
|
mr.labels = vec![];
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.label_names.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_assignee_usernames() {
|
|
let mr = make_test_mr();
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
|
|
assert_eq!(result.assignee_usernames.len(), 1);
|
|
assert_eq!(result.assignee_usernames[0], "bob");
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_reviewer_usernames() {
|
|
let mr = make_test_mr();
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
|
|
assert_eq!(result.reviewer_usernames.len(), 1);
|
|
assert_eq!(result.reviewer_usernames[0], "alice");
|
|
}
|
|
|
|
#[test]
|
|
fn handles_empty_assignees_and_reviewers() {
|
|
let mut mr = make_test_mr();
|
|
mr.assignees = vec![];
|
|
mr.reviewers = vec![];
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.assignee_usernames.is_empty());
|
|
assert!(result.reviewer_usernames.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn draft_prefers_draft_field() {
|
|
let mut mr = make_test_mr();
|
|
mr.draft = true;
|
|
mr.work_in_progress = false;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.merge_request.draft);
|
|
}
|
|
|
|
#[test]
|
|
fn draft_falls_back_to_work_in_progress() {
|
|
let mut mr = make_test_mr();
|
|
mr.draft = false;
|
|
mr.work_in_progress = true;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.merge_request.draft);
|
|
}
|
|
|
|
#[test]
|
|
fn draft_false_when_both_false() {
|
|
let mut mr = make_test_mr();
|
|
mr.draft = false;
|
|
mr.work_in_progress = false;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(!result.merge_request.draft);
|
|
}
|
|
|
|
#[test]
|
|
fn detailed_merge_status_prefers_non_legacy() {
|
|
let mut mr = make_test_mr();
|
|
mr.detailed_merge_status = Some("checking".to_string());
|
|
mr.merge_status_legacy = Some("can_be_merged".to_string());
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert_eq!(
|
|
result.merge_request.detailed_merge_status,
|
|
Some("checking".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn detailed_merge_status_falls_back_to_legacy() {
|
|
let mut mr = make_test_mr();
|
|
mr.detailed_merge_status = None;
|
|
mr.merge_status_legacy = Some("can_be_merged".to_string());
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert_eq!(
|
|
result.merge_request.detailed_merge_status,
|
|
Some("can_be_merged".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn merge_user_prefers_merge_user_field() {
|
|
let mut mr = make_test_mr();
|
|
mr.merge_user = Some(GitLabAuthor {
|
|
id: 10,
|
|
username: "merge_user_name".to_string(),
|
|
name: "Merge User".to_string(),
|
|
});
|
|
mr.merged_by = Some(GitLabAuthor {
|
|
id: 11,
|
|
username: "merged_by_name".to_string(),
|
|
name: "Merged By".to_string(),
|
|
});
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert_eq!(
|
|
result.merge_request.merge_user_username,
|
|
Some("merge_user_name".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn merge_user_falls_back_to_merged_by() {
|
|
let mut mr = make_test_mr();
|
|
mr.merge_user = None;
|
|
mr.merged_by = Some(GitLabAuthor {
|
|
id: 11,
|
|
username: "merged_by_name".to_string(),
|
|
name: "Merged By".to_string(),
|
|
});
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert_eq!(
|
|
result.merge_request.merge_user_username,
|
|
Some("merged_by_name".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn handles_missing_references() {
|
|
let mut mr = make_test_mr();
|
|
mr.references = None;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.merge_request.references_short.is_none());
|
|
assert!(result.merge_request.references_full.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn handles_missing_sha() {
|
|
let mut mr = make_test_mr();
|
|
mr.sha = None;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.merge_request.head_sha.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn handles_missing_description() {
|
|
let mut mr = make_test_mr();
|
|
mr.description = None;
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.merge_request.description.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn handles_closed_at_timestamp() {
|
|
let mut mr = make_test_mr();
|
|
mr.state = "closed".to_string();
|
|
mr.merged_at = None;
|
|
mr.closed_at = Some("2024-01-18T12:00:00.000Z".to_string());
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert!(result.merge_request.merged_at.is_none());
|
|
// 2024-01-18T12:00:00.000Z = 1705579200000 ms
|
|
assert_eq!(result.merge_request.closed_at, Some(1705579200000));
|
|
}
|
|
|
|
#[test]
|
|
fn passes_through_locked_state() {
|
|
let mut mr = make_test_mr();
|
|
mr.state = "locked".to_string();
|
|
|
|
let result = transform_merge_request(&mr, 200).unwrap();
|
|
assert_eq!(result.merge_request.state, "locked");
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_for_invalid_created_at() {
|
|
let mut mr = make_test_mr();
|
|
mr.created_at = "not-a-timestamp".to_string();
|
|
|
|
let result = transform_merge_request(&mr, 200);
|
|
assert!(result.is_err());
|
|
let err = result.unwrap_err();
|
|
assert!(err.contains("not-a-timestamp"));
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_for_invalid_updated_at() {
|
|
let mut mr = make_test_mr();
|
|
mr.updated_at = "invalid".to_string();
|
|
|
|
let result = transform_merge_request(&mr, 200);
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_for_invalid_merged_at() {
|
|
let mut mr = make_test_mr();
|
|
mr.merged_at = Some("bad-timestamp".to_string());
|
|
|
|
let result = transform_merge_request(&mr, 200);
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_for_invalid_closed_at() {
|
|
let mut mr = make_test_mr();
|
|
mr.closed_at = Some("garbage".to_string());
|
|
|
|
let result = transform_merge_request(&mr, 200);
|
|
assert!(result.is_err());
|
|
}
|