hterm: convert test suite to mocha

Mocha is a commonly used test framework in the wider world.
It provides all the functionality we need, and is usable in
the browser and command line.  It's also a bit more flexible
and expressive than our current framework.

Change-Id: I080f3ec52567f82a97716346d7a93fc19a5b5dd0
Reviewed-on: https://chromium-review.googlesource.com/c/apps/libapps/+/1646588
Reviewed-by: Vitaliy Shipitsyn <vsh@google.com>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/hterm/js/hterm_test.js b/hterm/js/hterm_test.js
index 754cb53..59a8ca4 100644
--- a/hterm/js/hterm_test.js
+++ b/hterm/js/hterm_test.js
@@ -4,76 +4,32 @@
 
 'use strict';
 
-var testManager;
-var testRun;
+/**
+ * @fileoverview Test framework setup when run inside the browser.
+ */
 
+// Setup the mocha framework.
+mocha.setup('bdd');
+mocha.checkLeaks();
+
+// Add a global shortcut to the assert API.
+const assert = chai.assert;
+
+// Catch any random errors before the test runner runs.
+let earlyError = null;
+window.onerror = function() {
+  earlyError = Array.from(arguments);
+};
+
+// Run the test framework once everything is finished.
 window.onload = function() {
   hterm.defaultStorage = new lib.Storage.Memory();
 
-  lib.init(function() {
-    testManager = new lib.TestManager();
-    testManager.log.save = true;
+  lib.init(() => {
+    mocha.run();
 
-    testManager.onTestRunComplete = (testRun) => {
-      var document = testRun.cx.window.document;
-      document.body.innerHTML = '';
-
-      var results = document.createElement('div');
-      var p, pre;
-
-      p = document.createElement('p');
-      p.innerText = 'Check JavaScript console for test log/status.';
-      results.appendChild(p);
-
-      p = document.createElement('p');
-      p.id = 'status';
-      p.innerText = 'Finished.';
-      p.className = (testRun.failures.length == 0) ? 'good' : 'bad';
-      results.appendChild(p);
-
-      p = document.createElement('p');
-      p.id = 'passed';
-      p.className = 'good';
-      document.title = p.innerText = testRun.passes.length + ' tests passed.';
-      results.appendChild(p);
-
-      p = document.createElement('p');
-      p.id = 'failed';
-      p.className = 'bad';
-      if (testRun.failures.length != 0)
-        document.title = p.innerText =
-            'ERROR: ' + testRun.failures.length + ' tests failed!';
-      results.appendChild(p);
-
-      pre = document.createElement('pre');
-      pre.id = 'log';
-      pre.innerText = testRun.testManager.log.data;
-      results.appendChild(pre);
-
-      // Only clear the body if everything passed in case the current rendering
-      // is useful to debugging.  Insert our log/results above it.
-      if (testRun.failures.length == 0)
-        document.body.innerText = '';
-      document.body.insertBefore(results, document.body.firstChild);
-    };
-
-    testManager.testPreamble = (result, cx) => {
-      var testRun = result.testRun;
-      cx.window.document.title =
-          '[' + (testRun.passes.length + testRun.failures.length) + '] ' +
-          result.test.fullName;
-    };
-
-    testRun = testManager.createTestRun({window: window});
-
-    // Stop after the first failure to make it easier to debug in the
-    // JS console.
-    testRun.maxFailures = 1;
-
-    const params = new URLSearchParams(document.location.search);
-    const pattern = params.get('pattern');
-    testRun.selectPattern(new RegExp(pattern ? pattern : '.'));
-    testRun.run();
-
-  }, console.log.bind(console));
+    if (earlyError !== null) {
+      assert.fail(`uncaught exception detected:\n${earlyError.join('\n')}\n`);
+    }
+  });
 };