test_tag.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. from typing import Any, Dict, List
  2. import pytest
  3. from reflex.components.tags import CondTag, Tag, tagless
  4. from reflex.event import EVENT_ARG, EventChain, EventHandler, EventSpec
  5. from reflex.style import Style
  6. from reflex.vars import BaseVar, Var
  7. def mock_event(arg):
  8. pass
  9. @pytest.mark.parametrize(
  10. "prop,formatted",
  11. [
  12. ("string", '"string"'),
  13. ("{wrapped_string}", "{wrapped_string}"),
  14. (True, "{true}"),
  15. (False, "{false}"),
  16. (123, "{123}"),
  17. (3.14, "{3.14}"),
  18. ([1, 2, 3], "{[1, 2, 3]}"),
  19. (["a", "b", "c"], '{["a", "b", "c"]}'),
  20. ({"a": 1, "b": 2, "c": 3}, '{{"a": 1, "b": 2, "c": 3}}'),
  21. ({"a": 'foo "bar" baz'}, r'{{"a": "foo \"bar\" baz"}}'),
  22. (
  23. {
  24. "a": 'foo "{ "bar" }" baz',
  25. "b": BaseVar(name="val", type_="str"),
  26. },
  27. r'{{"a": "foo \"{ \"bar\" }\" baz", "b": val}}',
  28. ),
  29. (
  30. EventChain(events=[EventSpec(handler=EventHandler(fn=mock_event))]),
  31. '{_e => Event([E("mock_event", {})], _e)}',
  32. ),
  33. (
  34. EventChain(
  35. events=[
  36. EventSpec(
  37. handler=EventHandler(fn=mock_event),
  38. args=((Var.create_safe("arg"), EVENT_ARG.target.value),),
  39. )
  40. ]
  41. ),
  42. '{_e => Event([E("mock_event", {arg:_e.target.value})], _e)}',
  43. ),
  44. ({"a": "red", "b": "blue"}, '{{"a": "red", "b": "blue"}}'),
  45. (BaseVar(name="var", type_="int"), "{var}"),
  46. (
  47. BaseVar(
  48. name="_",
  49. type_=Any,
  50. state="",
  51. is_local=True,
  52. is_string=False,
  53. ),
  54. "{_}",
  55. ),
  56. (BaseVar(name='state.colors["a"]', type_="str"), '{state.colors["a"]}'),
  57. ({"a": BaseVar(name="val", type_="str")}, '{{"a": val}}'),
  58. ({"a": BaseVar(name='"val"', type_="str")}, '{{"a": "val"}}'),
  59. (
  60. {"a": BaseVar(name='state.colors["val"]', type_="str")},
  61. '{{"a": state.colors["val"]}}',
  62. ),
  63. # tricky real-world case from markdown component
  64. (
  65. {
  66. "h1": f"{{({{node, ...props}}) => <Heading {{...props}} {''.join(Tag(name='', props=Style({'as_': 'h1'})).format_props())} />}}"
  67. },
  68. '{{"h1": ({node, ...props}) => <Heading {...props} as={`h1`} />}}',
  69. ),
  70. ],
  71. )
  72. def test_format_prop(prop: Var, formatted: str):
  73. """Test that the formatted value of an prop is correct.
  74. Args:
  75. prop: The prop to test.
  76. formatted: The expected formatted value.
  77. """
  78. assert Tag.format_prop(prop) == formatted
  79. @pytest.mark.parametrize(
  80. "props,test_props",
  81. [
  82. ({}, []),
  83. ({"key": 1}, ["key={1}"]),
  84. ({"key": "value"}, ["key={`value`}"]),
  85. ({"key": True, "key2": "value2"}, ["key={true}", "key2={`value2`}"]),
  86. ],
  87. )
  88. def test_format_props(props: Dict[str, Var], test_props: List):
  89. """Test that the formatted props are correct.
  90. Args:
  91. props: The props to test.
  92. test_props: The expected props.
  93. """
  94. tag_props = Tag(props=props).format_props()
  95. for i, tag_prop in enumerate(tag_props):
  96. assert tag_prop == test_props[i]
  97. @pytest.mark.parametrize(
  98. "prop,valid",
  99. [
  100. (1, True),
  101. (3.14, True),
  102. ("string", True),
  103. (False, True),
  104. ([], True),
  105. ({}, False),
  106. (None, False),
  107. ],
  108. )
  109. def test_is_valid_prop(prop: Var, valid: bool):
  110. """Test that the prop is valid.
  111. Args:
  112. prop: The prop to test.
  113. valid: The expected validity of the prop.
  114. """
  115. assert Tag.is_valid_prop(prop) == valid
  116. def test_add_props():
  117. """Test that the props are added."""
  118. tag = Tag().add_props(key="value", key2=42, invalid=None, invalid2={})
  119. assert tag.props["key"] == Var.create("value")
  120. assert tag.props["key2"] == Var.create(42)
  121. assert "invalid" not in tag.props
  122. assert "invalid2" not in tag.props
  123. @pytest.mark.parametrize(
  124. "tag,expected",
  125. [
  126. (Tag(), {"name": "", "contents": "", "props": {}}),
  127. (Tag(name="br"), {"name": "br", "contents": "", "props": {}}),
  128. (Tag(contents="hello"), {"name": "", "contents": "hello", "props": {}}),
  129. (
  130. Tag(name="h1", contents="hello"),
  131. {"name": "h1", "contents": "hello", "props": {}},
  132. ),
  133. (
  134. Tag(name="box", props={"color": "red", "textAlign": "center"}),
  135. {
  136. "name": "box",
  137. "contents": "",
  138. "props": {"color": "red", "textAlign": "center"},
  139. },
  140. ),
  141. (
  142. Tag(
  143. name="box",
  144. props={"color": "red", "textAlign": "center"},
  145. contents="text",
  146. ),
  147. {
  148. "name": "box",
  149. "contents": "text",
  150. "props": {"color": "red", "textAlign": "center"},
  151. },
  152. ),
  153. ],
  154. )
  155. def test_format_tag(tag: Tag, expected: Dict):
  156. """Test that the tag dict is correct.
  157. Args:
  158. tag: The tag to test.
  159. expected: The expected tag dictionary.
  160. """
  161. tag_dict = dict(tag)
  162. assert tag_dict["name"] == expected["name"]
  163. assert tag_dict["contents"] == expected["contents"]
  164. assert tag_dict["props"] == expected["props"]
  165. def test_format_cond_tag():
  166. """Test that the cond tag dict is correct."""
  167. tag = CondTag(
  168. true_value=dict(Tag(name="h1", contents="True content")),
  169. false_value=dict(Tag(name="h2", contents="False content")),
  170. cond=BaseVar(name="logged_in", type_=bool),
  171. )
  172. tag_dict = dict(tag)
  173. cond, true_value, false_value = (
  174. tag_dict["cond"],
  175. tag_dict["true_value"],
  176. tag_dict["false_value"],
  177. )
  178. assert cond == "logged_in"
  179. assert true_value["name"] == "h1"
  180. assert true_value["contents"] == "True content"
  181. assert false_value["name"] == "h2"
  182. assert false_value["contents"] == "False content"
  183. def test_tagless_string_representation():
  184. """Test that the string representation of a tagless is correct."""
  185. tag = tagless.Tagless(contents="Hello world")
  186. expected_output = "Hello world"
  187. assert str(tag) == expected_output