66from collections .abc import AsyncIterable
77from contextlib import suppress
88
9- import nicegui
109import pytest
1110import sqlalchemy as sa
1211from fastapi import FastAPI , status
@@ -37,21 +36,19 @@ def disable_status_monitor_background_task(mocker: MockerFixture) -> None:
3736def app_environment (
3837 monkeypatch : pytest .MonkeyPatch ,
3938 app_environment : EnvVarsDict ,
40- use_internal_scheduler : bool , # defined in conftest inside subdirectiories of this module
39+ use_internal_scheduler : bool , # has to be added to every test
4140 postgres_db : sa .engine .Engine ,
4241 postgres_host_config : PostgresTestConfig ,
4342 disable_status_monitor_background_task : None ,
4443 rabbit_service : RabbitSettings ,
4544 redis_service : RedisSettings ,
4645 remove_redis_data : None ,
4746) -> EnvVarsDict :
48- setenvs_from_dict (
49- monkeypatch ,
50- {
51- "DYNAMIC_SCHEDULER_USE_INTERNAL_SCHEDULER" : f"{ use_internal_scheduler } " ,
52- },
53- )
54- return app_environment
47+ to_set = {
48+ "DYNAMIC_SCHEDULER_USE_INTERNAL_SCHEDULER" : f"{ use_internal_scheduler } " ,
49+ }
50+ setenvs_from_dict (monkeypatch , to_set )
51+ return {** app_environment , ** to_set }
5552
5653
5754@pytest .fixture
@@ -62,8 +59,59 @@ def server_host_port() -> str:
6259@pytest .fixture
6360def not_initialized_app (app_environment : EnvVarsDict ) -> FastAPI :
6461 # forces rebuild of middleware stack on next test
65- nicegui .app .user_middleware .clear ()
62+ import importlib
63+
64+ import nicegui
65+ from nicegui import Client , binding , core , run
66+ from nicegui .page import page
67+ from starlette .routing import Route
68+
69+ for route in list (nicegui .app .routes ):
70+ if isinstance (route , Route ) and route .path .startswith ("/_nicegui/auto/static/" ):
71+ nicegui .app .remove_route (route .path )
72+
73+ all_page_routes = set (Client .page_routes .values ())
74+ all_page_routes .add ("/" )
75+ for path in all_page_routes :
76+ nicegui .app .remove_route (path )
77+
78+ for route in list (nicegui .app .routes ):
79+ if (
80+ isinstance (route , Route )
81+ and "{" in route .path
82+ and "}" in route .path
83+ and not route .path .startswith ("/_nicegui/" )
84+ ):
85+ nicegui .app .remove_route (route .path )
86+
87+ nicegui .app .openapi_schema = None
6688 nicegui .app .middleware_stack = None
89+ nicegui .app .user_middleware .clear ()
90+ nicegui .app .urls .clear ()
91+ core .air = None
92+ # # NOTE favicon routes must be removed separately because they are not "pages"
93+ # for route in list(nicegui.app.routes):
94+ # if isinstance(route, Route) and route.path.endswith('/favicon.ico'):
95+ # nicegui.app.routes.remove(route)
96+
97+ importlib .reload (core )
98+ importlib .reload (run )
99+
100+ Client .instances .clear ()
101+ Client .page_routes .clear ()
102+ nicegui .app .reset ()
103+
104+ # Client.auto_index_client = Client(
105+ # page("/"), request=None
106+ # ).__enter__() # pylint: disable=unnecessary-dunder-call
107+ # Client.auto_index_client.layout.parent_slot = (
108+ # None # NOTE: otherwise the layout is nested in the previous client
109+ # )
110+ # # NOTE we need to re-add the auto index route because we removed all routes above
111+ # nicegui.app.get("/")(Client.auto_index_client.build_response)
112+
113+ binding .reset ()
114+
67115 return create_app ()
68116
69117
@@ -118,6 +166,15 @@ def download_playwright_browser() -> None:
118166async def async_page (download_playwright_browser : None ) -> AsyncIterable [Page ]:
119167 async with async_playwright () as p :
120168 browser = await p .chromium .launch ()
121- page = await browser .new_page ()
169+ # Create a new incognito context (no shared cache/cookies)
170+ context = await browser .new_context ()
171+ page = await context .new_page ()
172+ # Optional: Intercept requests to forcibly disable cache
173+ await page .route (
174+ "**/*" ,
175+ lambda route , request : route .continue_ (
176+ headers = {** request .headers , "Cache-Control" : "no-store" }
177+ ),
178+ )
122179 yield page
123180 await browser .close ()
0 commit comments