diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-02 12:56:09 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-02 12:56:09 -0500 |
| commit | 42f3a75651ed8d2f8e601c654e482dc85363bb83 (patch) | |
| tree | fa737d9aab0afc407bcc2264ab1ff03a99590e0c /tests/test-pearl-default-view.el | |
| parent | 293c9f2a097991ca64f05f6252d0725f510d2e47 (diff) | |
| download | pearl-42f3a75651ed8d2f8e601c654e482dc85363bb83.tar.gz pearl-42f3a75651ed8d2f8e601c654e482dc85363bb83.zip | |
feat(views): default-view resolver and open command
Phase 1 of the default-view spec. I added the data and dispatch; keymap and the setter come in later phases.
pearl-default-view (defcustom) holds the legacy-mode default: nil for my open issues, or a local-view name. In accounts mode the per-account :default-view key wins instead, so pearl--resolve-account now carries :default-view in its context plist and pearl--resolve-default-view reads from the active account, falling back to the global only in legacy mode.
pearl-open-default-view dispatches the resolved default: nil runs pearl-list-issues, a known local-view name runs pearl-run-local-view, and a name that's since been deleted falls back to pearl-list-issues with a message instead of erroring. pearl-list-issues keeps its contract — it's still literal my-open-issues, the keymap rebind is phase 3.
Nine tests cover the resolver in both modes and the three dispatch paths. Suite 792 to 801, compile and lint clean.
Diffstat (limited to 'tests/test-pearl-default-view.el')
| -rw-r--r-- | tests/test-pearl-default-view.el | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/tests/test-pearl-default-view.el b/tests/test-pearl-default-view.el new file mode 100644 index 0000000..2794972 --- /dev/null +++ b/tests/test-pearl-default-view.el @@ -0,0 +1,134 @@ +;;; test-pearl-default-view.el --- Tests for the configurable default view -*- 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: + +;; Unit tests for the default-view resolver and the `pearl-open-default-view' +;; dispatcher (phase 1 of docs/default-view-spec.org). The resolver returns +;; the active scope's default -- `pearl-default-view' in legacy mode, the +;; active account's `:default-view' in accounts mode. The open command +;; dispatches nil -> my open issues, a known local-view name -> that view, and +;; a stale name -> my open issues with a message (never an error). The two +;; fetch commands are stubbed so no network is touched. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) + +;;; pearl--resolve-default-view -- scope resolution + +(ert-deftest test-pearl-resolve-default-view-legacy-nil () + "Legacy mode, no default set: the resolver returns nil." + (let ((pearl-accounts nil) + (pearl-default-view nil)) + (should-not (pearl--resolve-default-view)))) + +(ert-deftest test-pearl-resolve-default-view-legacy-name () + "Legacy mode with a default set: the resolver returns the local-view name." + (let ((pearl-accounts nil) + (pearl-default-view "My active work")) + (should (string-equal "My active work" (pearl--resolve-default-view))))) + +(ert-deftest test-pearl-resolve-default-view-accounts-reads-active () + "Accounts mode: the resolver returns the *active* account's :default-view." + (let ((pearl-accounts + '(("work" :api-key-source (:literal "kw") :org-file "/tmp/w.org" + :default-view "Work board") + ("home" :api-key-source (:literal "kh") :org-file "/tmp/h.org" + :default-view "Home triage"))) + (pearl-default-account nil) + (pearl-active-account "work")) + (should (string-equal "Work board" (pearl--resolve-default-view))))) + +(ert-deftest test-pearl-resolve-default-view-accounts-switch () + "Accounts mode: switching the active account switches the resolved default." + (let ((pearl-accounts + '(("work" :api-key-source (:literal "kw") :org-file "/tmp/w.org" + :default-view "Work board") + ("home" :api-key-source (:literal "kh") :org-file "/tmp/h.org" + :default-view "Home triage"))) + (pearl-default-account nil) + (pearl-active-account "home")) + (should (string-equal "Home triage" (pearl--resolve-default-view))))) + +(ert-deftest test-pearl-resolve-default-view-accounts-unset () + "Accounts mode, active account has no :default-view: the resolver returns nil. +The legacy `pearl-default-view' does not leak in when accounts are configured." + (let ((pearl-accounts + '(("work" :api-key-source (:literal "kw") :org-file "/tmp/w.org"))) + (pearl-default-account nil) + (pearl-active-account "work") + (pearl-default-view "Legacy default")) + (should-not (pearl--resolve-default-view)))) + +(ert-deftest test-pearl-resolve-account-carries-default-view () + "`pearl--resolve-account' surfaces the account's :default-view in its context." + (let ((pearl-accounts + '(("work" :api-key-source (:literal "kw") :org-file "/tmp/w.org" + :default-view "Work board")))) + (should (string-equal "Work board" + (plist-get (pearl--resolve-account "work") :default-view))))) + +;;; pearl-open-default-view -- dispatch + +(ert-deftest test-pearl-open-default-view-nil-runs-my-open-issues () + "An unset default dispatches to `pearl-list-issues' (my open issues)." + (let ((pearl-accounts nil) + (pearl-default-view nil) + (calls nil)) + (cl-letf (((symbol-function 'pearl-list-issues) + (lambda (&rest args) (push (cons 'list args) calls))) + ((symbol-function 'pearl-run-local-view) + (lambda (name) (push (cons 'view name) calls)))) + (pearl-open-default-view) + (should (equal calls '((list))))))) + +(ert-deftest test-pearl-open-default-view-name-runs-local-view () + "A default naming an existing local view dispatches to `pearl-run-local-view'." + (let ((pearl-accounts nil) + (pearl-default-view "My active work") + (pearl-local-views '(("My active work" :filter (:assignee :me :open t)))) + (calls nil)) + (cl-letf (((symbol-function 'pearl-list-issues) + (lambda (&rest args) (push (cons 'list args) calls))) + ((symbol-function 'pearl-run-local-view) + (lambda (name) (push (cons 'view name) calls)))) + (pearl-open-default-view) + (should (equal calls '((view . "My active work"))))))) + +(ert-deftest test-pearl-open-default-view-stale-name-falls-back () + "A default naming a deleted local view falls back to my open issues, no error. +It dispatches to `pearl-list-issues' and never calls `pearl-run-local-view'." + (let ((pearl-accounts nil) + (pearl-default-view "Deleted view") + (pearl-local-views '(("Some other view" :filter (:open t)))) + (calls nil) + (messaged nil)) + (cl-letf (((symbol-function 'pearl-list-issues) + (lambda (&rest args) (push (cons 'list args) calls))) + ((symbol-function 'pearl-run-local-view) + (lambda (name) (push (cons 'view name) calls))) + ((symbol-function 'message) + (lambda (&rest args) (setq messaged (or messaged args))))) + (pearl-open-default-view) + (should (equal calls '((list)))) + (should messaged)))) + +(provide 'test-pearl-default-view) +;;; test-pearl-default-view.el ends here |
