aboutsummaryrefslogtreecommitdiff
path: root/tests/test-pearl-save.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-25 21:06:42 -0500
committerCraig Jennings <c@cjennings.net>2026-05-25 21:06:42 -0500
commitf9841539b3adb192d0c15470fa9c31d6cbbdf447 (patch)
tree490433f58ccb3106e72b6685a7b3d99b3699788a /tests/test-pearl-save.el
parent684068a81103e9a9dace2f5cc6fd49edc1f01ab1 (diff)
downloadpearl-f9841539b3adb192d0c15470fa9c31d6cbbdf447.tar.gz
pearl-f9841539b3adb192d0c15470fa9c31d6cbbdf447.zip
feat(save): reconcile structured fields in save-issue and save-all
The four structured savers now run from the save engine. pearl--save-field-thunks queues a priority / state / assignee / labels saver for each dirty structured field alongside title, description, and comments, so save-issue and save-all reconcile a changed cookie, keyword-picker id, assignee, or label set at save time like any other edit. save-all's confirm prompt and the dirty-scan gate both count the structured fields, and a new pearl--issue-has-dirty-fields-p replaces the title/description/comment check that was duplicated in save-issue and the file-wide scan. This is the commit that turns the engine on. The old immediate-push setters still exist until the next commit retires them, so for this one commit both paths are live — the setter cutover and the org-sync removal follow.
Diffstat (limited to 'tests/test-pearl-save.el')
-rw-r--r--tests/test-pearl-save.el37
1 files changed, 37 insertions, 0 deletions
diff --git a/tests/test-pearl-save.el b/tests/test-pearl-save.el
index 8df7b3b..65f742a 100644
--- a/tests/test-pearl-save.el
+++ b/tests/test-pearl-save.el
@@ -676,5 +676,42 @@ description hash is left untouched and the title still saved."
;; only the still-valid second issue saved
(should (= 1 (length desc-pushes)))))))
+;;; structured fields wired into save-issue / save-all (save-model v2)
+
+(ert-deftest test-pearl-save-issue-routes-dirty-structured-field ()
+ "save-issue picks up a dirty structured field (assignee) and pushes it."
+ (test-pearl-save--in-rendered
+ '(:id "u" :identifier "ENG-1" :title "t" :priority 2
+ :state (:id "s1" :name "Todo") :assignee (:id "a1" :name "Craig")
+ :description "body")
+ (org-back-to-heading t)
+ (org-entry-put nil "LINEAR-ASSIGNEE-ID" "a2") ; the picker chose a new assignee
+ (let (pushed-input)
+ (cl-letf (((symbol-function 'pearl--fetch-issue-async)
+ (lambda (_id cb) (funcall cb '((assignee (id . "a1") (name . "Craig"))))))
+ ((symbol-function 'pearl--update-issue-async)
+ (lambda (_id input cb)
+ (setq pushed-input input) (funcall cb '(:success t)))))
+ (pearl-save-issue)
+ (should (string= "a2" (cdr (assoc "assigneeId" pushed-input))))
+ (should (string= "a2" (org-entry-get nil "LINEAR-ASSIGNEE-ID-SYNCED")))))))
+
+(ert-deftest test-pearl-save-all-counts-and-prompt-structured-fields ()
+ "save-all tallies and names priority / state / assignee / labels in the prompt."
+ (let* ((scan (list (cons (make-marker) '(:priority t))
+ (cons (make-marker) '(:state t :labels t :assignee t))))
+ (counts (pearl--save-all-counts scan nil)))
+ (should (= 2 (plist-get counts :issues)))
+ (should (= 1 (plist-get counts :priorities)))
+ (should (= 1 (plist-get counts :states)))
+ (should (= 1 (plist-get counts :assignees)))
+ (should (= 1 (plist-get counts :labels)))
+ (let ((prompt (pearl--save-all-prompt counts)))
+ (should (string-match-p "1 priority" prompt))
+ (should (string-match-p "1 state" prompt))
+ (should (string-match-p "1 assignee" prompt))
+ (should (string-match-p "1 label" prompt))
+ (should (string-match-p "Save 4 fields across 2 issues" prompt)))))
+
(provide 'test-pearl-save)
;;; test-pearl-save.el ends here