aboutsummaryrefslogtreecommitdiff
path: root/pocketbook/tests
diff options
context:
space:
mode:
Diffstat (limited to 'pocketbook/tests')
-rw-r--r--pocketbook/tests/__init__.py0
-rw-r--r--pocketbook/tests/conftest.py17
-rw-r--r--pocketbook/tests/test_app_toggle.py96
-rw-r--r--pocketbook/tests/test_note.py69
-rw-r--r--pocketbook/tests/test_panel.py40
-rw-r--r--pocketbook/tests/test_store.py103
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