aboutsummaryrefslogtreecommitdiff
path: root/tests/test-custom-buffer-file--diff-whitespace-only.el
blob: e792637b580b19fada1ef5d7849e6015e5f6b6da (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
;;; test-custom-buffer-file--diff-whitespace-only.el --- whitespace-only diff detection -*- lexical-binding: t; -*-

;;; Commentary:
;; Tests for cj/--diff-whitespace-only-p, the route-1 detector behind the
;; buffer-differs save prompt: two files differ ONLY in whitespace when a plain
;; diff finds changes but `diff -w' (ignore all whitespace) finds none.  Uses
;; real temp files and the real diff(1) binary (a system boundary we keep), so
;; nothing is mocked.

;;; Code:

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

(declare-function cj/--diff-whitespace-only-p "custom-buffer-file" (file-a file-b))

(defun test-cbf-ws--two-files (content-a content-b fn)
  "Write CONTENT-A and CONTENT-B to temp files, call FN with their paths, clean up."
  (let ((a (make-temp-file "cbf-ws-a-"))
        (b (make-temp-file "cbf-ws-b-")))
    (unwind-protect
        (progn
          (with-temp-file a (insert content-a))
          (with-temp-file b (insert content-b))
          (funcall fn a b))
      (delete-file a)
      (delete-file b))))

(ert-deftest test-cbf-diff-whitespace-only-trailing ()
  "Normal: files differing only by trailing whitespace are whitespace-only."
  (test-cbf-ws--two-files
   "alpha\nbeta\n" "alpha   \nbeta\n"
   (lambda (a b) (should (cj/--diff-whitespace-only-p a b)))))

(ert-deftest test-cbf-diff-whitespace-only-indentation ()
  "Normal: files differing only by leading indentation are whitespace-only."
  (test-cbf-ws--two-files
   "(foo)\n(bar)\n" "(foo)\n    (bar)\n"
   (lambda (a b) (should (cj/--diff-whitespace-only-p a b)))))

(ert-deftest test-cbf-diff-whitespace-only-real-content ()
  "Normal: files differing in actual content are NOT whitespace-only."
  (test-cbf-ws--two-files
   "alpha\nbeta\n" "alpha\nGAMMA\n"
   (lambda (a b) (should-not (cj/--diff-whitespace-only-p a b)))))

(ert-deftest test-cbf-diff-whitespace-only-identical ()
  "Boundary: identical files do not differ at all, so not whitespace-only."
  (test-cbf-ws--two-files
   "alpha\nbeta\n" "alpha\nbeta\n"
   (lambda (a b) (should-not (cj/--diff-whitespace-only-p a b)))))

(ert-deftest test-cbf-diff-whitespace-only-mixed ()
  "Boundary: whitespace change plus a real content change is NOT whitespace-only."
  (test-cbf-ws--two-files
   "alpha\nbeta\n" "alpha   \nGAMMA\n"
   (lambda (a b) (should-not (cj/--diff-whitespace-only-p a b)))))

;;; -------------------- cj/--diff-buffer-renderer -----------------------------
;; Which renderer the diff command uses: whitespace-only diffs go to a plain
;; unified diff (trailing whitespace highlighted, so it is actually visible)
;; because difftastic treats trailing-whitespace as no change and renders it
;; blank.  Real content diffs use difftastic when available, else plain diff.

(declare-function cj/--diff-buffer-renderer "custom-buffer-file" (ws-only difft-available))

(ert-deftest test-cbf-diff-renderer-whitespace-over-difftastic ()
  "Normal: a whitespace-only diff uses the whitespace renderer even when difft is present."
  (should (eq (cj/--diff-buffer-renderer t t) 'whitespace)))

(ert-deftest test-cbf-diff-renderer-whitespace-no-difft ()
  "Boundary: whitespace-only still uses the whitespace renderer without difft."
  (should (eq (cj/--diff-buffer-renderer t nil) 'whitespace)))

(ert-deftest test-cbf-diff-renderer-content-uses-difftastic ()
  "Normal: a content diff uses difftastic when it is available."
  (should (eq (cj/--diff-buffer-renderer nil t) 'difftastic)))

(ert-deftest test-cbf-diff-renderer-content-no-difft-regular ()
  "Boundary: a content diff falls back to the regular renderer without difft."
  (should (eq (cj/--diff-buffer-renderer nil nil) 'regular)))

;;; --------------- cj/--buffer-file-whitespace-only-p (buffer) ----------------
;; Buffer-vs-its-file variant: writes the buffer to a temp file and reuses the
;; detector against the buffer's visited file.  Uses a real visited-file buffer.

(declare-function cj/--buffer-file-whitespace-only-p "custom-buffer-file" (buffer))

(defun test-cbf-ws--with-visited (disk-content edit-fn body-fn)
  "Visit a temp file holding DISK-CONTENT, apply EDIT-FN in it, call BODY-FN with the buffer."
  (let ((f (make-temp-file "cbf-bws-" nil ".txt")))
    (unwind-protect
        (progn
          (with-temp-file f (insert disk-content))
          (let ((buf (find-file-noselect f)))
            (unwind-protect
                (with-current-buffer buf
                  (funcall edit-fn)
                  (funcall body-fn buf))
              (with-current-buffer buf (set-buffer-modified-p nil))
              (kill-buffer buf))))
      (when (file-exists-p f) (delete-file f)))))

(ert-deftest test-cbf-buffer-file-ws-only-trailing ()
  "Normal: an unsaved trailing-whitespace edit is whitespace-only vs the file."
  (test-cbf-ws--with-visited
   "alpha\nbeta\n"
   (lambda () (goto-char (point-min)) (end-of-line) (insert "   "))
   (lambda (buf) (should (cj/--buffer-file-whitespace-only-p buf)))))

(ert-deftest test-cbf-buffer-file-ws-only-content ()
  "Normal: an unsaved content edit is NOT whitespace-only vs the file."
  (test-cbf-ws--with-visited
   "alpha\nbeta\n"
   (lambda () (goto-char (point-max)) (insert "gamma\n"))
   (lambda (buf) (should-not (cj/--buffer-file-whitespace-only-p buf)))))

;;; --------- cj/diff-buffer-with-file return value (for the toggle) -----------

(ert-deftest test-cbf-diff-returns-buffer-when-differs ()
  "Normal: cj/diff-buffer-with-file returns the live diff buffer when the buffer differs."
  (test-cbf-ws--with-visited
   "x\ny\n"
   (lambda () (goto-char (point-max)) (insert "ADDED\n"))
   (lambda (buf)
     (let ((db (with-current-buffer buf (cj/diff-buffer-with-file))))
       (should (bufferp db))
       (should (buffer-live-p db))))))

(ert-deftest test-cbf-diff-returns-nil-when-identical ()
  "Boundary: with no differences, cj/diff-buffer-with-file returns nil."
  (test-cbf-ws--with-visited
   "x\ny\n"
   (lambda () nil)
   (lambda (buf)
     (should-not (with-current-buffer buf (cj/diff-buffer-with-file))))))

(ert-deftest test-cbf-buffer-file-ws-only-non-file ()
  "Boundary: a buffer not visiting a file is not whitespace-only."
  (with-temp-buffer
    (insert "scratch")
    (should-not (cj/--buffer-file-whitespace-only-p (current-buffer)))))

(provide 'test-custom-buffer-file--diff-whitespace-only)
;;; test-custom-buffer-file--diff-whitespace-only.el ends here