aboutsummaryrefslogtreecommitdiff
path: root/tests/test-chime-numeric-defcustom-setters.el
blob: ad339b99923fb64811978283c126320d05ee00e3 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
;;; test-chime-numeric-defcustom-setters.el --- Setter validation for numeric defcustoms -*- lexical-binding: t; -*-

;; Copyright (C) 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.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; The numeric defcustoms feed arithmetic (timer math, lookahead windows,
;; counters) and a bad value reaches the wrong layer if it slips past the
;; setter — the user gets an `arith-error' or a confusing timer failure
;; instead of a configuration error.  These tests pin down the contract:
;; bad values raise `user-error' at customize-time; valid values land.

;;; Code:

(require 'test-bootstrap (expand-file-name "test-bootstrap.el"))

;;;; chime--validate-integer-setting helper

(ert-deftest test-chime-validate-integer-setting-accepts-valid-non-negative ()
  "Normal: 0 passes when MIN is 0."
  (should (eq 0 (chime--validate-integer-setting
                 'fake-symbol 0 0 nil))))

(ert-deftest test-chime-validate-integer-setting-rejects-non-integer ()
  "Error: a string raises `user-error' naming the symbol."
  (let ((err (should-error (chime--validate-integer-setting
                            'fake-symbol "ten" 0 nil)
                           :type 'user-error)))
    (should (string-match-p "fake-symbol" (cadr err)))))

(ert-deftest test-chime-validate-integer-setting-rejects-below-min ()
  "Error: a value below MIN raises `user-error'."
  (should-error (chime--validate-integer-setting
                 'fake-symbol 0 1 nil)
                :type 'user-error))

(ert-deftest test-chime-validate-integer-setting-allows-nil-when-permitted ()
  "Boundary: nil passes when ALLOW-NIL is non-nil."
  (should (null (chime--validate-integer-setting
                 'fake-symbol nil 0 t))))

(ert-deftest test-chime-validate-integer-setting-rejects-nil-when-not-permitted ()
  "Error: nil fails when ALLOW-NIL is nil."
  (should-error (chime--validate-integer-setting
                 'fake-symbol nil 0 nil)
                :type 'user-error))

;;;; chime-modeline-lookahead-minutes — integer >= 0

(ert-deftest test-chime-modeline-lookahead-minutes-accepts-zero ()
  "Normal: 0 is valid (disables modeline display)."
  (let ((chime-modeline-lookahead-minutes 120))
    (customize-set-variable 'chime-modeline-lookahead-minutes 0)
    (should (= 0 chime-modeline-lookahead-minutes))))

(ert-deftest test-chime-modeline-lookahead-minutes-rejects-negative ()
  "Error: negative integer raises."
  (let ((chime-modeline-lookahead-minutes 120))
    (should-error (customize-set-variable
                   'chime-modeline-lookahead-minutes -5)
                  :type 'user-error)))

(ert-deftest test-chime-modeline-lookahead-minutes-rejects-non-integer ()
  "Error: string raises."
  (let ((chime-modeline-lookahead-minutes 120))
    (should-error (customize-set-variable
                   'chime-modeline-lookahead-minutes "many")
                  :type 'user-error)))

;;;; chime-tooltip-lookahead-hours — integer >= 1

(ert-deftest test-chime-tooltip-lookahead-hours-accepts-positive ()
  "Normal: 1 is the floor."
  (let ((chime-tooltip-lookahead-hours 168))
    (customize-set-variable 'chime-tooltip-lookahead-hours 1)
    (should (= 1 chime-tooltip-lookahead-hours))))

(ert-deftest test-chime-tooltip-lookahead-hours-rejects-zero ()
  "Error: 0 hours of lookahead would never find anything."
  (let ((chime-tooltip-lookahead-hours 168))
    (should-error (customize-set-variable
                   'chime-tooltip-lookahead-hours 0)
                  :type 'user-error)))

(ert-deftest test-chime-tooltip-lookahead-hours-rejects-negative ()
  "Error: negative integer raises."
  (let ((chime-tooltip-lookahead-hours 168))
    (should-error (customize-set-variable
                   'chime-tooltip-lookahead-hours -1)
                  :type 'user-error)))

;;;; chime-modeline-tooltip-max-events — nil or integer >= 1

(ert-deftest test-chime-modeline-tooltip-max-events-accepts-nil ()
  "Boundary: nil means show all (per docstring)."
  (let ((chime-modeline-tooltip-max-events 5))
    (customize-set-variable 'chime-modeline-tooltip-max-events nil)
    (should (null chime-modeline-tooltip-max-events))))

(ert-deftest test-chime-modeline-tooltip-max-events-accepts-positive ()
  "Normal: 1 is the floor when set."
  (let ((chime-modeline-tooltip-max-events 5))
    (customize-set-variable 'chime-modeline-tooltip-max-events 1)
    (should (= 1 chime-modeline-tooltip-max-events))))

(ert-deftest test-chime-modeline-tooltip-max-events-rejects-zero ()
  "Error: 0 events makes the tooltip empty by config rather than nil."
  (let ((chime-modeline-tooltip-max-events 5))
    (should-error (customize-set-variable
                   'chime-modeline-tooltip-max-events 0)
                  :type 'user-error)))

;;;; chime-day-wide-advance-notice — nil or integer >= 0

(ert-deftest test-chime-day-wide-advance-notice-accepts-nil ()
  "Boundary: nil means same-day only (per docstring)."
  (let ((chime-day-wide-advance-notice 1))
    (customize-set-variable 'chime-day-wide-advance-notice nil)
    (should (null chime-day-wide-advance-notice))))

(ert-deftest test-chime-day-wide-advance-notice-accepts-zero ()
  "Boundary: 0 is the floor (same-day only) when set."
  (let ((chime-day-wide-advance-notice nil))
    (customize-set-variable 'chime-day-wide-advance-notice 0)
    (should (= 0 chime-day-wide-advance-notice))))

(ert-deftest test-chime-day-wide-advance-notice-rejects-negative ()
  "Error: negative-day advance notice is meaningless."
  (let ((chime-day-wide-advance-notice nil))
    (should-error (customize-set-variable
                   'chime-day-wide-advance-notice -1)
                  :type 'user-error)))

;;;; chime-max-consecutive-failures — integer >= 0

(ert-deftest test-chime-max-consecutive-failures-accepts-zero ()
  "Normal: 0 disables failure warnings (per docstring)."
  (let ((chime-max-consecutive-failures 5))
    (customize-set-variable 'chime-max-consecutive-failures 0)
    (should (= 0 chime-max-consecutive-failures))))

(ert-deftest test-chime-max-consecutive-failures-rejects-negative ()
  "Error: negative threshold is meaningless."
  (let ((chime-max-consecutive-failures 5))
    (should-error (customize-set-variable
                   'chime-max-consecutive-failures -1)
                  :type 'user-error)))

;;;; chime-async-timeout — integer >= 1, or nil to disable

(ert-deftest test-chime-async-timeout-accepts-positive-integer ()
  "Normal: a positive timeout in seconds lands."
  (let ((chime-async-timeout 120))
    (customize-set-variable 'chime-async-timeout 300)
    (should (= 300 chime-async-timeout))))

(ert-deftest test-chime-async-timeout-accepts-nil ()
  "Boundary: nil disables the watchdog (per docstring)."
  (let ((chime-async-timeout 120))
    (customize-set-variable 'chime-async-timeout nil)
    (should (null chime-async-timeout))))

(ert-deftest test-chime-async-timeout-rejects-zero ()
  "Error: a zero-second timeout would interrupt every spawn immediately."
  (let ((chime-async-timeout 120))
    (should-error (customize-set-variable 'chime-async-timeout 0)
                  :type 'user-error)))

(ert-deftest test-chime-async-timeout-rejects-non-integer ()
  "Error: a string raises `user-error' at customize time."
  (let ((chime-async-timeout 120))
    (should-error (customize-set-variable 'chime-async-timeout "120")
                  :type 'user-error)))

;; Note: `chime--validation-max-retries' was demoted from defcustom to
;; defvar in 0.8 — no customize-time setter, no validation tests here.

(provide 'test-chime-numeric-defcustom-setters)
;;; test-chime-numeric-defcustom-setters.el ends here