Enable real app AppHarness tests to not specify state=
(#2358)
This commit is contained in:
parent
51baa94ed5
commit
87844c3f7d
@ -7,5 +7,10 @@ from code.pages import *
|
||||
|
||||
import reflex as rx
|
||||
|
||||
# Create the app and compile it.
|
||||
|
||||
class State(rx.State):
|
||||
"""Define empty state to allow access to rx.State.router."""
|
||||
|
||||
|
||||
# Create the app.
|
||||
app = rx.App(style=styles.base_style)
|
||||
|
@ -63,6 +63,7 @@ from reflex.state import (
|
||||
State,
|
||||
StateManager,
|
||||
StateUpdate,
|
||||
code_uses_state_contexts,
|
||||
)
|
||||
from reflex.utils import console, exceptions, format, prerequisites, types
|
||||
from reflex.utils.imports import ImportVar
|
||||
@ -169,7 +170,8 @@ class App(Base):
|
||||
deprecation_version="0.3.5",
|
||||
removal_version="0.4.0",
|
||||
)
|
||||
self.state = State
|
||||
if len(State.class_subclasses) > 0:
|
||||
self.state = State
|
||||
# Get the config
|
||||
config = get_config()
|
||||
|
||||
@ -636,7 +638,11 @@ class App(Base):
|
||||
return
|
||||
|
||||
def compile_(self):
|
||||
"""Compile the app and output it to the pages folder."""
|
||||
"""Compile the app and output it to the pages folder.
|
||||
|
||||
Raises:
|
||||
RuntimeError: When any page uses state, but no rx.State subclass is defined.
|
||||
"""
|
||||
# add the pages before the compile check so App know onload methods
|
||||
for render, kwargs in DECORATED_PAGES:
|
||||
self.add_page(render, **kwargs)
|
||||
@ -701,6 +707,16 @@ class App(Base):
|
||||
stateful_components_code,
|
||||
page_components,
|
||||
) = compiler.compile_stateful_components(self.pages.values())
|
||||
|
||||
# Catch "static" apps (that do not define a rx.State subclass) which are trying to access rx.State.
|
||||
if (
|
||||
code_uses_state_contexts(stateful_components_code)
|
||||
and self.state is None
|
||||
):
|
||||
raise RuntimeError(
|
||||
"To access rx.State in frontend components, at least one "
|
||||
"subclass of rx.State must be defined in the app."
|
||||
)
|
||||
compile_results.append((stateful_components_path, stateful_components_code))
|
||||
|
||||
result_futures = []
|
||||
|
@ -2181,3 +2181,15 @@ class ImmutableMutableProxy(MutableProxy):
|
||||
return super()._mark_dirty(
|
||||
wrapped=wrapped, instance=instance, args=args, kwargs=kwargs
|
||||
)
|
||||
|
||||
|
||||
def code_uses_state_contexts(javascript_code: str) -> bool:
|
||||
"""Check if the rendered Javascript uses state contexts.
|
||||
|
||||
Args:
|
||||
javascript_code: The Javascript code to check.
|
||||
|
||||
Returns:
|
||||
True if the code attempts to access a member of StateContexts.
|
||||
"""
|
||||
return bool("useContext(StateContexts" in javascript_code)
|
||||
|
@ -209,6 +209,8 @@ class AppHarness:
|
||||
reflex.config.get_config(reload=True)
|
||||
# reset rx.State subclasses
|
||||
State.class_subclasses.clear()
|
||||
# Ensure the AppHarness test does not skip State assignment due to running via pytest
|
||||
os.environ.pop(reflex.constants.PYTEST_CURRENT_TEST, None)
|
||||
# self.app_module.app.
|
||||
self.app_module = reflex.utils.prerequisites.get_compiled_app(reload=True)
|
||||
self.app_instance = self.app_module.app
|
||||
|
@ -159,6 +159,11 @@ def get_app(reload: bool = False) -> ModuleType:
|
||||
sys.path.insert(0, os.getcwd())
|
||||
app = __import__(module, fromlist=(constants.CompileVars.APP,))
|
||||
if reload:
|
||||
from reflex.state import State
|
||||
|
||||
# Reset rx.State subclasses to avoid conflict when reloading.
|
||||
State.class_subclasses.clear()
|
||||
# Reload the app module.
|
||||
importlib.reload(app)
|
||||
|
||||
return app
|
||||
|
Loading…
Reference in New Issue
Block a user