aboutsummaryrefslogtreecommitdiff
path: root/tests/test-music-config-more-commands.el
blob: a029a5a33c9768af2f54634a8fe7dd6c3dfb3cd2 (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
;;; test-music-config-more-commands.el --- More music-config command tests -*- lexical-binding: t; -*-

;;; Commentary:
;; Sibling `test-music-config-commands.el' covers add/fuzzy/clear/
;; next/previous/consume.  This file covers more wrappers:
;;
;;   cj/music-playlist-load
;;   cj/music-playlist-save
;;   cj/music-playlist-edit
;;   cj/music-playlist-toggle
;;   cj/music-playlist-show
;;   cj/music-create-radio-station

;;; Code:

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

(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
(require 'music-config)

;; Top-level defvars so let-binds reach the dynamic var under lexical
;; scope.
(defvar cj/music-playlist-file nil)
(defvar emms-source-playlist-ask-before-overwrite t)

;;; cj/music-playlist-load

(ert-deftest test-music-playlist-load-plays-selected-playlist ()
  "Normal: load picks an entry, clears the playlist, and plays the file."
  (let* ((tmp (file-name-as-directory (make-temp-file "cj-music-m3u-" t)))
         (rock (expand-file-name "rock.m3u" tmp))
         played)
    (with-temp-file rock (insert "/song.mp3\n"))
    (unwind-protect
        (cl-letf (((symbol-function 'cj/music--assert-m3u-files-exist)
                   (lambda () (list (cons "rock" rock))))
                  ((symbol-function 'completing-read)
                   (lambda (&rest _) "rock"))
                  ((symbol-function 'emms-playlist-clear) #'ignore)
                  ((symbol-function 'emms-play-playlist)
                   (lambda (f) (setq played f)))
                  ((symbol-function 'cj/music--sync-playlist-file) #'ignore)
                  ((symbol-function 'message) #'ignore))
          (cj/music-playlist-load))
      (delete-directory tmp t))
    (should (equal played rock))))

(ert-deftest test-music-playlist-load-errors-when-target-missing ()
  "Error: a missing target file signals user-error."
  (cl-letf (((symbol-function 'cj/music--assert-m3u-files-exist)
             (lambda () (list (cons "gone" "/no/such/file.m3u"))))
            ((symbol-function 'completing-read)
             (lambda (&rest _) "gone")))
    (should-error (cj/music-playlist-load) :type 'user-error)))

;;; cj/music-playlist-save

(ert-deftest test-music-playlist-save-writes-fresh-name ()
  "Normal: save with a fresh name writes via emms-playlist-save."
  (let* ((tmp (file-name-as-directory (make-temp-file "cj-music-save-" t)))
         (cj/music-m3u-root tmp)
         saved-args msg)
    (unwind-protect
        (cl-letf (((symbol-function 'cj/music--get-m3u-basenames)
                   (lambda () nil))
                  ((symbol-function 'completing-read)
                   (lambda (&rest _) "fresh"))
                  ((symbol-function 'cj/music--ensure-playlist-buffer)
                   (lambda () (current-buffer)))
                  ((symbol-function 'emms-playlist-save)
                   (lambda (fmt path) (setq saved-args (list fmt path))))
                  ((symbol-function 'cj/music--sync-playlist-file) #'ignore)
                  ((symbol-function 'message)
                   (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
          (cj/music-playlist-save))
      (delete-directory tmp t))
    (should (equal (car saved-args) 'm3u))
    (should (string-match-p "fresh\\.m3u\\'" (cadr saved-args)))
    (should (string-match-p "Saved playlist" msg))))

;;; cj/music-playlist-edit

(ert-deftest test-music-playlist-edit-opens-file-other-window ()
  "Normal: with an unmodified playlist file present, edit opens it."
  (let* ((tmp (make-temp-file "cj-music-edit-" nil ".m3u"))
         (cj/music-playlist-file tmp)
         opened)
    (with-temp-file tmp (insert "/song.mp3\n"))
    (unwind-protect
        (cl-letf (((symbol-function 'cj/music--assert-valid-playlist-file) #'ignore)
                  ((symbol-function 'cj/music--ensure-playlist-buffer)
                   (lambda () (current-buffer)))
                  ((symbol-function 'cj/music--playlist-modified-p)
                   (lambda () nil))
                  ((symbol-function 'find-file-other-window)
                   (lambda (f) (setq opened f))))
          (cj/music-playlist-edit))
      (delete-file tmp))
    (should (equal opened tmp))))

;;; cj/music-playlist-toggle

(ert-deftest test-music-playlist-toggle-hides-when-visible ()
  "Normal: with the playlist buffer showing, toggle deletes the window."
  (let* ((cj/music-playlist-buffer-name "*test-cj-music*")
         (buf (get-buffer-create cj/music-playlist-buffer-name))
         deleted msg)
    (unwind-protect
        (cl-letf (((symbol-function 'get-buffer-window)
                   (lambda (&rest _) 'fake-win))
                  ((symbol-function 'delete-window)
                   (lambda (w) (setq deleted w)))
                  ((symbol-function 'message)
                   (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
          (cj/music-playlist-toggle))
      (kill-buffer buf))
    (should (eq deleted 'fake-win))
    (should (string-match-p "closed" msg))))

;;; cj/music-playlist-show

(ert-deftest test-music-playlist-show-switches-to-playlist-buffer ()
  "Normal: show calls switch-to-buffer with the playlist buffer."
  (let* ((cj/music-playlist-buffer-name "*test-cj-music-show*")
         (buf (get-buffer-create cj/music-playlist-buffer-name))
         switched msg)
    (unwind-protect
        (cl-letf (((symbol-function 'cj/emms--setup) #'ignore)
                  ((symbol-function 'cj/music--ensure-playlist-buffer)
                   (lambda () buf))
                  ((symbol-function 'switch-to-buffer)
                   (lambda (b) (setq switched b)))
                  ((symbol-function 'message)
                   (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
          (cj/music-playlist-show))
      (kill-buffer buf))
    (should (eq switched buf))
    (should msg)))

;;; cj/music-create-radio-station

(ert-deftest test-music-create-radio-station-writes-m3u ()
  "Normal: with name+url, an EXTM3U-style file is written into music-m3u-root."
  (let* ((tmp (file-name-as-directory (make-temp-file "cj-music-radio-" t)))
         (cj/music-m3u-root tmp)
         msg)
    (unwind-protect
        (progn
          (cl-letf (((symbol-function 'message)
                     (lambda (fmt &rest args) (setq msg (apply #'format fmt args)))))
            (cj/music-create-radio-station "NPR" "https://example.test/stream"))
          (let ((file (expand-file-name "NPR_Radio.m3u" tmp)))
            (should (file-exists-p file))
            (with-temp-buffer
              (insert-file-contents file)
              (let ((text (buffer-string)))
                (should (string-match-p "#EXTM3U" text))
                (should (string-match-p "NPR" text))
                (should (string-match-p "https://example.test/stream" text))))))
      (delete-directory tmp t))
    (should (string-match-p "Created radio station" msg))))

(ert-deftest test-music-create-radio-station-rejects-empty-name ()
  "Error: an empty name is rejected with user-error."
  (should-error (cj/music-create-radio-station "" "https://x") :type 'user-error))

(ert-deftest test-music-create-radio-station-rejects-empty-url ()
  "Error: an empty URL is rejected with user-error."
  (should-error (cj/music-create-radio-station "NPR" "") :type 'user-error))

(provide 'test-music-config-more-commands)
;;; test-music-config-more-commands.el ends here