refactor(structure): reorganize codebase into domain-focused modules

This commit is contained in:
teernisse
2026-03-06 15:22:42 -05:00
parent 4d41d74ea7
commit bf977eca1a
78 changed files with 8704 additions and 6973 deletions

View File

@@ -0,0 +1,268 @@
use super::*;
fn default_options() -> SyncOptions {
SyncOptions {
full: false,
force: false,
no_embed: false,
no_docs: false,
no_events: false,
robot_mode: false,
dry_run: false,
issue_iids: vec![],
mr_iids: vec![],
project: None,
preflight_only: false,
}
}
#[test]
fn append_failures_skips_zeroes() {
let mut summary = "base".to_string();
append_failures(&mut summary, &[("errors", 0), ("failures", 0)]);
assert_eq!(summary, "base");
}
#[test]
fn append_failures_renders_non_zero_counts() {
let mut summary = "base".to_string();
append_failures(&mut summary, &[("errors", 2), ("failures", 1)]);
assert!(summary.contains("base"));
assert!(summary.contains("2 errors"));
assert!(summary.contains("1 failures"));
}
#[test]
fn summarize_status_enrichment_reports_skipped_when_all_skipped() {
let projects = vec![ProjectStatusEnrichment {
path: "vs/typescript-code".to_string(),
mode: "skipped".to_string(),
reason: None,
seen: 0,
enriched: 0,
cleared: 0,
without_widget: 0,
partial_errors: 0,
first_partial_error: None,
error: None,
}];
let (summary, has_errors) = summarize_status_enrichment(&projects);
assert!(summary.contains("0 statuses updated"));
assert!(summary.contains("skipped"));
assert!(!has_errors);
}
#[test]
fn summarize_status_enrichment_reports_errors() {
let projects = vec![ProjectStatusEnrichment {
path: "vs/typescript-code".to_string(),
mode: "fetched".to_string(),
reason: None,
seen: 3,
enriched: 1,
cleared: 1,
without_widget: 0,
partial_errors: 2,
first_partial_error: None,
error: Some("boom".to_string()),
}];
let (summary, has_errors) = summarize_status_enrichment(&projects);
assert!(summary.contains("1 statuses updated"));
assert!(summary.contains("1 cleared"));
assert!(summary.contains("3 seen"));
assert!(summary.contains("3 errors"));
assert!(has_errors);
}
#[test]
fn should_print_timings_only_when_enabled_and_non_empty() {
let stages = vec![StageTiming {
name: "x".to_string(),
elapsed_ms: 10,
items_processed: 0,
items_skipped: 0,
errors: 0,
rate_limit_hits: 0,
retries: 0,
project: None,
sub_stages: vec![],
}];
assert!(should_print_timings(true, &stages));
assert!(!should_print_timings(false, &stages));
assert!(!should_print_timings(true, &[]));
}
#[test]
fn issue_sub_rows_include_project_and_statuses() {
let rows = issue_sub_rows(&[ProjectSummary {
path: "vs/typescript-code".to_string(),
items_upserted: 2,
discussions_synced: 0,
events_fetched: 0,
events_failed: 0,
statuses_enriched: 1,
statuses_seen: 5,
status_errors: 0,
mr_diffs_fetched: 0,
mr_diffs_failed: 0,
}]);
assert_eq!(rows.len(), 1);
assert!(rows[0].contains("vs/typescript-code"));
assert!(rows[0].contains("2 issues"));
assert!(rows[0].contains("1 statuses updated"));
}
#[test]
fn mr_sub_rows_include_project_and_diff_failures() {
let rows = mr_sub_rows(&[ProjectSummary {
path: "vs/python-code".to_string(),
items_upserted: 3,
discussions_synced: 0,
events_fetched: 0,
events_failed: 0,
statuses_enriched: 0,
statuses_seen: 0,
status_errors: 0,
mr_diffs_fetched: 4,
mr_diffs_failed: 1,
}]);
assert_eq!(rows.len(), 1);
assert!(rows[0].contains("vs/python-code"));
assert!(rows[0].contains("3 MRs"));
assert!(rows[0].contains("4 diffs"));
assert!(rows[0].contains("1 diff failures"));
}
#[test]
fn status_sub_rows_include_project_and_skip_reason() {
let rows = status_sub_rows(&[ProjectStatusEnrichment {
path: "vs/python-code".to_string(),
mode: "skipped".to_string(),
reason: Some("disabled".to_string()),
seen: 0,
enriched: 0,
cleared: 0,
without_widget: 0,
partial_errors: 0,
first_partial_error: None,
error: None,
}]);
assert_eq!(rows.len(), 1);
assert!(rows[0].contains("vs/python-code"));
assert!(rows[0].contains("0 statuses updated"));
assert!(rows[0].contains("skipped (disabled)"));
}
#[test]
fn is_surgical_with_issues() {
let opts = SyncOptions {
issue_iids: vec![1],
..default_options()
};
assert!(opts.is_surgical());
}
#[test]
fn is_surgical_with_mrs() {
let opts = SyncOptions {
mr_iids: vec![10],
..default_options()
};
assert!(opts.is_surgical());
}
#[test]
fn is_surgical_empty() {
let opts = default_options();
assert!(!opts.is_surgical());
}
#[test]
fn max_surgical_targets_is_100() {
assert_eq!(SyncOptions::MAX_SURGICAL_TARGETS, 100);
}
#[test]
fn sync_result_default_omits_surgical_fields() {
let result = SyncResult::default();
let json = serde_json::to_value(&result).unwrap();
assert!(json.get("surgical_mode").is_none());
assert!(json.get("surgical_iids").is_none());
assert!(json.get("entity_results").is_none());
assert!(json.get("preflight_only").is_none());
}
#[test]
fn sync_result_with_surgical_fields_serializes_correctly() {
let result = SyncResult {
surgical_mode: Some(true),
surgical_iids: Some(SurgicalIids {
issues: vec![7, 42],
merge_requests: vec![10],
}),
entity_results: Some(vec![
EntitySyncResult {
entity_type: "issue".to_string(),
iid: 7,
outcome: "synced".to_string(),
error: None,
toctou_reason: None,
},
EntitySyncResult {
entity_type: "issue".to_string(),
iid: 42,
outcome: "skipped_toctou".to_string(),
error: None,
toctou_reason: Some("updated_at changed".to_string()),
},
]),
preflight_only: Some(false),
..SyncResult::default()
};
let json = serde_json::to_value(&result).unwrap();
assert_eq!(json["surgical_mode"], true);
assert_eq!(json["surgical_iids"]["issues"], serde_json::json!([7, 42]));
assert_eq!(json["entity_results"].as_array().unwrap().len(), 2);
assert_eq!(json["entity_results"][1]["outcome"], "skipped_toctou");
assert_eq!(json["preflight_only"], false);
}
#[test]
fn entity_sync_result_omits_none_fields() {
let entity = EntitySyncResult {
entity_type: "merge_request".to_string(),
iid: 10,
outcome: "synced".to_string(),
error: None,
toctou_reason: None,
};
let json = serde_json::to_value(&entity).unwrap();
assert!(json.get("error").is_none());
assert!(json.get("toctou_reason").is_none());
assert!(json.get("entity_type").is_some());
}
#[test]
fn is_surgical_with_both_issues_and_mrs() {
let opts = SyncOptions {
issue_iids: vec![1, 2],
mr_iids: vec![10],
..default_options()
};
assert!(opts.is_surgical());
}
#[test]
fn is_not_surgical_with_only_project() {
let opts = SyncOptions {
project: Some("group/repo".to_string()),
..default_options()
};
assert!(!opts.is_surgical());
}