;;; spine-index-model-test.el — ERT tests for spine-index-model with filter (require 'ert) (require 'cl-lib) (setq spine-skip-server-start t) (setq spine-org-file (expand-file-name "sample-books.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))) (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." (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")))) (ert-deftest spine-index-model-concise-includes-reading () "Concise view includes READING group with all reading 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")))) (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")) (groups (ht-get model "groups"))) (should (= (length groups) 1)) (should (string= (ht-get (car groups) "label") "read")) (should (= (ht-get (car groups) "count") 1)))) (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-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-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")))