""" Unit tests for DiffReviewManager parsing and presentation behavior. """ from unittest.mock import Mock import pytest import fenrirscreenreader.core.diffReviewManager as diff_review_module from fenrirscreenreader.core.diffReviewManager import DiffReviewManager @pytest.fixture def diff_manager(monkeypatch): """Create a DiffReviewManager with a minimal test environment.""" monkeypatch.setattr(diff_review_module, "_", lambda text: text) spoken_messages = [] output_manager = Mock() def _capture_message(message, **_kwargs): spoken_messages.append(message) output_manager.present_text.side_effect = _capture_message settings_manager = Mock() settings_manager.get_setting.side_effect = ( lambda section, setting: "compact" if (section, setting) == ("general", "diff_verbosity") else "default" ) env = { "runtime": { "DebugManager": Mock(write_debug_out=Mock()), "OutputManager": output_manager, "SettingsManager": settings_manager, "MemoryManager": Mock( is_index_list_empty=Mock(return_value=True), get_index_list_element=Mock(return_value=""), ), }, "bindings": {}, "rawBindings": {}, } manager = DiffReviewManager() manager.initialize(env) return manager, spoken_messages @pytest.mark.unit class TestDiffReviewManager: """Test diff review parsing and speech presentation edge cases.""" def test_parse_unified_diff_tracks_sections_and_counts(self, diff_manager): manager, _ = diff_manager lines = [ "diff --git a/example.txt b/example.txt", "index 1111111..2222222 100644", "--- a/example.txt", "+++ b/example.txt", "@@ -1,2 +1,3 @@", " context line", "-old line", "+new line one", "+new line two", ] manager._parse_lines(lines, "/tmp/example.diff") assert len(manager.file_sections) == 1 assert len(manager.hunk_sections) == 1 assert manager.total_added == 2 assert manager.total_removed == 1 assert manager.file_sections[0]["added_count"] == 2 assert manager.file_sections[0]["removed_count"] == 1 assert manager.hunk_sections[0]["position_in_file"] == 1 assert manager.hunk_sections[0]["hunks_in_file"] == 1 def test_formats_classic_diff_markers(self, diff_manager): manager, _ = diff_manager assert manager._format_classic_diff_command("17c17") == "line 17 changed" assert manager._format_classic_diff_command("17d16") == "line 17 deleted" assert manager._format_classic_diff_command("16a17") == "line 17 added" assert ( manager._format_classic_diff_command("20,22c30,32") == "lines 20 through 22 changed" ) assert manager._format_classic_diff_command("not a diff marker") is None def test_announces_classic_marker_line_as_plain_language(self, diff_manager): manager, spoken_messages = diff_manager manager._parse_lines(["17c17"], "/tmp/classic.diff") manager.current_line = 0 manager._announce_current_line() assert spoken_messages[-1] == "line 17 changed" def test_marker_only_added_removed_lines_become_words(self, diff_manager): manager, spoken_messages = diff_manager manager._parse_lines(["+++", "---"], "/tmp/markers.diff") manager.current_line = 0 manager._announce_current_line() manager.current_line = 1 manager._announce_current_line() assert spoken_messages[-2] == "added" assert spoken_messages[-1] == "removed" def test_large_diff_parsing_stays_consistent(self, diff_manager): manager, spoken_messages = diff_manager line_count = 1500 lines = [ "diff --git a/large.txt b/large.txt", "--- a/large.txt", "+++ b/large.txt", "@@ -1,1500 +1,1500 @@", ] for index in range(1, line_count + 1): lines.append(f"-old value {index}") lines.append(f"+new value {index}") manager._parse_lines(lines, "/tmp/large.diff") manager.next_added() assert len(manager.file_sections) == 1 assert len(manager.hunk_sections) == 1 assert manager.total_added == line_count assert manager.total_removed == line_count assert manager.current_line == manager.added_lines[0] assert spoken_messages[-1].startswith("Added line.")