"""Tests for the diff parser module.""" import pytest from cli_diff_auditor.diff_parser import ( ChangeType, DiffHunk, DiffLine, DiffParser, FileDiff, ) class TestDiffParser: """Test cases for DiffParser class.""" def setup_method(self): """Set up test fixtures.""" self.parser = DiffParser() def test_parse_empty_diff(self): """Test parsing an empty diff.""" result = self.parser.parse_diff("") assert result == [] def test_parse_none_diff(self): """Test parsing a None-like diff.""" result = self.parser.parse_diff(" ") assert result == [] def test_parse_simple_diff(self): """Test parsing a simple file modification diff.""" diff_output = """diff --git a/test.py b/test.py index 1234567..89abcdef 100644 --- a/test.py +++ b/test.py @@ -1,3 +1,3 @@ line 1 -old line +new line line 3 """ result = self.parser.parse_diff(diff_output) assert len(result) == 1 assert result[0].file_path == "test.py" assert result[0].change_type == ChangeType.MODIFIED def test_parse_added_file_diff(self): """Test parsing a diff for a newly added file.""" diff_output = """diff --git a/newfile.py b/newfile.py new file mode 100644 index 0000000..1234567 --- /dev/null +++ b/newfile.py @@ -0,0 +1,2 @@ +line 1 +line 2 """ result = self.parser.parse_diff(diff_output) assert len(result) == 1 assert result[0].change_type == ChangeType.ADDED assert result[0].file_path == "newfile.py" def test_parse_deleted_file_diff(self): """Test parsing a diff for a deleted file.""" diff_output = """diff --git a/oldfile.py b/oldfile.py deleted file mode 100644 index 1234567..0000000 --- a/oldfile.py +++ /dev/null @@ -1,2 +0,0 @@ -line 1 -line 2 """ result = self.parser.parse_diff(diff_output) assert len(result) == 1 assert result[0].change_type == ChangeType.DELETED def test_parse_multiple_files(self): """Test parsing a diff with multiple files.""" diff_output = """diff --git a/file1.py b/file1.py index 1234567..89abcdef 100644 --- a/file1.py +++ b/file1.py @@ -1,2 +1,2 @@ -old +new diff --git a/file2.py b/file2.py index abcdefg..1234567 100644 --- a/file2.py +++ b/file2.py @@ -1,2 +1,2 @@ -old2 +new2 """ result = self.parser.parse_diff(diff_output) assert len(result) == 2 assert result[0].file_path == "file1.py" assert result[1].file_path == "file2.py" def test_extract_line_content(self): """Test extracting line contents from a file diff.""" diff_output = """diff --git a/test.py b/test.py index 1234567..89abcdef 100644 --- a/test.py +++ b/test.py @@ -1,5 +1,5 @@ context line -old line +new line 1 +new line 2 context line 2 -old line 2 +new line 3 context line 3 """ result = self.parser.parse_diff(diff_output) assert len(result) == 1 file_diff = result[0] lines = self.parser.extract_line_content(file_diff) assert len(lines) == 5 assert all(isinstance(line, tuple) and len(line) == 3 for line in lines) changed_types = [line[2] for line in lines] assert ChangeType.ADDED in changed_types assert ChangeType.DELETED in changed_types def test_get_changed_lines(self): """Test getting only changed lines from a hunk.""" diff_output = """diff --git a/test.py b/test.py index 1234567..89abcdef 100644 --- a/test.py +++ b/test.py @@ -1,4 +1,5 @@ context -added +modified +another added context again -deleted final context """ result = self.parser.parse_diff(diff_output) assert len(result) == 1 file_diff = result[0] assert len(file_diff.hunks) == 1 hunk = file_diff.hunks[0] changed_lines = hunk.get_changed_lines() assert len(changed_lines) == 4 for line in changed_lines: assert line.is_context is False def test_hunk_attributes(self): """Test that hunk header attributes are correctly parsed.""" diff_output = """diff --git a/test.py b/test.py index 1234567..89abcdef 100644 --- a/test.py +++ b/test.py @@ -5,10 +7,15 @@ """ result = self.parser.parse_diff(diff_output) assert len(result) == 1 hunk = result[0].hunks[0] assert hunk.old_start == 5 assert hunk.old_lines == 10 assert hunk.new_start == 7 assert hunk.new_lines == 15 class TestDiffLine: """Test cases for DiffLine class.""" def test_diff_line_creation(self): """Test creating a DiffLine instance.""" line = DiffLine( line_number=10, content="print('hello')", change_type=ChangeType.ADDED ) assert line.line_number == 10 assert line.content == "print('hello')" assert line.change_type == ChangeType.ADDED assert line.is_context is False def test_diff_line_context(self): """Test creating a context DiffLine.""" line = DiffLine( line_number=5, content="def foo():", change_type=ChangeType.MODIFIED, is_context=True ) assert line.is_context is True class TestFileDiff: """Test cases for FileDiff class.""" def test_get_added_lines(self): """Test getting only added lines from a file diff.""" file_diff = FileDiff( file_path="test.py", change_type=ChangeType.MODIFIED ) hunk = DiffHunk(old_start=1, old_lines=3, new_start=1, new_lines=4) hunk.lines = [ DiffLine(line_number=1, content="old", change_type=ChangeType.DELETED), DiffLine(line_number=2, content="new", change_type=ChangeType.ADDED), DiffLine(line_number=3, content="context", change_type=ChangeType.MODIFIED, is_context=True), ] file_diff.hunks.append(hunk) added_lines = file_diff.get_added_lines() assert len(added_lines) == 1 assert added_lines[0].change_type == ChangeType.ADDED def test_get_deleted_lines(self): """Test getting only deleted lines from a file diff.""" file_diff = FileDiff( file_path="test.py", change_type=ChangeType.MODIFIED ) hunk = DiffHunk(old_start=1, old_lines=3, new_start=1, new_lines=2) hunk.lines = [ DiffLine(line_number=1, content="old", change_type=ChangeType.DELETED), DiffLine(line_number=2, content="new", change_type=ChangeType.ADDED), ] file_diff.hunks.append(hunk) deleted_lines = file_diff.get_deleted_lines() assert len(deleted_lines) == 1 assert deleted_lines[0].change_type == ChangeType.DELETED