aboutsummaryrefslogtreecommitdiff
path: root/tests/test-media-utils.el
blob: 9384d568f5bce143371beabcdd874620f316b5c5 (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
;;; 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))))

;; ---------------------------- cj/select-media-player -------------------------

(ert-deftest test-media-select-player-normal-sets-default-on-choice ()
  "Normal: choosing an available player updates `cj/default-media-player'."
  (let ((cj/media-players '((mpv . (:name "mpv" :command "mpv"))
                            (vlc . (:name "VLC" :command "vlc"))))
        (cj/default-media-player 'vlc))
    (cl-letf (((symbol-function 'cj/get-available-media-players)
               (lambda () '(mpv vlc)))
              ((symbol-function 'completing-read) (lambda (&rest _) "mpv"))
              ((symbol-function 'message) #'ignore))
      (cj/select-media-player)
      (should (eq cj/default-media-player 'mpv)))))

(ert-deftest test-media-select-player-boundary-no-match-keeps-default ()
  "Boundary: a selection matching no player leaves the default unchanged."
  (let ((cj/media-players '((mpv . (:name "mpv" :command "mpv"))
                            (vlc . (:name "VLC" :command "vlc"))))
        (cj/default-media-player 'vlc))
    (cl-letf (((symbol-function 'cj/get-available-media-players)
               (lambda () '(mpv vlc)))
              ((symbol-function 'completing-read) (lambda (&rest _) "Nonexistent"))
              ((symbol-function 'message) #'ignore))
      (cj/select-media-player)
      (should (eq cj/default-media-player 'vlc)))))

(provide 'test-media-utils)
;;; test-media-utils.el ends here