Files
shell-speak/tests/test_diff_parser.py
Auto User 95459fb4c8 fix: resolve CI test failure in output.py
- Fixed undefined 'tool' variable in display_history function
- Changed '[tool]' markup tag usage to proper Rich syntax
- All tests now pass (38/38 unit tests)
- Type checking passes with mypy --strict
2026-01-31 06:22:27 +00:00

251 lines
6.7 KiB
Python

"""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