summaryrefslogtreecommitdiff
path: root/tests/test-video-audio-recording--get-available-mics.el
blob: 5b549da3a8ebfba1cadcfa8356853d4b38da56e0 (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
;;; test-video-audio-recording--get-available-mics.el --- Tests for mic discovery -*- lexical-binding: t; -*-

;;; Commentary:
;; Unit tests for cj/recording--get-available-mics.
;; Verifies that available microphones are discovered correctly:
;; - Monitor sources are excluded (they capture output, not input)
;; - Muted sources are included (shown with [muted] label in UI)
;; - Friendly descriptions from PulseAudio are used
;; - PulseAudio state and mute status are included

;;; Code:

(require 'ert)

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

(require 'video-audio-recording)

;;; Helper

(defun test-mics--make-pactl-output (sources)
  "Build fake `pactl list sources' output from SOURCES.
Each source is (name description mute state)."
  (mapconcat (lambda (src)
               (format "Source #1\n\tState: %s\n\tName: %s\n\tDescription: %s\n\tMute: %s\n"
                       (nth 3 src) (nth 0 src) (nth 1 src) (nth 2 src)))
             sources ""))

;;; Normal Cases

(ert-deftest test-video-audio-recording--get-available-mics-normal-filters-monitors ()
  "Test that monitor sources are excluded from mic list."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("alsa_input.usb-Jabra.mono" "Jabra Mono" "no" "SUSPENDED")
                  ("alsa_output.usb-Jabra.monitor" "Monitor of Jabra" "no" "SUSPENDED"))))))
    (let ((mics (cj/recording--get-available-mics)))
      (should (= 1 (length mics)))
      (should (equal "alsa_input.usb-Jabra.mono" (nth 0 (car mics)))))))

(ert-deftest test-video-audio-recording--get-available-mics-normal-includes-muted ()
  "Test that muted sources are included in mic list."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("active-mic" "Active Mic" "no" "SUSPENDED")
                  ("muted-mic" "Muted Mic" "yes" "SUSPENDED"))))))
    (let ((mics (cj/recording--get-available-mics)))
      (should (= 2 (length mics)))
      (should (equal "yes" (nth 3 (nth 1 mics)))))))

(ert-deftest test-video-audio-recording--get-available-mics-normal-uses-descriptions ()
  "Test that friendly descriptions are returned as second element."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("raw-device-name" "Friendly Device Name" "no" "IDLE"))))))
    (let ((mics (cj/recording--get-available-mics)))
      (should (equal "Friendly Device Name" (nth 1 (car mics)))))))

(ert-deftest test-video-audio-recording--get-available-mics-normal-includes-state ()
  "Test that PulseAudio state is returned as third element."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("mic-a" "Mic A" "no" "RUNNING"))))))
    (let ((mics (cj/recording--get-available-mics)))
      (should (equal "RUNNING" (nth 2 (car mics)))))))

(ert-deftest test-video-audio-recording--get-available-mics-normal-includes-mute-status ()
  "Test that mute status is returned as fourth element."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("mic-a" "Mic A" "no" "RUNNING"))))))
    (let ((mics (cj/recording--get-available-mics)))
      (should (equal "no" (nth 3 (car mics)))))))

(ert-deftest test-video-audio-recording--get-available-mics-normal-multiple-mics ()
  "Test that multiple mics are returned including muted ones."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("mic-a" "Jabra Mono" "no" "SUSPENDED")
                  ("mic-b" "Built-in" "no" "IDLE")
                  ("alsa_output.jabra.monitor" "Monitor of Jabra" "no" "SUSPENDED")
                  ("muted-mic" "Muted Mic" "yes" "SUSPENDED"))))))
    (let ((mics (cj/recording--get-available-mics)))
      ;; 3 non-monitor sources (including the muted one)
      (should (= 3 (length mics))))))

;;; Boundary Cases

(ert-deftest test-video-audio-recording--get-available-mics-boundary-empty-output ()
  "Test that empty pactl output returns empty list."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd) "")))
    (should (null (cj/recording--get-available-mics)))))

(ert-deftest test-video-audio-recording--get-available-mics-boundary-all-monitors ()
  "Test that if all sources are monitors, returns empty list."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd)
               (test-mics--make-pactl-output
                '(("sink-a.monitor" "Monitor A" "no" "SUSPENDED")
                  ("sink-b.monitor" "Monitor B" "no" "SUSPENDED"))))))
    (should (null (cj/recording--get-available-mics)))))

;;; Error Cases

(ert-deftest test-video-audio-recording--get-available-mics-error-garbled-output ()
  "Test that garbled pactl output returns empty list, not an error."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd) "random garbage\nwith newlines\nbut no structure\n")))
    (should (null (cj/recording--get-available-mics)))))

(ert-deftest test-video-audio-recording--get-available-mics-error-missing-fields ()
  "Test that source with partial fields does not crash."
  (cl-letf (((symbol-function 'shell-command-to-string)
             (lambda (_cmd) "Source #1\n\tState: RUNNING\n\tName: partial-source\n")))
    ;; Missing Description and Mute — should not error
    (let ((mics (cj/recording--get-available-mics)))
      ;; May return empty or partial; must not signal
      (should (listp mics)))))

(provide 'test-video-audio-recording--get-available-mics)
;;; test-video-audio-recording--get-available-mics.el ends here