diff --git a/pkg/playground/exception.html b/pkg/playground/exception.html
new file mode 100644
index 000000000000..7294d5da2563
--- /dev/null
+++ b/pkg/playground/exception.html
@@ -0,0 +1,20 @@
+
+
+
+
+ Javascript exceptions
+
+
+
+
+
+
+
Exception
+
+
Clicking this button should make a javascript exception happen.
+
+
+
+
+
+
diff --git a/pkg/playground/exception.js b/pkg/playground/exception.js
new file mode 100644
index 000000000000..92b5d406b60f
--- /dev/null
+++ b/pkg/playground/exception.js
@@ -0,0 +1,13 @@
+/* An unhandled javascript exception */
+var button = document.getElementById("exception");
+button.addEventListener("click", function() {
+ var obj = { };
+ window.setTimeout(function() {
+ obj[0].value = 1;
+ }, 0);
+});
+
+var cockpit = require("cockpit");
+cockpit.transport.wait(function() {
+ document.body.removeAttribute("hidden");
+});
diff --git a/pkg/playground/manifest.json.in b/pkg/playground/manifest.json.in
index ec770119f2ea..0ae023217ec5 100644
--- a/pkg/playground/manifest.json.in
+++ b/pkg/playground/manifest.json.in
@@ -15,6 +15,9 @@
"translate": {
"label": "Translating"
},
+ "exception": {
+ "label": "Exceptions"
+ },
"pkgs": {
"label": "Packages"
}
diff --git a/src/base1/test-http.js b/src/base1/test-http.js
index a97780076471..ca3cc2cc1157 100644
--- a/src/base1/test-http.js
+++ b/src/base1/test-http.js
@@ -31,6 +31,9 @@ QUnit.asyncTest("simple request", function() {
"cockpit": "122"
},
tools: {
+ 'exception': {
+ 'label': 'Exceptions'
+ },
'patterns': {
label: "Design Patterns",
path: "jquery-patterns.html"
diff --git a/src/base1/test-stub.js b/src/base1/test-stub.js
index 25b666e511dd..28d3916bf1c2 100644
--- a/src/base1/test-stub.js
+++ b/src/base1/test-stub.js
@@ -70,6 +70,9 @@ QUnit.asyncTest("http", function() {
cockpit: "122"
},
tools: {
+ 'exception': {
+ label: 'Exceptions'
+ },
'patterns': {
label: "Design Patterns",
path: "jquery-patterns.html"
diff --git a/test/verify/check-menu b/test/verify/check-menu
index 8e36466bcd0c..499d19595284 100755
--- a/test/verify/check-menu
+++ b/test/verify/check-menu
@@ -21,6 +21,8 @@
import parent
from testlib import *
+import time
+
class TestMenu(MachineCase):
@enableAxe
def testBasic(self):
@@ -50,5 +52,22 @@ class TestMenu(MachineCase):
b.enter_page("/system")
b.wait_visible("#memory_status")
+ # Ensure that our tests pick up unhandled JS exceptions
+ b.switch_to_top()
+ b.click("a[href='/playground/exception']")
+ b.enter_page("/playground/exception")
+ b.wait_visible("button")
+ with self.assertRaisesRegex(RuntimeError, "TypeError:.*value.*undefined"):
+ b.click("button")
+ # Some round trips, one of which should update the deferred exception
+ for i in range(0, 5):
+ b.wait_visible("button")
+ time.sleep(2)
+
+ # UI should also show the crash
+ b.switch_to_top()
+ b.wait_present("#navbar-oops")
+ b.wait_visible("#navbar-oops")
+
if __name__ == '__main__':
test_main()
diff --git a/webpack.config.js b/webpack.config.js
index 35c3adfe8c3c..7a1905760603 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -65,6 +65,9 @@ var info = {
"ovirt/ovirt.less",
],
+ "playground/exception": [
+ "playground/exception.js",
+ ],
"playground/jquery-patterns": [
"playground/jquery-patterns.js",
],
@@ -223,6 +226,7 @@ var info = {
"packagekit/index.html",
+ "playground/exception.html",
"playground/hammer.gif",
"playground/jquery-patterns.html",
"playground/metrics.html",