diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-24 13:44:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-24 13:44:34 -0500 |
| commit | b081d62276378b3168c92c06153fd59db0589535 (patch) | |
| tree | 9be7f7d22e0c9b4a73432fe744c09bb456c671a9 /tests/test-pearl-views.el | |
| download | pearl-b081d62276378b3168c92c06153fd59db0589535.tar.gz pearl-b081d62276378b3168c92c06153fd59db0589535.zip | |
feat: pearl — manage Linear issues from org-mode
Pearl fetches Linear issues into an org file and syncs edits back. It covers list / custom views / saved queries, per-issue and bulk rendering with comments inline, conflict-aware sync of descriptions, titles, and comments, field commands for priority / state / assignee / labels, and a transient dispatch menu. The render folds to a scannable outline and nests issues under a sortable parent.
Based on and inspired by Gael Blanchemain's linear-emacs.
Diffstat (limited to 'tests/test-pearl-views.el')
| -rw-r--r-- | tests/test-pearl-views.el | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/tests/test-pearl-views.el b/tests/test-pearl-views.el new file mode 100644 index 0000000..2a5d6bd --- /dev/null +++ b/tests/test-pearl-views.el @@ -0,0 +1,130 @@ +;;; test-pearl-views.el --- Tests for Linear Custom Views -*- 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 reading and running Linear Custom Views: the cached views list, +;; the server-side `--query-view-async' run, `pearl-run-view', the view +;; branch of refresh, and opening the active view in the browser. HTTP is +;; stubbed. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) +(require 'testutil-request (expand-file-name "testutil-request.el")) +(require 'cl-lib) + +;;; --query-view-async + +(ert-deftest test-pearl-query-view-async-extracts-issues () + "Running a view extracts the server-side issue nodes into an ok result." + (testutil-linear-with-response + '((data (customView + (issues (nodes . [((id . "i1") (identifier . "ENG-1") (title . "A"))]) + (pageInfo (hasNextPage . :json-false) (endCursor . nil)))))) + (let (result) + (pearl--query-view-async "view-1" (lambda (r) (setq result r))) + (should (eq 'ok (pearl--query-result-status result))) + (should (= 1 (length (pearl--query-result-issues result))))))) + +;;; --custom-views (cached) + +(ert-deftest test-pearl-custom-views-caches () + "The views list is fetched once and served from cache." + (let ((pearl-api-key "test-key") + (pearl--cache-views nil) + (calls 0)) + (cl-letf (((symbol-function 'request) + (lambda (_url &rest args) + (cl-incf calls) + (funcall (plist-get args :success) :data + '((data (customViews + (nodes . [((id . "v1") (name . "My View") (url . "https://x"))]) + (pageInfo (hasNextPage . :json-false))))))))) + (let ((views (pearl--custom-views))) + (should (= 1 (length views))) + (pearl--custom-views) + (should (= 1 calls)))))) + +;;; run-view + +(ert-deftest test-pearl-run-view-renders-with-view-source () + "Running a view resolves its id and renders with a view-typed source." + (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"))))) + ((symbol-function 'pearl--query-view-async) + (lambda (id cb) (setq ran-id id) + (funcall cb (pearl--make-query-result 'ok :issues nil)))) + ((symbol-function 'pearl--render-query-result) + (lambda (_result source) (setq rendered-source source)))) + (pearl-run-view "My View") + (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)))))) + +;;; refresh-current-view, view branch + +(ert-deftest test-pearl-refresh-current-view-runs-view-source () + "Refresh on a view source calls the view query, not the filter query." + (let ((view-ran nil) + (source '(:type view :name "My View" :id "v1" :url "https://x"))) + (with-temp-buffer + (insert (format "#+title: Linear — My View\n#+LINEAR-SOURCE: %s\n\n" + (prin1-to-string source))) + (org-mode) + (cl-letf (((symbol-function 'pearl--query-view-async) + (lambda (id cb) (setq view-ran id) + (funcall cb (pearl--make-query-result 'ok :issues nil)))) + ((symbol-function 'pearl--merge-query-result) + (lambda (&rest _) nil))) + (pearl-refresh-current-view) + (should (string= "v1" view-ran)))))) + +;;; open-current-view-in-linear + +(ert-deftest test-pearl-open-current-view-visits-url () + "Opening the active view visits the source's url." + (let ((visited nil) + (source '(:type view :name "My View" :id "v1" :url "https://linear.app/view/v1"))) + (with-temp-buffer + (insert (format "#+LINEAR-SOURCE: %s\n" (prin1-to-string source))) + (org-mode) + (cl-letf (((symbol-function 'browse-url) (lambda (u &rest _) (setq visited u)))) + (pearl-open-current-view-in-linear) + (should (string= "https://linear.app/view/v1" visited)))))) + +(ert-deftest test-pearl-open-current-view-no-url-errors () + "Opening a non-view or url-less source signals a user error." + (let ((source '(:type filter :name "My open issues" :filter (:assignee :me)))) + (with-temp-buffer + (insert (format "#+LINEAR-SOURCE: %s\n" (prin1-to-string source))) + (org-mode) + (should-error (pearl-open-current-view-in-linear) :type 'user-error)))) + +;;; the view query fetches comments too + +(ert-deftest test-pearl-view-issues-query-requests-comments () + "The Custom View query selects comments, so a view-populated list shows them." + (should (string-match-p "comments[[:space:]]*{[[:space:]]*nodes" pearl--view-issues-query))) + +(provide 'test-pearl-views) +;;; test-pearl-views.el ends here |
