diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_controller.py | 88 | ||||
| -rw-r--r-- | tests/test_state.py | 41 |
2 files changed, 129 insertions, 0 deletions
diff --git a/tests/test_controller.py b/tests/test_controller.py new file mode 100644 index 0000000..61c291e --- /dev/null +++ b/tests/test_controller.py @@ -0,0 +1,88 @@ +from pathlib import Path +import tempfile +import threading +import unittest + +from parley.config import Config +from parley.controller import Controller +from parley.state import State + + +class FakeRecorder: + def __init__(self) -> None: + self.path = None + self.cancelled = False + + def start(self, path: Path) -> None: + self.path = path + path.write_bytes(b"RIFF") + + def stop(self) -> Path: + return self.path + + def cancel(self) -> None: + self.cancelled = True + if self.path: + self.path.unlink(missing_ok=True) + + +class FakeTranscriber: + def transcribe(self, wav_path: Path, workspace: Path) -> str: + return "hello from controller" + + def cancel(self) -> None: + pass + + +class ControllerTests(unittest.TestCase): + def setUp(self) -> None: + self.temporary = tempfile.TemporaryDirectory() + root = Path(self.temporary.name) + ffmpeg = root / "ffmpeg" + runtime = root / "transcribe-cli" + model = root / "model.gguf" + for path in (ffmpeg, runtime): + path.write_text("#!/bin/sh\n") + path.chmod(0o755) + model.touch() + self.config = Config(ffmpeg, runtime, model, root / "transcripts") + + def tearDown(self) -> None: + self.temporary.cleanup() + + def test_successful_operation_persists_before_callback(self) -> None: + ready = threading.Event() + received = [] + controller = Controller( + self.config, + on_transcript=lambda text, path: (received.append((text, path)), ready.set()), + ) + controller.recorder = FakeRecorder() + controller.transcriber = FakeTranscriber() + try: + controller.start() + self.assertEqual(controller.state, State.RECORDING) + controller.stop_and_transcribe() + self.assertTrue(ready.wait(2), "transcription callback was not delivered") + self.assertEqual(controller.state, State.IDLE) + text, path = received[0] + self.assertEqual(text, "hello from controller") + self.assertEqual(path.read_text(), "hello from controller\n") + finally: + controller.close() + + def test_cancel_recording_discards_operation(self) -> None: + controller = Controller(self.config) + recorder = FakeRecorder() + controller.recorder = recorder + try: + controller.start() + controller.cancel() + self.assertEqual(controller.state, State.IDLE) + self.assertTrue(recorder.cancelled) + finally: + controller.close() + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_state.py b/tests/test_state.py new file mode 100644 index 0000000..9fd223c --- /dev/null +++ b/tests/test_state.py @@ -0,0 +1,41 @@ +import unittest + +from parley.state import InvalidStateError, State, StateMachine + + +class StateMachineTests(unittest.TestCase): + def test_record_transcribe_complete(self) -> None: + machine = StateMachine() + self.assertEqual(machine.start_recording(), State.RECORDING) + self.assertEqual(machine.begin_transcription(), State.TRANSCRIBING) + self.assertEqual(machine.complete(), State.IDLE) + + def test_insertion_flow(self) -> None: + machine = StateMachine() + machine.start_recording() + machine.begin_transcription() + self.assertEqual(machine.begin_insertion(), State.INSERTING) + self.assertEqual(machine.complete(), State.IDLE) + + def test_rejects_second_recording(self) -> None: + machine = StateMachine() + machine.start_recording() + with self.assertRaisesRegex(InvalidStateError, "current state is recording"): + machine.start_recording() + + def test_cancel_recording_and_transcription(self) -> None: + machine = StateMachine() + machine.start_recording() + self.assertEqual(machine.cancel(), State.IDLE) + machine.start_recording() + machine.begin_transcription() + self.assertEqual(machine.cancel(), State.IDLE) + + def test_error_is_recoverable(self) -> None: + machine = StateMachine() + machine.fail() + self.assertEqual(machine.start_recording(), State.RECORDING) + + +if __name__ == "__main__": + unittest.main() |
