summaryrefslogtreecommitdiff
path: root/tests/test-video-audio-recording-select-device.el
blob: 53b1e665c57bde4de0ed1635ab6d8c55cb670595 (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
;;; test-video-audio-recording-select-device.el --- Tests for cj/recording-select-device -*- lexical-binding: t; -*-

;;; Commentary:
;; Unit tests for cj/recording-select-device function.
;; Tests interactive device selection with filtering.

;;; Code:

(require 'ert)

;; Stub dependencies before loading the module
(defvar cj/custom-keymap (make-sparse-keymap)
  "Stub keymap for testing.")

;; Now load the actual production module
(require 'video-audio-recording)

;;; Normal Cases

(ert-deftest test-video-audio-recording-select-device-normal-returns-selected-mic ()
  "Test that function returns selected microphone device."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED")
                   ("alsa_output.pci-device.monitor" "PipeWire" "SUSPENDED"))))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 ;; Select the first choice
                 (caar choices))))
      (let ((result (cj/recording-select-device "Select mic: " 'mic)))
        (should (stringp result))
        (should (equal "alsa_input.pci-device" result))))))

(ert-deftest test-video-audio-recording-select-device-normal-returns-selected-monitor ()
  "Test that function returns selected monitor device."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED")
                   ("alsa_output.pci-device.monitor" "PipeWire" "SUSPENDED"))))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 (caar choices))))
      (let ((result (cj/recording-select-device "Select monitor: " 'monitor)))
        (should (stringp result))
        (should (equal "alsa_output.pci-device.monitor" result))))))

(ert-deftest test-video-audio-recording-select-device-normal-filters-monitors-for-mic ()
  "Test that function filters out monitor devices when selecting mic."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED")
                   ("alsa_output.pci-device.monitor" "PipeWire" "SUSPENDED")
                   ("bluez_input.00:1B:66" "PipeWire" "RUNNING")))
        (presented-choices nil))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 (setq presented-choices choices)
                 (caar choices))))
      (cj/recording-select-device "Select mic: " 'mic)
      ;; Should have 2 mic devices (not the monitor)
      (should (= 2 (length presented-choices)))
      (should-not (cl-some (lambda (choice) (string-match-p "\\.monitor" (car choice)))
                           presented-choices)))))

(ert-deftest test-video-audio-recording-select-device-normal-filters-non-monitors-for-monitor ()
  "Test that function filters out non-monitor devices when selecting monitor."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED")
                   ("alsa_output.pci-device.monitor" "PipeWire" "SUSPENDED")
                   ("bluez_output.00_1B_66.1.monitor" "PipeWire" "RUNNING")))
        (presented-choices nil))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 (setq presented-choices choices)
                 (caar choices))))
      (cj/recording-select-device "Select monitor: " 'monitor)
      ;; Should have 2 monitor devices (not the input)
      (should (= 2 (length presented-choices)))
      (should (cl-every (lambda (choice) (string-match-p "\\.monitor" (car choice)))
                        presented-choices)))))

(ert-deftest test-video-audio-recording-select-device-normal-shows-friendly-state ()
  "Test that function shows friendly state in choices."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED")))
        (presented-choices nil))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 (setq presented-choices choices)
                 (caar choices))))
      (cj/recording-select-device "Select mic: " 'mic)
      ;; Choice should contain "Ready" (friendly for SUSPENDED)
      (should (string-match-p "Ready" (caar presented-choices))))))

;;; Boundary Cases

(ert-deftest test-video-audio-recording-select-device-boundary-single-device ()
  "Test that function works with single device."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED"))))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 (caar choices))))
      (let ((result (cj/recording-select-device "Select mic: " 'mic)))
        (should (equal "alsa_input.pci-device" result))))))

(ert-deftest test-video-audio-recording-select-device-boundary-multiple-states ()
  "Test that function handles devices in different states."
  (let ((sources '(("alsa_input.device1" "PipeWire" "SUSPENDED")
                   ("alsa_input.device2" "PipeWire" "RUNNING")
                   ("alsa_input.device3" "PipeWire" "IDLE")))
        (presented-choices nil))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources))
              ((symbol-function 'completing-read)
               (lambda (_prompt choices &rest _args)
                 (setq presented-choices choices)
                 (caar choices))))
      (cj/recording-select-device "Select mic: " 'mic)
      ;; All three should be presented
      (should (= 3 (length presented-choices)))
      ;; Check that friendly states appear
      (let ((choice-text (mapconcat #'car presented-choices " ")))
        (should (string-match-p "Ready\\|Active" choice-text))))))

;;; Error Cases

(ert-deftest test-video-audio-recording-select-device-error-no-mic-devices-signals-error ()
  "Test that function signals user-error when no mic devices found."
  (let ((sources '(("alsa_output.pci-device.monitor" "PipeWire" "SUSPENDED"))))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources)))
      (should-error (cj/recording-select-device "Select mic: " 'mic) :type 'user-error))))

(ert-deftest test-video-audio-recording-select-device-error-no-monitor-devices-signals-error ()
  "Test that function signals user-error when no monitor devices found."
  (let ((sources '(("alsa_input.pci-device" "PipeWire" "SUSPENDED"))))
    (cl-letf (((symbol-function 'cj/recording-parse-sources)
               (lambda () sources)))
      (should-error (cj/recording-select-device "Select monitor: " 'monitor) :type 'user-error))))

(ert-deftest test-video-audio-recording-select-device-error-empty-source-list ()
  "Test that function signals user-error when source list is empty."
  (cl-letf (((symbol-function 'cj/recording-parse-sources)
             (lambda () nil)))
    (should-error (cj/recording-select-device "Select mic: " 'mic) :type 'user-error)))

(ert-deftest test-video-audio-recording-select-device-error-message-mentions-device-type ()
  "Test that error message mentions the device type being searched for."
  (cl-letf (((symbol-function 'cj/recording-parse-sources)
             (lambda () nil)))
    (condition-case err
        (cj/recording-select-device "Select mic: " 'mic)
      (user-error
       (should (string-match-p "input" (error-message-string err)))))
    (condition-case err
        (cj/recording-select-device "Select monitor: " 'monitor)
      (user-error
       (should (string-match-p "monitor" (error-message-string err)))))))

(provide 'test-video-audio-recording-select-device)
;;; test-video-audio-recording-select-device.el ends here