aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-07 06:43:17 -0500
committerCraig Jennings <c@cjennings.net>2026-06-07 06:43:17 -0500
commite2208276021def42dadd5e422aa96e9004040dd9 (patch)
tree1352c74e299276dce750a3e6beddf87118899b3f /tests
parentc740e270721581120cc6e9317ab70dba40156820 (diff)
downloadpearl-e2208276021def42dadd5e422aa96e9004040dd9.tar.gz
pearl-e2208276021def42dadd5e422aa96e9004040dd9.zip
feat(render): highlight unsaved comments and update the cues live
Completes the modified-ticket indicator (docs/modified-ticket-indicator-spec.org) on top of the field highlight and count. A changed comment now gets its own highlight by ownership: your own comment (pushable) takes pearl-modified-highlight and bubbles up to the ticket heading; a non-own comment, which save skips, takes the muted pearl-modified-local; a comment seen before the viewer resolves takes the neutral pearl-modified-unknown until classification lands. The viewer is resolved only when a comment is actually dirty, so opening or editing a clean or field-only buffer makes no network call. The cues update live: a buffer-local after-change hook debounces a redecorate on an idle timer (pearl-modified-idle-delay), so an edit shows within a fraction of a second instead of waiting for a save or refresh. The timer is cancelled when pearl-mode turns off or the buffer is killed. One pearl--redecorate-modified now drives the field highlights, the comment classification, and the count from a single scan, called on mode enable, fetch/refresh, and the idle tick.
Diffstat (limited to 'tests')
-rw-r--r--tests/test-pearl-modified.el60
1 files changed, 60 insertions, 0 deletions
diff --git a/tests/test-pearl-modified.el b/tests/test-pearl-modified.el
index cfef923..8529b07 100644
--- a/tests/test-pearl-modified.el
+++ b/tests/test-pearl-modified.el
@@ -171,5 +171,65 @@
(should (null (seq-filter (lambda (o) (overlay-get o 'pearl-modified))
(overlays-in (point-min) (point-max)))))))
+;;; phase 4 -- per-comment highlight by ownership
+
+(ert-deftest test-pearl-comment-highlight-face-own-is-pushable ()
+ (should (eq 'pearl-modified-highlight
+ (pearl--comment-highlight-face '(:author-id "v") "v"))))
+
+(ert-deftest test-pearl-comment-highlight-face-non-own-is-local ()
+ (should (eq 'pearl-modified-local
+ (pearl--comment-highlight-face '(:author-id "other") "v"))))
+
+(ert-deftest test-pearl-comment-highlight-face-unresolved-viewer-is-unknown ()
+ (should (eq 'pearl-modified-unknown
+ (pearl--comment-highlight-face '(:author-id "v") nil)))
+ (should (eq 'pearl-modified-unknown
+ (pearl--comment-highlight-face '(:author-id "v") "v" t))))
+
+(ert-deftest test-pearl-comment-region-spans-the-comment-subtree ()
+ (with-temp-buffer
+ (insert "* F\n** TODO PEARL-1 Alpha\n:PROPERTIES:\n:LINEAR-ID: i1\n:END:\n"
+ "*** Comments\n**** Comment by X\n:PROPERTIES:\n:LINEAR-COMMENT-ID: c1\n:END:\n"
+ "the comment body\n")
+ (org-mode)
+ (goto-char (point-min)) (re-search-forward "Comment by X") (org-back-to-heading t)
+ (let ((text (let ((r (pearl--comment-region)))
+ (buffer-substring-no-properties (car r) (cdr r)))))
+ (should (string-match-p "Comment by X" text))
+ (should (string-match-p "the comment body" text)))))
+
+;;; phase 3 -- live after-change trigger
+
+(ert-deftest test-pearl-modified-after-change-schedules-timer ()
+ "An edit schedules a debounced redecorate timer when the indicator is on."
+ (with-temp-buffer
+ (let ((pearl-show-modified-indicator t)
+ (pearl--modified-timer nil))
+ (pearl--modified-after-change)
+ (should (timerp pearl--modified-timer))
+ (pearl--modified-cleanup)
+ (should (null pearl--modified-timer)))))
+
+(ert-deftest test-pearl-modified-after-change-off-schedules-nothing ()
+ "With the indicator disabled, an edit schedules no timer."
+ (with-temp-buffer
+ (let ((pearl-show-modified-indicator nil)
+ (pearl--modified-timer nil))
+ (pearl--modified-after-change)
+ (should (null pearl--modified-timer)))))
+
+(ert-deftest test-pearl-modified-after-change-cancels-prior-timer ()
+ "A second edit replaces the pending timer rather than leaking it."
+ (with-temp-buffer
+ (let ((pearl-show-modified-indicator t)
+ (pearl--modified-timer nil))
+ (pearl--modified-after-change)
+ (let ((first pearl--modified-timer))
+ (pearl--modified-after-change)
+ (should-not (eq first pearl--modified-timer))
+ (should (timerp pearl--modified-timer))
+ (pearl--modified-cleanup)))))
+
(provide 'test-pearl-modified)
;;; test-pearl-modified.el ends here