test: Add comprehensive test suite for MR ingestion
Introduces thorough test coverage for merge request functionality, following the established testing patterns from issue ingestion. New test files: - mr_transformer_tests.rs: NormalizedMergeRequest transformation tests covering full MR with all fields, minimal MR, draft detection via title prefix and work_in_progress field, label/assignee/reviewer extraction, and timestamp conversion - mr_discussion_tests.rs: MR discussion normalization tests including polymorphic noteable binding, DiffNote position extraction with line ranges and SHA triplet, and resolvable note handling - diffnote_position_tests.rs: Exhaustive DiffNote position scenarios covering text/image/file types, single-line vs multi-line comments, added/removed/modified lines, and missing position handling New fixtures: - fixtures/gitlab_merge_request.json: Representative MR API response with nested structures for integration testing Updated tests: - gitlab_types_tests.rs: Add MR type deserialization tests - migration_tests.rs: Update expected schema version to 6 Test design follows property-based patterns where feasible, with explicit edge case coverage for nullable fields and API variants across different GitLab versions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
105
tests/mr_discussion_tests.rs
Normal file
105
tests/mr_discussion_tests.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
//! Tests for MR discussion transformer.
|
||||
|
||||
use gi::gitlab::transformers::discussion::transform_mr_discussion;
|
||||
use gi::gitlab::types::{GitLabAuthor, GitLabDiscussion, GitLabNote};
|
||||
|
||||
fn make_author() -> GitLabAuthor {
|
||||
GitLabAuthor {
|
||||
id: 1,
|
||||
username: "testuser".to_string(),
|
||||
name: "Test User".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_basic_note(id: i64, created_at: &str) -> GitLabNote {
|
||||
GitLabNote {
|
||||
id,
|
||||
note_type: Some("DiscussionNote".to_string()),
|
||||
body: format!("Note {}", id),
|
||||
author: make_author(),
|
||||
created_at: created_at.to_string(),
|
||||
updated_at: created_at.to_string(),
|
||||
system: false,
|
||||
resolvable: false,
|
||||
resolved: false,
|
||||
resolved_by: None,
|
||||
resolved_at: None,
|
||||
position: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn make_discussion(notes: Vec<GitLabNote>) -> GitLabDiscussion {
|
||||
GitLabDiscussion {
|
||||
id: "abc123def456".to_string(),
|
||||
individual_note: false,
|
||||
notes,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_mr_discussion_sets_merge_request_id() {
|
||||
let note = make_basic_note(1, "2024-01-16T09:00:00.000Z");
|
||||
let discussion = make_discussion(vec![note]);
|
||||
|
||||
let result = transform_mr_discussion(&discussion, 100, 42);
|
||||
|
||||
assert_eq!(result.merge_request_id, Some(42));
|
||||
assert_eq!(result.issue_id, None);
|
||||
assert_eq!(result.noteable_type, "MergeRequest");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_mr_discussion_preserves_project_id() {
|
||||
let note = make_basic_note(1, "2024-01-16T09:00:00.000Z");
|
||||
let discussion = make_discussion(vec![note]);
|
||||
|
||||
let result = transform_mr_discussion(&discussion, 200, 42);
|
||||
|
||||
assert_eq!(result.project_id, 200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_mr_discussion_preserves_discussion_id() {
|
||||
let note = make_basic_note(1, "2024-01-16T09:00:00.000Z");
|
||||
let discussion = make_discussion(vec![note]);
|
||||
|
||||
let result = transform_mr_discussion(&discussion, 100, 42);
|
||||
|
||||
assert_eq!(result.gitlab_discussion_id, "abc123def456");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_mr_discussion_computes_resolvable_from_notes() {
|
||||
let mut note = make_basic_note(1, "2024-01-16T09:00:00.000Z");
|
||||
note.resolvable = true;
|
||||
let discussion = make_discussion(vec![note]);
|
||||
|
||||
let result = transform_mr_discussion(&discussion, 100, 42);
|
||||
|
||||
assert!(result.resolvable);
|
||||
assert!(!result.resolved); // resolvable but not resolved
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_mr_discussion_computes_resolved_when_all_resolved() {
|
||||
let mut note = make_basic_note(1, "2024-01-16T09:00:00.000Z");
|
||||
note.resolvable = true;
|
||||
note.resolved = true;
|
||||
let discussion = make_discussion(vec![note]);
|
||||
|
||||
let result = transform_mr_discussion(&discussion, 100, 42);
|
||||
|
||||
assert!(result.resolvable);
|
||||
assert!(result.resolved);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transform_mr_discussion_handles_individual_note() {
|
||||
let note = make_basic_note(1, "2024-01-16T09:00:00.000Z");
|
||||
let mut discussion = make_discussion(vec![note]);
|
||||
discussion.individual_note = true;
|
||||
|
||||
let result = transform_mr_discussion(&discussion, 100, 42);
|
||||
|
||||
assert!(result.individual_note);
|
||||
}
|
||||
Reference in New Issue
Block a user