aboutsummaryrefslogtreecommitdiff
path: root/tests/test-system-lib-executable-find-or-warn.el
blob: e9a540bd2acfef3c9ec943342a98a06d52d1f656 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
;;; test-system-lib-executable-find-or-warn.el --- Tests for cj/executable-find-or-warn -*- lexical-binding: t; -*-

;;; Commentary:
;; `cj/executable-find-or-warn' generalizes the mail-specific
;; `cj/mail--executable-or-warn' pattern.  Returns the program's
;; executable path when found.  When the program is missing, returns
;; nil AND emits a `display-warning' naming the feature that's
;; unavailable, so the user gets a clear hint about what won't work.
;; The optional GROUP argument controls `display-warning' grouping so
;; per-feature filters keep working.

;;; Code:

(require 'ert)
(require 'cl-lib)

(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'system-lib)

(defmacro test-system-lib-find-or-warn--with-stubs (executable-fn warning-capture &rest body)
  "Run BODY with `executable-find' and `display-warning' stubbed.

EXECUTABLE-FN replaces `executable-find' (takes a string program name,
returns path or nil).  WARNING-CAPTURE is a symbol bound in BODY's scope
to a list of (TYPE MESSAGE LEVEL) entries collected from
`display-warning' calls."
  (declare (indent 2))
  `(let ((,warning-capture nil))
     (cl-letf (((symbol-function 'executable-find) ,executable-fn)
               ((symbol-function 'display-warning)
                (lambda (type message &optional level)
                  (push (list type message level) ,warning-capture))))
       ,@body)))

(ert-deftest test-cj-executable-find-or-warn-program-found-returns-path ()
  "Normal: when the program exists, return its path and emit no warning."
  (test-system-lib-find-or-warn--with-stubs
      (lambda (prog) (when (string= prog "mbsync") "/usr/bin/mbsync"))
      warnings
    (let ((result (cj/executable-find-or-warn "mbsync" "mu4e mail sync")))
      (should (equal result "/usr/bin/mbsync"))
      (should-not warnings))))

(ert-deftest test-cj-executable-find-or-warn-program-missing-returns-nil ()
  "Normal: when the program is missing, return nil."
  (test-system-lib-find-or-warn--with-stubs
      (lambda (_prog) nil)
      _warnings
    (should-not (cj/executable-find-or-warn "missing-prog" "fake feature"))))

(ert-deftest test-cj-executable-find-or-warn-missing-emits-warning ()
  "Normal: a missing program produces a warning that names PROGRAM and FEATURE."
  (test-system-lib-find-or-warn--with-stubs
      (lambda (_prog) nil)
      warnings
    (cj/executable-find-or-warn "missing-prog" "fake feature")
    (should (= 1 (length warnings)))
    (let ((entry (car warnings)))
      (should (string-match-p "missing-prog" (nth 1 entry)))
      (should (string-match-p "fake feature" (nth 1 entry)))
      (should (eq :warning (nth 2 entry))))))

(ert-deftest test-cj-executable-find-or-warn-default-group ()
  "Boundary: with no GROUP arg, the warning uses the default `cj/system-lib' symbol."
  (test-system-lib-find-or-warn--with-stubs
      (lambda (_prog) nil)
      warnings
    (cj/executable-find-or-warn "missing-prog" "feature")
    (should (eq 'cj/system-lib (car (car warnings))))))

(ert-deftest test-cj-executable-find-or-warn-explicit-group ()
  "Normal: an explicit GROUP arg flows through to `display-warning'."
  (test-system-lib-find-or-warn--with-stubs
      (lambda (_prog) nil)
      warnings
    (cj/executable-find-or-warn "missing-prog" "feature" 'mail-config)
    (should (eq 'mail-config (car (car warnings))))))

(provide 'test-system-lib-executable-find-or-warn)
;;; test-system-lib-executable-find-or-warn.el ends here