From ed955c2a7309d583cfc8781dfa8ae6dcf3cb09b3 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Fri, 29 May 2026 19:56:17 -0700 Subject: [PATCH] Add additional tests. --- borgmatic/actions/browse/loading.py | 17 ++- .../actions/browse/test_loading.py | 101 ++++++++++++++++++ 2 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 tests/integration/actions/browse/test_loading.py diff --git a/borgmatic/actions/browse/loading.py b/borgmatic/actions/browse/loading.py index 18d140a4..351014e7 100644 --- a/borgmatic/actions/browse/loading.py +++ b/borgmatic/actions/browse/loading.py @@ -13,6 +13,10 @@ logger = logging.getLogger('__name__') def update_inline_loading_indicator(widget): + ''' + Given a textual.widgets.OptionList or a textual.widgets.RichLog instance, animate the existing + loading indicator inside it. + ''' if isinstance(widget, textual.widgets.OptionList): with contextlib.suppress(textual.widgets.option_list.OptionDoesNotExist): widget.replace_option_prompt( @@ -28,15 +32,20 @@ def update_inline_loading_indicator(widget): raise ValueError(f'Unsupported widget type: {type(widget)}') -def add_inline_loading_indicator(widget): - loading_message = '⏳ loading...' +LOADING_MESSAGE = '⏳ loading...' + +def add_inline_loading_indicator(widget): + ''' + Given a textual.widgets.OptionList or a textual.widgets.RichLog instance, add a loading + indicator to it. + ''' if isinstance(widget, textual.widgets.OptionList): - loading_option = textual.widgets.option_list.Option(loading_message, id='loading-indicator') + loading_option = textual.widgets.option_list.Option(LOADING_MESSAGE, id='loading-indicator') widget.add_option(loading_option) widget.highlighted = None elif isinstance(widget, textual.widgets.RichLog): - widget.write(loading_message) + widget.write(LOADING_MESSAGE) else: raise ValueError(f'Unsupported widget type: {type(widget)}') diff --git a/tests/integration/actions/browse/test_loading.py b/tests/integration/actions/browse/test_loading.py new file mode 100644 index 00000000..e1117b73 --- /dev/null +++ b/tests/integration/actions/browse/test_loading.py @@ -0,0 +1,101 @@ +from borgmatic.actions.browse import loading as module + +from flexmock import flexmock +import pytest +import textual.app +import textual.widgets + + +def test_update_inline_loading_indicator_with_option_list_adds_a_dot(): + widget = textual.widgets.OptionList() + widget.add_option( + textual.widgets.option_list.Option('HOLD.', id='loading-indicator') + ) + + module.update_inline_loading_indicator(widget) + + assert len(widget.options) == 1 + assert widget.options[0].prompt == 'HOLD..' + + +def test_update_inline_loading_indicator_with_option_list_wraps_dots_beyond_three(): + widget = textual.widgets.OptionList() + widget.add_option( + textual.widgets.option_list.Option('HOLD...', id='loading-indicator') + ) + + module.update_inline_loading_indicator(widget) + + assert len(widget.options) == 1 + assert widget.options[0].prompt == 'HOLD' + + +def test_update_inline_loading_indicator_with_option_list_and_missing_indicator_does_not_raise(): + widget = textual.widgets.OptionList() + + module.update_inline_loading_indicator(widget) + + assert len(widget.options) == 0 + + +async def test_update_inline_loading_indicator_with_rich_log_adds_a_dot(): + async with textual.app.App().run_test() as pilot: + widget = textual.widgets.RichLog() + widget._size_known = True + widget.write('HOLD.') + + module.update_inline_loading_indicator(widget) + + assert str(widget.lines[0].text) == 'HOLD..' + + +async def test_update_inline_loading_indicator_with_rich_log_wraps_dots_beyond_three(): + async with textual.app.App().run_test() as pilot: + widget = textual.widgets.RichLog() + widget._size_known = True + widget.write('HOLD...') + + module.update_inline_loading_indicator(widget) + + assert str(widget.lines[0].text) == 'HOLD' + + +def test_update_inline_loading_indicator_with_rich_log_and_missing_indicator_does_not_raise(): + widget = textual.widgets.RichLog() + + module.update_inline_loading_indicator(widget) + + assert len(widget.lines) == 0 + + +def test_update_inline_loading_indicator_with_unsupported_widget_type_raises(): + with pytest.raises(ValueError): + module.update_inline_loading_indicator(flexmock()) + + +def test_add_inline_loading_indicator_with_option_list_adds_loading_indicator_option(): + widget = textual.widgets.OptionList() + flexmock(widget).should_receive('set_interval') + + module.add_inline_loading_indicator(widget) + + assert len(widget.options) == 1 + assert widget.options[0].prompt == module.LOADING_MESSAGE + assert widget.options[0].id == 'loading-indicator' + assert widget.highlighted is None + + +async def test_add_inline_loading_indicator_with_rich_log_writes_loading_indicator_text(): + async with textual.app.App().run_test() as pilot: + widget = textual.widgets.RichLog() + widget._size_known = True + flexmock(widget).should_receive('set_interval') + + module.add_inline_loading_indicator(widget) + + assert str(widget.lines[0].text) == module.LOADING_MESSAGE + + +def test_add_inline_loading_indicator_with_unsupported_widget_type_raises(): + with pytest.raises(ValueError): + module.add_inline_loading_indicator(flexmock())