diff options
Diffstat (limited to 'tests/test-pearl-saved-query-sync.el')
| -rw-r--r-- | tests/test-pearl-saved-query-sync.el | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/tests/test-pearl-saved-query-sync.el b/tests/test-pearl-saved-query-sync.el index 7a40566..ebf4622 100644 --- a/tests/test-pearl-saved-query-sync.el +++ b/tests/test-pearl-saved-query-sync.el @@ -375,5 +375,133 @@ team-key lookups." (should captured-query) (should (string-match-p "key" captured-query))))) +;;; pearl--customview-delete-async + +(ert-deftest test-pearl-customview-delete-async-success () + "A successful `customViewDelete' invokes the callback with `:success' t." + (testutil-linear-with-response + '((data (customViewDelete (success . t)))) + (let (result) + (pearl--customview-delete-async "view-uuid" (lambda (r) (setq result r))) + (should (eq t (plist-get result :success)))))) + +(ert-deftest test-pearl-customview-delete-async-failure () + "A non-success `customViewDelete' invokes the callback with `:success' nil." + (testutil-linear-with-response + '((data (customViewDelete (success . :json-false)))) + (let (result) + (pearl--customview-delete-async "view-uuid" (lambda (r) (setq result r))) + (should-not (plist-get result :success))))) + +;;; pearl-delete-saved-query — synced-entry second-stage prompt + +(defun test-pearl--make-yes-no-stub (answers) + "Return a `yes-or-no-p' replacement that returns each ANSWERS in order. +Each call pops the head; the test fails the call sequence assertion if +more prompts fire than answers were prepared for." + (let ((remaining answers)) + (lambda (&rest _) + (if remaining + (pop remaining) + (error "Unexpected extra yes-or-no-p prompt"))))) + +(ert-deftest test-pearl-delete-saved-query-synced-yes-yes-calls-customview-delete () + "Synced entry, both prompts yes: customViewDelete fires and the local entry is removed." + (let ((pearl-saved-queries + (copy-tree '(("Q" :filter (:open t) + :linear-view-id "view-uuid" + :linear-view-team-id nil + :linear-view-shared :json-false)))) + (delete-called-with nil)) + (cl-letf (((symbol-function 'yes-or-no-p) + (test-pearl--make-yes-no-stub '(t t))) + ((symbol-function 'customize-save-variable) (lambda (_ _) nil)) + ((symbol-function 'pearl--progress) (lambda (&rest _) nil)) + ((symbol-function 'message) (lambda (&rest _) nil)) + ((symbol-function 'pearl--customview-delete-async) + (lambda (vid cb) + (setq delete-called-with vid) + (funcall cb (list :success t))))) + (pearl-delete-saved-query "Q") + (should (equal "view-uuid" delete-called-with)) + (should-not (assoc "Q" pearl-saved-queries))))) + +(ert-deftest test-pearl-delete-saved-query-synced-yes-no-unlinks-only () + "Synced entry, first prompt yes second prompt no: local entry removed, customViewDelete not called." + (let ((pearl-saved-queries + (copy-tree '(("Q" :filter (:open t) + :linear-view-id "view-uuid")))) + (delete-called nil)) + (cl-letf (((symbol-function 'yes-or-no-p) + (test-pearl--make-yes-no-stub '(t nil))) + ((symbol-function 'customize-save-variable) (lambda (_ _) nil)) + ((symbol-function 'pearl--progress) (lambda (&rest _) nil)) + ((symbol-function 'message) (lambda (&rest _) nil)) + ((symbol-function 'pearl--customview-delete-async) + (lambda (_ _) (setq delete-called t)))) + (pearl-delete-saved-query "Q") + (should-not delete-called) + (should-not (assoc "Q" pearl-saved-queries))))) + +(ert-deftest test-pearl-delete-saved-query-synced-api-failure-then-delete-anyway () + "Synced entry, customViewDelete fails, user accepts delete-anyway prompt: local removed, message names the orphan id." + (let ((pearl-saved-queries + (copy-tree '(("Q" :filter (:open t) + :linear-view-id "ORPHAN-UUID")))) + (last-message nil)) + (cl-letf (((symbol-function 'yes-or-no-p) + (test-pearl--make-yes-no-stub '(t t t))) ; delete? + also-on-Linear? + delete-anyway? + ((symbol-function 'customize-save-variable) (lambda (_ _) nil)) + ((symbol-function 'pearl--progress) (lambda (&rest _) nil)) + ((symbol-function 'message) + (lambda (fmt &rest args) + (setq last-message (apply #'format fmt args)))) + ((symbol-function 'pearl--customview-delete-async) + (lambda (_ cb) + (funcall cb (list :success nil :error "permission denied"))))) + (pearl-delete-saved-query "Q") + (should-not (assoc "Q" pearl-saved-queries)) + (should (string-match-p "ORPHAN-UUID" last-message)) + (should (string-match-p "orphan" last-message))))) + +(ert-deftest test-pearl-delete-saved-query-synced-api-failure-then-keep () + "Synced entry, customViewDelete fails, user rejects delete-anyway: both kept untouched. +Verifies the API call actually fires (so the keep branch only runs when the +delete-anyway prompt explicitly declines), guarding against a future refactor +that silently routes to the unlink branch and skips the API call." + (let ((pearl-saved-queries + (copy-tree '(("Q" :filter (:open t) + :linear-view-id "view-uuid")))) + (delete-called-with nil)) + (cl-letf (((symbol-function 'yes-or-no-p) + (test-pearl--make-yes-no-stub '(t t nil))) ; yes / yes / no on delete-anyway + ((symbol-function 'customize-save-variable) (lambda (_ _) nil)) + ((symbol-function 'pearl--progress) (lambda (&rest _) nil)) + ((symbol-function 'message) (lambda (&rest _) nil)) + ((symbol-function 'pearl--customview-delete-async) + (lambda (vid cb) + (setq delete-called-with vid) + (funcall cb (list :success nil :error "permission denied"))))) + (pearl-delete-saved-query "Q") + (should (equal "view-uuid" delete-called-with)) + (should (assoc "Q" pearl-saved-queries))))) + +(ert-deftest test-pearl-delete-saved-query-local-only-entry-unchanged-behavior () + "Local-only entry (no `:linear-view-id'): one yes-or-no-p, no second prompt, no API call." + (let ((pearl-saved-queries + (copy-tree '(("Q" :filter (:open t))))) + (delete-called nil) + (prompt-count 0)) + (cl-letf (((symbol-function 'yes-or-no-p) + (lambda (&rest _) (cl-incf prompt-count) t)) + ((symbol-function 'customize-save-variable) (lambda (_ _) nil)) + ((symbol-function 'message) (lambda (&rest _) nil)) + ((symbol-function 'pearl--customview-delete-async) + (lambda (_ _) (setq delete-called t)))) + (pearl-delete-saved-query "Q") + (should (= 1 prompt-count)) + (should-not delete-called) + (should-not (assoc "Q" pearl-saved-queries))))) + (provide 'test-pearl-saved-query-sync) ;;; test-pearl-saved-query-sync.el ends here |
