use ai::agent::action::CommentSide; use super::{DiffHunkParseError, parse_diff_hunk}; #[test] fn test_parse_preserves_whitespace() { let diff_hunk = "@@ -1,2 +1,3 @@ first line + indented line last line"; // Diff line index 2 is the added line with indentation let result = parse_diff_hunk(diff_hunk, 2, None); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, "+ indented line"); } #[test] fn test_parse_empty_hunk() { let result = parse_diff_hunk("", 1, None); assert!(matches!(result, Err(DiffHunkParseError::EmptyHunk))); } #[test] fn test_parse_malformed_header() { // Header doesn't have valid format let diff_hunk = "@@ invalid @@"; let result = parse_diff_hunk(diff_hunk, 1, None); assert!(matches!(result, Err(DiffHunkParseError::InvalidHeader(_)))); } #[test] fn test_parse_missing_header() { // Content without a valid header line let diff_hunk = " line1\n+line2\n line3"; let result = parse_diff_hunk(diff_hunk, 1, None); assert!(matches!(result, Err(DiffHunkParseError::InvalidHeader(_)))); } #[test] fn test_parse_hunk_with_two_headers() { // Diff with an unexpected second header line let diff_hunk = "@@ -1,3 +1,4 @@\n line1\n@@ -5,2 +5,2 @@\n line2"; let result = parse_diff_hunk(diff_hunk, 2, None); assert!(matches!( result, Err(DiffHunkParseError::UnexpectedHunkHeader { line_index: 2 }) )); } // --------------------------------------------------------------------------- // Regression: markdown list items in diff hunks (PR #23626) // --------------------------------------------------------------------------- /// Regression test for diff hunks from PR #23626 where the commented line is a /// markdown list item (`+- ...`). The leading `-` is part of the content, not a /// diff deletion marker. #[test] fn test_parse_markdown_list_item_in_pure_addition_hunk() { // Trimmed hunk shape from PR #23626 comment 2997753460 let diff_hunk = "@@ -0,0 +16,1 @@\n+- `specs//TECH.md`"; let result = parse_diff_hunk(diff_hunk, 16, Some(CommentSide::Right)); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, "+- `specs//TECH.md`"); assert_eq!(content.original_text(), "- `specs//TECH.md`"); } /// Same scenario but with more surrounding context, matching the full diff hunk /// shape from the GitHub API for PR #23626. #[test] fn test_parse_markdown_list_item_in_full_addition_hunk() { let diff_hunk = "@@ -0,0 +1,116 @@\n\ +---\n\ +name: write-tech-spec\n\ +description: desc\n\ +---\n\ +\n\ +# write-tech-spec\n\ +\n\ +Write a spec.\n\ +\n\ +## Overview\n\ +\n\ +The tech spec overview.\n\ +\n\ +Write specs into source control under:\n\ +\n\ +- `specs//TECH.md`"; let result = parse_diff_hunk(diff_hunk, 16, Some(CommentSide::Right)); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, "+- `specs//TECH.md`"); assert_eq!(content.original_text(), "- `specs//TECH.md`"); } /// Diff line whose content starts with `+` after the diff `+` prefix. #[test] fn test_parse_addition_with_leading_plus_in_content() { let diff_hunk = "@@ -0,0 +1,1 @@\n++positive value"; let result = parse_diff_hunk(diff_hunk, 1, Some(CommentSide::Right)); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, "++positive value"); assert_eq!(content.original_text(), "+positive value"); } /// Diff line whose content starts with `-` after the diff `-` prefix (deletion /// of a markdown list item). #[test] fn test_parse_deletion_with_leading_dash_in_content() { let diff_hunk = "@@ -1,1 +1,0 @@\n-- list item"; let result = parse_diff_hunk(diff_hunk, 1, Some(CommentSide::Left)); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, "-- list item"); assert_eq!(content.original_text(), "- list item"); } /// Context line with content that starts with `-`. #[test] fn test_parse_context_line_starting_with_dash() { let diff_hunk = "@@ -1,3 +1,4 @@\n - list item\n+added\n second\n third"; let result = parse_diff_hunk(diff_hunk, 1, Some(CommentSide::Right)); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, " - list item"); } /// Context line with content that starts with `@`. #[test] fn test_parse_context_line_starting_with_at_sign() { let diff_hunk = "@@ -1,2 +1,3 @@\n @decorator\n+added\n next"; let result = parse_diff_hunk(diff_hunk, 1, Some(CommentSide::Right)); assert!(result.is_ok()); let (_, content) = result.unwrap(); assert_eq!(content.content, " @decorator"); }