summaryrefslogtreecommitdiff
path: root/tests/test-custom-comments-delete-buffer-comments.el
blob: a21386f95de34821505c34c1df20a25409bb06ae (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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
;;; test-custom-comments-delete-buffer-comments.el --- Tests for cj/delete-buffer-comments -*- lexical-binding: t; -*-

;;; Commentary:
;; Tests for the cj/delete-buffer-comments function from custom-comments.el
;;
;; This function deletes all comments in the current buffer by delegating to
;; Emacs' built-in `comment-kill` function.
;;
;; Cross-Language Testing Strategy:
;; --------------------------------
;; This function works across multiple programming languages/major modes because
;; it delegates to `comment-kill`, which respects each mode's comment syntax
;; (comment-start, comment-end).
;;
;; Rather than testing exhaustively in every language (8+ languages = 100+ tests),
;; we test strategically:
;;
;; 1. EXTENSIVE testing in Emacs Lisp (our primary language):
;;    - ~15 tests covering all normal/boundary/error cases
;;    - Tests edge cases: empty buffers, inline comments, unicode, etc.
;;
;; 2. REPRESENTATIVE testing in Python and C:
;;    - ~3 tests each proving different comment syntaxes work
;;    - Python: hash-based comments (#)
;;    - C: C-style line (//) and block (/* */) comments
;;
;; Why this approach?
;; - OUR code is simple: (goto-char (point-min)) + (comment-kill ...)
;; - We're testing OUR integration logic, not Emacs' comment-kill implementation
;; - After proving 3 different syntaxes work, additional languages have
;;   diminishing returns (testing Emacs internals, not our code)
;; - Avoids test suite bloat (21 tests vs 100+) while maintaining confidence
;; - Groups languages by similarity: C-style covers C/Java/Go/JavaScript/Rust
;;
;; See ai-prompts/quality-engineer.org: "Testing Framework/Library Integration"

;;; Code:

(require 'ert)
(require 'testutil-general)

;; Add modules directory to load path
(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))

;; Stub dependencies before loading the module
(defvar cj/custom-keymap (make-sparse-keymap)
  "Stub keymap for testing.")

;; Now load the actual production module
(require 'custom-comments)

;;; Test Helper

(defun test-delete-comments-in-mode (mode content-before expected-after)
  "Test comment deletion in MODE.
Insert CONTENT-BEFORE, run cj/delete-buffer-comments, verify EXPECTED-AFTER."
  (with-temp-buffer
    (funcall mode)
    (insert content-before)
    (cj/delete-buffer-comments)
    (should (equal (string-trim (buffer-string)) (string-trim expected-after)))))

;;; Emacs Lisp Tests (Primary Language - Comprehensive Coverage)

(ert-deftest test-delete-comments-elisp-simple-line-comments ()
  "Should delete simple line comments in emacs-lisp-mode."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ";; This is a comment\n(defun foo () nil)"
   "(defun foo () nil)"))

(ert-deftest test-delete-comments-elisp-inline-comments ()
  "Should delete inline/end-of-line comments."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   "(setq x 10) ;; set x to 10"
   "(setq x 10)"))

(ert-deftest test-delete-comments-elisp-only-comments ()
  "Buffer with only comments should become empty."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ";; Comment 1\n;; Comment 2\n;; Comment 3"
   ""))

(ert-deftest test-delete-comments-elisp-mixed-code-and-comments ()
  "Should preserve code and delete all comments."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ";; Header comment\n(defun foo ()\n  ;; body comment\n  (+ 1 2)) ;; inline"
   "(defun foo ()\n\n  (+ 1 2))"))

(ert-deftest test-delete-comments-elisp-empty-buffer ()
  "Should do nothing in empty buffer."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ""
   ""))

(ert-deftest test-delete-comments-elisp-no-comments ()
  "Should preserve all content when no comments exist."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   "(defun foo ()\n  (+ 1 2))"
   "(defun foo ()\n  (+ 1 2))"))

(ert-deftest test-delete-comments-elisp-whitespace-only-comments ()
  "Should delete comments containing only whitespace."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ";;    \n;; \t\n(setq x 1)"
   "(setq x 1)"))

