summaryrefslogtreecommitdiff
path: root/tests/test-prog-json--json-format-buffer.el
blob: 227eafb956bf65e5c926e0ccb05808a29ba46b53 (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
;;; test-prog-json--json-format-buffer.el --- Tests for cj/json-format-buffer -*- lexical-binding: t -*-

;;; Commentary:
;; Tests for the cj/json-format-buffer function in prog-json.el.
;; Tests both the jq path and the built-in fallback path.

;;; Code:

(require 'ert)
(require 'json)
(require 'prog-json)

;;; Normal Cases — jq path

(ert-deftest test-prog-json--json-format-buffer-normal-formats-object ()
  "Compact JSON object is pretty-printed with sorted keys."
  (with-temp-buffer
    (insert "{\"zebra\":1,\"alpha\":2}")
    (cj/json-format-buffer)
    (should (string= (string-trim (buffer-string))
                     "{\n  \"alpha\": 2,\n  \"zebra\": 1\n}"))))

(ert-deftest test-prog-json--json-format-buffer-normal-formats-array ()
  "Compact JSON array is pretty-printed."
  (with-temp-buffer
    (insert "[1,2,3]")
    (cj/json-format-buffer)
    (should (string= (string-trim (buffer-string))
                     "[\n  1,\n  2,\n  3\n]"))))

(ert-deftest test-prog-json--json-format-buffer-normal-nested ()
  "Nested JSON is pretty-printed with sorted keys at all levels."
  (with-temp-buffer
    (insert "{\"b\":{\"d\":1,\"c\":2},\"a\":3}")
    (cj/json-format-buffer)
    (should (string-match-p "\"a\": 3" (buffer-string)))
    (should (string-match-p "\"c\": 2" (buffer-string)))
    ;; "a" should appear before "b" (sorted)
    (should (< (string-match "\"a\"" (buffer-string))
               (string-match "\"b\"" (buffer-string))))))

(ert-deftest test-prog-json--json-format-buffer-normal-already-formatted ()
  "Already-formatted JSON is unchanged."
  (let ((formatted "{\n  \"alpha\": 1,\n  \"beta\": 2\n}\n"))
    (with-temp-buffer
      (insert formatted)
      (cj/json-format-buffer)
      (should (string= (buffer-string) formatted)))))

;;; Boundary Cases

(ert-deftest test-prog-json--json-format-buffer-boundary-empty-object ()
  "Empty JSON object formats cleanly."
  (with-temp-buffer
    (insert "{}")
    (cj/json-format-buffer)
    (should (string= (string-trim (buffer-string)) "{}"))))

(ert-deftest test-prog-json--json-format-buffer-boundary-empty-array ()
  "Empty JSON array formats cleanly."
  (with-temp-buffer
    (insert "[]")
    (cj/json-format-buffer)
    (should (string= (string-trim (buffer-string)) "[]"))))

(ert-deftest test-prog-json--json-format-buffer-boundary-scalar-string ()
  "Bare JSON string scalar formats without error."
  (with-temp-buffer
    (insert "\"hello\"")
    (cj/json-format-buffer)
    (should (string= (string-trim (buffer-string)) "\"hello\""))))

(ert-deftest test-prog-json--json-format-buffer-boundary-unicode ()
  "JSON with unicode characters is preserved."
  (with-temp-buffer
    (insert "{\"emoji\":\"\\u2764\",\"name\":\"café\"}")
    (cj/json-format-buffer)
    (should (string-match-p "café" (buffer-string)))))

;;; Fallback path — built-in formatter

(ert-deftest test-prog-json--json-format-buffer-fallback-formats-without-jq ()
  "Falls back to built-in formatter when jq is not found."
  (cl-letf (((symbol-function 'executable-find) (lambda (_) nil)))
    (with-temp-buffer
      (insert "{\"b\":1,\"a\":2}")
      (cj/json-format-buffer)
      ;; Built-in formatter should pretty-print (key order may vary)
      (should (string-match-p "\"a\"" (buffer-string)))
      (should (string-match-p "\"b\"" (buffer-string)))
      ;; Should be multi-line (formatted, not compact)
      (should (> (count-lines (point-min) (point-max)) 1)))))

;;; Error Cases

(ert-deftest test-prog-json--json-format-buffer-error-invalid-json ()
  "Invalid JSON produces an error, does not silently corrupt buffer."
  (with-temp-buffer
    (insert "{not valid json}")
    (let ((original (buffer-string)))
      ;; jq will fail on invalid JSON — buffer should not be emptied
      (condition-case _err
          (cj/json-format-buffer)
        (error nil))
      ;; Buffer should still have content (not wiped)
      (should (> (length (buffer-string)) 0)))))

(provide 'test-prog-json--json-format-buffer)
;;; test-prog-json--json-format-buffer.el ends here