feat: rewrite spine-index-model for shelf grouping
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
;;; spine-index-model-test.el — ERT tests for spine-index-model with filter
|
||||
;;; spine-index-model-test.el — ERT tests for spine-index-model with shelf grouping
|
||||
|
||||
(require 'ert)
|
||||
(require 'cl-lib)
|
||||
@@ -14,90 +14,61 @@
|
||||
(defconst spine-index-model-test--books (spine-books)
|
||||
"Books fixture loaded once from sample-books.org.")
|
||||
|
||||
(ert-deftest spine-index-model-concise-hides-read-and-abandoned ()
|
||||
"Concise view (filter=nil) omits READ/ABANDONED groups, adds summary-groups."
|
||||
(ert-deftest spine-index-model-groups-by-shelf ()
|
||||
"Index model groups books by :shelf."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books))
|
||||
(groups (ht-get model "groups"))
|
||||
(summaries (ht-get model "summary_groups"))
|
||||
(group-labels (mapcar (lambda (g) (ht-get g "label")) groups)))
|
||||
(should-not (member "read" group-labels))
|
||||
(should-not (member "abandoned" group-labels))
|
||||
(should summaries)
|
||||
(should (= (length summaries) 1))
|
||||
(should (string= (ht-get (car summaries) "label") "read"))
|
||||
(should (= (ht-get (car summaries) "count") 1))
|
||||
(should (string= (ht-get (car summaries) "href") "/index?filter=read"))))
|
||||
(groups (ht-get model "groups")))
|
||||
(should groups)
|
||||
(should (= (length groups) 3)) ;; Fiction, Science Fiction, Non-Fiction
|
||||
(let ((labels (mapcar (lambda (g) (ht-get g "label")) groups)))
|
||||
(should (member "Fiction" labels))
|
||||
(should (member "Science Fiction" labels))
|
||||
(should (member "Non-Fiction" labels)))))
|
||||
|
||||
(ert-deftest spine-index-model-concise-includes-reading ()
|
||||
"Concise view includes READING group with all reading books."
|
||||
(ert-deftest spine-index-model-shelf-counts ()
|
||||
"Each shelf group has the correct number of books."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books))
|
||||
(groups (ht-get model "groups"))
|
||||
(reading-group (cl-find "reading" groups
|
||||
:key (lambda (g) (ht-get g "label"))
|
||||
:test #'string=)))
|
||||
(should reading-group)
|
||||
(should (= (ht-get reading-group "count") 1))
|
||||
(should (string= (ht-get (car (ht-get reading-group "books")) "title")
|
||||
"Use of Weapons"))))
|
||||
(groups (ht-get model "groups")))
|
||||
(dolist (g groups)
|
||||
(let ((label (ht-get g "label"))
|
||||
(count (ht-get g "count")))
|
||||
(cond
|
||||
((equal label "Fiction")
|
||||
(should (= count 4))
|
||||
(should (= (length (ht-get g "books")) 4)))
|
||||
((equal label "Science Fiction")
|
||||
(should (= count 1))
|
||||
(should (= (length (ht-get g "books")) 1)))
|
||||
((equal label "Non-Fiction")
|
||||
(should (= count 1))
|
||||
(should (= (length (ht-get g "books")) 1))))))))
|
||||
|
||||
(ert-deftest spine-index-model-concise-want-limited-to-five ()
|
||||
"Concise view limits WANT group to 5 books, sorted by :LAST_MODIFIED: desc."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books))
|
||||
(groups (ht-get model "groups"))
|
||||
(want-group (cl-find "on deck" groups
|
||||
:key (lambda (g) (ht-get g "label"))
|
||||
:test #'string=)))
|
||||
(should want-group)
|
||||
(let ((books (ht-get want-group "books")))
|
||||
(should (<= (length books) 5))
|
||||
(should (= (length books) 3))
|
||||
;; Piranesi (2026-06-01), Dune (2026-05-10), Left Hand (2026-04-01)
|
||||
(should (string= (ht-get (nth 0 books) "title") "Piranesi"))
|
||||
(should (string= (ht-get (nth 1 books) "title") "Dune"))
|
||||
(should (string= (ht-get (nth 2 books) "title") "The Left Hand of Darkness")))))
|
||||
|
||||
(ert-deftest spine-index-model-filter-all-shows-all-groups ()
|
||||
"filter=all returns all groups, no summary-groups."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books "all"))
|
||||
(groups (ht-get model "groups"))
|
||||
(summaries (ht-get model "summary_groups"))
|
||||
(group-labels (mapcar (lambda (g) (ht-get g "label")) groups)))
|
||||
(should-not summaries)
|
||||
(should (member "on deck" group-labels))
|
||||
(should (member "reading" group-labels))
|
||||
(should (member "read" group-labels))
|
||||
(should (= (length groups) 3))))
|
||||
|
||||
(ert-deftest spine-index-model-filter-read-returns-only-read ()
|
||||
"filter=read returns only the READ group."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books "read"))
|
||||
(ert-deftest spine-index-model-filters-by-shelf ()
|
||||
"filter=shelf-name shows only that shelf's books."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books "Fiction"))
|
||||
(groups (ht-get model "groups")))
|
||||
(should (= (length groups) 1))
|
||||
(should (string= (ht-get (car groups) "label") "read"))
|
||||
(should (= (ht-get (car groups) "count") 1))))
|
||||
(should (equal (ht-get (car groups) "label") "Fiction"))))
|
||||
|
||||
(ert-deftest spine-index-model-filter-want-returns-only-want ()
|
||||
"filter=want returns only the WANT group."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books "want"))
|
||||
(groups (ht-get model "groups")))
|
||||
(should (= (length groups) 1))
|
||||
(should (string= (ht-get (car groups) "label") "on deck"))
|
||||
(should (= (ht-get (car groups) "count") 3))))
|
||||
(ert-deftest spine-index-model-includes-all-shelves-in-nav ()
|
||||
"Shelf nav includes all shelves, including empties."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books))
|
||||
(shelf-nav (ht-get model "shelf_nav")))
|
||||
(should (= (length shelf-nav) 3))
|
||||
(should (member "Non-Fiction" (mapcar (lambda (n) (ht-get n "name")) shelf-nav)))))
|
||||
|
||||
(ert-deftest spine-index-model-invalid-filter-falls-back-to-concise ()
|
||||
"Unrecognised filter value behaves like nil (concise view)."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books "bogus"))
|
||||
(groups (ht-get model "groups"))
|
||||
(summaries (ht-get model "summary_groups"))
|
||||
(group-labels (mapcar (lambda (g) (ht-get g "label")) groups)))
|
||||
(should summaries)
|
||||
(should-not (member "read" group-labels))
|
||||
(should (member "reading" group-labels))
|
||||
(should (member "on deck" group-labels))))
|
||||
(ert-deftest spine-index-model-current-shelf ()
|
||||
"current_shelf is set when filter is active."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books "Science Fiction")))
|
||||
(should (equal (ht-get model "current_shelf") "Science Fiction"))))
|
||||
|
||||
(ert-deftest spine-index-model-includes-current-filter ()
|
||||
"Model includes current_filter key matching the filter argument."
|
||||
(should (not (ht-get (spine-index-model spine-index-model-test--books) "current_filter")))
|
||||
(should (equal (ht-get (spine-index-model spine-index-model-test--books "all") "current_filter") "all"))
|
||||
(should (equal (ht-get (spine-index-model spine-index-model-test--books "read") "current_filter") "read"))
|
||||
(should (equal (ht-get (spine-index-model spine-index-model-test--books "want") "current_filter") "want")))
|
||||
(ert-deftest spine-index-model-no-current-shelf-without-filter ()
|
||||
"current_shelf is nil when no filter."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books)))
|
||||
(should-not (ht-get model "current_shelf"))))
|
||||
|
||||
(ert-deftest spine-index-model-total-and-shelf-count ()
|
||||
"Titlebar shows correct totals."
|
||||
(let* ((model (spine-index-model spine-index-model-test--books)))
|
||||
(should (= (ht-get model "total_books") 6))
|
||||
(should (= (ht-get model "shelf_count") 3))))
|
||||
|
||||
Reference in New Issue
Block a user