diff options
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 |
