diff options
Diffstat (limited to 'tests/test-integration-recording-modeline-sync.el')
| -rw-r--r-- | tests/test-integration-recording-modeline-sync.el | 384 |
1 files changed, 0 insertions, 384 deletions
diff --git a/tests/test-integration-recording-modeline-sync.el b/tests/test-integration-recording-modeline-sync.el deleted file mode 100644 index fab442bd..00000000 --- a/tests/test-integration-recording-modeline-sync.el +++ /dev/null @@ -1,384 +0,0 @@ -;;; test-integration-recording-modeline-sync.el --- Integration tests for modeline sync -*- lexical-binding: t; -*- - -;;; Commentary: -;; Integration tests validating that the modeline indicator NEVER desyncs -;; from the actual recording state throughout the entire toggle lifecycle. -;; -;; This tests the critical requirement: modeline must always accurately -;; reflect whether recording is happening, with NO desyncs. -;; -;; Components integrated: -;; - cj/audio-recording-toggle (state changes) -;; - cj/video-recording-toggle (state changes) -;; - cj/recording-modeline-indicator (UI state display) -;; - cj/ffmpeg-record-audio (process creation) -;; - cj/ffmpeg-record-video (process creation) -;; - cj/recording-process-sentinel (auto-updates modeline) -;; - cj/audio-recording-stop (cleanup triggers update) -;; - cj/video-recording-stop (cleanup triggers update) -;; - force-mode-line-update (explicit refresh calls) -;; -;; Validates: -;; - Modeline updates immediately on toggle start -;; - Modeline updates immediately on toggle stop -;; - Modeline updates when sentinel runs (process dies) -;; - Modeline shows correct state for audio, video, or both -;; - Modeline never shows stale state -;; - process-live-p check prevents desync on dead processes - -;;; Code: - -(require 'ert) - -;; Stub dependencies before loading the module -(defvar cj/custom-keymap (make-sparse-keymap) - "Stub keymap for testing.") - -;; Stub directory variables -(defvar video-recordings-dir "/tmp/video-recordings/") -(defvar audio-recordings-dir "/tmp/audio-recordings/") - -;; Now load the actual production module -(require 'video-audio-recording) - -;;; Setup and Teardown - -(defun test-integration-modeline-setup () - "Reset all variables before each test." - (setq cj/video-recording-ffmpeg-process nil) - (setq cj/audio-recording-ffmpeg-process nil) - (setq cj/recording-mic-device "test-mic") - (setq cj/recording-system-device "test-monitor")) - -(defun test-integration-modeline-teardown () - "Clean up after each test." - (when cj/video-recording-ffmpeg-process - (ignore-errors (delete-process cj/video-recording-ffmpeg-process))) - (when cj/audio-recording-ffmpeg-process - (ignore-errors (delete-process cj/audio-recording-ffmpeg-process))) - (setq cj/video-recording-ffmpeg-process nil) - (setq cj/audio-recording-ffmpeg-process nil) - (setq cj/recording-mic-device nil) - (setq cj/recording-system-device nil)) - -;;; Integration Tests - Modeline Sync on Toggle - -(ert-deftest test-integration-recording-modeline-sync-audio-start-updates-immediately () - "Test that modeline updates immediately when audio recording starts. - -When user toggles audio recording on: -1. Process is created -2. Modeline indicator updates to show 🔴Audio -3. State is in sync immediately (not delayed) - -Components integrated: -- cj/audio-recording-toggle -- cj/ffmpeg-record-audio (calls force-mode-line-update) -- cj/recording-modeline-indicator - -Validates: -- Modeline syncs on start -- No delay or race condition" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - (make-process :name name :command '("sleep" "1000"))))) - - ;; Before toggle: no recording - (should (equal "" (cj/recording-modeline-indicator))) - - ;; Toggle on - (cj/audio-recording-toggle nil) - - ;; Immediately after toggle: modeline should show recording - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - - ;; Process should be alive - (should (process-live-p cj/audio-recording-ffmpeg-process))) - (test-integration-modeline-teardown))) - -(ert-deftest test-integration-recording-modeline-sync-audio-stop-updates-immediately () - "Test that modeline updates immediately when audio recording stops. - -When user toggles audio recording off: -1. Process is interrupted -2. Variable is cleared -3. Modeline indicator updates to show empty -4. State is in sync immediately - -Components integrated: -- cj/audio-recording-toggle (stop path) -- cj/audio-recording-stop (calls force-mode-line-update) -- cj/recording-modeline-indicator - -Validates: -- Modeline syncs on stop -- No stale indicator after stop" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - (make-process :name name :command '("sleep" "1000"))))) - - ;; Start recording - (cj/audio-recording-toggle nil) - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - - ;; Stop recording - (cj/audio-recording-toggle nil) - - ;; Immediately after stop: modeline should be empty - (should (equal "" (cj/recording-modeline-indicator))) - - ;; Process should be nil - (should (null cj/audio-recording-ffmpeg-process))) - (test-integration-modeline-teardown))) - -(ert-deftest test-integration-recording-modeline-sync-video-lifecycle () - "Test modeline sync through complete video recording lifecycle. - -Components integrated: -- cj/video-recording-toggle (both start and stop) -- cj/ffmpeg-record-video -- cj/video-recording-stop -- cj/recording-modeline-indicator - -Validates: -- Video recording follows same sync pattern as audio -- Modeline shows 🔴Video correctly" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - (make-process :name name :command '("sleep" "1000"))))) - - ;; Initial state - (should (equal "" (cj/recording-modeline-indicator))) - - ;; Start video - (cj/video-recording-toggle nil) - (should (equal " 🔴Video " (cj/recording-modeline-indicator))) - - ;; Stop video - (cj/video-recording-toggle nil) - (should (equal "" (cj/recording-modeline-indicator)))) - (test-integration-modeline-teardown))) - -;;; Integration Tests - Modeline Sync with Both Recordings - -(ert-deftest test-integration-recording-modeline-sync-both-recordings-transitions () - "Test modeline sync through all possible state transitions. - -Tests transitions: -- none → audio → both → video → none -- Validates modeline updates at every transition - -Components integrated: -- cj/audio-recording-toggle -- cj/video-recording-toggle -- cj/recording-modeline-indicator (handles all states) - -Validates: -- Modeline accurately reflects all combinations -- Transitions are clean with no stale state" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - (make-process :name name :command '("sleep" "1000"))))) - - ;; State 1: None - (should (equal "" (cj/recording-modeline-indicator))) - - ;; State 2: Audio only - (cj/audio-recording-toggle nil) - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - - ;; State 3: Both - (cj/video-recording-toggle nil) - (should (equal " 🔴A+V " (cj/recording-modeline-indicator))) - - ;; State 4: Video only (stop audio) - (cj/audio-recording-toggle nil) - (should (equal " 🔴Video " (cj/recording-modeline-indicator))) - - ;; State 5: None (stop video) - (cj/video-recording-toggle nil) - (should (equal "" (cj/recording-modeline-indicator)))) - (test-integration-modeline-teardown))) - -;;; Integration Tests - Modeline Sync with Sentinel - -(ert-deftest test-integration-recording-modeline-sync-sentinel-updates-on-crash () - "Test that modeline syncs when process dies and sentinel runs. - -When recording process crashes: -1. Sentinel detects process death -2. Sentinel clears variable -3. Sentinel calls force-mode-line-update -4. Modeline indicator shows no recording - -Components integrated: -- cj/ffmpeg-record-audio (attaches sentinel) -- cj/recording-process-sentinel (cleanup + modeline update) -- cj/recording-modeline-indicator - -Validates: -- Sentinel updates modeline on process death -- Modeline syncs automatically without user action -- Critical: prevents desync when process crashes" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - ;; Create process that exits immediately - (make-process :name name :command '("sh" "-c" "exit 1"))))) - - ;; Start recording - (cj/audio-recording-toggle nil) - - ;; Immediately after start: should show recording - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - - ;; Wait for process to exit and sentinel to run - (sit-for 0.3) - - ;; After sentinel runs: modeline should be clear - (should (equal "" (cj/recording-modeline-indicator))) - - ;; Variable should be nil - (should (null cj/audio-recording-ffmpeg-process))) - (test-integration-modeline-teardown))) - -(ert-deftest test-integration-recording-modeline-sync-dead-process-not-shown () - "Test that modeline never shows dead process as recording. - -The modeline indicator uses process-live-p to check if process is ACTUALLY -alive, not just if the variable is set. This prevents desync. - -Components integrated: -- cj/recording-modeline-indicator (uses process-live-p) - -Validates: -- Dead process doesn't show as recording -- process-live-p check prevents desync -- Critical: if variable is set but process is dead, shows empty" - (test-integration-modeline-setup) - (unwind-protect - (let ((dead-process (make-process :name "test-audio" :command '("sh" "-c" "exit 0")))) - ;; Set variable to dead process (simulating race condition) - (setq cj/audio-recording-ffmpeg-process dead-process) - - ;; Wait for process to die - (sit-for 0.1) - - ;; Modeline should NOT show recording (process is dead) - (should (equal "" (cj/recording-modeline-indicator))) - - ;; Even though variable is set - (should (eq dead-process cj/audio-recording-ffmpeg-process)) - - ;; Process is dead - (should-not (process-live-p dead-process))) - (test-integration-modeline-teardown))) - -;;; Integration Tests - Modeline Sync Under Rapid Toggling - -(ert-deftest test-integration-recording-modeline-sync-rapid-toggle-stays-synced () - "Test modeline stays synced under rapid start/stop toggling. - -When user rapidly toggles recording on and off: -- Modeline should stay in sync at every step -- No race conditions or stale state - -Components integrated: -- cj/audio-recording-toggle (rapid calls) -- cj/ffmpeg-record-audio -- cj/audio-recording-stop -- cj/recording-modeline-indicator - -Validates: -- Modeline syncs even with rapid state changes -- No race conditions in update logic" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - (make-process :name name :command '("sleep" "1000"))))) - - ;; Rapid toggling - (dotimes (_i 5) - ;; Start - (cj/audio-recording-toggle nil) - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - (should cj/audio-recording-ffmpeg-process) - - ;; Stop - (cj/audio-recording-toggle nil) - (should (equal "" (cj/recording-modeline-indicator))) - (should (null cj/audio-recording-ffmpeg-process)))) - (test-integration-modeline-teardown))) - -(ert-deftest test-integration-recording-modeline-sync-both-recordings-independent () - "Test that audio and video modeline updates are independent. - -When one recording stops, the other's indicator persists. -When one recording starts, both indicators combine correctly. - -Components integrated: -- cj/audio-recording-toggle -- cj/video-recording-toggle -- cj/recording-modeline-indicator (combines states) - -Validates: -- Independent recordings don't interfere -- Modeline correctly shows: audio-only, video-only, or both -- Stopping one doesn't affect other's indicator" - (test-integration-modeline-setup) - (unwind-protect - (cl-letf (((symbol-function 'file-directory-p) - (lambda (_dir) t)) - ((symbol-function 'start-process-shell-command) - (lambda (name _buffer _cmd) - (make-process :name name :command '("sleep" "1000"))))) - - ;; Start audio - (cj/audio-recording-toggle nil) - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - - ;; Add video - modeline should combine - (cj/video-recording-toggle nil) - (should (equal " 🔴A+V " (cj/recording-modeline-indicator))) - - ;; Stop audio - video indicator should persist - (cj/audio-recording-toggle nil) - (should (equal " 🔴Video " (cj/recording-modeline-indicator))) - - ;; Start audio again - should recombine - (cj/audio-recording-toggle nil) - (should (equal " 🔴A+V " (cj/recording-modeline-indicator))) - - ;; Stop video - audio indicator should persist - (cj/video-recording-toggle nil) - (should (equal " 🔴Audio " (cj/recording-modeline-indicator))) - - ;; Stop audio - should be empty - (cj/audio-recording-toggle nil) - (should (equal "" (cj/recording-modeline-indicator)))) - (test-integration-modeline-teardown))) - -(provide 'test-integration-recording-modeline-sync) -;;; test-integration-recording-modeline-sync.el ends here |
