example_check.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # -*- coding: utf-8 -*-
  2. """
  3. This file is mean to be called with a path to an example directory as
  4. its argument. We import the application entry point for the example
  5. and add instrument them with a puppeteer test that makes sure
  6. there are no console errors or uncaught errors prior to a sentinal
  7. string being printed.
  8. e.g. python example_check.py ./app
  9. """
  10. from concurrent.futures import ThreadPoolExecutor
  11. import importlib.util
  12. import logging
  13. from os import path as osp
  14. import os
  15. import shutil
  16. import sys
  17. import subprocess
  18. from tornado.ioloop import IOLoop
  19. from traitlets import Bool, Unicode
  20. from jupyterlab.labapp import get_app_dir
  21. here = osp.abspath(osp.dirname(__file__))
  22. # Load the main file and grab the example class so we can subclass
  23. example_dir = sys.argv.pop()
  24. mod_path = osp.abspath(osp.join(example_dir, 'main.py'))
  25. spec = importlib.util.spec_from_file_location("example", mod_path)
  26. mod = importlib.util.module_from_spec(spec)
  27. spec.loader.exec_module(mod)
  28. class LogErrorHandler(logging.Handler):
  29. """A handler that exits with 1 on a logged error."""
  30. def emit(self, record):
  31. if record.level < logging.ERROR:
  32. return
  33. print(record.msg, file=sys.stderr)
  34. logging.shutdown()
  35. sys.exit(1)
  36. class ExampleCheckApp(mod.ExampleApp):
  37. """An example app that adds instrumentation."""
  38. open_browser = Bool(False)
  39. default_url = '/example'
  40. base_url = '/foo/'
  41. ip = '127.0.0.1'
  42. def start(self):
  43. self.log.addHandler(LogErrorHandler())
  44. pool = ThreadPoolExecutor()
  45. future = pool.submit(run_browser, self.display_url)
  46. IOLoop.current().add_future(future, self._browser_finished)
  47. super().start()
  48. def _browser_finished(self, future):
  49. try:
  50. sys.exit(future.result())
  51. except Exception as e:
  52. self.log.error(str(e))
  53. def run_browser(url):
  54. """Run the browser test and return an exit code.
  55. """
  56. target = osp.join(get_app_dir(), 'example_test')
  57. if not osp.exists(osp.join(target, 'node_modules')):
  58. os.makedirs(target)
  59. subprocess.call(["jlpm"], cwd=target)
  60. subprocess.call(["jlpm", "add", "puppeteer"], cwd=target)
  61. shutil.copy(osp.join(here, 'chrome-example-test.js'), osp.join(target, 'chrome-example-test.js'))
  62. return subprocess.check_call(["node", "chrome-example-test.js", url], cwd=target)
  63. if __name__ == '__main__':
  64. ExampleCheckApp.launch_instance()