Browse Source

Improve the selenium check and add uncaught error checking

Steven Silvester 7 years ago
parent
commit
90d87ed78c
3 changed files with 68 additions and 36 deletions
  1. 15 0
      jupyterlab/index.app.js
  2. 16 0
      jupyterlab/index.js
  3. 37 36
      jupyterlab/selenium_check.py

+ 15 - 0
jupyterlab/index.app.js

@@ -73,6 +73,21 @@ function main() {
         // No-op
     }
     lab.start({ "ignorePlugins": ignorePlugins });
+
+    // Handle a selenium test.
+    var seleniumTest = PageConfig.getOption('seleniumTest');
+    if (seleniumTest.toLowerCase() === 'true') {
+        var caught_errors = []
+        window.onerror = function(msg, url, line, col, error) {
+           caught_errors.push(String(error));
+        };
+        lab.restored.then(() => {
+            var el = document.createElement('div');
+            el.id = 'seleniumResult';
+            el.textContent = JSON.stringify(caught_errors);
+            document.body.appendChild(el);
+        });
+    }
 }
 
 window.onload = main;

+ 16 - 0
jupyterlab/index.js

@@ -73,6 +73,22 @@ function main() {
         // No-op
     }
     lab.start({ "ignorePlugins": ignorePlugins });
+
+    // Handle a selenium test.
+    var seleniumTest = PageConfig.getOption('seleniumTest');
+    if (seleniumTest.toLowerCase() === 'true') {
+        var caught_errors = []
+        window.onerror = function(msg, url, line, col, error) {
+           caught_errors.push(String(error));
+        };
+        lab.restored.then(() => {
+            var el = document.createElement('div');
+            el.id = 'seleniumResult';
+            el.textContent = JSON.stringify(caught_errors);
+            document.body.appendChild(el);
+        });
+    }
+
 }
 
 window.onload = main;

+ 37 - 36
jupyterlab/selenium_check.py

@@ -2,19 +2,18 @@
 # -*- coding: utf-8 -*-
 from __future__ import print_function, absolute_import
 
+import json
 import os
 import sys
 import time
 import threading
 
 from tornado import ioloop
-from notebook.notebookapp import NotebookApp, flags, aliases
+from notebook.notebookapp import flags, aliases
 from traitlets import Bool, Unicode
-from jupyterlab_launcher import LabConfig, add_handlers
 
 from selenium import webdriver
-
-from .commands import get_app_dir
+from .labapp import LabApp
 
 
 here = os.path.dirname(__file__)
@@ -31,9 +30,8 @@ test_aliases = dict(aliases)
 test_aliases['app-dir'] = 'TestApp.app_dir'
 
 
-class TestApp(NotebookApp):
+class TestApp(LabApp):
 
-    default_url = Unicode('/lab')
     open_browser = Bool(False)
     base_url = '/foo'
     flags = test_flags
@@ -46,64 +44,67 @@ class TestApp(NotebookApp):
         help="The app directory to build in")
 
     def start(self):
-        self.io_loop = ioloop.IOLoop.current()
-        config = LabConfig()
-        if self.core_mode:
-            config.assets_dir = os.path.join(here, 'build')
-        elif self.app_dir:
-            config.assets_dir = os.path.join(self.app_dir, 'static')
-        else:
-            config.assets_dir = os.path.join(get_app_dir(), 'static')
-
-        print('****Testing assets dir %s' % config.assets_dir)
+        web_app = self.web_app
+        web_app.settings.setdefault('page_config_data', dict())
+        web_app.settings['page_config_data']['seleniumTest'] = True
 
-        config.settings_dir = ''
-
-        add_handlers(self.web_app, config)
+        self.io_loop = ioloop.IOLoop.current()
         self.io_loop.call_later(1, self._run_selenium)
         super(TestApp, self).start()
 
     def _run_selenium(self):
+        # This must be done in a thread to allow the selenium driver
+        # to connect to the server.
         thread = threading.Thread(target=run_selenium,
-            args=(self.display_url, self._selenium_finished))
+            args=(self.display_url, self.log, self._selenium_finished))
         thread.start()
 
     def _selenium_finished(self, result):
         self.io_loop.add_callback(lambda: sys.exit(result))
 
 
-def run_selenium(url, callback):
+def run_selenium(url, log, callback):
     """Run the selenium test and call the callback with the exit code.exit
     """
 
-    print('Starting Firefox Driver')
+    log.info('Starting Firefox Driver')
     driver = webdriver.Firefox()
 
-    print('Navigating to page:', url)
+    log.info('Navigating to page:', url)
     driver.get(url)
 
-    completed = False
-
     # Start a poll loop.
     t0 = time.time()
-    while time.time() - t0 < 10:
-        el = driver.find_element_by_id('main')
-        if el:
-            completed = True
-            break
+    while time.time() - t0 < 20:
+        try:
+            el = driver.find_element_by_id('seleniumResult')
+            if el:
+                break
+        except Exception as e:
+            pass
 
         # Avoid hogging the main thread.
         time.sleep(0.5)
 
+    if not el:
+        driver.quit()
+        log.error('Application did not restore properly')
+        callback(1)
+        return
+
+    errors = json.loads(el.get_attribute('textContent'))
     driver.quit()
 
-    # Return the exit code.
-    if not completed:
-        callback(1)
-    else:
-        if os.path.exists('./geckodriver.log'):
+    if os.path.exists('./geckodriver.log'):
             os.remove('./geckodriver.log')
-        callback(0)
+
+    if errors:
+        for error in errors:
+            log.error(error)
+        callback(1)
+        return
+
+    callback(0)
 
 
 if __name__ == '__main__':