diff options
| author | historia <historiavg@proton.me> | 2026-08-26 19:12:11 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-26 19:12:11 -0400 |
| commit | 5af37bbd575eec89c6ac2fecf2d8c2eda4c1728d (patch) | |
| tree | 4f8fe9b79d339695ca83968e03301b853eb2e2ef /app/tests/test_tui.py | |
| parent | df95e7034df683c38fde67890430ab4c2abfa4ba (diff) | |
| download | tts-audiobook-generator-5af37bbd575eec89c6ac2fecf2d8c2eda4c1728d.tar.gz | |
fix: crash when menu of clone voices is empty
Diffstat (limited to 'app/tests/test_tui.py')
| -rw-r--r-- | app/tests/test_tui.py | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/app/tests/test_tui.py b/app/tests/test_tui.py index 7821ebb..4ff70fb 100644 --- a/app/tests/test_tui.py +++ b/app/tests/test_tui.py @@ -781,6 +781,41 @@ class FormTests(TuiTestCase): result = tui.form(screen, "Settings", fields) self.assertEqual(result, {"fmt": "b"}) + def test_empty_static_choices_flash_hint_and_keep_form_open(self): + # A choice field with no options at all cannot be opened (menu() + # would raise): the on_empty_choices hint flashes instead and the + # form stays usable. + fields = [{"key": "fmt", "label": "Format", "kind": "choice", + "value": "", "choices": [], + "on_empty_choices": "nothing to pick — add some"}, + {"key": "chunk", "label": "Chunk", "kind": "text", + "value": "1"}] + # Enter flashes (the next key dismisses it), Tab -> Save, Enter. + screen = FakeScreen(keys=[10, ord("x"), 9, 10]) + result = tui.form(screen, "Settings", fields) + self.assertEqual(result, {"fmt": "", "chunk": "1"}) + texts = [text for _, _, text, _ in screen.strings] + self.assertTrue(any("nothing to pick" in text for text in texts)) + + def test_empty_callable_choices_flash_without_opening_menu(self): + # The regression this guards: a dynamic list that resolved empty + # used to crash form() with ValueError from menu(). A message may + # itself be a callable of the field list. + fields = [{"key": "voice", "label": "Voice", "kind": "choice", + "value": None, + "choices": lambda fs: [], + "on_empty_choices": + lambda fs: f"{len(fs)} fields but no voices"}] + # Enter opens nothing (the flash consumes the next key), then + # Tab -> Save, Enter. + screen = FakeScreen(keys=[10, ord("x"), 9, 10]) + with patch.object(tui, "menu", + side_effect=AssertionError("menu() was opened")): + result = tui.form(screen, "Convert", fields) + self.assertEqual(result, {"voice": None}) + texts = [text for _, _, text, _ in screen.strings] + self.assertTrue(any("no voices" in text for text in texts)) + def test_on_change_fires_after_value_change(self): calls = [] fields = [{"key": "fmt", "label": "Format", "kind": "choice", |
