aboutsummaryrefslogtreecommitdiff
path: root/tests/test-pearl-save.el
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-pearl-save.el')
-rw-r--r--tests/test-pearl-save.el75
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/test-pearl-save.el b/tests/test-pearl-save.el
index 1f4f273..22df84e 100644
--- a/tests/test-pearl-save.el
+++ b/tests/test-pearl-save.el
@@ -153,6 +153,21 @@
(org-entry-put nil "LINEAR-STATE-ID" "s2")
(should (plist-get (pearl--issue-dirty-fields) :state))))
+(ert-deftest test-pearl-dirty-fields-state-keyword-cycle ()
+ "Cycling the TODO keyword away from the synced state-name slug marks state dirty,
+even when the explicit state id still matches its baseline."
+ (test-pearl-save--in-rendered (test-pearl-save--structured-issue)
+ (org-back-to-heading t)
+ (let ((org-after-todo-state-change-hook nil))
+ (org-todo "DONE")) ; TODO -> DONE, id untouched
+ (should (plist-get (pearl--issue-dirty-fields) :state))))
+
+(ert-deftest test-pearl-dirty-fields-state-fresh-keyword-not-dirty ()
+ "A freshly rendered state (keyword equals the state-name slug) is not state dirty."
+ (test-pearl-save--in-rendered (test-pearl-save--structured-issue)
+ (org-back-to-heading t)
+ (should-not (plist-get (pearl--issue-dirty-fields) :state))))
+
(ert-deftest test-pearl-dirty-fields-assignee-change ()
"An assignee id different from the synced baseline marks assignee dirty."
(test-pearl-save--in-rendered (test-pearl-save--structured-issue)
@@ -495,6 +510,66 @@ skipped (the remote push already landed), not signal."
(should (string= "s2" pushed))
(should (string= "s2" (org-entry-get marker "LINEAR-STATE-ID-SYNCED")))))))
+(ert-deftest test-pearl-save-state-keyword-cycle-resolves-and-pushes ()
+ "A keyword-cycled state (id unmoved) resolves the keyword to its team state id
+by slug match, pushes that id, and writes the resolved name/id/baseline."
+ (test-pearl-save--in-rendered
+ '(:id "u" :identifier "ENG-1" :title "t" :priority 2
+ :state (:id "s1" :name "Todo") :description "body")
+ (goto-char (point-min))
+ (insert "#+TODO: TODO IN-PROGRESS | DONE\n")
+ (org-mode) ; re-init so the keywords take
+ (goto-char (point-min))
+ (re-search-forward "ENG-1")
+ (org-back-to-heading t)
+ (org-entry-put nil "LINEAR-TEAM-ID" "team-1")
+ (progn
+ (let ((org-after-todo-state-change-hook nil))
+ (org-todo "IN-PROGRESS")) ; cycle keyword, leave id = s1
+ (let ((marker (point-marker)) outcome pushed)
+ (cl-letf (((symbol-function 'pearl--team-states)
+ (lambda (_tid)
+ '(((id . "s1") (name . "Todo") (type . "unstarted") (position . 1.0))
+ ((id . "s2") (name . "In Progress") (type . "started") (position . 2.0)))))
+ ((symbol-function 'pearl--fetch-issue-async)
+ (lambda (_id cb) (funcall cb '((state (id . "s1") (name . "Todo"))))))
+ ((symbol-function 'pearl--update-issue-async)
+ (lambda (_id input cb)
+ (setq pushed (cdr (assoc "stateId" input)))
+ (funcall cb '(:success t)))))
+ (pearl--save-state-field marker (lambda (o) (setq outcome o)))
+ (should (eq 'pushed (plist-get outcome :status)))
+ (should (string= "s2" pushed))
+ (should (string= "s2" (org-entry-get marker "LINEAR-STATE-ID")))
+ (should (string= "In Progress" (org-entry-get marker "LINEAR-STATE-NAME")))
+ (should (string= "s2" (org-entry-get marker "LINEAR-STATE-ID-SYNCED"))))))))
+
+(ert-deftest test-pearl-save-state-keyword-cycle-unknown-keyword-skips ()
+ "A keyword no team state slugifies to cannot be resolved, so the save is skipped
+with no push."
+ (test-pearl-save--in-rendered
+ '(:id "u" :identifier "ENG-1" :title "t" :priority 2
+ :state (:id "s1" :name "Todo") :description "body")
+ (goto-char (point-min))
+ (insert "#+TODO: TODO BLOCKED | DONE\n")
+ (org-mode)
+ (goto-char (point-min))
+ (re-search-forward "ENG-1")
+ (org-back-to-heading t)
+ (org-entry-put nil "LINEAR-TEAM-ID" "team-1")
+ (progn
+ (let ((org-after-todo-state-change-hook nil))
+ (org-todo "BLOCKED")) ; no team state slugifies to BLOCKED
+ (let ((marker (point-marker)) outcome (pushed :none))
+ (cl-letf (((symbol-function 'pearl--team-states)
+ (lambda (_tid)
+ '(((id . "s1") (name . "Todo") (type . "unstarted") (position . 1.0)))))
+ ((symbol-function 'pearl--update-issue-async)
+ (lambda (_id _input cb) (setq pushed :called) (funcall cb '(:success t)))))
+ (pearl--save-state-field marker (lambda (o) (setq outcome o)))
+ (should (eq 'skipped (plist-get outcome :status)))
+ (should (eq :none pushed)))))))
+
(ert-deftest test-pearl-save-labels-clean-push-advances-baseline ()
"A changed label set with an unmoved remote pushes labelIds and advances the baseline."
(test-pearl-save--in-rendered