"""Tests for the DiffParser module.""" import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent / 'src')) from gdiffer.models import DiffFile, DiffHunk from gdiffer.parser import parse_diff class TestDiffParser: """Tests for DiffParser class.""" def test_parse_simple_diff(self, diff_parser, sample_diff): """Test parsing a simple diff.""" files = diff_parser.parse(sample_diff) assert len(files) == 1 assert files[0].filename == "src/main.py" assert len(files[0].hunks) == 1 def test_parse_new_file(self, diff_parser): """Test parsing diff with new file.""" diff = """diff --git a/new_file.py b/new_file.py new file mode 100644 index 0000000..1234567 --- /dev/null +++ b/new_file.py @@ -0,0 +1,3 @@ +def new_function(): + pass """ files = diff_parser.parse(diff) assert len(files) == 1 assert files[0].is_new assert files[0].change_type == "add" assert files[0].new_file_mode == "100644" def test_parse_deleted_file(self, diff_parser): """Test parsing diff with deleted file.""" diff = """diff --git a/old_file.py b/old_file.py deleted file mode 100644 index 1234567..0000000 --- a/old_file.py +++ /dev/null @@ -1,3 +0,0 @@ -def old_function(): - pass - """ files = diff_parser.parse(diff) assert len(files) == 1 assert files[0].is_deleted assert files[0].change_type == "delete" def test_parse_rename(self, diff_parser): """Test parsing diff with renamed file.""" diff = """diff --git a/old_name.py b/new_name.py similarity index 95% rename from old_name.py rename to new_name.py index 1234567..89abcde 100644 --- a/old_name.py +++ b/new_name.py @@ -1,3 +1,3 @@ def renamed_function(): - return "old" + return "new" """ files = diff_parser.parse(diff) assert len(files) == 1 assert files[0].is_rename assert files[0].rename_from == "old_name.py" assert files[0].rename_to == "new_name.py" assert files[0].change_type == "rename" def test_parse_multi_file(self, diff_parser, multi_file_diff): """Test parsing diff with multiple files.""" files = diff_parser.parse(multi_file_diff) assert len(files) == 3 file_types = [f.change_type for f in files] assert "add" in file_types assert "delete" in file_types assert "modify" in file_types def test_hunk_parsing(self, diff_parser, sample_diff): """Test that hunks are correctly parsed.""" files = diff_parser.parse(sample_diff) file_obj = files[0] assert len(file_obj.hunks) == 1 hunk = file_obj.hunks[0] assert hunk.old_start > 0 assert hunk.new_start > 0 assert hunk.old_lines > 0 assert hunk.new_lines > 0 def test_get_added_lines(self, diff_parser): """Test getting added lines from hunk.""" diff = """diff --git a/test.py b/test.py --- a/test.py +++ b/test.py @@ -1,3 +1,5 @@ +import os +import sys def test(): return True """ files = diff_parser.parse(diff) hunk = files[0].hunks[0] added_lines = hunk.get_added_lines() assert len(added_lines) == 2 def test_get_removed_lines(self, diff_parser): """Test getting removed lines from hunk.""" diff = """diff --git a/test.py b/test.py --- a/test.py +++ b/test.py @@ -1,3 +1,2 @@ -import os def test(): return True """ files = diff_parser.parse(diff) hunk = files[0].hunks[0] removed_lines = hunk.get_removed_lines() assert len(removed_lines) == 1 def test_file_extension(self, diff_parser): """Test file extension detection.""" diff_py = """diff --git a/test.py b/test.py --- a/test.py +++ b/test.py @@ -1 +1 @@ -old +new """ diff_js = """diff --git a/app.js b/app.js --- a/app.js +++ b/app.js @@ -1 +1 @@ -old +new """ files_py = diff_parser.parse(diff_py) files_js = diff_parser.parse(diff_js) assert files_py[0].extension == "py" assert files_js[0].extension == "js" def test_empty_diff(self, diff_parser): """Test parsing empty diff.""" files = diff_parser.parse("") assert len(files) == 0 def test_parse_diff_function(self): """Test the parse_diff convenience function.""" diff = """diff --git a/test.py b/test.py --- a/test.py +++ b/test.py @@ -1 +1 @@ -old +new """ files = parse_diff(diff) assert len(files) == 1 assert files[0].filename == "test.py" class TestDiffFile: """Tests for DiffFile model.""" def test_filename_property(self): """Test filename property returns correct value.""" file_obj = DiffFile(old_path="old.py", new_path="new.py") assert file_obj.filename == "new.py" def test_filename_only_old_path(self): """Test filename when only old path exists.""" file_obj = DiffFile(old_path="old.py", new_path=None) assert file_obj.filename == "old.py" def test_is_new_property(self): """Test is_new property.""" file_obj = DiffFile(old_path=None, new_path="new.py", new_file_mode="100644") assert file_obj.is_new file_obj2 = DiffFile(old_path="old.py", new_path="new.py") assert not file_obj2.is_new def test_is_deleted_property(self): """Test is_deleted property.""" file_obj = DiffFile(old_path="old.py", new_path=None, deleted_file_mode="100644") assert file_obj.is_deleted def test_is_rename_property(self): """Test is_rename property.""" file_obj = DiffFile( old_path="old.py", new_path="new.py", rename_from="old.py", rename_to="new.py" ) assert file_obj.is_rename class TestDiffHunk: """Tests for DiffHunk model.""" def test_get_modified_lines(self): """Test getting modified lines.""" hunk = DiffHunk( old_start=1, old_lines=3, new_start=1, new_lines=3, old_lines_content=["-old1", "-old2", "-old3"], new_lines_content=["+new1", "+new2", "+new3"] ) modified = hunk.get_modified_lines() assert len(modified) == 3