summaryrefslogtreecommitdiff
path: root/tests/test-music-config--playlist-modified-p.el
blob: cbfc71e3de3170e51e28512aa951283080f3d353 (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
;;; test-music-config--playlist-modified-p.el --- Tests for playlist modification detection -*- coding: utf-8; lexical-binding: t; -*-
;;
;; Author: Craig Jennings <c@cjennings.net>
;;
;;; Commentary:
;; Unit tests for cj/music--playlist-modified-p function.
;; Tests the logic that compares the current EMMS playlist buffer
;; against its associated M3U file to detect unsaved changes.
;;
;; Test organization:
;; - Normal Cases: Matching/differing track lists
;; - Boundary Cases: Empty playlists, nil file, ordering
;; - Error Cases: Missing M3U file, missing buffer
;;
;;; 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-modified--setup-playlist-buffer (track-names)
  "Create an EMMS playlist buffer with TRACK-NAMES and return it.
Each entry in TRACK-NAMES becomes a file track in the playlist."
  (let ((buf (get-buffer-create cj/music-playlist-buffer-name)))
    (with-current-buffer buf
      (emms-playlist-mode)
      (setq emms-playlist-buffer-p t)
      (let ((inhibit-read-only t))
        (erase-buffer)
        (dolist (name track-names)
          (emms-playlist-insert-track (emms-track 'file name)))))
    (setq emms-playlist-buffer buf)
    buf))

(defun test-modified--teardown ()
  "Clean up test playlist buffer."
  (when-let ((buf (get-buffer cj/music-playlist-buffer-name)))
    (kill-buffer buf)))

;;; Normal Cases

(ert-deftest test-music-config--playlist-modified-p-normal-identical-tracks-returns-nil ()
  "Identical track lists in file and playlist returns nil (not modified)."
  (unwind-protect
      (let* ((tracks '("/music/a.mp3" "/music/b.mp3" "/music/c.mp3"))
             (cj/music-playlist-file "/fake/playlist.m3u"))
        (test-modified--setup-playlist-buffer tracks)
        (cl-letf (((symbol-function 'cj/music--m3u-file-tracks)
                   (lambda (_file) tracks)))
          (should-not (cj/music--playlist-modified-p))))
    (test-modified--teardown)))

(ert-deftest test-music-config--playlist-modified-p-normal-different-tracks-returns-non-nil ()
  "Different track lists returns non-nil (modified)."
  (unwind-protect
      (let* ((file-tracks '("/music/a.mp3" "/music/b.mp3"))
             (buf-tracks '("/music/a.mp3" "/music/c.mp3"))
             (cj/music-playlist-file "/fake/playlist.m3u"))
        (test-modified--setup-playlist-buffer buf-tracks)
        (cl-letf (((symbol-function 'cj/music--m3u-file-tracks)
                   (lambda (_file) file-tracks)))
          (should (cj/music--playlist-modified-p))))
    (test-modified--teardown)))

(ert-deftest test-music-config--playlist-modified-p-normal-extra-track-returns-non-nil ()
  "Playlist with extra track compared to file returns non-nil."
  (unwind-protect
      (let* ((file-tracks '("/music/a.mp3" "/music/b.mp3"))
             (buf-tracks '("/music/a.mp3" "/music/b.mp3" "/music/c.mp3"))
             (cj/music-playlist-file "/fake/playlist.m3u"))
        (test-modified--setup-playlist-buffer buf-tracks)
        (cl-letf (((symbol-function 'cj/music--m3u-file-tracks)
                   (lambda (_file) file-tracks)))
          (should (cj/music--playlist-modified-p))))
    (test-modified--teardown)))

;;; Boundary Cases

(ert-deftest test-music-config--playlist-modified-p-boundary-no-playlist-file-returns-nil ()
  "Nil cj/music-playlist-file returns nil without comparing tracks."
  (unwind-protect
      (let ((cj/music-playlist-file nil))
        (test-modified--setup-playlist-buffer '("/music/a.mp3"))
        (should-not (cj/music--playlist-modified-p)))
    (test-modified--teardown)))

(ert-deftest test-music-config--playlist-modified-p-boundary-empty-file-and-playlist-returns-nil ()
  "Both empty file tracks and empty playlist returns nil."
  (unwind-protect
      (let ((cj/music-playlist-file "/fake/playlist.m3u"))
        (test-modified--setup-playlist-buffer '())
        (cl-letf (((symbol-function 'cj/music--m3u-file-tracks)
                   (lambda (_file) nil)))
          (should-not (cj/music--playlist-modified-p))))
    (test-modified--teardown)))

(ert-deftest test-music-config--playlist-modified-p-boundary-order-difference-returns-non-nil ()
  "Same tracks in different order returns non-nil."
  (unwind-protect
      (let* ((file-tracks '("/music/a.mp3" "/music/b.mp3"))
             (buf-tracks '("/music/b.mp3" "/music/a.mp3"))
             (cj/music-playlist-file "/fake/playlist.m3u"))
        (test-modified--setup-playlist-buffer buf-tracks)
        (cl-letf (((symbol-function 'cj/music--m3u-file-tracks)
                   (lambda (_file) file-tracks)))
          (should (cj/music--playlist-modified-p))))
    (test-modified--teardown)))

;;; Error Cases

(ert-deftest test-music-config--playlist-modified-p-error-missing-m3u-file-returns-nil ()
  "When M3U file doesn't exist, m3u-file-tracks returns nil; empty playlist matches."
  (unwind-protect
      (let ((cj/music-playlist-file "/nonexistent/playlist.m3u"))
        (test-modified--setup-playlist-buffer '())
        ;; cj/music--m3u-file-tracks returns nil for nonexistent files
        ;; empty playlist also returns nil, so equal = not modified
        (should-not (cj/music--playlist-modified-p)))
    (test-modified--teardown)))

(ert-deftest test-music-config--playlist-modified-p-error-missing-m3u-with-tracks-returns-non-nil ()
  "When M3U file doesn't exist but playlist has tracks, returns non-nil."
  (unwind-protect
      (let ((cj/music-playlist-file "/nonexistent/playlist.m3u"))
        (test-modified--setup-playlist-buffer '("/music/a.mp3"))
        ;; m3u-file-tracks returns nil, but playlist has tracks = modified
        (should (cj/music--playlist-modified-p)))
    (test-modified--teardown)))

(provide 'test-music-config--playlist-modified-p)
;;; test-music-config--playlist-modified-p.el ends here