aboutsummaryrefslogtreecommitdiff
path: root/tests/test-help-utils--arch-wiki-search.el
blob: d02dd0419fcc39aaec179790f52cd9564b3ff2f8 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
;;; test-help-utils--arch-wiki-search.el --- Tests for the ArchWiki search guard -*- lexical-binding: t; -*-

;;; Commentary:
;; Tests for cj/--arch-wiki-topics and the cj/local-arch-wiki-search command.
;;
;; The bug: the command read "/usr/share/doc/arch-wiki/html/en" with
;; `directory-files' before checking the directory existed.  On a machine
;; without arch-wiki-docs -- the exact state the command's own error text is
;; written for -- that signaled file-missing on the first line, so the friendly
;; "Is arch-wiki-docs installed?" message below it was unreachable.  The user
;; got a raw Lisp error naming a path instead of the install hint.
;;
;; Two things had to change to make this testable.  The directory was
;; hardcoded inside the command, so a test could only ever exercise whatever
;; the developer's own machine happened to have installed; it is now
;; `cj/arch-wiki-html-dir'.  And the directory read is now the pure helper
;; cj/--arch-wiki-topics, which takes a directory and returns an alist, so the
;; interesting cases are driven with real temporary directories instead of
;; mocking `directory-files'.
;;
;; Test organization:
;; - Normal Cases: topics found and returned; the command opens the choice
;; - Boundary Cases: empty dir, single topic, a name matching no topic
;; - Error Cases: missing dir returns nil and reports the install hint
;;
;;; Code:

(require 'ert)
(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'help-utils)

(defmacro test-arch-wiki--with-topics (dir-var topics &rest body)
  "Bind DIR-VAR to a temp dir holding TOPICS (a list of html basenames).
The directory is removed after BODY."
  (declare (indent 2))
  `(let ((,dir-var (make-temp-file "arch-wiki-test" t)))
     (unwind-protect
         (progn
           (dolist (name ,topics)
             (write-region "" nil (expand-file-name (concat name ".html") ,dir-var)))
           ,@body)
       (delete-directory ,dir-var t))))

;;; Normal Cases — the pure helper

(ert-deftest test-help-utils-arch-wiki-topics-lists-html-basenames ()
  "Normal: each .html file becomes a (basename . fullpath) pair."
  (test-arch-wiki--with-topics dir '("Systemd" "Pacman")
    (let ((topics (cj/--arch-wiki-topics dir)))
      (should (equal '("Pacman" "Systemd") (sort (mapcar #'car topics) #'string<)))
      (should (string-suffix-p "Systemd.html" (cdr (assoc "Systemd" topics)))))))

(ert-deftest test-help-utils-arch-wiki-topics-ignores-non-html ()
  "Normal: files without the .html extension are not topics."
  (test-arch-wiki--with-topics dir '("Systemd")
    (write-region "" nil (expand-file-name "README.txt" dir))
    (should (equal '("Systemd") (mapcar #'car (cj/--arch-wiki-topics dir))))))

;;; Boundary Cases

(ert-deftest test-help-utils-arch-wiki-topics-empty-dir-is-nil ()
  "Boundary: an existing but empty directory yields no topics."
  (test-arch-wiki--with-topics dir '()
    (should (null (cj/--arch-wiki-topics dir)))))

(ert-deftest test-help-utils-arch-wiki-topics-single-topic ()
  "Boundary: one topic returns a one-element alist."
  (test-arch-wiki--with-topics dir '("Systemd")
    (should (= 1 (length (cj/--arch-wiki-topics dir))))))

;;; Error Cases — the missing-install path

(ert-deftest test-help-utils-arch-wiki-topics-missing-dir-returns-nil ()
  "Error: an absent directory returns nil rather than signaling file-missing."
  (let ((missing (expand-file-name "definitely-absent-arch-wiki"
                                   temporary-file-directory)))
    (should-not (file-directory-p missing))
    (should (null (cj/--arch-wiki-topics missing)))))

(ert-deftest test-help-utils-arch-wiki-search-missing-dir-reports-hint ()
  "Error: the command reports the install hint and opens nothing."
  (let ((cj/arch-wiki-html-dir (expand-file-name "definitely-absent-arch-wiki"
                                                 temporary-file-directory))
        (said nil)
        (opened nil))
    (cl-letf (((symbol-function 'message)
               (lambda (fmt &rest args) (setq said (apply #'format fmt args)) nil))
              ((symbol-function 'eww-browse-url)
               (lambda (url &rest _) (setq opened url))))
      ;; Must not signal: this is the case that used to raise file-missing.
      (cj/local-arch-wiki-search))
    (should-not opened)
    (should (string-match-p "arch-wiki-docs" said))))

;;; Normal Cases — the command

(ert-deftest test-help-utils-arch-wiki-search-opens-chosen-topic ()
  "Normal: the chosen topic is opened as a file URL in EWW."
  (test-arch-wiki--with-topics dir '("Systemd")
    (let ((cj/arch-wiki-html-dir dir)
          (opened nil))
      (cl-letf (((symbol-function 'completing-read) (lambda (&rest _) "Systemd"))
                ((symbol-function 'eww-browse-url)
                 (lambda (url &rest _) (setq opened url))))
        (cj/local-arch-wiki-search))
      (should (string-prefix-p "file://" opened))
      (should (string-suffix-p "Systemd.html" opened))
      ;; The opened path is the one in the temp dir, not a system copy.
      (should (string-match-p (regexp-quote dir) opened)))))

(ert-deftest test-help-utils-arch-wiki-search-unknown-topic-opens-nothing ()
  "Boundary: a name matching no topic reports rather than opening."
  (test-arch-wiki--with-topics dir '("Systemd")
    (let ((cj/arch-wiki-html-dir dir)
          (opened nil))
      (cl-letf (((symbol-function 'completing-read) (lambda (&rest _) "NotATopic"))
                ((symbol-function 'message) (lambda (&rest _) nil))
                ((symbol-function 'eww-browse-url)
                 (lambda (url &rest _) (setq opened url))))
        (cj/local-arch-wiki-search))
      (should-not opened))))

(provide 'test-help-utils--arch-wiki-search)
;;; test-help-utils--arch-wiki-search.el ends here