diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-05 01:06:18 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-05 01:06:18 -0500 |
| commit | 3f491e73cdbdc03d652bce81fdfc68eabb313213 (patch) | |
| tree | 772f0e109ac0eda3a789f0d83bb8737234dd0ed9 /tests | |
| parent | 951abea0b2ed07d71676cd4d10ff7c6ca50d1390 (diff) | |
| download | pearl-3f491e73cdbdc03d652bce81fdfc68eabb313213.tar.gz pearl-3f491e73cdbdc03d652bce81fdfc68eabb313213.zip | |
feat(comments): fetch an issue's full comment thread
pearl-fetch-all-comments pages the whole comment connection for the issue at point and replaces its Comments subtree with the complete set. It's bound to C-; L f c and in the transient. The bulk list and view fetch showed only the newest pearl-list-comments-shown comments with an N/M+ overflow marker, so anything past the cap couldn't surface in the buffer.
The replacement is surgical: pearl--replace-comments-subtree swaps only the Comments subtree, so the issue title, drawer, and description body keep any unsaved edits, and the new heading carries an exact N/N count. It refuses when the issue has unpushed comment edits (reusing the save model's dirty scanner) so the fetch can't clobber an unsent change.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test-pearl-fetch-all-comments.el | 128 | ||||
| -rw-r--r-- | tests/test-pearl-menu.el | 4 |
2 files changed, 131 insertions, 1 deletions
diff --git a/tests/test-pearl-fetch-all-comments.el b/tests/test-pearl-fetch-all-comments.el new file mode 100644 index 0000000..04dfe31 --- /dev/null +++ b/tests/test-pearl-fetch-all-comments.el @@ -0,0 +1,128 @@ +;;; test-pearl-fetch-all-comments.el --- Tests for fetching a full comment thread -*- 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 pearl-fetch-all-comments: the keybinding, the in-place +;; Comments-subtree replacement with an exact N/N count, and the unpushed-edit +;; guard that refuses to clobber a locally-edited comment. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) +(require 'cl-lib) + +(defmacro test-pearl-fac--in-org (content &rest body) + "Run BODY in an org-mode temp buffer holding CONTENT." + (declare (indent 1)) + `(let ((org-todo-keywords '((sequence "TODO" "IN-PROGRESS" "|" "DONE")))) + (with-temp-buffer + (insert ,content) + (org-mode) + (goto-char (point-min)) + ,@body))) + +(defconst test-pearl-fac--with-comments + (concat + "* My open issues\n" + "** TODO SE-1: Alpha\n:PROPERTIES:\n:LINEAR-ID: i1\n:LINEAR-IDENTIFIER: SE-1\n:END:\n" + "The description body.\n" + "*** Comments 2/5+\n" + "**** Old Author — 2026-01-01T00:00:00.000Z\n" + ":PROPERTIES:\n:LINEAR-COMMENT-ID: oc1\n:LINEAR-COMMENT-AUTHOR-ID: u1\n" + ":LINEAR-COMMENT-SHA256: deadbeef\n:LINEAR-COMMENT-ORG-SHA256: deadbeef\n:END:\n" + "old comment one\n") + "An issue with a capped (overflowing) Comments subtree and a stale-hash comment.") + +(defconst test-pearl-fac--no-comments + (concat + "* My open issues\n" + "** TODO SE-1: Alpha\n:PROPERTIES:\n:LINEAR-ID: i1\n:LINEAR-IDENTIFIER: SE-1\n:END:\n" + "The description body.\n") + "An issue with no Comments subtree.") + +(defun test-pearl-fac--goto-issue () + "Move point onto the issue heading." + (goto-char (point-min)) + (re-search-forward "^\\*\\* TODO SE-1") + (beginning-of-line)) + +;;; keybinding + +(ert-deftest test-pearl-fetch-all-comments-bound () + "The command is bound under the fetch sub-keymap at `c'." + (should (eq 'pearl-fetch-all-comments (lookup-key pearl-fetch-map (kbd "c"))))) + +;;; subtree replacement + +(ert-deftest test-pearl-replace-comments-subtree-replaces-and-counts () + "Replacing swaps the capped thread for the full set with an exact N/N count." + (test-pearl-fac--in-org test-pearl-fac--with-comments + (test-pearl-fac--goto-issue) + (pearl--replace-comments-subtree + (list '(:id "c1" :author "Bob" :created-at "2026-02-01T00:00:00.000Z" :body "new one") + '(:id "c2" :author "Sue" :created-at "2026-02-02T00:00:00.000Z" :body "new two"))) + (goto-char (point-min)) + (should (search-forward "Comments 2/2" nil t)) + (goto-char (point-min)) + (should (search-forward "The description body." nil t)) + (goto-char (point-min)) + (should (search-forward "new one" nil t)) + (goto-char (point-min)) + (should-not (search-forward "old comment one" nil t)))) + +(ert-deftest test-pearl-replace-comments-subtree-creates-when-absent () + "An issue with no Comments subtree gets one inserted." + (test-pearl-fac--in-org test-pearl-fac--no-comments + (test-pearl-fac--goto-issue) + (pearl--replace-comments-subtree + (list '(:id "c1" :author "Bob" :created-at "2026-02-01T00:00:00.000Z" :body "hello"))) + (goto-char (point-min)) + (should (search-forward "Comments 1/1" nil t)) + (goto-char (point-min)) + (should (search-forward "hello" nil t)) + (goto-char (point-min)) + (should (search-forward "The description body." nil t)))) + +(ert-deftest test-pearl-replace-comments-subtree-empty-clears () + "An empty thread clears the Comments subtree." + (test-pearl-fac--in-org test-pearl-fac--with-comments + (test-pearl-fac--goto-issue) + (pearl--replace-comments-subtree nil) + (goto-char (point-min)) + (should-not (search-forward "Comments" nil t)) + (goto-char (point-min)) + (should (search-forward "The description body." nil t)))) + +;;; unpushed-edit guard + +(ert-deftest test-pearl-unpushed-comment-edits-p-detects-dirty () + "A comment whose body no longer matches its stored hash is an unpushed edit." + (test-pearl-fac--in-org test-pearl-fac--with-comments + (test-pearl-fac--goto-issue) + (should (pearl--unpushed-comment-edits-p)))) + +(ert-deftest test-pearl-unpushed-comment-edits-p-clean-when-no-comments () + "An issue with no comments has no unpushed comment edits." + (test-pearl-fac--in-org test-pearl-fac--no-comments + (test-pearl-fac--goto-issue) + (should-not (pearl--unpushed-comment-edits-p)))) + +(provide 'test-pearl-fetch-all-comments) +;;; test-pearl-fetch-all-comments.el ends here diff --git a/tests/test-pearl-menu.el b/tests/test-pearl-menu.el index 8d23023..825d6bc 100644 --- a/tests/test-pearl-menu.el +++ b/tests/test-pearl-menu.el @@ -76,7 +76,9 @@ menu entry that still points at it fails here." pearl-switch-account pearl-copy-issue-url ;; set-default-view: the new Views-group entry - pearl-set-default-view)) + pearl-set-default-view + ;; fetch the full comment thread for the issue at point + pearl-fetch-all-comments)) (should (memq expected cmds))))) (provide 'test-pearl-menu) |
