diff options
Diffstat (limited to 'tests/test_tui.py')
| -rw-r--r-- | tests/test_tui.py | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/tests/test_tui.py b/tests/test_tui.py index 58d8273..c121d55 100644 --- a/tests/test_tui.py +++ b/tests/test_tui.py @@ -365,6 +365,82 @@ class LineEditTests(TuiTestCase): self.assertEqual(value, "teq") +class FormTests(TuiTestCase): + def _fields(self): + # Fresh dicts each call: form() edits field values in place, and a + # shared class attribute would leak edits between tests. + return [ + {"key": "fmt", "label": "Format", "kind": "choice", + "value": "m4b", "choices": ["mp3", "m4b", "ogg"]}, + {"key": "chunk", "label": "Chunk", "kind": "text", + "value": "250"}, + ] + + def test_save_returns_current_values(self): + screen = FakeScreen(keys=[9, 10]) # Tab -> Save, Enter + result = tui.form(screen, "Settings", self._fields()) + self.assertEqual(result, {"fmt": "m4b", "chunk": "250"}) + + def test_cancel_returns_back_value(self): + marker = object() + # Tab -> buttons, Left -> Cancel, Enter. + screen = FakeScreen(keys=[9, FakeCurses.KEY_LEFT, 10]) + result = tui.form(screen, "Settings", self._fields(), + back_value=marker) + self.assertIs(result, marker) + + def test_esc_returns_back_value(self): + marker = object() + screen = FakeScreen(keys=[27]) + self.assertIs( + tui.form(screen, "Settings", self._fields(), back_value=marker), + marker) + + def test_q_still_aborts_with_back_value(self): + marker = object() + screen = FakeScreen(keys=[ord("q")]) + with self.assertRaises(tui.WizardCancelled): + tui.form(screen, "Settings", self._fields(), back_value=marker) + + def test_choice_field_picks_another_value(self): + # Enter opens the choice menu on 'm4b' (index 1); Down moves to + # 'ogg', Enter accepts; Tab -> Save, Enter. + screen = FakeScreen(keys=[10, FakeCurses.KEY_DOWN, 10, 9, 10]) + result = tui.form(screen, "Settings", self._fields()) + self.assertEqual(result, {"fmt": "ogg", "chunk": "250"}) + + def test_text_field_edits_then_saves(self): + # Down to the text row, Enter opens the editor, type 'x', Enter, + # then Tab -> Save, Enter. + screen = FakeScreen( + keys=[FakeCurses.KEY_DOWN, 10, ord("x"), 10, 9, 10]) + result = tui.form(screen, "Settings", self._fields()) + self.assertEqual(result, {"fmt": "m4b", "chunk": "250x"}) + + def test_validation_error_refuses_save_then_recovers(self): + fields = [ + {"key": "chunk", "label": "Chunk", "kind": "text", "value": "bad", + "validate": lambda s: None if s.isdigit() else "digits only"}, + {"key": "fmt", "label": "Format", "kind": "text", "value": "x"}, + ] + # Tab->Save(Enter) fails, the flash consumes the next key; Enter + # reopens the editor, Ctrl-U clears 'bad', type '120', Enter; then + # Tab->Save(Enter). + keys = [9, 10, 10, 10, 21, ord("1"), ord("2"), ord("0"), 10, 9, 10] + screen = FakeScreen(keys=keys) + result = tui.form(screen, "Settings", fields) + self.assertEqual(result, {"chunk": "120", "fmt": "x"}) + + def test_rows_left_justified_inside_the_border(self): + screen = FakeScreen(keys=[9, 10]) + tui.form(screen, "Settings", self._fields()) + self.assert_inside_border(screen) + + def test_empty_fields_rejected(self): + with self.assertRaises(ValueError): + tui.form(self.screen, "Settings", []) + + def _accept_audio_cpp(entry: Path): """auto_select callback that accepts an 'audio.cpp' checkout root.""" if entry.name == "audio.cpp" and (entry / "model_specs").is_dir(): |
