from unittest.mock import AsyncMock, MagicMock, patch import numpy as np import pytest from whisper_local.__main__ import App class TestApp: @patch("whisper_local.__main__.create_tray") @patch("whisper_local.__main__.Transcriber") @patch("whisper_local.__main__.create_listener") @patch("whisper_local.__main__.create_inserter") def test_app_init(self, mock_inserter_factory, mock_listener_factory, mock_transcriber_class, mock_tray_factory): app = App() assert app.recorder is not None mock_transcriber_class.assert_called_once() mock_listener_factory.assert_called_once() mock_inserter_factory.assert_called_once() @patch("whisper_local.__main__.create_tray") @patch("whisper_local.__main__.Transcriber") @patch("whisper_local.__main__.create_listener") @patch("whisper_local.__main__.create_inserter") def test_on_press_starts_recording(self, mock_inserter_factory, mock_listener_factory, mock_transcriber_class, mock_tray_factory): app = App() app.recorder = MagicMock() import asyncio asyncio.run(app.on_press()) app.recorder.start.assert_called_once() @patch("whisper_local.__main__.create_tray") @patch("whisper_local.__main__.Transcriber") @patch("whisper_local.__main__.create_listener") @patch("whisper_local.__main__.create_inserter") def test_on_release_stops_and_transcribes(self, mock_inserter_factory, mock_listener_factory, mock_transcriber_class, mock_tray_factory): mock_transcriber = MagicMock() mock_transcriber.transcribe.return_value = "Hallo" mock_transcriber_class.return_value = mock_transcriber app = App() app.recorder = MagicMock() audio = np.zeros(16000, dtype=np.float32) app.recorder.stop.return_value = audio app.inserter = MagicMock() app.inserter.insert = AsyncMock() import asyncio asyncio.run(app.on_release()) app.recorder.stop.assert_called_once() mock_transcriber.transcribe.assert_called_once_with(audio) app.inserter.insert.assert_awaited_once_with("Hallo") @patch("whisper_local.__main__.create_tray") @patch("whisper_local.__main__.Transcriber") @patch("whisper_local.__main__.create_listener") @patch("whisper_local.__main__.create_inserter") def test_on_release_no_audio_skips(self, mock_inserter_factory, mock_listener_factory, mock_transcriber_class, mock_tray_factory): mock_transcriber = MagicMock() mock_transcriber_class.return_value = mock_transcriber app = App() app.recorder = MagicMock() app.recorder.stop.return_value = None app.inserter = MagicMock() app.inserter.insert = AsyncMock() import asyncio asyncio.run(app.on_release()) mock_transcriber.transcribe.assert_not_called() app.inserter.insert.assert_not_awaited() @patch("whisper_local.__main__.create_tray") @patch("whisper_local.__main__.Transcriber") @patch("whisper_local.__main__.create_listener") @patch("whisper_local.__main__.create_inserter") def test_on_press_sets_recording_state( self, mock_inserter_factory, mock_listener_factory, mock_transcriber_class, mock_tray_factory ): from whisper_local.tray import AppState mock_tray = MagicMock() mock_tray_factory.return_value = mock_tray app = App() app.recorder = MagicMock() import asyncio asyncio.run(app.on_press()) mock_tray.set_state.assert_called_with(AppState.RECORDING) @patch("whisper_local.__main__.create_tray") @patch("whisper_local.__main__.Transcriber") @patch("whisper_local.__main__.create_listener") @patch("whisper_local.__main__.create_inserter") def test_on_release_sets_waiting_state_after_transcription( self, mock_inserter_factory, mock_listener_factory, mock_transcriber_class, mock_tray_factory ): from whisper_local.tray import AppState mock_tray = MagicMock() mock_tray_factory.return_value = mock_tray mock_transcriber = MagicMock() mock_transcriber.transcribe.return_value = "Text" mock_transcriber_class.return_value = mock_transcriber app = App() app.recorder = MagicMock() app.recorder.stop.return_value = np.zeros(16000, dtype=np.float32) app.inserter = MagicMock() app.inserter.insert = AsyncMock() import asyncio asyncio.run(app.on_release()) calls = [c.args[0] for c in mock_tray.set_state.call_args_list] assert AppState.TRANSCRIBING in calls assert calls[-1] == AppState.WAITING