diff options
Diffstat (limited to 'pocketbook/tests')
| -rw-r--r-- | pocketbook/tests/__init__.py | 0 | ||||
| -rw-r--r-- | pocketbook/tests/conftest.py | 17 | ||||
| -rw-r--r-- | pocketbook/tests/test_app_toggle.py | 96 | ||||
| -rw-r--r-- | pocketbook/tests/test_note.py | 69 | ||||
| -rw-r--r-- | pocketbook/tests/test_panel.py | 40 | ||||
| -rw-r--r-- | pocketbook/tests/test_store.py | 103 |
6 files changed, 0 insertions, 325 deletions
diff --git a/pocketbook/tests/__init__.py b/pocketbook/tests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/pocketbook/tests/__init__.py +++ /dev/null diff --git a/pocketbook/tests/conftest.py b/pocketbook/tests/conftest.py deleted file mode 100644 index db04f88..0000000 --- a/pocketbook/tests/conftest.py +++ /dev/null @@ -1,17 +0,0 @@ -import pytest - - -@pytest.fixture -def notes_dir(tmp_path): - """Temporary directory for note storage.""" - d = tmp_path / "quicknotes" - d.mkdir() - return d - - -@pytest.fixture -def sample_note_file(notes_dir): - """A sample note file on disk.""" - path = notes_dir / "0001-20260101-120000-abc12.txt" - path.write_text("Shopping List\n\nMilk\nEggs\nBread\n") - return path diff --git a/pocketbook/tests/test_app_toggle.py b/pocketbook/tests/test_app_toggle.py deleted file mode 100644 index cb5ab89..0000000 --- a/pocketbook/tests/test_app_toggle.py +++ /dev/null @@ -1,96 +0,0 @@ -from pocketbook.app import ToggleStateMachine, EscapeStateMachine, navigate - - -class TestToggleStateMachine: - def test_initial_state_visible(self): - sm = ToggleStateMachine(start_hidden=False) - assert sm.visible is True - - def test_initial_state_hidden(self): - sm = ToggleStateMachine(start_hidden=True) - assert sm.visible is False - - def test_toggle_alternates(self): - sm = ToggleStateMachine(start_hidden=False) - assert sm.visible is True - sm.toggle() - assert sm.visible is False - sm.toggle() - assert sm.visible is True - - def test_toggle_from_hidden(self): - sm = ToggleStateMachine(start_hidden=True) - assert sm.visible is False - sm.toggle() - assert sm.visible is True - sm.toggle() - assert sm.visible is False - - -class TestEscapeStateMachine: - def test_escape_while_editing_returns_exit_edit(self): - esc = EscapeStateMachine() - toggle = ToggleStateMachine(start_hidden=False) - action = esc.escape(is_editing=True, toggle=toggle) - assert action == "exit_edit" - # Toggle state should not change - assert toggle.visible is True - - def test_escape_while_browsing_returns_hide(self): - esc = EscapeStateMachine() - toggle = ToggleStateMachine(start_hidden=False) - action = esc.escape(is_editing=False, toggle=toggle) - assert action == "hide" - assert toggle.visible is False - - def test_escape_edit_then_browse_hides(self): - """Simulates: editing → Escape (exit edit) → Escape (hide).""" - esc = EscapeStateMachine() - toggle = ToggleStateMachine(start_hidden=False) - - # First escape: exit edit mode - action1 = esc.escape(is_editing=True, toggle=toggle) - assert action1 == "exit_edit" - assert toggle.visible is True - - # Second escape: now in browse mode, hide panel - action2 = esc.escape(is_editing=False, toggle=toggle) - assert action2 == "hide" - assert toggle.visible is False - - def test_escape_hide_does_not_change_when_already_hidden(self): - esc = EscapeStateMachine() - toggle = ToggleStateMachine(start_hidden=True) - assert toggle.visible is False - action = esc.escape(is_editing=False, toggle=toggle) - assert action == "hide" - # Toggled again — now visible (edge case if called when hidden) - assert toggle.visible is True - - -class TestNavigate: - def test_no_notes(self): - assert navigate(None, 0, 1) is None - assert navigate(None, 0, -1) is None - - def test_no_focus_next_goes_to_first(self): - assert navigate(None, 3, 1) == 0 - - def test_no_focus_prev_goes_to_last(self): - assert navigate(None, 3, -1) == 2 - - def test_next_from_middle(self): - assert navigate(1, 3, 1) == 2 - - def test_prev_from_middle(self): - assert navigate(1, 3, -1) == 0 - - def test_next_clamps_at_end(self): - assert navigate(2, 3, 1) == 2 - - def test_prev_clamps_at_start(self): - assert navigate(0, 3, -1) == 0 - - def test_single_note(self): - assert navigate(0, 1, 1) == 0 - assert navigate(0, 1, -1) == 0 diff --git a/pocketbook/tests/test_note.py b/pocketbook/tests/test_note.py deleted file mode 100644 index 539451a..0000000 --- a/pocketbook/tests/test_note.py +++ /dev/null @@ -1,69 +0,0 @@ -from pocketbook.note import Note - - -class TestNoteSerialisation: - def test_round_trip(self): - note = Note(title="Shopping", body="Milk\nEggs\nBread") - content = note.to_file_content() - restored = Note.from_file_content(content) - assert restored.title == note.title - assert restored.body == note.body - - def test_empty_body(self): - note = Note(title="Empty", body="") - content = note.to_file_content() - restored = Note.from_file_content(content) - assert restored.title == "Empty" - assert restored.body == "" - - def test_empty_title(self): - note = Note(title="", body="some body") - content = note.to_file_content() - restored = Note.from_file_content(content) - assert restored.title == "" - assert restored.body == "some body" - - def test_unicode(self): - note = Note(title="日本語タイトル", body="Ünïcödé bödý 🎉") - content = note.to_file_content() - restored = Note.from_file_content(content) - assert restored.title == "日本語タイトル" - assert restored.body == "Ünïcödé bödý 🎉" - - def test_multiline_body(self): - body = "Line 1\nLine 2\n\nLine 4\n" - note = Note(title="Multi", body=body) - content = note.to_file_content() - restored = Note.from_file_content(content) - assert restored.body == body - - def test_file_content_format(self): - """Title on line 1, blank line, then body.""" - note = Note(title="Title", body="Body text") - content = note.to_file_content() - assert content == "Title\n\nBody text" - - def test_from_file_content_no_blank_line(self): - """Gracefully handle files without a blank separator.""" - restored = Note.from_file_content("JustTitle") - assert restored.title == "JustTitle" - assert restored.body == "" - - -class TestNoteFilename: - def test_generate_filename(self): - note = Note(title="Test", body="") - filename = note.generate_filename(order=1) - assert filename.startswith("0001-") - assert filename.endswith(".txt") - # Format: 0001-YYYYMMDD-HHMMSS-shortid.txt - parts = filename.split("-") - assert len(parts) == 4 - assert len(parts[0]) == 4 # order - assert len(parts[1]) == 8 # date - # parts[2] = HHMMSS + shortid.txt combined via split on - - # Actually: 0001-20260225-143012-abc12.txt has 4 parts - - def test_parse_order_from_filename(self): - assert Note.parse_order("0005-20260101-120000-abc12.txt") == 5 - assert Note.parse_order("0001-20260101-120000-xyz99.txt") == 1 diff --git a/pocketbook/tests/test_panel.py b/pocketbook/tests/test_panel.py deleted file mode 100644 index 92f8648..0000000 --- a/pocketbook/tests/test_panel.py +++ /dev/null @@ -1,40 +0,0 @@ -from unittest.mock import MagicMock -from pocketbook.note import Note - - -class TestPanelController: - """Test panel controller logic with a mocked store.""" - - def _make_controller(self): - from pocketbook.panel import PanelController - store = MagicMock() - controller = PanelController(store) - return controller, store - - def test_add_note_calls_store_create(self): - controller, store = self._make_controller() - store.create.return_value = "0001-20260101-120000-abc12.txt" - controller.add_note() - store.create.assert_called_once_with("New Note", "") - - def test_delete_note_calls_store_delete(self): - controller, store = self._make_controller() - controller.delete_note("0001-20260101-120000-abc12.txt") - store.delete.assert_called_once_with("0001-20260101-120000-abc12.txt") - - def test_update_note_calls_store_update(self): - controller, store = self._make_controller() - controller.update_note("0001-20260101-120000-abc12.txt", "New Title", "New Body") - store.update.assert_called_once_with( - "0001-20260101-120000-abc12.txt", "New Title", "New Body" - ) - - def test_get_notes_calls_store_list(self): - controller, store = self._make_controller() - store.list_notes.return_value = [ - ("0001-20260101-120000-abc12.txt", Note(title="A", body="a")), - ] - notes = controller.get_notes() - store.list_notes.assert_called_once() - assert len(notes) == 1 - assert notes[0][1].title == "A" diff --git a/pocketbook/tests/test_store.py b/pocketbook/tests/test_store.py deleted file mode 100644 index fab5bd6..0000000 --- a/pocketbook/tests/test_store.py +++ /dev/null @@ -1,103 +0,0 @@ -import pytest -from pocketbook.store import NoteStore -from pocketbook.note import Note - - -class TestNoteStoreCreate: - def test_create_note(self, notes_dir): - store = NoteStore(notes_dir) - filename = store.create("My Title", "My Body") - assert (notes_dir / filename).exists() - content = (notes_dir / filename).read_text() - assert content == "My Title\n\nMy Body" - - def test_create_assigns_incrementing_order(self, notes_dir): - store = NoteStore(notes_dir) - f1 = store.create("First", "") - f2 = store.create("Second", "") - assert Note.parse_order(f1) == 1 - assert Note.parse_order(f2) == 2 - - def test_create_auto_creates_directory(self, tmp_path): - d = tmp_path / "nonexistent" / "pocketbook" - store = NoteStore(d) - filename = store.create("Test", "body") - assert d.exists() - assert (d / filename).exists() - - -class TestNoteStoreList: - def test_list_empty(self, notes_dir): - # Remove the sample file if any fixture created one - for f in notes_dir.iterdir(): - f.unlink() - store = NoteStore(notes_dir) - assert store.list_notes() == [] - - def test_list_returns_sorted_by_order(self, notes_dir): - (notes_dir / "0002-20260101-120000-abc12.txt").write_text("B\n\nbody b") - (notes_dir / "0001-20260101-120000-def34.txt").write_text("A\n\nbody a") - (notes_dir / "0003-20260101-120000-ghi56.txt").write_text("C\n\nbody c") - store = NoteStore(notes_dir) - notes = store.list_notes() - assert len(notes) == 3 - assert notes[0][1].title == "A" - assert notes[1][1].title == "B" - assert notes[2][1].title == "C" - - def test_list_skips_non_txt_files(self, notes_dir): - (notes_dir / "0001-20260101-120000-abc12.txt").write_text("Note\n\nbody") - (notes_dir / "README.md").write_text("not a note") - store = NoteStore(notes_dir) - assert len(store.list_notes()) == 1 - - def test_list_skips_corrupted_filenames(self, notes_dir): - (notes_dir / "0001-20260101-120000-abc12.txt").write_text("Good\n\nbody") - (notes_dir / "bad-name.txt").write_text("Bad\n\nbody") - store = NoteStore(notes_dir) - notes = store.list_notes() - assert len(notes) == 1 - assert notes[0][1].title == "Good" - - -class TestNoteStoreUpdate: - def test_update_note(self, notes_dir): - fname = "0001-20260101-120000-abc12.txt" - (notes_dir / fname).write_text("Old Title\n\nOld body") - store = NoteStore(notes_dir) - store.update(fname, "New Title", "New body") - content = (notes_dir / fname).read_text() - assert content == "New Title\n\nNew body" - - def test_update_nonexistent_raises(self, notes_dir): - store = NoteStore(notes_dir) - with pytest.raises(FileNotFoundError): - store.update("0099-20260101-120000-nope0.txt", "T", "B") - - -class TestNoteStoreDelete: - def test_delete_note(self, notes_dir): - fname = "0001-20260101-120000-abc12.txt" - (notes_dir / fname).write_text("Delete me\n\nbody") - store = NoteStore(notes_dir) - store.delete(fname) - assert not (notes_dir / fname).exists() - - def test_delete_nonexistent_raises(self, notes_dir): - store = NoteStore(notes_dir) - with pytest.raises(FileNotFoundError): - store.delete("0099-20260101-120000-nope0.txt") - - -class TestNoteStoreReorder: - def test_reorder_renumbers_files(self, notes_dir): - # Create files with gaps in ordering - (notes_dir / "0001-20260101-120000-aaa11.txt").write_text("A\n\na") - (notes_dir / "0005-20260101-120000-bbb22.txt").write_text("B\n\nb") - (notes_dir / "0010-20260101-120000-ccc33.txt").write_text("C\n\nc") - store = NoteStore(notes_dir) - store.reorder() - notes = store.list_notes() - assert Note.parse_order(notes[0][0]) == 1 - assert Note.parse_order(notes[1][0]) == 2 - assert Note.parse_order(notes[2][0]) == 3 |
