diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-26 00:31:44 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-26 00:31:44 -0500 |
| commit | 8c42615b09471db089d81b7d702c60917fb85c79 (patch) | |
| tree | 34b847a3e92658ad5c6d1cc6f566ff6622c14495 /tests/test-pearl-todo-keywords.el | |
| parent | 5ee0bdcc4a1bd4b935973be7201b20380ec8cb80 (diff) | |
| download | pearl-8c42615b09471db089d81b7d702c60917fb85c79.tar.gz pearl-8c42615b09471db089d81b7d702c60917fb85c79.zip | |
feat: resolve a cycled TODO keyword to its Linear state at save
Cycling a ticket's TODO keyword (C-c C-t) now counts as a state edit. The dirty scan gains a keyword-cycle arm: state is dirty when the explicit id moved off its baseline (the picker arm, as before) or when the keyword diverged from the synced state name's slug. At save, the picker arm pushes the explicit id; the keyword-cycle arm resolves the keyword to a team state id by slug match, first by position, and pushes that. A keyword no team state matches is reported skipped rather than guessed.
set-heading-state now slugifies the keyword instead of the static-map lookup, so the picker writes the same keyword the renderer derives. Without that, a picker edit to a non-standard state would read as permanently cycled. That retires pearl--map-linear-state-to-org, whose only caller this was, and its tests.
Diffstat (limited to 'tests/test-pearl-todo-keywords.el')
| -rw-r--r-- | tests/test-pearl-todo-keywords.el | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/tests/test-pearl-todo-keywords.el b/tests/test-pearl-todo-keywords.el index 281beea..0555a4e 100644 --- a/tests/test-pearl-todo-keywords.el +++ b/tests/test-pearl-todo-keywords.el @@ -150,5 +150,27 @@ ;; SHIPPED is an org done-keyword, so it lands on the done side (should (re-search-forward "^#\\+TODO: *\\| SHIPPED$" nil t))))) +;;; --resolve-keyword-to-state (keyword -> team state id, save-time) + +(ert-deftest test-pearl-resolve-keyword-to-state-collision-first-by-position () + "When two state names slugify to the same keyword, the lower position wins." + (cl-letf (((symbol-function 'pearl--team-states) + (lambda (_tid) + '(((id . "s-hi") (name . "Dev Review") (type . "started") (position . 5.0)) + ((id . "s-lo") (name . "Dev-Review") (type . "started") (position . 2.0)))))) + (let ((r (pearl--resolve-keyword-to-state "DEV-REVIEW" "t1"))) + (should (string= "s-lo" (plist-get r :id))) + (should (string= "Dev-Review" (plist-get r :name))) + (should (string= "started" (plist-get r :type)))))) + +(ert-deftest test-pearl-resolve-keyword-to-state-no-match-or-empty-returns-nil () + "A keyword no state slugifies to yields nil, as does an empty/failed fetch." + (cl-letf (((symbol-function 'pearl--team-states) + (lambda (_tid) + '(((id . "s1") (name . "Todo") (type . "unstarted") (position . 1.0)))))) + (should-not (pearl--resolve-keyword-to-state "BLOCKED" "t1"))) + (cl-letf (((symbol-function 'pearl--team-states) (lambda (_tid) nil))) + (should-not (pearl--resolve-keyword-to-state "TODO" "t1")))) + (provide 'test-pearl-todo-keywords) ;;; test-pearl-todo-keywords.el ends here |
