;;; spine-edit-test.el — ERT tests for spine-edit functions (require 'ert) (require 'cl-lib) (setq spine-skip-server-start t) (setq spine-org-file (expand-file-name "test-edit-temp.org" (file-name-directory (directory-file-name (file-name-directory load-file-name))))) (load-file (expand-file-name "../spine.el" (file-name-directory load-file-name))) (defun spine-edit-test--setup () "Create a test Org file with one WANT book." (spine-add-book :title "Edit Test Book" :author "Test Author")) (defun spine-edit-test--cleanup () "Remove the test Org file." (ignore-errors (delete-file spine-org-file))) (ert-deftest spine-set-status-want-to-reading () "spine-set-status changes TODO from WANT to READING." (spine-edit-test--cleanup) (unwind-protect (progn (spine-edit-test--setup) (let* ((books (spine-books)) (book (car books)) (id (plist-get book :id))) (spine-set-status id "READING") (let ((updated (cl-find id (spine-books) :key (lambda (b) (plist-get b :id)) :test #'equal))) (should updated) (should (equal (plist-get updated :status) "READING"))))) (spine-edit-test--cleanup))) (ert-deftest spine-set-status-reading-to-read () "spine-set-status changes TODO from READING to READ." (spine-edit-test--cleanup) (unwind-protect (progn (spine-edit-test--setup) (let* ((books (spine-books)) (book (car books)) (id (plist-get book :id))) (spine-set-status id "READING") (spine-set-status id "READ") (let ((updated (cl-find id (spine-books) :key (lambda (b) (plist-get b :id)) :test #'equal))) (should updated) (should (equal (plist-get updated :status) "READ"))))) (spine-edit-test--cleanup))) (ert-deftest spine-add-note-appends () "spine-add-note appends a note with date and text." (spine-edit-test--cleanup) (unwind-protect (progn (spine-edit-test--setup) (let* ((books (spine-books)) (book (car books)) (id (plist-get book :id))) (spine-add-note id "Great book!" "2026-06-21") (let ((updated (cl-find id (spine-books) :key (lambda (b) (plist-get b :id)) :test #'equal))) (should updated) (let ((notes (plist-get updated :notes))) (should notes) (should (equal (caar notes) "2026-06-21")) (should (equal (cadar notes) "Great book!")))))) (spine-edit-test--cleanup))) (ert-deftest spine-add-note-default-date () "spine-add-note uses today's date when none provided." (spine-edit-test--cleanup) (unwind-protect (progn (spine-edit-test--setup) (let* ((books (spine-books)) (book (car books)) (id (plist-get book :id)) (today (format-time-string "%Y-%m-%d"))) (spine-add-note id "Note without date") (let ((updated (cl-find id (spine-books) :key (lambda (b) (plist-get b :id)) :test #'equal))) (should updated) (let ((notes (plist-get updated :notes))) (should notes) (should (equal (caar notes) today)) (should (equal (cadar notes) "Note without date")))))) (spine-edit-test--cleanup))) (ert-deftest spine-set-rating-sets-rating () "spine-set-rating sets the RATING property." (spine-edit-test--cleanup) (unwind-protect (progn (spine-edit-test--setup) (let* ((books (spine-books)) (book (car books)) (id (plist-get book :id))) (spine-set-rating id "4") (let ((updated (cl-find id (spine-books) :key (lambda (b) (plist-get b :id)) :test #'equal))) (should updated) (should (equal (plist-get updated :rating) "4"))))) (spine-edit-test--cleanup))) (ert-deftest spine-set-status-missing-id () "spine-set-status signals error for unknown ID." (should-error (spine-set-status "nonexistent-id" "READING"))) (ert-deftest spine-edit-model-minibuffer-want () "Selected WANT book has Mark reading and Add note actions." (spine-edit-test--cleanup) (unwind-protect (progn (spine-edit-test--setup) (let* ((books (spine-books)) (book (car books)) (id (plist-get book :id)) (model (spine-index-model books nil id)) (groups (ht-get model "groups"))) (cl-labels ((find-book-model (groups id) (cl-block nil (dolist (g groups) (dolist (b (ht-get g "books")) (when (string= (ht-get b "title") "Edit Test Book") (cl-return b))))))) (let ((bm (find-book-model groups id))) (should bm) (let ((mb (ht-get bm "minibuffer"))) (should mb) (let ((actions (ht-get mb "actions"))) (should (= (length actions) 2)) (should (string= (ht-get (nth 0 actions) "label") "Mark reading")) (should (string= (ht-get (nth 1 actions) "label") "Add note")))))))) (spine-edit-test--cleanup)))