conftest.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import json
  2. import os
  3. import pytest
  4. import requests
  5. from subprocess import Popen
  6. import sys
  7. from testpath.tempdir import TemporaryDirectory
  8. import time
  9. from urllib.parse import urljoin
  10. from selenium.webdriver import Firefox, Remote, Chrome
  11. from .utils import Notebook
  12. pjoin = os.path.join
  13. def _wait_for_server(proc, info_file_path):
  14. """Wait 30 seconds for the notebook server to start"""
  15. for i in range(300):
  16. if proc.poll() is not None:
  17. raise RuntimeError("Notebook server failed to start")
  18. if os.path.exists(info_file_path):
  19. try:
  20. with open(info_file_path) as f:
  21. return json.load(f)
  22. except ValueError:
  23. # If the server is halfway through writing the file, we may
  24. # get invalid JSON; it should be ready next iteration.
  25. pass
  26. time.sleep(0.1)
  27. raise RuntimeError("Didn't find %s in 30 seconds", info_file_path)
  28. @pytest.fixture(scope='session')
  29. def notebook_server():
  30. info = {}
  31. with TemporaryDirectory() as td:
  32. nbdir = info['nbdir'] = pjoin(td, 'notebooks')
  33. os.makedirs(pjoin(nbdir, u'sub ∂ir1', u'sub ∂ir 1a'))
  34. os.makedirs(pjoin(nbdir, u'sub ∂ir2', u'sub ∂ir 1b'))
  35. info['extra_env'] = {
  36. 'JUPYTER_CONFIG_DIR': pjoin(td, 'jupyter_config'),
  37. 'JUPYTER_RUNTIME_DIR': pjoin(td, 'jupyter_runtime'),
  38. 'IPYTHONDIR': pjoin(td, 'ipython'),
  39. }
  40. env = os.environ.copy()
  41. env.update(info['extra_env'])
  42. command = [sys.executable, '-m', 'notebook',
  43. '--no-browser',
  44. '--notebook-dir', nbdir,
  45. # run with a base URL that would be escaped,
  46. # to test that we don't double-escape URLs
  47. '--NotebookApp.base_url=/a@b/',
  48. ]
  49. print("command=", command)
  50. proc = info['popen'] = Popen(command, cwd=nbdir, env=env)
  51. info_file_path = pjoin(td, 'jupyter_runtime',
  52. 'nbserver-%i.json' % proc.pid)
  53. info.update(_wait_for_server(proc, info_file_path))
  54. print("Notebook server info:", info)
  55. yield info
  56. # Shut the server down
  57. requests.post(urljoin(info['url'], 'api/shutdown'),
  58. headers={'Authorization': 'token '+info['token']})
  59. def make_sauce_driver():
  60. """This function helps travis create a driver on Sauce Labs.
  61. This function will err if used without specifying the variables expected
  62. in that context.
  63. """
  64. username = os.environ["SAUCE_USERNAME"]
  65. access_key = os.environ["SAUCE_ACCESS_KEY"]
  66. capabilities = {
  67. "tunnel-identifier": os.environ["TRAVIS_JOB_NUMBER"],
  68. "build": os.environ["TRAVIS_BUILD_NUMBER"],
  69. "tags": [os.environ['TRAVIS_PYTHON_VERSION'], 'CI'],
  70. "platform": "Windows 10",
  71. "browserName": os.environ['JUPYTER_TEST_BROWSER'],
  72. "version": "latest",
  73. }
  74. if capabilities['browserName'] == 'firefox':
  75. # Attempt to work around issue where browser loses authentication
  76. capabilities['version'] = '57.0'
  77. hub_url = "%s:%s@localhost:4445" % (username, access_key)
  78. print("Connecting remote driver on Sauce Labs")
  79. driver = Remote(desired_capabilities=capabilities,
  80. command_executor="http://%s/wd/hub" % hub_url)
  81. return driver
  82. @pytest.fixture(scope='session')
  83. def selenium_driver():
  84. if os.environ.get('SAUCE_USERNAME'):
  85. driver = make_sauce_driver()
  86. elif os.environ.get('JUPYTER_TEST_BROWSER') == 'chrome':
  87. driver = Chrome()
  88. else:
  89. driver = Firefox()
  90. yield driver
  91. # Teardown
  92. driver.quit()
  93. @pytest.fixture(scope='module')
  94. def authenticated_browser(selenium_driver, notebook_server):
  95. selenium_driver.jupyter_server_info = notebook_server
  96. selenium_driver.get("{url}?token={token}".format(**notebook_server))
  97. return selenium_driver
  98. @pytest.fixture
  99. def notebook(authenticated_browser):
  100. return Notebook.new_notebook(authenticated_browser)