diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-23 03:42:53 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-23 03:42:53 -0500 |
| commit | 14896ac779ec2b63af4eb7bf1930cf40a6b9988b (patch) | |
| tree | ad5a355c014e650efbb86e09308de5cf89be91e3 /tests/test-media-utils.el | |
| parent | 9dc7590eaa804bbca3aa924304989dbc26a69af3 (diff) | |
| download | dotemacs-14896ac779ec2b63af4eb7bf1930cf40a6b9988b.tar.gz dotemacs-14896ac779ec2b63af4eb7bf1930cf40a6b9988b.zip | |
test(media-utils): cover player discovery and play/download commands
media-utils.el had no tests. I added eight: cj/get-available-media-players filtering by executable-find, cj/media-play-it building a direct command versus the yt-dlp -g stream-URL wrap (plus the missing-player error), and cj/yt-dl-it erroring when yt-dlp or tsp is absent and queueing through tsp + yt-dlp when both are present. Every external boundary is mocked, so nothing launches.
Diffstat (limited to 'tests/test-media-utils.el')
| -rw-r--r-- | tests/test-media-utils.el | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/tests/test-media-utils.el b/tests/test-media-utils.el new file mode 100644 index 00000000..85ee826f --- /dev/null +++ b/tests/test-media-utils.el @@ -0,0 +1,105 @@ +;;; test-media-utils.el --- Tests for media-utils.el -*- lexical-binding: t; -*- + +;;; Commentary: +;; Coverage for the media playback/download helpers. All external boundaries +;; are mocked: `executable-find' decides which players are present, and +;; `start-process' / `start-process-shell-command' capture the command instead +;; of launching anything. The tests assert the integration logic — which +;; players are reported available, and how the play/download command strings +;; are built — not that mpv/yt-dlp themselves work. + +;;; Code: + +(require 'ert) +(require 'cl-lib) +(require 'media-utils) + +;; media-utils.el declares videos-dir with a bare (defvar videos-dir), which is +;; only file-local; declare it special here so the let-binding below is dynamic +;; and reaches cj/yt-dl-it (which reads videos-dir for default-directory). +(defvar videos-dir nil) + +;; ---------------------- cj/get-available-media-players ----------------------- + +(ert-deftest test-media-get-available-players-filters-by-executable () + "Normal: only players whose :command is on PATH are reported." + (cl-letf (((symbol-function 'executable-find) + (lambda (cmd) (and (member cmd '("mpv" "vlc")) cmd)))) + (let ((result (cj/get-available-media-players))) + (should (memq 'mpv result)) + (should (memq 'vlc result)) + (should-not (memq 'mplayer result))))) + +(ert-deftest test-media-get-available-players-none-installed () + "Boundary: with nothing on PATH, the list is empty." + (cl-letf (((symbol-function 'executable-find) (lambda (_) nil))) + (should-not (cj/get-available-media-players)))) + +;; ----------------------------- cj/media-play-it ------------------------------ + +(ert-deftest test-media-play-it-direct-playback-command () + "Normal: a player that needs no stream URL gets a plain command, no yt-dlp." + (let (captured cj/default-media-player) + (setq cj/default-media-player 'mpv) + (cl-letf (((symbol-function 'executable-find) (lambda (_) "/usr/bin/mpv")) + ((symbol-function 'start-process-shell-command) + (lambda (_n _b cmd) (setq captured cmd) 'proc)) + ((symbol-function 'set-process-sentinel) #'ignore) + ((symbol-function 'message) #'ignore) + ((symbol-function 'cj/log-silently) #'ignore)) + (cj/media-play-it "https://example.com/v")) + (should (string-match-p "mpv" captured)) + (should (string-match-p "example\\.com" captured)) + (should-not (string-match-p "yt-dlp" captured)))) + +(ert-deftest test-media-play-it-stream-url-wraps-yt-dlp () + "Normal: a player needing a stream URL wraps the URL in a yt-dlp -g call." + (let (captured cj/default-media-player) + (setq cj/default-media-player 'vlc) + (cl-letf (((symbol-function 'executable-find) (lambda (_) "/usr/bin/vlc")) + ((symbol-function 'start-process-shell-command) + (lambda (_n _b cmd) (setq captured cmd) 'proc)) + ((symbol-function 'set-process-sentinel) #'ignore) + ((symbol-function 'message) #'ignore) + ((symbol-function 'cj/log-silently) #'ignore)) + (cj/media-play-it "https://example.com/v")) + (should (string-match-p "yt-dlp" captured)) + (should (string-match-p "-g" captured)) + (should (string-match-p "-f 22/18/best" captured)))) + +(ert-deftest test-media-play-it-missing-player-errors () + "Error: an unavailable player command signals an error before launching." + (let (cj/default-media-player) + (setq cj/default-media-player 'mpv) + (cl-letf (((symbol-function 'executable-find) (lambda (_) nil))) + (should-error (cj/media-play-it "https://example.com/v"))))) + +;; ------------------------------- cj/yt-dl-it --------------------------------- + +(ert-deftest test-media-yt-dl-it-errors-without-yt-dlp () + "Error: a missing yt-dlp aborts the download." + (cl-letf (((symbol-function 'executable-find) + (lambda (cmd) (unless (equal cmd "yt-dlp") "/usr/bin/x")))) + (should-error (cj/yt-dl-it "https://example.com/v")))) + +(ert-deftest test-media-yt-dl-it-errors-without-tsp () + "Error: yt-dlp present but tsp missing aborts the download." + (cl-letf (((symbol-function 'executable-find) + (lambda (cmd) (unless (equal cmd "tsp") "/usr/bin/x")))) + (should-error (cj/yt-dl-it "https://example.com/v")))) + +(ert-deftest test-media-yt-dl-it-builds-tsp-yt-dlp-process () + "Normal: with both tools present, the URL is queued via tsp + yt-dlp." + (let (captured (videos-dir "/tmp/videos")) + (cl-letf (((symbol-function 'executable-find) (lambda (_) "/usr/bin/x")) + ((symbol-function 'start-process) + (lambda (&rest args) (setq captured args) 'proc)) + ((symbol-function 'set-process-sentinel) #'ignore) + ((symbol-function 'message) #'ignore)) + (cj/yt-dl-it "https://example.com/v")) + (should (member "tsp" captured)) + (should (member "yt-dlp" captured)) + (should (member "https://example.com/v" captured)))) + +(provide 'test-media-utils) +;;; test-media-utils.el ends here |
