aboutsummaryrefslogtreecommitdiff
path: root/tests/test-music-config--renumber-rows.el
blob: 8abe17044a2c4925ed4e4a95396754d6a6f5aed7 (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
;;; test-music-config--renumber-rows.el --- Tests for playlist row numbering -*- coding: utf-8; lexical-binding: t; -*-
;;
;; Author: Craig Jennings <c@cjennings.net>
;;
;;; Commentary:
;; Playlist rows carry a numeric overlay prefix so the cursor stays visible
;; when it sits on a cover-art thumbnail and each row's position in the list
;; is readable.  The renumber walks the buffer and rebuilds the overlays; a
;; buffer-local after-change hook debounces it behind an idle timer.  Overlays
;; leave the buffer text untouched (EMMS owns it), so these tests drive plain
;; temp buffers.

;;; Code:

(require 'ert)
(require 'cl-lib)

(defvar cj/custom-keymap (make-sparse-keymap)
  "Stub keymap for testing.")

(require 'music-config)

(defun test-music-renumber--numbers (buffer)
  "Return the overlay number strings in BUFFER, in position order."
  (with-current-buffer buffer
    (mapcar (lambda (ov) (overlay-get ov 'before-string))
            (sort (seq-filter (lambda (ov) (overlay-get ov 'cj-music-row-number))
                              (overlays-in (point-min) (point-max)))
                  (lambda (a b) (< (overlay-start a) (overlay-start b)))))))

;;; Normal Cases

(ert-deftest test-music-renumber-rows-numbers-each-line ()
  "Normal: every non-blank line gets a sequential number overlay."
  (with-temp-buffer
    (insert "track one\ntrack two\ntrack three\n")
    (cj/music--renumber-rows (current-buffer))
    (should (equal (mapcar #'substring-no-properties
                           (test-music-renumber--numbers (current-buffer)))
                   '("  1 " "  2 " "  3 ")))))

(ert-deftest test-music-renumber-rows-idempotent ()
  "Normal: renumbering twice leaves one overlay per line, not two."
  (with-temp-buffer
    (insert "track one\ntrack two\n")
    (cj/music--renumber-rows (current-buffer))
    (cj/music--renumber-rows (current-buffer))
    (should (= 2 (length (test-music-renumber--numbers (current-buffer)))))))

;;; Boundary Cases

(ert-deftest test-music-renumber-rows-skips-blank-lines ()
  "Boundary: blank lines are not numbered and don't advance the count."
  (with-temp-buffer
    (insert "track one\n\ntrack two\n")
    (cj/music--renumber-rows (current-buffer))
    (should (equal (mapcar #'substring-no-properties
                           (test-music-renumber--numbers (current-buffer)))
                   '("  1 " "  2 ")))))

(ert-deftest test-music-renumber-rows-empty-buffer-no-overlays ()
  "Boundary: an empty buffer gets no overlays and no error."
  (with-temp-buffer
    (cj/music--renumber-rows (current-buffer))
    (should-not (test-music-renumber--numbers (current-buffer)))))

;;; Error Cases

(ert-deftest test-music-renumber-rows-dead-buffer-noop ()
  "Error: renumbering a killed buffer is a silent no-op (the debounce timer
can fire after the playlist buffer is gone)."
  (let ((buf (generate-new-buffer " *test-renumber-dead*")))
    (kill-buffer buf)
    (should-not (cj/music--renumber-rows buf))))

;;; Hook wiring

(ert-deftest test-music-renumber-ensure-playlist-buffer-wires-hook ()
  "Normal: the playlist buffer gets the debounced renumber on after-change."
  (let (created)
    (cl-letf (((symbol-function 'emms-playlist-mode) #'ignore))
      (unwind-protect
          (progn
            (setq created (cj/music--ensure-playlist-buffer))
            (with-current-buffer created
              (should (member #'cj/music--schedule-renumber after-change-functions))))
        (when (buffer-live-p created) (kill-buffer created))))))

(provide 'test-music-config--renumber-rows)
;;; test-music-config--renumber-rows.el ends here