"""Tests for terminal search functionality.""" import pytest from development_hub.terminal_display import TerminalDisplay class TestTerminalSearch: """Tests for terminal display search.""" def test_search_empty_pattern(self, qtbot): """Empty search pattern returns no matches.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) count = display.search("") assert count == 0 assert display.search_match_count == 0 def test_search_no_matches(self, qtbot): """Search with no matches returns 0.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"Hello world\r\n") count = display.search("xyz") assert count == 0 assert display.current_match_number == 0 def test_search_single_match(self, qtbot): """Search finds a single match.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"Hello world\r\n") count = display.search("world") assert count == 1 assert display.current_match_number == 1 def test_search_multiple_matches(self, qtbot): """Search finds multiple matches.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"test one test two test three\r\n") count = display.search("test") assert count == 3 assert display.current_match_number == 1 def test_search_case_insensitive(self, qtbot): """Search is case-insensitive by default.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"Hello HELLO hello\r\n") count = display.search("hello") assert count == 3 def test_search_case_sensitive(self, qtbot): """Case-sensitive search works.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"Hello HELLO hello\r\n") count = display.search("Hello", case_sensitive=True) assert count == 1 def test_next_match_cycles(self, qtbot): """Next match cycles through matches.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"a b a c a\r\n") display.search("a") assert display.current_match_number == 1 display.next_match() assert display.current_match_number == 2 display.next_match() assert display.current_match_number == 3 display.next_match() # Cycles back assert display.current_match_number == 1 def test_prev_match_cycles(self, qtbot): """Previous match cycles through matches backwards.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"a b a c a\r\n") display.search("a") assert display.current_match_number == 1 display.prev_match() # Cycles to end assert display.current_match_number == 3 display.prev_match() assert display.current_match_number == 2 def test_clear_search(self, qtbot): """Clear search removes matches.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) display.feed(b"test test test\r\n") display.search("test") assert display.search_match_count == 3 display.clear_search() assert display.search_match_count == 0 assert display.current_match_number == 0 def test_next_match_no_matches(self, qtbot): """Next match returns False when no matches.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) result = display.next_match() assert result is False def test_prev_match_no_matches(self, qtbot): """Previous match returns False when no matches.""" display = TerminalDisplay(rows=10, cols=40) qtbot.addWidget(display) result = display.prev_match() assert result is False class TestProjectFilter: """Tests for project list filtering.""" def test_filter_by_title(self, qtbot, tmp_path): """Filter matches project titles.""" from pathlib import Path from development_hub.project_list import ProjectListWidget from unittest.mock import patch from development_hub.project_discovery import Project # Create temp directories so exists() works p1 = tmp_path / "p1" p2 = tmp_path / "p2" p3 = tmp_path / "p3" p1.mkdir() p2.mkdir() p3.mkdir() mock_projects = [ Project(key="project-one", path=p1, title="Project One"), Project(key="project-two", path=p2, title="Project Two"), Project(key="other-thing", path=p3, title="Other Thing"), ] with patch('development_hub.project_list.discover_projects', return_value=mock_projects): widget = ProjectListWidget() qtbot.addWidget(widget) # Initially shows all assert widget.list_widget.count() == 3 # Filter by "one" widget.filter_input.setText("one") assert widget.list_widget.count() == 1 assert widget.list_widget.item(0).text() == "Project One" def test_filter_by_key(self, qtbot, tmp_path): """Filter matches project keys.""" from development_hub.project_list import ProjectListWidget from unittest.mock import patch from development_hub.project_discovery import Project p1 = tmp_path / "p1" p2 = tmp_path / "p2" p1.mkdir() p2.mkdir() mock_projects = [ Project(key="dev-hub", path=p1, title="Development Hub"), Project(key="cmd-forge", path=p2, title="CmdForge"), ] with patch('development_hub.project_list.discover_projects', return_value=mock_projects): widget = ProjectListWidget() qtbot.addWidget(widget) widget.filter_input.setText("hub") assert widget.list_widget.count() == 1 assert widget.list_widget.item(0).text() == "Development Hub" def test_filter_case_insensitive(self, qtbot, tmp_path): """Filter is case-insensitive.""" from development_hub.project_list import ProjectListWidget from unittest.mock import patch from development_hub.project_discovery import Project p1 = tmp_path / "p1" p1.mkdir() mock_projects = [ Project(key="test", path=p1, title="Test Project"), ] with patch('development_hub.project_list.discover_projects', return_value=mock_projects): widget = ProjectListWidget() qtbot.addWidget(widget) widget.filter_input.setText("TEST") assert widget.list_widget.count() == 1 def test_filter_clears(self, qtbot, tmp_path): """Clearing filter shows all projects.""" from development_hub.project_list import ProjectListWidget from unittest.mock import patch from development_hub.project_discovery import Project p1 = tmp_path / "a" p2 = tmp_path / "b" p1.mkdir() p2.mkdir() mock_projects = [ Project(key="a", path=p1, title="Alpha"), Project(key="b", path=p2, title="Beta"), ] with patch('development_hub.project_list.discover_projects', return_value=mock_projects): widget = ProjectListWidget() qtbot.addWidget(widget) widget.filter_input.setText("alpha") assert widget.list_widget.count() == 1 widget.filter_input.clear() assert widget.list_widget.count() == 2 if __name__ == "__main__": pytest.main([__file__, "-v"])