Ver código fonte

[REF-3334] Validate Toast Props (#3793)

Elijah Ahianyo 9 meses atrás
pai
commit
4190a79835

+ 1 - 1
reflex/app.py

@@ -125,8 +125,8 @@ def default_backend_exception_handler(exception: Exception) -> EventSpec:
     )
     if Toaster.is_used:
         return toast(
+            "An error occurred.",
             level="error",
-            title="An error occurred.",
             description="<br/>".join(error_message),
             position="top-center",
             id="backend_error",

+ 27 - 1
reflex/components/sonner/toast.py

@@ -4,6 +4,8 @@ from __future__ import annotations
 
 from typing import Any, ClassVar, Literal, Optional, Union
 
+from pydantic import ValidationError
+
 from reflex.base import Base
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.lucide.icon import Icon
@@ -27,7 +29,6 @@ LiteralPosition = Literal[
     "bottom-right",
 ]
 
-
 toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False)
 
 
@@ -128,6 +129,24 @@ class ToastProps(PropsBase):
     # Function that gets called when the toast disappears automatically after it's timeout (duration` prop).
     on_auto_close: Optional[Any]
 
+    def __init__(self, **kwargs):
+        """Initialize the props.
+
+        Args:
+            kwargs: Kwargs to initialize the props.
+
+        Raises:
+            ValueError: If invalid props are passed on instantiation.
+        """
+        try:
+            super().__init__(**kwargs)
+        except ValidationError as e:
+            invalid_fields = ", ".join([error["loc"][0] for error in e.errors()])  # type: ignore
+            supported_props_str = ", ".join(f'"{field}"' for field in self.get_fields())
+            raise ValueError(
+                f"Invalid prop(s) {invalid_fields} for rx.toast. Supported props are {supported_props_str}"
+            ) from None
+
     def dict(self, *args, **kwargs) -> dict[str, Any]:
         """Convert the object to a dictionary.
 
@@ -159,6 +178,13 @@ class ToastProps(PropsBase):
             )
         return d
 
+    class Config:
+        """Pydantic config."""
+
+        arbitrary_types_allowed = True
+        use_enum_values = True
+        extra = "forbid"
+
 
 class Toaster(Component):
     """A Toaster Component for displaying toast notifications."""

+ 5 - 0
reflex/components/sonner/toast.pyi

@@ -51,6 +51,11 @@ class ToastProps(PropsBase):
 
     def dict(self, *args, **kwargs) -> dict[str, Any]: ...
 
+    class Config:
+        arbitrary_types_allowed = True
+        use_enum_values = True
+        extra = "forbid"
+
 class Toaster(Component):
     is_used: ClassVar[bool] = False
 

+ 1 - 1
tests/test_state.py

@@ -1565,7 +1565,7 @@ async def test_state_with_invalid_yield(capsys, mock_app):
             assert update.events == rx.event.fix_events(
                 [
                     rx.toast(
-                        title="An error occurred.",
+                        "An error occurred.",
                         description="TypeError: Your handler test_state_with_invalid_yield.<locals>.StateWithInvalidYield.invalid_handler must only return/yield: None, Events or other EventHandlers referenced by their class (not using `self`).<br/>See logs for details.",
                         level="error",
                         id="backend_error",