conftest.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. """Shared conftest for all integration tests."""
  2. import os
  3. import re
  4. from pathlib import Path
  5. from typing import Generator, Type
  6. import pytest
  7. import reflex.constants
  8. from reflex.config import EnvironmentVariables
  9. from reflex.constants.base import Env
  10. from reflex.testing import AppHarness, AppHarnessProd
  11. DISPLAY = None
  12. XVFB_DIMENSIONS = (800, 600)
  13. @pytest.fixture(scope="session", autouse=True)
  14. def xvfb():
  15. """Create virtual X display.
  16. This function is a no-op unless GITHUB_ACTIONS is set in the environment.
  17. Yields:
  18. the pyvirtualdisplay object that the browser will be open on
  19. """
  20. if (
  21. os.environ.get("GITHUB_ACTIONS")
  22. and not EnvironmentVariables.APP_HARNESS_HEADLESS.get()
  23. ):
  24. from pyvirtualdisplay.smartdisplay import ( # pyright: ignore [reportMissingImports]
  25. SmartDisplay,
  26. )
  27. global DISPLAY
  28. with SmartDisplay(visible=False, size=XVFB_DIMENSIONS) as DISPLAY:
  29. yield DISPLAY
  30. DISPLAY = None
  31. else:
  32. yield None
  33. def pytest_exception_interact(node, call, report):
  34. """Take and upload screenshot when tests fail.
  35. Args:
  36. node: The pytest item that failed.
  37. call: The pytest call describing when/where the test was invoked.
  38. report: The pytest log report object.
  39. """
  40. screenshot_dir = EnvironmentVariables.SCREENSHOT_DIR.get()
  41. if DISPLAY is None or screenshot_dir is None:
  42. return
  43. screenshot_dir = Path(screenshot_dir)
  44. screenshot_dir.mkdir(parents=True, exist_ok=True)
  45. safe_filename = re.sub(
  46. r"(?u)[^-\w.]",
  47. "_",
  48. str(node.nodeid).strip().replace(" ", "_").replace(":", "_").replace(".py", ""),
  49. )
  50. try:
  51. DISPLAY.waitgrab().save(
  52. (Path(screenshot_dir) / safe_filename).with_suffix(".png"),
  53. )
  54. except Exception as e:
  55. print(f"Failed to take screenshot for {node}: {e}")
  56. @pytest.fixture(
  57. scope="session",
  58. params=[
  59. AppHarness,
  60. AppHarnessProd,
  61. ],
  62. ids=[
  63. reflex.constants.Env.DEV.value,
  64. reflex.constants.Env.PROD.value,
  65. ],
  66. )
  67. def app_harness_env(
  68. request: pytest.FixtureRequest,
  69. ) -> Generator[Type[AppHarness], None, None]:
  70. """Parametrize the AppHarness class to use for the test, either dev or prod.
  71. Args:
  72. request: The pytest fixture request object.
  73. Yields:
  74. The AppHarness class to use for the test.
  75. """
  76. harness: Type[AppHarness] = request.param
  77. if issubclass(harness, AppHarnessProd):
  78. EnvironmentVariables.REFLEX_ENV_MODE.set(Env.PROD)
  79. yield harness
  80. if isinstance(harness, AppHarnessProd):
  81. EnvironmentVariables.REFLEX_ENV_MODE.set(None)