aboutsummaryrefslogtreecommitdiff
path: root/tests/test_hub.py
blob: 5f6d992a9afe88deeb5f43c055b5b2b2c2e4fc74 (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
"""Tests for the TUI hub (hub.py) menu and helpers.

The hub drives the same curses widgets as tui.py, so these tests reuse the
fake curses/screen from test_tui to run the menu without a terminal.
"""

import unittest
from pathlib import Path
from unittest.mock import patch

import hub
import tui
from tests.test_tui import FakeCurses, FakeScreen


class HubHelperTests(unittest.TestCase):
    """Pure helpers in hub.py (no curses)."""

    def test_is_float(self):
        self.assertTrue(hub._is_float("1.0"))
        self.assertTrue(hub._is_float("2"))
        self.assertFalse(hub._is_float("abc"))
        self.assertFalse(hub._is_float(""))

    def test_list_voices_from_dir(self):
        with __import__("tempfile").TemporaryDirectory() as td:
            d = Path(td)
            (d / "Narrator.wav").write_bytes(b"x")
            (d / "Alpha.WAV").write_bytes(b"x")
            (d / "notes.txt").write_bytes(b"x")
            voices = hub._list_voices(str(d))
        # Stems preserve case; sorting is case-insensitive.
        self.assertEqual(voices, ["Alpha", "Narrator"])

    def test_list_voices_missing_dir(self):
        self.assertEqual(hub._list_voices("/no/such/dir"), [])

    def test_status_mark(self):
        from backends import BackendStatus
        ready = BackendStatus("k", "l", installed=True, configured=True)
        half = BackendStatus("k", "l", installed=True, configured=False)
        none = BackendStatus("k", "l", installed=False, configured=False)
        self.assertEqual(hub._status_mark("k", [ready]), "ready")
        self.assertEqual(hub._status_mark("k", [half]), "installed")
        self.assertEqual(hub._status_mark("k", [none]), "not set up")
        self.assertEqual(hub._status_mark("missing", []), "not set up")


class HubMenuTests(unittest.TestCase):
    """Drive _hub_menu with a fake screen (no terminal)."""

    def setUp(self):
        tui._THEME.clear()
        self.curses = FakeCurses()
        from unittest.mock import patch as _patch
        self._patcher = _patch.dict("sys.modules", {"curses": self.curses})
        self._patcher.start()
        self.addCleanup(self._patcher.stop)
        self.addCleanup(tui._THEME.clear)

    def test_quit_returns_none(self):
        # Main menu: move to "Quit" (4th option, index 3) and press Enter.
        screen = FakeScreen(keys=[FakeCurses.KEY_DOWN, FakeCurses.KEY_DOWN,
                                  FakeCurses.KEY_DOWN, 10])
        with patch.object(hub, "detect_all", return_value=[]):
            result = hub._hub_menu(screen)
        self.assertIsNone(result)

    def test_convert_with_no_ready_backend_offers_setup(self):
        # Convert -> "Set up a backend..." is the only entry -> Enter selects
        # it -> setup menu lists 3 backends; press Esc to go back -> convert
        # returns None -> main menu loops. Then quit (Down x3 + Enter).
        from backends import BackendInfo, BackendStatus
        none = BackendStatus("k", "l", installed=False, configured=False)
        infos = [BackendInfo("audiocpp", "audio.cpp", lambda: none,
                             lambda: 0),
                 BackendInfo("qwen", "Qwen", lambda: none, lambda: 0),
                 BackendInfo("faster", "faster", lambda: none, lambda: 0)]
        with patch.object(hub, "detect_all", return_value=[none, none, none]), \
                patch.object(hub, "REGISTRY", infos):
            # Convert(Enter), setup-entry(Enter), Esc on setup menu,
            # back at main menu -> Down x3 -> Enter (Quit).
            screen = FakeScreen(keys=[10, 10, 27,
                                      FakeCurses.KEY_DOWN, FakeCurses.KEY_DOWN,
                                      FakeCurses.KEY_DOWN, 10])
            result = hub._hub_menu(screen)
        self.assertIsNone(result)


if __name__ == "__main__":
    unittest.main()