test_foreach.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. from typing import Dict, List, Set, Tuple
  2. import pytest
  3. from reflex.components import box, foreach, text
  4. from reflex.components.layout import Foreach
  5. from reflex.state import State
  6. class ForEachState(State):
  7. """A state for testing the ForEach component."""
  8. colors_list: List[str] = ["red", "yellow"]
  9. nested_colors_list: List[List[str]] = [["red", "yellow"], ["blue", "green"]]
  10. colors_dict_list: List[Dict[str, str]] = [
  11. {
  12. "name": "red",
  13. },
  14. {"name": "yellow"},
  15. ]
  16. colors_nested_dict_list: List[Dict[str, List[str]]] = [{"shades": ["light-red"]}]
  17. primary_color: Dict[str, str] = {"category": "primary", "name": "red"}
  18. color_with_shades: Dict[str, List[str]] = {
  19. "red": ["orange", "yellow"],
  20. "yellow": ["orange", "green"],
  21. }
  22. nested_colors_with_shades: Dict[str, Dict[str, List[Dict[str, str]]]] = {
  23. "primary": {"red": [{"shade": "dark"}]}
  24. }
  25. color_tuple: Tuple[str, str] = (
  26. "red",
  27. "yellow",
  28. )
  29. colors_set: Set[str] = {"red", "green"}
  30. def display_color(color):
  31. return box(text(color))
  32. def display_color_name(color):
  33. return box(text(color["name"]))
  34. def display_shade(color):
  35. return box(text(color["shades"][0]))
  36. def display_primary_colors(color):
  37. return box(text(color[0]), text(color[1]))
  38. def display_color_with_shades(color):
  39. return box(text(color[0]), text(color[1][0]))
  40. def display_nested_color_with_shades(color):
  41. return box(text(color[0]), text(color[1]["red"][0]["shade"]))
  42. def show_shade(item):
  43. return text(item[1][0]["shade"])
  44. def display_nested_color_with_shades_v2(color):
  45. return box(text(foreach(color[1], show_shade)))
  46. def display_color_tuple(color):
  47. return box(text(color))
  48. def display_colors_set(color):
  49. return box(text(color))
  50. def display_nested_list_element(element: str, index: int):
  51. return box(text(element[index]))
  52. @pytest.mark.parametrize(
  53. "state_var, render_fn, render_dict",
  54. [
  55. (
  56. ForEachState.colors_list,
  57. display_color,
  58. {
  59. "iterable_state": "for_each_state.colors_list",
  60. "arg_index": "i",
  61. "iterable_type": "list",
  62. },
  63. ),
  64. (
  65. ForEachState.colors_dict_list,
  66. display_color_name,
  67. {
  68. "iterable_state": "for_each_state.colors_dict_list",
  69. "arg_index": "i",
  70. "iterable_type": "list",
  71. },
  72. ),
  73. (
  74. ForEachState.colors_nested_dict_list,
  75. display_shade,
  76. {
  77. "iterable_state": "for_each_state.colors_nested_dict_list",
  78. "arg_index": "i",
  79. "iterable_type": "list",
  80. },
  81. ),
  82. (
  83. ForEachState.primary_color,
  84. display_primary_colors,
  85. {
  86. "iterable_state": "for_each_state.primary_color",
  87. "arg_index": "i",
  88. "iterable_type": "dict",
  89. },
  90. ),
  91. (
  92. ForEachState.color_with_shades,
  93. display_color_with_shades,
  94. {
  95. "iterable_state": "for_each_state.color_with_shades",
  96. "arg_index": "i",
  97. "iterable_type": "dict",
  98. },
  99. ),
  100. (
  101. ForEachState.nested_colors_with_shades,
  102. display_nested_color_with_shades,
  103. {
  104. "iterable_state": "for_each_state.nested_colors_with_shades",
  105. "arg_index": "i",
  106. "iterable_type": "dict",
  107. },
  108. ),
  109. (
  110. ForEachState.nested_colors_with_shades,
  111. display_nested_color_with_shades_v2,
  112. {
  113. "iterable_state": "for_each_state.nested_colors_with_shades",
  114. "arg_index": "i",
  115. "iterable_type": "dict",
  116. },
  117. ),
  118. (
  119. ForEachState.color_tuple,
  120. display_color_tuple,
  121. {
  122. "iterable_state": "for_each_state.color_tuple",
  123. "arg_index": "i",
  124. "iterable_type": "tuple",
  125. },
  126. ),
  127. (
  128. ForEachState.colors_set,
  129. display_colors_set,
  130. {
  131. "iterable_state": "for_each_state.colors_set",
  132. "arg_index": "i",
  133. "iterable_type": "set",
  134. },
  135. ),
  136. (
  137. ForEachState.nested_colors_list,
  138. lambda el, i: display_nested_list_element(el, i),
  139. {
  140. "iterable_state": "for_each_state.nested_colors_list",
  141. "arg_index": "i",
  142. "iterable_type": "list",
  143. },
  144. ),
  145. ],
  146. )
  147. def test_foreach_render(state_var, render_fn, render_dict):
  148. """Test that the foreach component renders without error.
  149. Args:
  150. state_var: the state var.
  151. render_fn: The render callable
  152. render_dict: return dict on calling `component.render`
  153. """
  154. component = Foreach.create(state_var, render_fn)
  155. rend = component.render()
  156. arg_index = rend["arg_index"]
  157. assert rend["iterable_state"] == render_dict["iterable_state"]
  158. assert rend["arg_index"] == render_dict["arg_index"]
  159. assert arg_index.type_ == int
  160. assert rend["iterable_type"] == render_dict["iterable_type"]