test_prerequisites.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import tempfile
  2. from unittest.mock import Mock, mock_open
  3. import pytest
  4. from reflex import constants
  5. from reflex.config import Config
  6. from reflex.utils.prerequisites import (
  7. _update_next_config,
  8. cached_procedure,
  9. initialize_requirements_txt,
  10. )
  11. @pytest.mark.parametrize(
  12. "config, export, expected_output",
  13. [
  14. (
  15. Config(
  16. app_name="test",
  17. ),
  18. False,
  19. 'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true};',
  20. ),
  21. (
  22. Config(
  23. app_name="test",
  24. next_compression=False,
  25. ),
  26. False,
  27. 'module.exports = {basePath: "", compress: false, reactStrictMode: true, trailingSlash: true};',
  28. ),
  29. (
  30. Config(
  31. app_name="test",
  32. frontend_path="/test",
  33. ),
  34. False,
  35. 'module.exports = {basePath: "/test", compress: true, reactStrictMode: true, trailingSlash: true};',
  36. ),
  37. (
  38. Config(
  39. app_name="test",
  40. frontend_path="/test",
  41. next_compression=False,
  42. ),
  43. False,
  44. 'module.exports = {basePath: "/test", compress: false, reactStrictMode: true, trailingSlash: true};',
  45. ),
  46. (
  47. Config(
  48. app_name="test",
  49. ),
  50. True,
  51. 'module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true, output: "export", distDir: "_static"};',
  52. ),
  53. ],
  54. )
  55. def test_update_next_config(config, export, expected_output):
  56. output = _update_next_config(config, export=export)
  57. assert output == expected_output
  58. def test_initialize_requirements_txt_no_op(mocker):
  59. # File exists, reflex is included, do nothing
  60. mocker.patch("pathlib.Path.exists", return_value=True)
  61. mocker.patch(
  62. "charset_normalizer.from_path",
  63. return_value=Mock(best=lambda: Mock(encoding="utf-8")),
  64. )
  65. mock_fp_touch = mocker.patch("pathlib.Path.touch")
  66. open_mock = mock_open(read_data="reflex==0.2.9")
  67. mocker.patch("builtins.open", open_mock)
  68. initialize_requirements_txt()
  69. assert open_mock.call_count == 1
  70. assert open_mock.call_args.kwargs["encoding"] == "utf-8"
  71. assert open_mock().write.call_count == 0
  72. mock_fp_touch.assert_not_called()
  73. def test_initialize_requirements_txt_missing_reflex(mocker):
  74. # File exists, reflex is not included, add reflex
  75. mocker.patch("pathlib.Path.exists", return_value=True)
  76. mocker.patch(
  77. "charset_normalizer.from_path",
  78. return_value=Mock(best=lambda: Mock(encoding="utf-8")),
  79. )
  80. open_mock = mock_open(read_data="random-package=1.2.3")
  81. mocker.patch("builtins.open", open_mock)
  82. initialize_requirements_txt()
  83. # Currently open for read, then open for append
  84. assert open_mock.call_count == 2
  85. for call_args in open_mock.call_args_list:
  86. assert call_args.kwargs["encoding"] == "utf-8"
  87. assert (
  88. open_mock().write.call_args[0][0]
  89. == f"\n{constants.RequirementsTxt.DEFAULTS_STUB}{constants.Reflex.VERSION}\n"
  90. )
  91. def test_initialize_requirements_txt_not_exist(mocker):
  92. # File does not exist, create file with reflex
  93. mocker.patch("pathlib.Path.exists", return_value=False)
  94. open_mock = mock_open()
  95. mocker.patch("builtins.open", open_mock)
  96. initialize_requirements_txt()
  97. assert open_mock.call_count == 2
  98. # By default, use utf-8 encoding
  99. for call_args in open_mock.call_args_list:
  100. assert call_args.kwargs["encoding"] == "utf-8"
  101. assert open_mock().write.call_count == 1
  102. assert (
  103. open_mock().write.call_args[0][0]
  104. == f"{constants.RequirementsTxt.DEFAULTS_STUB}{constants.Reflex.VERSION}\n"
  105. )
  106. def test_requirements_txt_cannot_detect_encoding(mocker):
  107. mocker.patch("pathlib.Path.exists", return_value=True)
  108. mock_open = mocker.patch("builtins.open")
  109. mocker.patch(
  110. "charset_normalizer.from_path",
  111. return_value=Mock(best=lambda: None),
  112. )
  113. initialize_requirements_txt()
  114. mock_open.assert_not_called()
  115. def test_requirements_txt_other_encoding(mocker):
  116. mocker.patch("pathlib.Path.exists", return_value=True)
  117. mocker.patch(
  118. "charset_normalizer.from_path",
  119. return_value=Mock(best=lambda: Mock(encoding="utf-16")),
  120. )
  121. initialize_requirements_txt()
  122. open_mock = mock_open(read_data="random-package=1.2.3")
  123. mocker.patch("builtins.open", open_mock)
  124. initialize_requirements_txt()
  125. # Currently open for read, then open for append
  126. assert open_mock.call_count == 2
  127. for call_args in open_mock.call_args_list:
  128. assert call_args.kwargs["encoding"] == "utf-16"
  129. assert (
  130. open_mock().write.call_args[0][0]
  131. == f"\n{constants.RequirementsTxt.DEFAULTS_STUB}{constants.Reflex.VERSION}\n"
  132. )
  133. def test_cached_procedure():
  134. call_count = 0
  135. @cached_procedure(tempfile.mktemp(), payload_fn=lambda: "constant")
  136. def _function_with_no_args():
  137. nonlocal call_count
  138. call_count += 1
  139. _function_with_no_args()
  140. assert call_count == 1
  141. _function_with_no_args()
  142. assert call_count == 1
  143. call_count = 0
  144. @cached_procedure(
  145. tempfile.mktemp(),
  146. payload_fn=lambda *args, **kwargs: f"{repr(args), repr(kwargs)}",
  147. )
  148. def _function_with_some_args(*args, **kwargs):
  149. nonlocal call_count
  150. call_count += 1
  151. _function_with_some_args(1, y=2)
  152. assert call_count == 1
  153. _function_with_some_args(1, y=2)
  154. assert call_count == 1
  155. _function_with_some_args(100, y=300)
  156. assert call_count == 2
  157. _function_with_some_args(100, y=300)
  158. assert call_count == 2