summaryrefslogtreecommitdiff
path: root/tests/test-music-config--track-description.el
blob: a1a1cc6d9f0000f518f025e28398e3b0cfbd0d64 (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
174
175
176
177
178
179
180
181
;;; test-music-config--track-description.el --- Tests for track description -*- coding: utf-8; lexical-binding: t; -*-
;;
;; Author: Craig Jennings <c@cjennings.net>
;;
;;; Commentary:
;; Unit tests for cj/music--track-description function.
;; Tests the custom track description that replaces EMMS's default file-path display
;; with human-readable formats based on track type and available metadata.
;;
;; Track construction: EMMS tracks are alists created with `emms-track' and
;; populated with `emms-track-set'. No playlist buffer or player state needed.
;;
;; Test organization:
;; - Normal Cases: Tagged tracks (artist+title+duration), partial metadata, file fallback, URL
;; - Boundary Cases: Empty strings, missing fields, special characters, long names
;; - Error Cases: Unknown track type fallback
;;
;;; 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-track-description--make-file-track (path &optional title artist duration)
  "Create a file TRACK with PATH and optional metadata TITLE, ARTIST, DURATION."
  (let ((track (emms-track 'file path)))
    (when title (emms-track-set track 'info-title title))
    (when artist (emms-track-set track 'info-artist artist))
    (when duration (emms-track-set track 'info-playing-time duration))
    track))

(defun test-track-description--make-url-track (url &optional title artist duration)
  "Create a URL TRACK with URL and optional metadata TITLE, ARTIST, DURATION."
  (let ((track (emms-track 'url url)))
    (when title (emms-track-set track 'info-title title))
    (when artist (emms-track-set track 'info-artist artist))
    (when duration (emms-track-set track 'info-playing-time duration))
    track))

;;; Normal Cases — Tagged tracks (artist + title + duration)

(ert-deftest test-music-config--track-description-normal-full-metadata ()
  "Validate track with artist, title, and duration shows all three."
  (let ((track (test-track-description--make-file-track
                "/music/Kind of Blue/01 - So What.flac"
                "So What" "Miles Davis" 562)))
    (should (string= (cj/music--track-description track)
                     "Miles Davis - So What  [9:22]"))))

(ert-deftest test-music-config--track-description-normal-title-and-artist-no-duration ()
  "Validate track with artist and title but no duration omits bracket."
  (let ((track (test-track-description--make-file-track
                "/test/uncached-nodur.mp3" "Blue in Green" "Miles Davis")))
    (should (string= (cj/music--track-description track)
                     "Miles Davis - Blue in Green"))))

(ert-deftest test-music-config--track-description-normal-title-only ()
  "Validate track with title but no artist shows title alone."
  (let ((track (test-track-description--make-file-track
                "/test/uncached-noartist.mp3" "Flamenco Sketches" nil 566)))
    (should (string= (cj/music--track-description track)
                     "Flamenco Sketches  [9:26]"))))

(ert-deftest test-music-config--track-description-normal-title-only-no-duration ()
  "Validate track with only title shows just the title."
  (let ((track (test-track-description--make-file-track
                "/test/uncached-titleonly.mp3" "All Blues")))
    (should (string= (cj/music--track-description track)
                     "All Blues"))))

;;; Normal Cases — File tracks without tags

(ert-deftest test-music-config--track-description-normal-file-no-tags ()
  "Validate untagged file shows filename without path or extension."
  (let ((track (test-track-description--make-file-track
                "/music/Kind of Blue/02 - Freddie Freeloader.flac")))
    (should (string= (cj/music--track-description track)
                     "02 - Freddie Freeloader"))))

(ert-deftest test-music-config--track-description-normal-file-nested-path ()
  "Validate deeply nested path still shows only the filename."
  (let ((track (test-track-description--make-file-track
                "/music/Jazz/Miles Davis/Kind of Blue/01 - So What.mp3")))
    (should (string= (cj/music--track-description track)
                     "01 - So What"))))

;;; Normal Cases — URL tracks

(ert-deftest test-music-config--track-description-normal-url-plain ()
  "Validate plain URL is shown as-is."
  (let ((track (test-track-description--make-url-track
                "https://radio.example.com/stream")))
    (should (string= (cj/music--track-description track)
                     "https://radio.example.com/stream"))))

(ert-deftest test-music-config--track-description-normal-url-percent-encoded ()
  "Validate percent-encoded URL characters are decoded."
  (let ((track (test-track-description--make-url-track
                "https://radio.example.com/my%20station%21")))
    (should (string= (cj/music--track-description track)
                     "https://radio.example.com/my station!"))))

(ert-deftest test-music-config--track-description-normal-url-with-tags ()
  "Validate URL track with tags uses tag display, not URL."
  (let ((track (test-track-description--make-url-track
                "https://radio.example.com/stream"
                "Jazz FM" "Radio Station" 0)))
    ;; Duration 0 → nil from format-duration, so no bracket
    (should (string= (cj/music--track-description track)
                     "Radio Station - Jazz FM"))))

;;; Boundary Cases

(ert-deftest test-music-config--track-description-boundary-empty-title-string ()
  "Validate empty title string is still truthy, shows empty result."
  (let ((track (test-track-description--make-file-track
                "/music/track.mp3" "" "Artist")))
    ;; Empty string is non-nil, so title branch is taken
    (should (string= (cj/music--track-description track)
                     "Artist - "))))

(ert-deftest test-music-config--track-description-boundary-file-no-extension ()
  "Validate file without extension shows full filename."
  (let ((track (test-track-description--make-file-track "/music/README")))
    (should (string= (cj/music--track-description track)
                     "README"))))

(ert-deftest test-music-config--track-description-boundary-file-multiple-dots ()
  "Validate file with multiple dots strips only the final extension."
  (let ((track (test-track-description--make-file-track
                "/music/disc.1.track.03.flac")))
    (should (string= (cj/music--track-description track)
                     "disc.1.track.03"))))

(ert-deftest test-music-config--track-description-boundary-unicode-title ()
  "Validate unicode characters in metadata are preserved."
  (let ((track (test-track-description--make-file-track
                "/music/track.mp3" "夜に駆ける" "YOASOBI" 258)))
    (should (string= (cj/music--track-description track)
                     "YOASOBI - 夜に駆ける  [4:18]"))))

(ert-deftest test-music-config--track-description-boundary-url-utf8-percent-encoded ()
  "Validate percent-encoded UTF-8 in URL is decoded correctly."
  (let ((track (test-track-description--make-url-track
                "https://example.com/caf%C3%A9")))
    (should (string= (cj/music--track-description track)
                     "https://example.com/café"))))

(ert-deftest test-music-config--track-description-boundary-short-duration ()
  "Validate 1-second track formats correctly in bracket."
  (let ((track (test-track-description--make-file-track
                "/music/t.mp3" "Beep" nil 1)))
    (should (string= (cj/music--track-description track)
                     "Beep  [0:01]"))))

;;; Error Cases

(ert-deftest test-music-config--track-description-error-unknown-type-fallback ()
  "Validate unknown track type uses emms-track-simple-description fallback."
  (let ((track (emms-track 'streamlist "https://example.com/playlist.m3u")))
    ;; Should not error; falls through to simple-description
    (let ((result (cj/music--track-description track)))
      (should (stringp result))
      (should (string-match-p "example\\.com" result)))))

(provide 'test-music-config--track-description)
;;; test-music-config--track-description.el ends here