aboutsummaryrefslogtreecommitdiff
path: root/tests/test-pearl-todo-keywords.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-25 22:35:12 -0500
committerCraig Jennings <c@cjennings.net>2026-05-25 22:35:12 -0500
commit6924c27963ddd25f91ea3a1a02d462f0badabfc4 (patch)
tree9e87d325ee4155d9fce20da1dd9b17155acbaf29 /tests/test-pearl-todo-keywords.el
parent504133e600a197b50f05d3916264433ee9e4cb12 (diff)
downloadpearl-6924c27963ddd25f91ea3a1a02d462f0badabfc4.tar.gz
pearl-6924c27963ddd25f91ea3a1a02d462f0badabfc4.zip
feat(render): rebuild the derived #+TODO header on merge refresh
A same-source refresh updates issue subtrees in place and keeps retained dirty subtrees the merge skips, so the #+TODO line has to stay honest across it -- a refresh can surface a new state, and a kept heading's keyword must still be declared. pearl--update-derived-todo-header scans the final displayed buffer (every LINEAR-ID heading's TODO keyword + :LINEAR-STATE-TYPE: drawer), unions that with the fetched teams' states, and rewrites the line via pearl--derive-todo-line. Scanning the final buffer rather than the fetched issue list is what covers the retained subtrees. A legacy heading with no state-type drawer is classified by org-done-keywords. pearl--merge-query-result calls it after the merge, beside the source-header update. The merge and integration test setups stub pearl--team-states so the gather stays network-free.
Diffstat (limited to 'tests/test-pearl-todo-keywords.el')
-rw-r--r--tests/test-pearl-todo-keywords.el29
1 files changed, 29 insertions, 0 deletions
diff --git a/tests/test-pearl-todo-keywords.el b/tests/test-pearl-todo-keywords.el
index b941b26..281beea 100644
--- a/tests/test-pearl-todo-keywords.el
+++ b/tests/test-pearl-todo-keywords.el
@@ -121,5 +121,34 @@
(let ((out (pearl--build-org-content '() '(:type filter :name "X" :filter nil) nil nil)))
(should (string-match-p "^#\\+TODO: TODO IN-PROGRESS IN-REVIEW BACKLOG BLOCKED \\| DONE$" out))))
+;;; --update-derived-todo-header (merge-refresh, final-buffer scan)
+
+(ert-deftest test-pearl-update-derived-todo-header-covers-buffer-headings ()
+ "The header rebuild scans the final buffer so every visible heading is declared."
+ (let ((org-todo-keywords '((sequence "TODO" "IN-PROGRESS" "|" "DONE"))))
+ (with-temp-buffer
+ (insert "#+STARTUP: show3levels\n#+TODO: TODO | DONE\n\n"
+ "* View\n"
+ "** IN-PROGRESS Issue A\n:PROPERTIES:\n:LINEAR-ID: a\n:LINEAR-STATE-TYPE: started\n:END:\n"
+ "** DONE Issue B\n:PROPERTIES:\n:LINEAR-ID: b\n:LINEAR-STATE-TYPE: completed\n:END:\n")
+ (org-mode)
+ ;; no team states passed -- the rebuild comes purely from the buffer scan
+ (pearl--update-derived-todo-header '())
+ (goto-char (point-min))
+ (should (re-search-forward "^#\\+TODO: IN-PROGRESS \\| DONE$" nil t)))))
+
+(ert-deftest test-pearl-update-derived-todo-header-classifies-legacy-by-done-keyword ()
+ "A retained heading with no STATE-TYPE drawer is classified by org-done-keywords."
+ (let ((org-todo-keywords '((sequence "TODO" "|" "SHIPPED"))))
+ (with-temp-buffer
+ (insert "#+STARTUP: show3levels\n#+TODO: TODO | SHIPPED\n\n"
+ "* View\n"
+ "** SHIPPED Old Issue\n:PROPERTIES:\n:LINEAR-ID: a\n:END:\n") ; no STATE-TYPE
+ (org-mode)
+ (pearl--update-derived-todo-header '())
+ (goto-char (point-min))
+ ;; SHIPPED is an org done-keyword, so it lands on the done side
+ (should (re-search-forward "^#\\+TODO: *\\| SHIPPED$" nil t)))))
+
(provide 'test-pearl-todo-keywords)
;;; test-pearl-todo-keywords.el ends here