feat: wire book detail page with working shelf/status moves and note posting

- Add spine-move-book: move book between shelves by cutting/pasting headline
- Add spine-set-status: change TODO keyword (WANT/READING/READ/none)
- Add action=shelf and action=status cases to httpd/edit POST handler
- Wrap shelf/status selects in forms with onchange auto-submit to /edit
- Wire note composer as POST form to /edit with action=note
- Redirect all edit POSTs back to /book?id=X
- 7 new tests for move-book and set-status (error handling, property preservation)
This commit is contained in:
2026-06-22 22:38:14 -04:00
parent cf511ac190
commit bbd9a455cd
3 changed files with 186 additions and 15 deletions
+86
View File
@@ -101,3 +101,89 @@
(model (spine-index-model books nil nil)))
(should-not (ht-get model "minibuffer"))))
(spine-edit-test--cleanup)))
(defun spine-edit-test--two-shelf-setup ()
"Create a test Org file with two shelves and a book on the first."
(with-temp-file spine-org-file
(insert "* Fiction\n** WANT Edit Test Book\n:PROPERTIES:\n:AUTHOR: Test Author\n:ID: test-0001\n:END:\n* Science Fiction\n"))
t)
(ert-deftest spine-move-book-moves-to-target-shelf ()
"spine-move-book moves the book to the target shelf."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--two-shelf-setup)
(spine-move-book "test-0001" "Science Fiction")
(let* ((books (spine-books))
(book (cl-find "test-0001" books :key (lambda (b) (plist-get b :id)) :test #'equal)))
(should book)
(should (equal (plist-get book :shelf) "Science Fiction"))))
(spine-edit-test--cleanup)))
(ert-deftest spine-move-book-keeps-properties ()
"spine-move-book preserves book properties after move."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--two-shelf-setup)
(spine-move-book "test-0001" "Science Fiction")
(let* ((books (spine-books))
(book (cl-find "test-0001" books :key (lambda (b) (plist-get b :id)) :test #'equal)))
(should book)
(should (equal (plist-get book :title) "WANT Edit Test Book"))
(should (equal (plist-get book :author) "Test Author"))))
(spine-edit-test--cleanup)))
(ert-deftest spine-move-book-errors-on-missing-book ()
"spine-move-book errors when book not found."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--two-shelf-setup)
(should-error (spine-move-book "nonexistent" "Science Fiction")))
(spine-edit-test--cleanup)))
(ert-deftest spine-move-book-errors-on-missing-shelf ()
"spine-move-book errors when target shelf not found."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--two-shelf-setup)
(should-error (spine-move-book "test-0001" "Nonexistent Shelf")))
(spine-edit-test--cleanup)))
(ert-deftest spine-set-status-changes-todo ()
"spine-set-status changes the TODO keyword."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--setup)
(spine-set-status "test-0001" "reading")
(let* ((books (spine-books))
(book (cl-find "test-0001" books :key (lambda (b) (plist-get b :id)) :test #'equal)))
(should book)
(should (equal (plist-get book :title) "READING Edit Test Book"))))
(spine-edit-test--cleanup)))
(ert-deftest spine-set-status-clears-todo ()
"spine-set-status with empty string removes TODO keyword."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--setup)
(spine-set-status "test-0001" "")
(let* ((books (spine-books))
(book (cl-find "test-0001" books :key (lambda (b) (plist-get b :id)) :test #'equal)))
(should book)
(should (equal (plist-get book :title) "Edit Test Book"))))
(spine-edit-test--cleanup)))
(ert-deftest spine-set-status-errors-on-missing-book ()
"spine-set-status errors when book not found."
(spine-edit-test--cleanup)
(unwind-protect
(progn
(spine-edit-test--setup)
(should-error (spine-set-status "nonexistent" "reading")))
(spine-edit-test--cleanup)))