diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-09 16:08:47 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-09 16:08:47 -0500 |
| commit | ce396bd2683b0ca4e11279af73f8e733dc16ddc6 (patch) | |
| tree | 499b8fba4d918206a6267fd30e31e5e55b651bd9 /tests/test-chime-async-injection.el | |
| parent | ce3a1014d929b94bd90cbc565608655d10d843bc (diff) | |
| download | chime-ce396bd2683b0ca4e11279af73f8e733dc16ddc6.tar.gz chime-ce396bd2683b0ca4e11279af73f8e733dc16ddc6.zip | |
fix: inject the lookahead variables into the async fetch child
The child sizes its agenda span from chime-modeline-lookahead-minutes and chime-tooltip-lookahead-hours, but neither was in chime-default-environment-regex. The child requires chime, so both were bound there at their defaults. Customizing either did nothing past the default eight days, with no error to explain why. The tooltip docstring invites 8760 hours to see distant events, and that setting was inert.
I added both names to the injected set.
The test that matters walks the child form and fails on any chime defcustom it reads that the regex doesn't cover, so a variable added to the child later can't reintroduce this quietly. Its companions pin the regex's anchoring and the additional-regexes extension point.
Diffstat (limited to 'tests/test-chime-async-injection.el')
| -rw-r--r-- | tests/test-chime-async-injection.el | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/tests/test-chime-async-injection.el b/tests/test-chime-async-injection.el new file mode 100644 index 0000000..3c9e304 --- /dev/null +++ b/tests/test-chime-async-injection.el @@ -0,0 +1,101 @@ +;;; test-chime-async-injection.el --- Tests for async environment injection -*- lexical-binding: t; -*- + +;; Copyright (C) 2024-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. + +;;; Commentary: + +;; Tests that every chime defcustom the async child reads is injected into +;; the child by `chime--environment-regex'. +;; +;; The child calls (require 'chime), so an uninjected defcustom is still +;; *bound* there -- at its default. A user who customizes it sees no error +;; and no effect, which is the worst shape a bug can take. That is exactly +;; what happened to chime-tooltip-lookahead-hours: the docstring invites +;; 8760 "to see distant events", and the child kept fetching 168 hours. +;; +;; The load-bearing test walks the child form and fails on any chime +;; defcustom it reads that the regex doesn't cover, so a variable added to +;; the child later cannot reintroduce the bug quietly. + +;;; Code: + +(require 'test-bootstrap (expand-file-name "test-bootstrap.el")) + +;;; Helpers + +(defun test-chime-injection--symbols (form) + "Return every symbol appearing anywhere in FORM." + (cond + ((symbolp form) (and form (list form))) + ((consp form) (append (test-chime-injection--symbols (car form)) + (test-chime-injection--symbols (cdr form)))) + (t nil))) + +(defun test-chime-injection--chime-defcustoms (form) + "Return the chime defcustoms appearing in FORM, deduplicated." + (seq-uniq + (seq-filter (lambda (sym) + (and (custom-variable-p sym) + (string-prefix-p "chime-" (symbol-name sym)))) + (test-chime-injection--symbols form)))) + +;;; Normal Cases + +(ert-deftest test-chime-async-injection-covers-every-chime-defcustom-in-the-child () + "Every chime defcustom the async child reads is injected into it. +An uninjected one silently runs at its default in the child, so a user's +customization is ignored without any error." + (let* ((form (chime--retrieve-events)) + (regex (chime--environment-regex)) + (uncovered (seq-remove + (lambda (sym) (string-match-p regex (symbol-name sym))) + (test-chime-injection--chime-defcustoms form)))) + (should-not uncovered))) + +(ert-deftest test-chime-async-injection-covers-the-lookahead-variables () + "Both lookahead variables reach the child. +The child sizes its agenda span from them, so without injection it fetches +the default 168-hour window no matter what the user set." + (let ((regex (chime--environment-regex))) + (should (string-match-p regex "chime-modeline-lookahead-minutes")) + (should (string-match-p regex "chime-tooltip-lookahead-hours")))) + +(ert-deftest test-chime-async-injection-covers-the-pre-existing-variables () + "The variables injected before the lookahead fix still are." + (let ((regex (chime--environment-regex))) + (dolist (name '("org-agenda-files" "load-path" "org-todo-keywords" + "chime-alert-intervals" "chime-include-filters" + "chime-exclude-filters")) + (should (string-match-p regex name))))) + +;;; Boundary Cases + +(ert-deftest test-chime-async-injection-regex-is-anchored () + "The regex matches whole variable names, not substrings. +Without anchoring, a user's unrelated `my-org-agenda-files-backup' would +be swept into the child." + (let ((regex (chime--environment-regex))) + (should-not (string-match-p regex "my-org-agenda-files")) + (should-not (string-match-p regex "org-agenda-files-extra")))) + +(ert-deftest test-chime-async-injection-honors-additional-regexes () + "`chime-additional-environment-regexes' extends the injected set." + (let* ((chime-additional-environment-regexes '("\\`my-var\\'")) + (regex (chime--environment-regex))) + (should (string-match-p regex "my-var")) + (should (string-match-p regex "org-agenda-files")))) + +(provide 'test-chime-async-injection) +;;; test-chime-async-injection.el ends here |
