aboutsummaryrefslogtreecommitdiff
path: root/tests/test-pearl-views.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-03 00:11:25 -0500
committerCraig Jennings <c@cjennings.net>2026-06-03 00:11:25 -0500
commit8acc99d88527a9dfecf7ebceb858f344819d10c3 (patch)
tree025136d5f9dcce9641d28b19ec9113fb38e05a13 /tests/test-pearl-views.el
parent68d51b341bccc72c7b01f547e43ce90a76729244 (diff)
downloadpearl-8acc99d88527a9dfecf7ebceb858f344819d10c3.tar.gz
pearl-8acc99d88527a9dfecf7ebceb858f344819d10c3.zip
fix(views): rebuild Linear view URLs instead of querying the missing url field
Linear's CustomView type has no url field. Three GraphQL selections requested it (the custom-views list query and both the create and update mutation payloads), so each of those requests returned HTTP 400 and pearl got nil back. Running a Linear view came up with an empty picker, and publishing or updating a local view to Linear failed silently. The test suite stayed green because the view tests mocked a url field the real API never returns. I dropped url from all three selections. The workspace urlKey is now fetched once and cached, and a view's web URL is rebuilt as https://linear.app/<urlKey>/view/<view-id>, the shape Linear's own favorite URLs use (the full view UUID, not the slug id). pearl-open-current-view-in-linear keeps working, and when the urlKey is unavailable it degrades to nil so the link builder can't throw. That also stops a urlKey hiccup right after a successful publish from aborting the record step and orphaning the new view. I added regression locks asserting neither the list query nor the mutation payload selection requests url, since the field name is the schema contract that broke.
Diffstat (limited to 'tests/test-pearl-views.el')
-rw-r--r--tests/test-pearl-views.el49
1 files changed, 46 insertions, 3 deletions
diff --git a/tests/test-pearl-views.el b/tests/test-pearl-views.el
index a750ae0..e22a6d3 100644
--- a/tests/test-pearl-views.el
+++ b/tests/test-pearl-views.el
@@ -55,13 +55,52 @@
(cl-incf calls)
(funcall (plist-get args :success) :data
'((data (customViews
- (nodes . [((id . "v1") (name . "My View") (url . "https://x"))])
+ (nodes . [((id . "v1") (name . "My View"))])
(pageInfo (hasNextPage . :json-false)))))))))
(let ((views (pearl--custom-views)))
(should (= 1 (length views)))
(pearl--custom-views)
(should (= 1 calls))))))
+(ert-deftest test-pearl-custom-views-query-omits-url ()
+ "The Custom Views list query must not select the unsupported `url' field.
+Linear's `CustomView' type has no `url'; requesting it 400s the whole query
+and leaves the run-view picker empty (the 2026-06-02 regression)."
+ (should-not (string-match-p "\\burl\\b" (pearl--custom-views-query))))
+
+;;; --org-url-key (cached) and --view-url (reconstructed)
+
+(ert-deftest test-pearl-org-url-key-caches ()
+ "The workspace url key is fetched once and served from cache."
+ (let ((pearl-api-key "test-key")
+ (pearl--cache-org-url-key nil)
+ (calls 0))
+ (cl-letf (((symbol-function 'request)
+ (lambda (_url &rest args)
+ (cl-incf calls)
+ (funcall (plist-get args :success) :data
+ '((data (organization (urlKey . "deepsat"))))))))
+ (should (string= "deepsat" (pearl--org-url-key)))
+ (pearl--org-url-key)
+ (should (= 1 calls)))))
+
+(ert-deftest test-pearl-view-url-builds-from-urlkey ()
+ "A view's web URL is reconstructed from the workspace url key and view id."
+ (cl-letf (((symbol-function 'pearl--org-url-key) (lambda (&optional _) "deepsat")))
+ (should (string= "https://linear.app/deepsat/view/abc123"
+ (pearl--view-url "abc123")))))
+
+(ert-deftest test-pearl-view-url-nil-when-no-urlkey ()
+ "With no workspace url key, the view URL is nil so callers degrade gracefully."
+ (cl-letf (((symbol-function 'pearl--org-url-key) (lambda (&optional _) nil)))
+ (should-not (pearl--view-url "abc123"))))
+
+(ert-deftest test-pearl-view-url-nil-when-empty-view-id ()
+ "A nil or empty view id yields no URL rather than a malformed link."
+ (cl-letf (((symbol-function 'pearl--org-url-key) (lambda (&optional _) "deepsat")))
+ (should-not (pearl--view-url nil))
+ (should-not (pearl--view-url ""))))
+
;;; run-view
(ert-deftest test-pearl-run-view-renders-with-view-source ()
@@ -69,7 +108,10 @@
(let ((ran-id nil) (rendered-source nil))
(cl-letf (((symbol-function 'pearl--custom-views)
(lambda (&optional _force)
- '(((id . "v1") (name . "My View") (url . "https://linear.app/view/v1")))))
+ ;; Nodes carry no `url' -- Linear's CustomView has none; the
+ ;; source URL is reconstructed from the workspace url key.
+ '(((id . "v1") (name . "My View")))))
+ ((symbol-function 'pearl--org-url-key) (lambda (&optional _) "deepsat"))
((symbol-function 'pearl--query-view-async)
(lambda (id cb) (setq ran-id id)
(funcall cb (pearl--make-query-result 'ok :issues nil))))
@@ -79,7 +121,8 @@
(should (string= "v1" ran-id))
(should (eq 'view (plist-get rendered-source :type)))
(should (string= "v1" (plist-get rendered-source :id)))
- (should (string= "https://linear.app/view/v1" (plist-get rendered-source :url))))))
+ (should (string= "https://linear.app/deepsat/view/v1"
+ (plist-get rendered-source :url))))))
;;; refresh-current-view, view branch