test_cond.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import json
  2. from typing import Any, Union
  3. import pytest
  4. from reflex.components.base.fragment import Fragment
  5. from reflex.components.core.cond import Cond, cond
  6. from reflex.components.radix.themes.typography.text import Text
  7. from reflex.ivars.base import ImmutableVar, LiteralVar, immutable_computed_var
  8. from reflex.state import BaseState, State
  9. from reflex.utils.format import format_state_name
  10. from reflex.vars import Var
  11. @pytest.fixture
  12. def cond_state(request):
  13. class CondState(BaseState):
  14. value: request.param["value_type"] = request.param["value"] # noqa
  15. return CondState
  16. def test_f_string_cond_interpolation():
  17. # make sure backticks inside interpolation don't get escaped
  18. var = LiteralVar.create(f"x {cond(True, 'a', 'b')}")
  19. assert str(var) == '("x "+(true ? "a" : "b"))'
  20. @pytest.mark.parametrize(
  21. "cond_state",
  22. [
  23. pytest.param({"value_type": bool, "value": True}),
  24. pytest.param({"value_type": int, "value": 0}),
  25. pytest.param({"value_type": str, "value": "true"}),
  26. ],
  27. indirect=True,
  28. )
  29. def test_validate_cond(cond_state: BaseState):
  30. """Test if cond can be a rx.Var with any values.
  31. Args:
  32. cond_state: A fixture.
  33. """
  34. cond_component = cond(
  35. cond_state.value,
  36. Text.create("cond is True"),
  37. Text.create("cond is False"),
  38. )
  39. cond_dict = cond_component.render() if type(cond_component) == Fragment else {}
  40. assert cond_dict["name"] == "Fragment"
  41. [condition] = cond_dict["children"]
  42. assert condition["cond_state"] == f"isTrue({cond_state.get_full_name()}.value)"
  43. # true value
  44. true_value = condition["true_value"]
  45. assert true_value["name"] == "Fragment"
  46. [true_value_text] = true_value["children"]
  47. assert true_value_text["name"] == "RadixThemesText"
  48. assert true_value_text["children"][0]["contents"] == '{"cond is True"}'
  49. # false value
  50. false_value = condition["false_value"]
  51. assert false_value["name"] == "Fragment"
  52. [false_value_text] = false_value["children"]
  53. assert false_value_text["name"] == "RadixThemesText"
  54. assert false_value_text["children"][0]["contents"] == '{"cond is False"}'
  55. @pytest.mark.parametrize(
  56. "c1, c2",
  57. [
  58. (True, False),
  59. (32, 0),
  60. ("hello", ""),
  61. (2.3, 0.0),
  62. (Var.create("a"), Var.create("b")),
  63. ],
  64. )
  65. def test_prop_cond(c1: Any, c2: Any):
  66. """Test if cond can be a prop.
  67. Args:
  68. c1: truth condition value
  69. c2: false condition value
  70. """
  71. prop_cond = cond(
  72. True,
  73. c1,
  74. c2,
  75. )
  76. assert isinstance(prop_cond, Var)
  77. if not isinstance(c1, Var):
  78. c1 = json.dumps(c1)
  79. if not isinstance(c2, Var):
  80. c2 = json.dumps(c2)
  81. assert str(prop_cond) == f"(true ? {c1} : {c2})"
  82. def test_cond_no_mix():
  83. """Test if cond can't mix components and props."""
  84. with pytest.raises(ValueError):
  85. cond(True, Var.create("hello"), Text.create("world"))
  86. def test_cond_no_else():
  87. """Test if cond can be used without else."""
  88. # Components should support the use of cond without else
  89. comp = cond(True, Text.create("hello"))
  90. assert isinstance(comp, Fragment)
  91. comp = comp.children[0]
  92. assert isinstance(comp, Cond)
  93. assert comp.cond._decode() is True # type: ignore
  94. assert comp.comp1.render() == Fragment.create(Text.create("hello")).render()
  95. assert comp.comp2 == Fragment.create()
  96. # Props do not support the use of cond without else
  97. with pytest.raises(ValueError):
  98. cond(True, "hello") # type: ignore
  99. def test_cond_computed_var():
  100. """Test if cond works with computed vars."""
  101. class CondStateComputed(State):
  102. @immutable_computed_var
  103. def computed_int(self) -> int:
  104. return 0
  105. @immutable_computed_var
  106. def computed_str(self) -> str:
  107. return "a string"
  108. comp = cond(True, CondStateComputed.computed_int, CondStateComputed.computed_str)
  109. # TODO: shouln't this be a ComputedVar?
  110. assert isinstance(comp, ImmutableVar)
  111. state_name = format_state_name(CondStateComputed.get_full_name())
  112. assert (
  113. str(comp) == f"(true ? {state_name}.computed_int : {state_name}.computed_str)"
  114. )
  115. assert comp._var_type == Union[int, str]