summaryrefslogtreecommitdiff
path: root/tests/test-music-config-create-radio-station.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-04-01 08:13:33 -0500
committerCraig Jennings <c@cjennings.net>2026-04-01 08:13:33 -0500
commitfdc63ea6675709d6ca42362b1be1918f8bf24478 (patch)
tree056dd89c3879b4fd4e928ce8c6772501a7d7ffa5 /tests/test-music-config-create-radio-station.el
parent0d55edecf82b32b75780f24751dfa8d693b72708 (diff)
feat(music): add test coverage for 7 functions, refactor with extracted helpersHEADmain
Add 47 new unit tests across 7 test files covering playlist-modified-p, assert-valid-playlist-file, playlist-tracks, create-radio-station, ensure-playlist-buffer, after-playlist-clear, and header-text. Extract three helpers to reduce duplication: assert-m3u-files-exist (dedupes 2 identical guards), sync-playlist-file (dedupes 3 state-sync patterns), and select-m3u-file (reusable M3U selection with cancel). Simplify append-track-to-playlist nesting from 6 to 4 levels. Delete unused cj/music-keymap-prefix variable.
Diffstat (limited to 'tests/test-music-config-create-radio-station.el')
-rw-r--r--tests/test-music-config-create-radio-station.el153
1 files changed, 153 insertions, 0 deletions
diff --git a/tests/test-music-config-create-radio-station.el b/tests/test-music-config-create-radio-station.el
new file mode 100644
index 00000000..1f4365a4
--- /dev/null
+++ b/tests/test-music-config-create-radio-station.el
@@ -0,0 +1,153 @@
+;;; test-music-config-create-radio-station.el --- Tests for radio station creation -*- coding: utf-8; lexical-binding: t; -*-
+;;
+;; Author: Craig Jennings <c@cjennings.net>
+;;
+;;; Commentary:
+;; Unit tests for cj/music-create-radio-station function.
+;; Tests M3U file creation for radio stations with stream URLs.
+;;
+;; Test organization:
+;; - Normal Cases: Standard creation, EXTM3U format, safe filename
+;; - Boundary Cases: Unicode name, complex URL, overwrite confirmed
+;; - Error Cases: Empty name, empty URL, overwrite declined
+;;
+;;; Code:
+
+(require 'ert)
+(require 'testutil-general)
+
+;; Stub missing dependencies before loading music-config
+(defvar-keymap cj/custom-keymap
+ :doc "Stub keymap for testing")
+
+;; Load production code
+(require 'music-config)
+
+;;; Setup & Teardown
+
+(defun test-music-config-create-radio-station-setup ()
+ "Setup test environment with temp directory for M3U output."
+ (cj/create-test-base-dir)
+ (cj/create-test-subdirectory "radio-playlists"))
+
+(defun test-music-config-create-radio-station-teardown ()
+ "Clean up test environment."
+ (cj/delete-test-base-dir))
+
+;;; Normal Cases
+
+(ert-deftest test-music-config-create-radio-station-normal-creates-m3u-file ()
+ "Creating a radio station produces an M3U file in the music root."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir))
+ (cj/music-create-radio-station "Jazz FM" "http://stream.jazzfm.com/radio")
+ (let ((expected-file (expand-file-name "Jazz_FM_Radio.m3u" test-dir)))
+ (should (file-exists-p expected-file))))
+ (test-music-config-create-radio-station-teardown))))
+
+(ert-deftest test-music-config-create-radio-station-normal-extm3u-format ()
+ "Created file contains EXTM3U header, EXTINF with station name, and URL."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir))
+ (cj/music-create-radio-station "Jazz FM" "http://stream.jazzfm.com/radio")
+ (let ((content (with-temp-buffer
+ (insert-file-contents
+ (expand-file-name "Jazz_FM_Radio.m3u" test-dir))
+ (buffer-string))))
+ (should (string-match-p "^#EXTM3U" content))
+ (should (string-match-p "#EXTINF:-1,Jazz FM" content))
+ (should (string-match-p "http://stream.jazzfm.com/radio" content))))
+ (test-music-config-create-radio-station-teardown))))
+
+(ert-deftest test-music-config-create-radio-station-normal-safe-filename ()
+ "Station name with special characters produces filesystem-safe filename."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir))
+ (cj/music-create-radio-station "Rock & Roll 101.5" "http://example.com/stream")
+ ;; Spaces and special chars replaced with underscores
+ (let ((expected-file (expand-file-name "Rock___Roll_101_5_Radio.m3u" test-dir)))
+ (should (file-exists-p expected-file))))
+ (test-music-config-create-radio-station-teardown))))
+
+;;; Boundary Cases
+
+(ert-deftest test-music-config-create-radio-station-boundary-unicode-name-safe-filename ()
+ "Unicode station name produces safe filename while preserving name in EXTINF."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir))
+ (cj/music-create-radio-station "Klassik Radio" "http://example.com/stream")
+ ;; Name is all ASCII-safe, so filename uses it directly
+ (should (file-exists-p (expand-file-name "Klassik_Radio_Radio.m3u" test-dir)))
+ ;; Original name preserved in EXTINF inside the file
+ (let ((content (with-temp-buffer
+ (insert-file-contents
+ (expand-file-name "Klassik_Radio_Radio.m3u" test-dir))
+ (buffer-string))))
+ (should (string-match-p "Klassik Radio" content))))
+ (test-music-config-create-radio-station-teardown))))
+
+(ert-deftest test-music-config-create-radio-station-boundary-url-with-query-params ()
+ "Complex URL with query parameters preserved in file content."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir)
+ (url "https://stream.example.com/radio?format=mp3&quality=320&token=abc123"))
+ (cj/music-create-radio-station "Test Radio" url)
+ (let ((content (with-temp-buffer
+ (insert-file-contents
+ (expand-file-name "Test_Radio_Radio.m3u" test-dir))
+ (buffer-string))))
+ (should (string-match-p (regexp-quote url) content))))
+ (test-music-config-create-radio-station-teardown))))
+
+(ert-deftest test-music-config-create-radio-station-boundary-overwrite-confirmed ()
+ "Overwriting existing file when user confirms succeeds."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir))
+ ;; Create initial file
+ (cj/music-create-radio-station "MyRadio" "http://old.url/stream")
+ (let ((file (expand-file-name "MyRadio_Radio.m3u" test-dir)))
+ (should (file-exists-p file))
+ ;; Overwrite with user confirming
+ (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+ (cj/music-create-radio-station "MyRadio" "http://new.url/stream"))
+ ;; File should now contain new URL
+ (let ((content (with-temp-buffer
+ (insert-file-contents file)
+ (buffer-string))))
+ (should (string-match-p "http://new.url/stream" content))
+ (should-not (string-match-p "http://old.url/stream" content)))))
+ (test-music-config-create-radio-station-teardown))))
+
+;;; Error Cases
+
+(ert-deftest test-music-config-create-radio-station-error-empty-name-signals-user-error ()
+ "Empty station name signals user-error."
+ (should-error (cj/music-create-radio-station "" "http://example.com/stream")
+ :type 'user-error))
+
+(ert-deftest test-music-config-create-radio-station-error-empty-url-signals-user-error ()
+ "Empty URL signals user-error."
+ (should-error (cj/music-create-radio-station "Test Radio" "")
+ :type 'user-error))
+
+(ert-deftest test-music-config-create-radio-station-error-overwrite-declined-signals-user-error ()
+ "Declining overwrite signals user-error."
+ (let ((test-dir (test-music-config-create-radio-station-setup)))
+ (unwind-protect
+ (let ((cj/music-m3u-root test-dir))
+ ;; Create initial file
+ (cj/music-create-radio-station "MyRadio" "http://old.url/stream")
+ ;; Decline overwrite
+ (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) nil)))
+ (should-error (cj/music-create-radio-station "MyRadio" "http://new.url/stream")
+ :type 'user-error)))
+ (test-music-config-create-radio-station-teardown))))
+
+(provide 'test-music-config-create-radio-station)
+;;; test-music-config-create-radio-station.el ends here