(ert-deftest test-delete-comments-elisp-unicode-in-comments ()
  "Should handle unicode characters in comments."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ";; Hello 👋 مرحبا café\n(setq x 1)"
   "(setq x 1)"))

(ert-deftest test-delete-comments-elisp-indented-comments ()
  "Should delete comments at various indentation levels."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   "(defun foo ()\n  ;; indented comment\n    ;; more indented\n  (+ 1 2))"
   "(defun foo ()\n\n\n  (+ 1 2))"))

(ert-deftest test-delete-comments-elisp-special-chars-in-comments ()
  "Should handle special characters in comments."
  (test-delete-comments-in-mode
   'emacs-lisp-mode
   ";; Special: !@#$%^&*()[]{}|\\/<>?\n(setq x 1)"
   "(setq x 1)"))

(ert-deftest test-delete-comments-elisp-point-not-at-beginning ()
  "Should work regardless of initial point position."
  (with-temp-buffer
    (emacs-lisp-mode)
    (insert ";; Comment 1\n(setq x 1)\n;; Comment 2")
    (goto-char (point-max))  ; Point at end
    (cj/delete-buffer-comments)
    (should (equal (string-trim (buffer-string)) "(setq x 1)"))))

(ert-deftest test-delete-comments-elisp-does-not-affect-kill-ring ()
  "Should not add deleted comments to kill-ring."
  (with-temp-buffer
    (emacs-lisp-mode)
    (insert ";; Comment\n(setq x 1)")
    (setq kill-ring nil)
    (cj/delete-buffer-comments)
    (should (null kill-ring))))

(ert-deftest test-delete-comments-elisp-read-only-buffer ()
  "Should signal error in read-only buffer."
  (with-temp-buffer
    (emacs-lisp-mode)
    (insert ";; Comment\n(setq x 1)")
    (read-only-mode 1)
    (should-error (cj/delete-buffer-comments))))

(ert-deftest test-delete-comments-elisp-narrowed-buffer ()
  "Should only affect visible region when narrowed."
  (with-temp-buffer
    (emacs-lisp-mode)
    (insert ";; Comment 1\n(setq x 1)\n;; Comment 2\n(setq y 2)")
    (goto-char (point-min))
    (forward-line 2)
    (narrow-to-region (point) (point-max))
    (cj/delete-buffer-comments)
    (widen)
    ;; First comment should remain (was outside narrowed region)
    ;; Second comment should be deleted
    (should (string-match-p "Comment 1" (buffer-string)))
    (should-not (string-match-p "Comment 2" (buffer-string)))))


;;; Python Tests (Hash-based comments)

(ert-deftest test-delete-comments-python-simple ()
  "Should delete Python hash comments."
  (test-delete-comments-in-mode
   'python-mode
   "# This is a comment\ndef foo():\n    return 42"
   "def foo():\n    return 42"))

(ert-deftest test-delete-comments-python-inline ()
  "Should delete inline Python comments."
  (test-delete-comments-in-mode
   'python-mode
   "x = 10  # set x to 10\ny = 20"
   "x = 10\ny = 20"))

(ert-deftest test-delete-comments-python-mixed ()
  "Should preserve code and delete Python comments."
  (test-delete-comments-in-mode
   'python-mode
   "# Header\ndef foo():\n    # body\n    return 42  # inline"
   "def foo():\n\n    return 42"))

;;; C Tests (C-style line and block comments)

(ert-deftest test-delete-comments-c-line-comments ()
  "Should delete C line comments (//)."
  (test-delete-comments-in-mode
   'c-mode
   "// This is a comment\nint main() {\n    return 0;\n}"
   "int main() {\n    return 0;\n}"))

(ert-deftest test-delete-comments-c-block-comments ()
  "Should delete C block comments (/* */)."
  (test-delete-comments-in-mode
   'c-mode
   "/* Block comment */\nint x = 10;"
   "int x = 10;"))

(ert-deftest test-delete-comments-c-mixed ()
  "Should delete both line and block comments in C."
  (test-delete-comments-in-mode
   'c-mode
   "// Line comment\n/* Block comment */\nint x = 10; // inline"
   "int x = 10;"))

(provide 'test-custom-comments-delete-buffer-comments)
;;; test-custom-comments-delete-buffer-comments.el ends here