From b081d62276378b3168c92c06153fd59db0589535 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 24 May 2026 13:44:34 -0500 Subject: feat: pearl — manage Linear issues from org-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- tests/test-pearl-org-write.el | 85 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/test-pearl-org-write.el (limited to 'tests/test-pearl-org-write.el') diff --git a/tests/test-pearl-org-write.el b/tests/test-pearl-org-write.el new file mode 100644 index 0000000..c253190 --- /dev/null +++ b/tests/test-pearl-org-write.el @@ -0,0 +1,85 @@ +;;; test-pearl-org-write.el --- Tests for pearl org file write-back -*- lexical-binding: t; -*- + +;; Copyright (C) 2026 Craig Jennings + +;; Author: Craig Jennings + +;; 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 . + +;;; Commentary: + +;; Tests for `pearl--update-org-from-issues', the buffer-aware +;; write-back. Uses real temp files (file I/O is the behavior under test); +;; the three branches are no-buffer, clean-buffer, and dirty-buffer. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) + +(defvar test-pearl--sample-issues + '((:id "u" :identifier "ENG-1" :title "T" :priority 3 :state (:name "Todo"))) + "One normalized issue, enough to render a recognizable org entry.") + +(defmacro test-pearl--with-org-file (var &rest body) + "Bind VAR to a fresh temp .org path and run BODY, cleaning up after. +The state mapping is bound so rendering is deterministic." + (declare (indent 1)) + `(let* ((,var (make-temp-file "linear-test-" nil ".org")) + (pearl-org-file-path ,var) + (pearl-state-to-todo-mapping '(("Todo" . "TODO")))) + (unwind-protect + (progn ,@body) + (let ((b (find-buffer-visiting ,var))) + (when b + (with-current-buffer b (set-buffer-modified-p nil)) + (kill-buffer b))) + (when (file-exists-p ,var) (delete-file ,var))))) + +(ert-deftest test-pearl-update-org-no-buffer-writes-file () + "With no buffer visiting the file, issues are written to disk." + (test-pearl--with-org-file tmp + (let ((b (find-buffer-visiting tmp))) (when b (kill-buffer b))) + (pearl--update-org-from-issues test-pearl--sample-issues) + (let ((content (with-temp-buffer (insert-file-contents tmp) (buffer-string)))) + (should (string-match-p "#\\+title: Linear" content)) + (should (string-match-p "#\\+LINEAR-SOURCE: " content)) + (should (string-match-p "\\*\\* TODO \\[#C\\] T" content))))) + +(ert-deftest test-pearl-update-org-clean-buffer-replaces-contents () + "A clean visiting buffer is replaced in place and saved." + (test-pearl--with-org-file tmp + (let ((buf (find-file-noselect tmp))) + (with-current-buffer buf + (insert "old content") + (save-buffer)) + (pearl--update-org-from-issues test-pearl--sample-issues) + (with-current-buffer buf + (should-not (buffer-modified-p)) + (should (string-match-p "\\*\\* TODO \\[#C\\] T" (buffer-string))) + (should-not (string-match-p "old content" (buffer-string))))))) + +(ert-deftest test-pearl-update-org-dirty-buffer-not-overwritten () + "A buffer with unsaved edits is left untouched, not clobbered." + (test-pearl--with-org-file tmp + (let ((buf (find-file-noselect tmp))) + (with-current-buffer buf + (insert "unsaved edits")) + (pearl--update-org-from-issues test-pearl--sample-issues) + (with-current-buffer buf + (should (buffer-modified-p)) + (should (string-match-p "unsaved edits" (buffer-string))) + (should-not (string-match-p "ENG-1" (buffer-string))))))) + +(provide 'test-pearl-org-write) +;;; test-pearl-org-write.el ends here -- cgit v1.2.3