blob: 42dcf0e327550c328f68fcb77e9bea96de45d249 (
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
|
;;; test-music-config--after-playlist-clear.el --- Tests for playlist clear advice -*- coding: utf-8; lexical-binding: t; -*-
;;
;; Author: Craig Jennings <c@cjennings.net>
;;
;;; Commentary:
;; Unit tests for cj/music--after-playlist-clear function.
;; Tests the advice function that resets cj/music-playlist-file
;; when the EMMS playlist is cleared.
;;
;; Test organization:
;; - Normal Cases: Clears file variable, noop when no buffer
;; - Boundary Cases: Already nil stays nil, idempotent on multiple calls
;; - Error Cases: Killed buffer doesn't crash
;;
;;; Code:
(require 'ert)
;; Stub missing dependencies before loading music-config
(defvar-keymap cj/custom-keymap
:doc "Stub keymap for testing")
;; Add EMMS elpa directory to load path for batch testing
(let ((emms-dir (car (file-expand-wildcards
(expand-file-name "elpa/emms-*" user-emacs-directory)))))
(when emms-dir
(add-to-list 'load-path emms-dir)))
(require 'emms)
(require 'emms-playlist-mode)
(require 'music-config)
;;; Test helpers
(defun test-after-clear--setup ()
"Create playlist buffer with a playlist file set."
(let ((buf (get-buffer-create cj/music-playlist-buffer-name)))
(with-current-buffer buf
(emms-playlist-mode)
(setq emms-playlist-buffer-p t))
(setq emms-playlist-buffer buf)
buf))
(defun test-after-clear--teardown ()
"Clean up test playlist buffer."
(when-let ((buf (get-buffer cj/music-playlist-buffer-name)))
(with-current-buffer buf
(setq cj/music-playlist-file nil))
(kill-buffer buf)))
;;; Normal Cases
(ert-deftest test-music-config--after-playlist-clear-normal-clears-file-variable ()
"Calling after-playlist-clear sets cj/music-playlist-file to nil."
(unwind-protect
(progn
(test-after-clear--setup)
(with-current-buffer cj/music-playlist-buffer-name
(setq cj/music-playlist-file "/path/to/playlist.m3u"))
(cj/music--after-playlist-clear)
(with-current-buffer cj/music-playlist-buffer-name
(should-not cj/music-playlist-file)))
(test-after-clear--teardown)))
(ert-deftest test-music-config--after-playlist-clear-normal-noop-when-no-buffer ()
"Does nothing when playlist buffer doesn't exist."
(unwind-protect
(progn
;; Ensure no buffer exists
(when-let ((buf (get-buffer cj/music-playlist-buffer-name)))
(kill-buffer buf))
;; Should not error
(cj/music--after-playlist-clear))
(test-after-clear--teardown)))
;;; Boundary Cases
(ert-deftest test-music-config--after-playlist-clear-boundary-already-nil-stays-nil ()
"Already-nil playlist file remains nil after clear."
(unwind-protect
(progn
(test-after-clear--setup)
(with-current-buffer cj/music-playlist-buffer-name
(setq cj/music-playlist-file nil))
(cj/music--after-playlist-clear)
(with-current-buffer cj/music-playlist-buffer-name
(should-not cj/music-playlist-file)))
(test-after-clear--teardown)))
(ert-deftest test-music-config--after-playlist-clear-boundary-multiple-calls-idempotent ()
"Multiple calls produce same result as single call."
(unwind-protect
(progn
(test-after-clear--setup)
(with-current-buffer cj/music-playlist-buffer-name
(setq cj/music-playlist-file "/path/to/playlist.m3u"))
(cj/music--after-playlist-clear)
(cj/music--after-playlist-clear)
(cj/music--after-playlist-clear)
(with-current-buffer cj/music-playlist-buffer-name
(should-not cj/music-playlist-file)))
(test-after-clear--teardown)))
;;; Error Cases
(ert-deftest test-music-config--after-playlist-clear-error-killed-buffer-no-crash ()
"Killed buffer doesn't cause an error."
(let ((buf (test-after-clear--setup)))
(kill-buffer buf)
;; Should not error when buffer is gone
(should-not (condition-case err
(progn (cj/music--after-playlist-clear) nil)
(error err)))))
(ert-deftest test-music-header-toggle-advice-is-named-and-installed ()
"Normal: the header-refresh toggle advice is a named, removable function.
An anonymous lambda can't be advice-removed and stacks a copy on every
:config reload, firing the header refresh N times per toggle."
(should (fboundp 'cj/music--refresh-header-after-toggle))
(dolist (fn '(emms-toggle-repeat-playlist
emms-toggle-repeat-track
emms-toggle-random-playlist
cj/music-toggle-consume))
(should (advice-member-p #'cj/music--refresh-header-after-toggle fn))))
(ert-deftest test-music-header-toggle-advice-does-not-stack ()
"Boundary: re-running the install (a :config reload) keeps one advice copy."
(dolist (fn '(emms-toggle-repeat-playlist emms-toggle-repeat-track))
(advice-remove fn #'cj/music--refresh-header-after-toggle)
(advice-add fn :after #'cj/music--refresh-header-after-toggle)
(advice-remove fn #'cj/music--refresh-header-after-toggle)
(advice-add fn :after #'cj/music--refresh-header-after-toggle)
(let ((count 0))
(advice-mapc (lambda (f _props)
(when (eq f 'cj/music--refresh-header-after-toggle)
(setq count (1+ count))))
fn)
(should (= count 1)))))
(provide 'test-music-config--after-playlist-clear)
;;; test-music-config--after-playlist-clear.el ends here
|