diff --git a/lib/streamlit/testing/v1/element_tree.py b/lib/streamlit/testing/v1/element_tree.py index 784e9986c544..8b46afdcd951 100644 --- a/lib/streamlit/testing/v1/element_tree.py +++ b/lib/streamlit/testing/v1/element_tree.py @@ -1915,6 +1915,13 @@ def parse_tree_from_messages(messages: list[ForwardMsg]) -> ElementTree: children[idx] = child assert isinstance(child, Block) current_node = child + + # Handle a block when we already have a placeholder for that location + if isinstance(new_node, Block): + placeholder_block = current_node.children.get(delta_path[-1]) + if placeholder_block is not None: + new_node.children = placeholder_block.children + current_node.children[delta_path[-1]] = new_node return root diff --git a/lib/tests/streamlit/testing/app_test_test.py b/lib/tests/streamlit/testing/app_test_test.py index 8dae7f69bed7..c8866fb8481a 100644 --- a/lib/tests/streamlit/testing/app_test_test.py +++ b/lib/tests/streamlit/testing/app_test_test.py @@ -181,3 +181,27 @@ def script(): assert len(at.text) == 4 # querying elements via a block only returns the elements in that block assert len(at.get("expandable")[0].text) == 2 + + +def test_out_of_order_blocks() -> None: + # Regression test for #7711 + def script(): + import streamlit as st + + container = st.container() + with container: + st.markdown("BarFoo") + + def button_one_clicked(cont): + cont.info("Hi!") + cont.markdown("FooBar") + + st.button("one", on_click=button_one_clicked, args=[container]) + + at = AppTest.from_function(script).run() + + at.button[0].click().run() + + assert at.markdown.len == 2 + assert at.info[0].value == "Hi!" + assert at.markdown.values == ["FooBar", "BarFoo"]