conftest.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import importlib
  2. import os
  3. import shutil
  4. from pathlib import Path
  5. from typing import Dict, Generator
  6. import icecream
  7. import pytest
  8. from selenium import webdriver
  9. from selenium.webdriver.chrome.service import Service
  10. from nicegui import Client, app, binding, core
  11. from nicegui.page import page
  12. from .screen import Screen
  13. DOWNLOAD_DIR = Path(__file__).parent / 'download'
  14. icecream.install()
  15. @pytest.fixture
  16. def chrome_options(chrome_options: webdriver.ChromeOptions) -> webdriver.ChromeOptions:
  17. chrome_options.add_argument('disable-dev-shm-using')
  18. chrome_options.add_argument('no-sandbox')
  19. chrome_options.add_argument('headless')
  20. chrome_options.add_argument('disable-gpu')
  21. chrome_options.add_argument('window-size=600x600')
  22. chrome_options.add_experimental_option('prefs', {
  23. "download.default_directory": str(DOWNLOAD_DIR),
  24. "download.prompt_for_download": False, # To auto download the file
  25. "download.directory_upgrade": True,
  26. })
  27. if 'CHROME_BINARY_LOCATION' in os.environ:
  28. chrome_options.binary_location = os.environ['CHROME_BINARY_LOCATION']
  29. return chrome_options
  30. @pytest.fixture
  31. def capabilities(capabilities: Dict) -> Dict:
  32. capabilities['goog:loggingPrefs'] = {'browser': 'ALL'}
  33. return capabilities
  34. @pytest.fixture(autouse=True)
  35. def reset_globals() -> Generator[None, None, None]:
  36. for route in app.routes:
  37. if route.path.startswith('/_nicegui/auto/static/'):
  38. app.remove_route(route.path)
  39. for path in {'/'}.union(Client.page_routes.values()):
  40. app.remove_route(path)
  41. app.openapi_schema = None
  42. app.middleware_stack = None
  43. app.user_middleware.clear()
  44. # NOTE favicon routes must be removed separately because they are not "pages"
  45. for route in app.routes:
  46. if route.path.endswith('/favicon.ico'):
  47. app.routes.remove(route)
  48. importlib.reload(core)
  49. Client.instances.clear()
  50. Client.page_routes.clear()
  51. Client.auto_index_client = Client(page('/'), shared=True).__enter__()
  52. app.reset()
  53. # NOTE we need to re-add the auto index route because we removed all routes above
  54. app.get('/')(Client.auto_index_client.build_response)
  55. binding.reset()
  56. @pytest.fixture(scope='session', autouse=True)
  57. def remove_all_screenshots() -> None:
  58. if os.path.exists(Screen.SCREENSHOT_DIR):
  59. for name in os.listdir(Screen.SCREENSHOT_DIR):
  60. os.remove(os.path.join(Screen.SCREENSHOT_DIR, name))
  61. @pytest.fixture(scope='function')
  62. def driver(chrome_options: webdriver.ChromeOptions) -> webdriver.Chrome:
  63. s = Service()
  64. driver_ = webdriver.Chrome(service=s, options=chrome_options)
  65. driver_.implicitly_wait(Screen.IMPLICIT_WAIT)
  66. driver_.set_page_load_timeout(4)
  67. yield driver_
  68. driver_.quit()
  69. @pytest.fixture
  70. def screen(driver: webdriver.Chrome, request: pytest.FixtureRequest, caplog: pytest.LogCaptureFixture) \
  71. -> Generator[Screen, None, None]:
  72. screen_ = Screen(driver, caplog)
  73. yield screen_
  74. if screen_.is_open:
  75. screen_.shot(request.node.name)
  76. logs = screen_.caplog.get_records('call')
  77. screen_.stop_server()
  78. if DOWNLOAD_DIR.exists():
  79. shutil.rmtree(DOWNLOAD_DIR)
  80. if logs:
  81. pytest.fail('There were unexpected logs. See "Captured log call" below.', pytrace=False)