aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test-pearl-favorites.el12
-rw-r--r--tests/test-pearl-menu.el2
-rw-r--r--tests/test-pearl-single-issue.el117
3 files changed, 127 insertions, 4 deletions
diff --git a/tests/test-pearl-favorites.el b/tests/test-pearl-favorites.el
index 3f1452f..cb229b6 100644
--- a/tests/test-pearl-favorites.el
+++ b/tests/test-pearl-favorites.el
@@ -160,13 +160,17 @@ string -- the favorites query selects customView.name for exactly this."
(let ((s (pearl--favorite->source (test-pearl-fav--norm 'user "user-1" "Vrezh"))))
(should (equal '(:assignee-id "user-1" :open t) (plist-get s :filter)))))
-(ert-deftest test-pearl-favorite->source-issue-is-browser ()
- "Issue favorites are browser-only in v1 (no source)."
+(ert-deftest test-pearl-favorite->source-issue-renders-in-buffer ()
+ "An issue favorite resolves to a `:type issue' source, rendered in-buffer
+\(not the v1 browser punt). The identifier becomes the source name."
(let ((s (pearl--favorite->source
(append (test-pearl-fav--norm 'issue "iss-1" "Some bug" "https://linear.app/x/issue/ENG-1")
(list :identifier "ENG-1")))))
- (should (plist-get s :browser))
- (should (string= "https://linear.app/x/issue/ENG-1" (plist-get s :url)))))
+ (should-not (plist-get s :browser))
+ (should (eq 'issue (plist-get s :type)))
+ (should (string= "iss-1" (plist-get s :id)))
+ (should (string= "ENG-1" (plist-get s :identifier)))
+ (should (string= "ENG-1" (plist-get s :name)))))
(ert-deftest test-pearl-favorite->source-other-is-browser ()
"An unknown-kind favorite is browser-only."
diff --git a/tests/test-pearl-menu.el b/tests/test-pearl-menu.el
index d939a9e..1795a41 100644
--- a/tests/test-pearl-menu.el
+++ b/tests/test-pearl-menu.el
@@ -79,6 +79,8 @@ menu entry that still points at it fails here."
pearl-set-default-view
;; fetch the full comment thread for the issue at point
pearl-fetch-all-comments
+ ;; single-issue source: open one issue by identifier
+ pearl-open-issue-by-id
;; view-shaping commands added to the Views group
pearl-set-sort
pearl-set-grouping
diff --git a/tests/test-pearl-single-issue.el b/tests/test-pearl-single-issue.el
new file mode 100644
index 0000000..a686ea5
--- /dev/null
+++ b/tests/test-pearl-single-issue.el
@@ -0,0 +1,117 @@
+;;; test-pearl-single-issue.el --- Tests for the single-issue source -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2026 Craig Jennings
+
+;; Author: Craig Jennings <c@cjennings.net>
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for the single-issue source: `pearl--issue-source' (id/identifier ->
+;; source plist), the `#+LINEAR-SOURCE' round-trip for that plist,
+;; `pearl--fetch-and-render-issue' (fetch one issue and render it like every
+;; other source), and `pearl-open-issue-by-id' (the jump-by-identifier command).
+;; The async fetch and the render boundary are stubbed at their seams.
+
+;;; Code:
+
+(require 'test-bootstrap (expand-file-name "test-bootstrap.el"))
+
+;;; pearl--issue-source
+
+(ert-deftest test-pearl-issue-source-builds-plist ()
+ "An id + identifier builds a `:type issue' source named by the identifier."
+ (let ((s (pearl--issue-source "u1" "ENG-7")))
+ (should (eq 'issue (plist-get s :type)))
+ (should (string= "u1" (plist-get s :id)))
+ (should (string= "ENG-7" (plist-get s :identifier)))
+ (should (string= "ENG-7" (plist-get s :name)))))
+
+(ert-deftest test-pearl-issue-source-name-falls-back-to-id ()
+ "With no identifier the source name falls back to the id, never nil."
+ (let ((s (pearl--issue-source "u1" nil)))
+ (should (string= "u1" (plist-get s :name)))))
+
+(ert-deftest test-pearl-issue-source-round-trips-through-header ()
+ "The issue source survives `#+LINEAR-SOURCE' serialization and read-back."
+ (let* ((s (pearl--issue-source "u1" "ENG-7"))
+ (back (car (read-from-string (pearl--linear-source-string s)))))
+ (should (equal s back))))
+
+;;; pearl--fetch-and-render-issue
+
+(ert-deftest test-pearl-fetch-and-render-issue-renders-one ()
+ "A fetched node renders through the shared query-result boundary as one issue,
+tagged with an issue source built from the node's own id and identifier."
+ (let ((node '((id . "u1") (identifier . "ENG-7") (title . "A bug")))
+ captured)
+ (cl-letf (((symbol-function 'pearl--fetch-issue-async)
+ (lambda (_ref cb) (funcall cb node)))
+ ((symbol-function 'pearl--render-query-result)
+ (lambda (result source) (setq captured (list result source)))))
+ (pearl--fetch-and-render-issue "ENG-7")
+ (should captured)
+ (let ((result (nth 0 captured))
+ (source (nth 1 captured)))
+ (should (equal (list node) (pearl--query-result-issues result)))
+ (should (eq 'issue (plist-get source :type)))
+ (should (string= "u1" (plist-get source :id)))
+ (should (string= "ENG-7" (plist-get source :identifier)))))))
+
+(ert-deftest test-pearl-fetch-and-render-issue-missing-does-not-render ()
+ "A `:missing' result reports and renders nothing (no buffer rewrite)."
+ (let (rendered)
+ (cl-letf (((symbol-function 'pearl--fetch-issue-async)
+ (lambda (_ref cb) (funcall cb :missing)))
+ ((symbol-function 'pearl--render-query-result)
+ (lambda (&rest _) (setq rendered t)))
+ ((symbol-function 'message) (lambda (&rest _) nil)))
+ (pearl--fetch-and-render-issue "ENG-404")
+ (should-not rendered))))
+
+(ert-deftest test-pearl-fetch-and-render-issue-error-does-not-render ()
+ "An `:error' result reports and renders nothing."
+ (let (rendered)
+ (cl-letf (((symbol-function 'pearl--fetch-issue-async)
+ (lambda (_ref cb) (funcall cb :error)))
+ ((symbol-function 'pearl--render-query-result)
+ (lambda (&rest _) (setq rendered t)))
+ ((symbol-function 'message) (lambda (&rest _) nil)))
+ (pearl--fetch-and-render-issue "ENG-7")
+ (should-not rendered))))
+
+;;; pearl-open-issue-by-id
+
+(ert-deftest test-pearl-open-issue-by-id-forwards-trimmed-ref ()
+ "The command trims the typed ref and forwards it to the fetch/render path."
+ (let (got)
+ (cl-letf (((symbol-function 'pearl--require-account-context) #'ignore)
+ ((symbol-function 'pearl--progress) (lambda (&rest _) nil))
+ ((symbol-function 'pearl--fetch-and-render-issue)
+ (lambda (ref) (setq got ref))))
+ (pearl-open-issue-by-id " ENG-7 ")
+ (should (string= "ENG-7" got)))))
+
+(ert-deftest test-pearl-open-issue-by-id-rejects-empty ()
+ "An empty/whitespace identifier is a `user-error', not a fetch."
+ (let (fetched)
+ (cl-letf (((symbol-function 'pearl--require-account-context) #'ignore)
+ ((symbol-function 'pearl--fetch-and-render-issue)
+ (lambda (&rest _) (setq fetched t))))
+ (should-error (pearl-open-issue-by-id " ") :type 'user-error)
+ (should-not fetched))))
+
+(provide 'test-pearl-single-issue)
+;;; test-pearl-single-issue.el ends here