From dcac72fccc9881d85ce7a264d5a22d1f10ed9e65 Mon Sep 17 00:00:00 2001 From: "Maarten A. Breddels" Date: Thu, 5 Oct 2023 14:37:48 +0200 Subject: [PATCH] test: make test more robust by non using globals and guessing the context We relied on a global variable to wait for the component to be called, but this seems to not be very robust. Instead, we pass a unique ID via a query parameter to not re-use the Event object, and store the context that we actually use, instead of relying on the last used context found. --- solara/test/pytest_plugin.py | 38 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/solara/test/pytest_plugin.py b/solara/test/pytest_plugin.py index 5138e0946..ab1ca79e0 100644 --- a/solara/test/pytest_plugin.py +++ b/solara/test/pytest_plugin.py @@ -9,6 +9,8 @@ import textwrap import threading import typing +import urllib.parse +import uuid from io import BytesIO from pathlib import Path from typing import Any, Callable, Dict, Generator, List, Union @@ -19,6 +21,7 @@ from IPython.display import display import solara.server.app +import solara.server.kernel_context import solara.server.server import solara.server.settings from solara.server import reload @@ -151,36 +154,43 @@ def run(app: Union[solara.server.app.AppScript, str]): return run -run_event = threading.Event() -run_calls = 0 +run_events: Dict[str, threading.Event] = {} +used_contexts: Dict[str, solara.server.kernel_context.VirtualKernelContext] = {} @solara.component def SyncWrapper(): global run_calls - import reacton.ipywidgets as w + router = solara.use_router() + values = urllib.parse.parse_qs(router.search, keep_blank_values=True) + id = values.get("id", [None])[0] # type: ignore + if id is None: + solara.Error("No id found in url") + else: - run_calls += 1 - run_event.set() - return w.VBox(children=[w.HTML(value="Test in solara"), w.VBox()]) + import reacton.ipywidgets as w + + used_contexts[id] = solara.server.kernel_context.get_current_context() + run_events[id].set() + + return w.VBox(children=[w.HTML(value="Test in solara"), w.VBox()]) @pytest.fixture() def solara_test(solara_server, solara_app, page_session: "playwright.sync_api.Page"): - global run_calls with solara_app("solara.test.pytest_plugin:SyncWrapper"): - page_session.goto(solara_server.base_url) + id = str(uuid.uuid4()) + run_events[id] = run_event = threading.Event() + page_session.goto(solara_server.base_url + f"?id={id}") run_event.wait() try: - assert run_calls == 1 - keys = list(solara.server.kernel_context.contexts) - assert len(keys) == 1, "expected only one context, got %s" % keys - context = solara.server.kernel_context.contexts[keys[0]] + context = used_contexts[id] with context: test_output_warmup = widgets.Output() test_output = widgets.Output() try: page_session.locator("text=Test in solara").wait_for() + assert context.container context.container.children[0].children[1].children[1].children = [test_output_warmup] # type: ignore with test_output_warmup: warmup() @@ -197,9 +207,9 @@ def solara_test(solara_server, solara_app, page_session: "playwright.sync_api.Pa test_output.close() test_output_warmup.close() finally: - run_event.clear() + del run_events[id] + del used_contexts[id] test_output = None - run_calls = 0 class ServerVoila(ServerBase):