aboutsummaryrefslogtreecommitdiff
path: root/tests/test-mu4e-org-contacts-integration.el
blob: c86d61b3f5c305adc3ccc68e8a49bf812129d5f2 (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
125
126
127
128
129
130
131
132
133
134
135
;;; test-mu4e-org-contacts-integration.el --- Tests for mu4e org-contacts completion -*- lexical-binding: t; -*-

;;; Commentary:

;; Characterization tests for the org-contacts completion glue.  The module
;; loads without mu4e or org-contacts (both are required with noerror), and the
;; tests stub the header-field predicate, the mode actions, and the contact
;; source, so they run headless with no package dependency.  Coverage centers
;; on the two highest-value behaviors: the capf only fires inside a header
;; field of a compose buffer, and TAB dispatches to completion / org-cycle /
;; indent by context.

;;; Code:

(require 'ert)
(require 'cl-lib)
(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'mu4e-org-contacts-integration)

;;; cj/org-contacts-completion-at-point

(ert-deftest test-mu4e-org-contacts-capf-nil-outside-header ()
  "Boundary: the capf declines when point is not in a header field."
  (with-temp-buffer
    (cl-letf (((symbol-function 'derived-mode-p) (lambda (&rest _) t))
              ((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () nil)))
      (should-not (cj/org-contacts-completion-at-point)))))

(ert-deftest test-mu4e-org-contacts-capf-nil-outside-compose-mode ()
  "Boundary: the capf declines outside the mu4e/org-msg compose modes."
  (with-temp-buffer
    (cl-letf (((symbol-function 'derived-mode-p) (lambda (&rest _) nil))
              ((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () t)))
      (should-not (cj/org-contacts-completion-at-point)))))

(ert-deftest test-mu4e-org-contacts-capf-returns-spec-in-header ()
  "Normal: in a header field with contacts the capf returns bounds and a table."
  (with-temp-buffer
    (insert "To: ali")
    (cl-letf (((symbol-function 'derived-mode-p) (lambda (&rest _) t))
              ((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () t))
              ((symbol-function 'cj/get-all-contact-emails)
               (lambda () '("Alice <alice@example.com>" "Bob <bob@example.com>"))))
      (let ((result (cj/org-contacts-completion-at-point)))
        (should result)
        (should (integerp (nth 0 result)))
        (should (= (point) (nth 1 result)))
        ;; the completion start sits just after the "To:" prefix
        (should (string= "ali" (buffer-substring-no-properties
                                (nth 0 result) (nth 1 result))))
        (should (member "Alice <alice@example.com>"
                        (all-completions "" (nth 2 result))))))))

(ert-deftest test-mu4e-org-contacts-capf-nil-when-no-contacts ()
  "Boundary: a header field with no contacts yields no completion."
  (with-temp-buffer
    (insert "To: ")
    (cl-letf (((symbol-function 'derived-mode-p) (lambda (&rest _) t))
              ((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () t))
              ((symbol-function 'cj/get-all-contact-emails) (lambda () nil)))
      (should-not (cj/org-contacts-completion-at-point)))))

;;; cj/mu4e-org-contacts-tab-complete

(ert-deftest test-mu4e-org-contacts-tab-completes-in-header ()
  "Normal: TAB in a header field triggers completion-at-point."
  (let ((capf-calls 0) (org-cycled nil) (indented nil))
    (cl-letf (((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () t))
              ((symbol-function 'completion-at-point) (lambda () (cl-incf capf-calls)))
              ((symbol-function 'org-cycle) (lambda (&rest _) (setq org-cycled t)))
              ((symbol-function 'indent-for-tab-command)
               (lambda (&rest _) (setq indented t))))
      (cj/mu4e-org-contacts-tab-complete)
      (should (= capf-calls 1))
      (should-not org-cycled)
      (should-not indented))))

(ert-deftest test-mu4e-org-contacts-tab-cycles-in-org-msg-body ()
  "Normal: TAB in the org-msg body (not a header) calls org-cycle."
  (with-temp-buffer
    (setq major-mode 'org-msg-edit-mode)
    (let ((org-cycled nil) (capf-called nil))
      (cl-letf (((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () nil))
                ((symbol-function 'org-cycle) (lambda (&rest _) (setq org-cycled t)))
                ((symbol-function 'completion-at-point)
                 (lambda () (setq capf-called t))))
        (cj/mu4e-org-contacts-tab-complete)
        (should org-cycled)
        (should-not capf-called)))))

(ert-deftest test-mu4e-org-contacts-tab-indents-elsewhere ()
  "Boundary: TAB outside a header and outside the org-msg body indents."
  (with-temp-buffer
    (setq major-mode 'fundamental-mode)
    (let ((indented nil))
      (cl-letf (((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () nil))
                ((symbol-function 'indent-for-tab-command)
                 (lambda (&rest _) (setq indented t))))
        (cj/mu4e-org-contacts-tab-complete)
        (should indented)))))

;;; cj/mu4e-org-contacts-comma-complete

(ert-deftest test-mu4e-org-contacts-comma-inserts-spaced-in-header ()
  "Normal: a comma in a header field inserts a comma and a space."
  (with-temp-buffer
    (insert "To: alice@example.com")
    (cl-letf (((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () t))
              ((symbol-function 'completion-at-point) #'ignore))
      (cj/mu4e-org-contacts-comma-complete)
      (should (string-suffix-p ", " (buffer-string))))))

(ert-deftest test-mu4e-org-contacts-comma-plain-outside-header ()
  "Boundary: a comma outside a header field inserts a bare comma."
  (with-temp-buffer
    (insert "some body text")
    (cl-letf (((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () nil)))
      (cj/mu4e-org-contacts-comma-complete)
      (should (string-suffix-p "text," (buffer-string)))
      (should-not (string-suffix-p ", " (buffer-string))))))

;;; cj/mu4e-org-contacts-insert-email

(ert-deftest test-mu4e-org-contacts-insert-email-noop-outside-header ()
  "Boundary: direct insert does nothing and does not prompt outside a header."
  (with-temp-buffer
    (insert "body")
    (cl-letf (((symbol-function 'mail-abbrev-in-expansion-header-p) (lambda () nil))
              ((symbol-function 'completing-read)
               (lambda (&rest _) (error "should not prompt outside a header"))))
      (cj/mu4e-org-contacts-insert-email)
      (should (string= "body" (buffer-string))))))

(provide 'test-mu4e-org-contacts-integration)
;;; test-mu4e-org-contacts-integration.el ends here