From 7381e9c9465b8007139c5b7430cab21969ce27e6 Mon Sep 17 00:00:00 2001 From: TomJGooding <101601846+TomJGooding@users.noreply.github.com> Date: Thu, 16 Jan 2025 13:36:09 +0000 Subject: [PATCH] fix(option list): fix render cache option indexing Fixes #5431 --- src/textual/widgets/_option_list.py | 4 +- ...ion_list_updating_with_separator_lines.svg | 153 ++++++++++++++++++ tests/snapshot_tests/test_snapshots.py | 30 ++++ 3 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 tests/snapshot_tests/__snapshots__/test_snapshots/test_option_list_updating_with_separator_lines.svg diff --git a/src/textual/widgets/_option_list.py b/src/textual/widgets/_option_list.py index 2b895797c8..d17fe837d2 100644 --- a/src/textual/widgets/_option_list.py +++ b/src/textual/widgets/_option_list.py @@ -358,11 +358,11 @@ def _add_lines( assert self._lines is not None assert self._spans is not None - for index, content in enumerate(new_content, len(self._lines)): + for content in new_content: if isinstance(content, Option): height = len( self._render_option_content( - index, content, "", width - self._left_gutter_width() + option_index, content, "", width - self._left_gutter_width() ) ) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_option_list_updating_with_separator_lines.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_option_list_updating_with_separator_lines.svg new file mode 100644 index 0000000000..4c28ed1f65 --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_option_list_updating_with_separator_lines.svg @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OptionListApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +This is option 1                                                             +──────────────────────────────────────────────────────────────────────────── +This is option 3                                                             +──────────────────────────────────────────────────────────────────────────── +This is option 5                                                             +──────────────────────────────────────────────────────────────────────────── +This is option 7                                                             +──────────────────────────────────────────────────────────────────────────── +This is option 9                                                             +──────────────────────────────────────────────────────────────────────────── +This is option 11                                                            +──────────────────────────────────────────────────────────────────────────── +This is option 13                                                            + + + + + + + + + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 892d897a30..4570b77af7 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -22,6 +22,7 @@ HorizontalGroup, ) from textual.pilot import Pilot +from textual.reactive import var from textual.renderables.gradient import LinearGradient from textual.screen import ModalScreen, Screen from textual.widgets import ( @@ -3348,3 +3349,32 @@ async def run_before(pilot: Pilot) -> None: await pilot.pause() assert snap_compare(LApp(), run_before=run_before) + + +def test_option_list_updating_with_separator_lines(snap_compare): + """You should see options with consecutive odd numbers, with separator + lines between each option. + + Regression test for https://github.com/Textualize/textual/issues/5431""" + + class OptionListApp(App): + BINDINGS = [("a", "add_option")] + + CSS = """ + OptionList { + height: 1fr; + } + """ + + counter: var[int] = var(0) + + def compose(self) -> ComposeResult: + yield OptionList() + + def action_add_option(self) -> None: + self.counter += 1 + self.query_one(OptionList).add_option( + (f"This is option {self.counter}" if self.counter % 2 else None) + ) + + snap_compare(OptionListApp(), press=["a"] * 13)