test_file_selector.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. """
  2. Tests for FileSelector UI component.
  3. """
  4. import pytest
  5. # Skip tests if PyQt6 is not installed
  6. pytest.importorskip("PyQt6")
  7. from pathlib import Path
  8. from datetime import datetime
  9. from PyQt6.QtWidgets import QApplication
  10. from PyQt6.QtCore import Qt, QFileSystemWatcher
  11. from PyQt6.QtTest import QTest
  12. from src.ui.file_selector import FileSelector
  13. @pytest.fixture
  14. def app(qtbot):
  15. """Create QApplication fixture."""
  16. test_app = QApplication.instance()
  17. if test_app is None:
  18. test_app = QApplication([])
  19. yield test_app
  20. @pytest.fixture
  21. def file_selector(app, qtbot, tmp_path):
  22. """Create FileSelector fixture with temp directory."""
  23. selector = FileSelector()
  24. qtbot.addWidget(selector)
  25. yield selector, tmp_path
  26. selector.close()
  27. class TestFileSelector:
  28. """Test FileSelector functionality."""
  29. def test_initialization(self, file_selector):
  30. """Test file selector initializes correctly."""
  31. selector, _ = file_selector
  32. assert selector.current_path is None
  33. assert not selector.is_valid
  34. assert selector._path_display.placeholderText() == selector.DEFAULT_PLACEHOLDER
  35. def test_no_file_selected_initially(self, file_selector):
  36. """Test no file is selected initially."""
  37. selector, _ = file_selector
  38. assert selector.current_path is None
  39. assert not selector.is_valid
  40. assert selector._name_value.text() == "-"
  41. assert selector._size_value.text() == "-"
  42. assert selector._lines_value.text() == "-"
  43. def test_set_valid_file(self, file_selector):
  44. """Test setting a valid file."""
  45. selector, tmp_path = file_selector
  46. # Create a test file
  47. test_file = tmp_path / "test.txt"
  48. test_file.write_text("Line 1\nLine 2\nLine 3\n", encoding='utf-8')
  49. # Set the file
  50. selector.set_file(test_file)
  51. assert selector.current_path == test_file
  52. assert selector.is_valid
  53. assert selector._name_value.text() == "test.txt"
  54. def test_file_info_display(self, file_selector):
  55. """Test file information is displayed correctly."""
  56. selector, tmp_path = file_selector
  57. # Create a test file with known content
  58. content = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n"
  59. test_file = tmp_path / "test.txt"
  60. test_file.write_text(content, encoding='utf-8')
  61. selector.set_file(test_file)
  62. # Check name
  63. assert selector._name_value.text() == "test.txt"
  64. # Check size (should be non-zero)
  65. size_text = selector._size_value.text()
  66. assert "B" in size_text
  67. # Check line count
  68. lines_text = selector._lines_value.text()
  69. assert "5" in lines_text or "5," in lines_text # 5 lines
  70. def test_clear_selection(self, file_selector):
  71. """Test clearing file selection."""
  72. selector, tmp_path = file_selector
  73. # Create and set a file
  74. test_file = tmp_path / "test.txt"
  75. test_file.write_text("Content\n", encoding='utf-8')
  76. selector.set_file(test_file)
  77. assert selector.is_valid
  78. # Clear the selection
  79. selector.clear()
  80. assert selector.current_path is None
  81. assert not selector.is_valid
  82. assert selector._name_value.text() == "-"
  83. def test_file_selected_signal(self, file_selector, qtbot):
  84. """Test file_selected signal is emitted."""
  85. selector, tmp_path = file_selector
  86. signal_received = []
  87. def on_file_selected(path):
  88. signal_received.append(path)
  89. selector.file_selected.connect(on_file_selected)
  90. # Create and set a file
  91. test_file = tmp_path / "test.txt"
  92. test_file.write_text("Content\n", encoding='utf-8')
  93. selector.set_file(test_file)
  94. assert len(signal_received) == 1
  95. assert signal_received[0] == test_file
  96. def test_selection_cleared_signal(self, file_selector):
  97. """Test selection_cleared signal is emitted."""
  98. selector, tmp_path = file_selector
  99. signal_received = []
  100. def on_cleared():
  101. signal_received.append(True)
  102. selector.selection_cleared.connect(on_cleared)
  103. # Create and set a file
  104. test_file = tmp_path / "test.txt"
  105. test_file.write_text("Content\n", encoding='utf-8')
  106. selector.set_file(test_file)
  107. # Clear the selection
  108. selector.clear()
  109. assert len(signal_received) == 1
  110. def test_size_formatting(self):
  111. """Test file size formatting."""
  112. selector = FileSelector()
  113. # Test different size units
  114. assert "B" in selector._format_size(512)
  115. assert "KB" in selector._format_size(2048)
  116. assert "MB" in selector._format_size(1024 * 1024 * 5)
  117. assert "GB" in selector._format_size(1024 * 1024 * 1024 * 2)
  118. def test_line_count_property(self, file_selector):
  119. """Test line_count property."""
  120. selector, tmp_path = file_selector
  121. # No file selected
  122. assert selector.line_count is None
  123. # Create a file with 10 lines
  124. test_file = tmp_path / "test.txt"
  125. test_file.write_text("\n".join([f"Line {i}" for i in range(10)]), encoding='utf-8')
  126. selector.set_file(test_file)
  127. assert selector.line_count == 10
  128. def test_non_existent_file(self, file_selector):
  129. """Test handling of non-existent file."""
  130. selector, tmp_path = file_selector
  131. # Set a non-existent path
  132. non_existent = tmp_path / "does_not_exist.txt"
  133. selector.set_file(non_existent)
  134. # Should handle gracefully
  135. assert selector.current_path == non_existent
  136. assert not selector.is_valid
  137. def test_empty_file(self, file_selector):
  138. """Test handling of empty file."""
  139. selector, tmp_path = file_selector
  140. # Create an empty file
  141. test_file = tmp_path / "empty.txt"
  142. test_file.write_text("", encoding='utf-8')
  143. selector.set_file(test_file)
  144. assert selector.is_valid
  145. assert selector.line_count == 0
  146. def test_chinese_text_file(self, file_selector):
  147. """Test handling of Chinese text file."""
  148. selector, tmp_path = file_selector
  149. # Create a file with Chinese text
  150. test_file = tmp_path / "chinese.txt"
  151. test_file.write_text("第一章:开始\n第二章:发展\n第三章:结束\n", encoding='utf-8')
  152. selector.set_file(test_file)
  153. assert selector.is_valid
  154. assert selector.line_count == 3
  155. class TestFileSelectorUI:
  156. """Test FileSelector UI elements."""
  157. def test_browse_button_exists(self, file_selector):
  158. """Test browse button exists."""
  159. selector, _ = file_selector
  160. assert selector._browse_btn is not None
  161. assert selector._browse_btn.text() == "Browse..."
  162. def test_clear_button_initially_disabled(self, file_selector):
  163. """Test clear button is initially disabled."""
  164. selector, _ = file_selector
  165. assert not selector._clear_btn.isEnabled()
  166. def test_clear_button_enabled_with_file(self, file_selector):
  167. """Test clear button is enabled when file is selected."""
  168. selector, tmp_path = file_selector
  169. test_file = tmp_path / "test.txt"
  170. test_file.write_text("Content\n", encoding='utf-8')
  171. selector.set_file(test_file)
  172. assert selector._clear_btn.isEnabled()
  173. def test_groups_exist(self, file_selector):
  174. """Test UI groups are created."""
  175. selector, _ = file_selector
  176. # Check for groups (they should exist)
  177. assert selector.layout() is not None
  178. assert selector.layout().count() > 0