summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/webcomponents
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/mochitest/webcomponents')
-rw-r--r--dom/tests/mochitest/webcomponents/chrome.ini9
-rw-r--r--dom/tests/mochitest/webcomponents/dummy_page.html10
-rw-r--r--dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js81
-rw-r--r--dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js247
-rw-r--r--dom/tests/mochitest/webcomponents/mochitest.ini6
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html42
-rw-r--r--dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html41
7 files changed, 436 insertions, 0 deletions
diff --git a/dom/tests/mochitest/webcomponents/chrome.ini b/dom/tests/mochitest/webcomponents/chrome.ini
new file mode 100644
index 000000000..5e25c2123
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/chrome.ini
@@ -0,0 +1,9 @@
+[DEFAULT]
+support-files =
+ dummy_page.html
+
+[test_custom_element_htmlconstructor_chrome.html]
+skip-if = os == 'android' # bug 1323645
+support-files =
+ htmlconstructor_autonomous_tests.js
+ htmlconstructor_builtin_tests.js
diff --git a/dom/tests/mochitest/webcomponents/dummy_page.html b/dom/tests/mochitest/webcomponents/dummy_page.html
new file mode 100644
index 000000000..fd238954c
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/dummy_page.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>Dummy test page</title>
+<meta charset="utf-8"/>
+</head>
+<body>
+<p>Dummy test page</p>
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js b/dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js
new file mode 100644
index 000000000..636d9aff6
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/htmlconstructor_autonomous_tests.js
@@ -0,0 +1,81 @@
+promises.push(test_with_new_window((testWindow) => {
+ // Test calling the HTMLElement constructor.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ testWindow.HTMLElement();
+ }, 'calling the HTMLElement constructor should throw a TypeError');
+ })();
+
+ // Test constructing a HTMLELement.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ new testWindow.HTMLElement();
+ }, 'constructing a HTMLElement should throw a TypeError');
+ })();
+
+ // Test constructing a custom element with defining HTMLElement as entry.
+ (() => {
+ testWindow.customElements.define('x-defining-html-element',
+ testWindow.HTMLElement);
+ SimpleTest.doesThrow(() => {
+ new testWindow.HTMLElement();
+ }, 'constructing a custom element with defining HTMLElement as registry ' +
+ 'entry should throw a TypeError');
+ })();
+
+ // Test calling a custom element constructor and constructing an autonomous
+ // custom element.
+ (() => {
+ let num_constructor_invocations = 0;
+ class X extends testWindow.HTMLElement {
+ constructor() {
+ super();
+ num_constructor_invocations++;
+ }
+ }
+ testWindow.customElements.define('x-element', X);
+ SimpleTest.doesThrow(() => {
+ X();
+ }, 'calling an autonomous custom element constructor should throw a TypeError');
+
+ let element = new X();
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(element)), X.prototype,
+ 'constructing an autonomous custom element; ' +
+ 'the element should be a registered constructor');
+ SimpleTest.is(element.localName, 'x-element',
+ 'constructing an autonomous custom element; ' +
+ 'the element tag name should be "x-element"');
+ SimpleTest.is(element.namespaceURI, 'http://www.w3.org/1999/xhtml',
+ 'constructing an autonomous custom element; ' +
+ 'the element should be in the HTML namespace');
+ SimpleTest.is(element.prefix, null,
+ 'constructing an autonomous custom element; ' +
+ 'the element name should not have a prefix');
+ SimpleTest.is(element.ownerDocument, testWindow.document,
+ 'constructing an autonomous custom element; ' +
+ 'the element should be owned by the registry\'s associated ' +
+ 'document');
+ SimpleTest.is(num_constructor_invocations, 1,
+ 'constructing an autonomous custom element; ' +
+ 'the constructor should have been invoked once');
+ })();
+
+ // Test if prototype is no an object.
+ (() => {
+ function ElementWithNonObjectPrototype() {
+ let o = Reflect.construct(testWindow.HTMLElement, [], new.target);
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(o)), window.HTMLElement.prototype,
+ 'constructing an autonomous custom element; ' +
+ 'if prototype is not object, fallback from NewTarget\'s realm');
+ }
+
+ // Prototype have to be an object during define(), otherwise define will
+ // throw an TypeError exception.
+ ElementWithNonObjectPrototype.prototype = {};
+ testWindow.customElements.define('x-non-object-prototype',
+ ElementWithNonObjectPrototype);
+
+ ElementWithNonObjectPrototype.prototype = "string";
+ new ElementWithNonObjectPrototype();
+ })();
+}));
diff --git a/dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js b/dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js
new file mode 100644
index 000000000..dd6515148
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/htmlconstructor_builtin_tests.js
@@ -0,0 +1,247 @@
+[
+ // [TagName, InterfaceName]
+ ['a', 'Anchor'],
+ ['abbr', ''],
+ ['acronym', ''],
+ ['address', ''],
+ ['area', 'Area'],
+ ['article', ''],
+ ['aside', ''],
+ ['audio', 'Audio'],
+ ['b', ''],
+ ['base', 'Base'],
+ ['basefont', ''],
+ ['bdo', ''],
+ ['big', ''],
+ ['blockquote', 'Quote'],
+ ['body', 'Body'],
+ ['br', 'BR'],
+ ['button', 'Button'],
+ ['canvas', 'Canvas'],
+ ['caption', 'TableCaption'],
+ ['center', ''],
+ ['cite', ''],
+ ['code', ''],
+ ['col', 'TableCol'],
+ ['colgroup', 'TableCol'],
+ ['data', 'Data'],
+ ['datalist', 'DataList'],
+ ['dd', ''],
+ ['del', 'Mod'],
+ ['details', 'Details'],
+ ['dfn', ''],
+ ['dir', 'Directory'],
+ ['div', 'Div'],
+ ['dl', 'DList'],
+ ['dt', ''],
+ ['em', ''],
+ ['embed', 'Embed'],
+ ['fieldset', 'FieldSet'],
+ ['figcaption', ''],
+ ['figure', ''],
+ ['font', 'Font'],
+ ['footer', ''],
+ ['form', 'Form'],
+ ['frame', 'Frame'],
+ ['frameset', 'FrameSet'],
+ ['h1', 'Heading'],
+ ['h2', 'Heading'],
+ ['h3', 'Heading'],
+ ['h4', 'Heading'],
+ ['h5', 'Heading'],
+ ['h6', 'Heading'],
+ ['head', 'Head'],
+ ['header', ''],
+ ['hgroup', ''],
+ ['hr', 'HR'],
+ ['html', 'Html'],
+ ['i', ''],
+ ['iframe', 'IFrame'],
+ ['image', ''],
+ ['img', 'Image'],
+ ['input', 'Input'],
+ ['ins', 'Mod'],
+ ['kbd', ''],
+ ['label', 'Label'],
+ ['legend', 'Legend'],
+ ['li', 'LI'],
+ ['link', 'Link'],
+ ['listing', 'Pre'],
+ ['main', ''],
+ ['map', 'Map'],
+ ['mark', ''],
+ ['marquee', 'Div'],
+ ['menu', 'Menu'],
+ ['menuitem', 'MenuItem'],
+ ['meta', 'Meta'],
+ ['meter', 'Meter'],
+ ['nav', ''],
+ ['nobr', ''],
+ ['noembed', ''],
+ ['noframes', ''],
+ ['noscript', ''],
+ ['object', 'Object'],
+ ['ol', 'OList'],
+ ['optgroup', 'OptGroup'],
+ ['option', 'Option'],
+ ['output', 'Output'],
+ ['p', 'Paragraph'],
+ ['param', 'Param'],
+ ['picture', 'Picture'],
+ ['plaintext', ''],
+ ['pre', 'Pre'],
+ ['progress', 'Progress'],
+ ['q', 'Quote'],
+ ['rb', ''],
+ ['rp', ''],
+ ['rt', ''],
+ ['rtc', ''],
+ ['ruby', ''],
+ ['s', ''],
+ ['samp', ''],
+ ['script', 'Script'],
+ ['section', ''],
+ ['select', 'Select'],
+ ['small', ''],
+ ['source', 'Source'],
+ ['span', 'Span'],
+ ['strike', ''],
+ ['strong', ''],
+ ['style', 'Style'],
+ ['sub', ''],
+ ['summary', ''],
+ ['sup', ''],
+ ['table', 'Table'],
+ ['tbody', 'TableSection'],
+ ['td', 'TableCell'],
+ ['textarea', 'TextArea'],
+ ['tfoot', 'TableSection'],
+ ['th', 'TableCell'],
+ ['thead', 'TableSection'],
+ ['template', 'Template'],
+ ['time', 'Time'],
+ ['title', 'Title'],
+ ['tr', 'TableRow'],
+ ['track', 'Track'],
+ ['tt', ''],
+ ['u', ''],
+ ['ul', 'UList'],
+ ['var', ''],
+ ['video', 'Video'],
+ ['wbr', ''],
+ ['xmp', 'Pre'],
+].forEach((e) => {
+ let tagName = e[0];
+ let interfaceName = 'HTML' + e[1] + 'Element';
+ promises.push(test_with_new_window((testWindow) => {
+ // Use window from iframe to isolate the test.
+ // Test calling the HTML*Element constructor.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ testWindow[interfaceName]();
+ }, 'calling the ' + interfaceName + ' constructor should throw a TypeError');
+ })();
+
+ // Test constructing a HTML*ELement.
+ (() => {
+ SimpleTest.doesThrow(() => {
+ new testWindow[interfaceName]();
+ }, 'constructing a ' + interfaceName + ' should throw a TypeError');
+ })();
+
+ // Test constructing a custom element with defining HTML*Element as entry.
+ (() => {
+ testWindow.customElements.define('x-defining-' + tagName,
+ testWindow[interfaceName]);
+ SimpleTest.doesThrow(() => {
+ new testWindow[interfaceName]();
+ }, 'constructing a custom element with defining ' + interfaceName +
+ ' as registry entry should throw a TypeError');
+ })();
+
+ // Since HTMLElement can be registered without specifying "extends", skip
+ // testing HTMLElement tags.
+ if (interfaceName !== "HTMLElement") {
+ // Test constructing a customized HTML*Element with defining a registry entry
+ // without specifying "extends".
+ (() => {
+ class X extends testWindow[interfaceName] {}
+ testWindow.customElements.define('x-defining-invalid-' + tagName, X);
+ SimpleTest.doesThrow(() => {
+ new X();
+ }, 'constructing a customized ' + interfaceName + ' with defining a ' +
+ 'registry entry without specifying "extends" should throw a TypeError');
+ })();
+ }
+
+ // Test constructing a built-in custom element with defining a registry entry
+ // with incorrect "extends" information.
+ (() => {
+ class X extends testWindow[interfaceName] {}
+ testWindow.customElements.define('x-defining-incorrect-' + tagName, X,
+ { extends: tagName === 'img' ? 'p' : 'img' });
+ SimpleTest.doesThrow(() => {
+ new X();
+ }, 'constructing a customized ' + interfaceName + ' with defining a ' +
+ 'registry entry with incorrect "extends" should throw a TypeError');
+ })();
+
+ // Test calling a custom element constructor and constructing a built-in
+ // custom element.
+ (() => {
+ let num_constructor_invocations = 0;
+ class X extends testWindow[interfaceName] {
+ constructor() {
+ super();
+ num_constructor_invocations++;
+ }
+ }
+ testWindow.customElements.define('x-' + tagName, X, { extends: tagName });
+ SimpleTest.doesThrow(() => {
+ X();
+ }, 'calling a customized ' + interfaceName + ' constructor should throw a TypeError');
+
+ let element = new X();
+
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(element)), X.prototype,
+ 'constructing a customized ' + interfaceName +
+ '; the element should be a registered constructor');
+ SimpleTest.is(element.localName, tagName,
+ 'constructing a customized ' + interfaceName +
+ '; the element tag name should be "' + tagName + '"');
+ SimpleTest.is(element.namespaceURI, 'http://www.w3.org/1999/xhtml',
+ 'constructing a customized ' + interfaceName +
+ '; the element should be in the HTML namespace');
+ SimpleTest.is(element.prefix, null,
+ 'constructing a customized ' + interfaceName +
+ '; the element name should not have a prefix');
+ SimpleTest.is(element.ownerDocument, testWindow.document,
+ 'constructing a customized ' + interfaceName +
+ '; the element should be owned by the registry\'s associated ' +
+ 'document');
+ SimpleTest.is(num_constructor_invocations, 1,
+ 'constructing a customized ' + interfaceName +
+ '; the constructor should have been invoked once');
+ })();
+
+ // Test if prototype is no an object.
+ (() => {
+ function ElementWithNonObjectPrototype() {
+ let o = Reflect.construct(testWindow[interfaceName], [], new.target);
+ SimpleTest.is(Object.getPrototypeOf(Cu.waiveXrays(o)), window[interfaceName].prototype,
+ 'constructing a customized ' + interfaceName +
+ '; if prototype is not object, fallback from NewTarget\'s realm');
+ }
+
+ // Prototype have to be an object during define(), otherwise define will
+ // throw an TypeError exception.
+ ElementWithNonObjectPrototype.prototype = {};
+ testWindow.customElements.define('x-non-object-prototype-' + tagName,
+ ElementWithNonObjectPrototype,
+ { extends: tagName });
+
+ ElementWithNonObjectPrototype.prototype = "string";
+ new ElementWithNonObjectPrototype();
+ })();
+ }));
+});
diff --git a/dom/tests/mochitest/webcomponents/mochitest.ini b/dom/tests/mochitest/webcomponents/mochitest.ini
index 496f7ea4d..3ab56de95 100644
--- a/dom/tests/mochitest/webcomponents/mochitest.ini
+++ b/dom/tests/mochitest/webcomponents/mochitest.ini
@@ -1,6 +1,7 @@
[DEFAULT]
support-files =
inert_style.css
+ dummy_page.html
[test_bug900724.html]
[test_bug1017896.html]
@@ -11,6 +12,11 @@ support-files =
[test_custom_element_callback_innerhtml.html]
[test_custom_element_clone_callbacks.html]
[test_custom_element_clone_callbacks_extended.html]
+[test_custom_element_htmlconstructor.html]
+skip-if = os == 'android' # bug 1323645
+support-files =
+ htmlconstructor_autonomous_tests.js
+ htmlconstructor_builtin_tests.js
[test_custom_element_import_node_created_callback.html]
[test_custom_element_in_shadow.html]
[test_custom_element_register_invalid_callbacks.html]
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html
new file mode 100644
index 000000000..b022a7887
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1274159
+-->
+<head>
+ <title>Test HTMLConstructor for custom elements.</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1274159">Bug 1274159</a>
+<script type="text/javascript">
+function test_with_new_window(f) {
+ return new Promise((aResolve) => {
+ let iframe = document.createElement('iframe');
+ iframe.setAttribute('type', 'content');
+ iframe.setAttribute('src', 'dummy_page.html');
+ iframe.onload = function() {
+ f(iframe.contentWindow);
+ aResolve();
+ };
+ document.body.appendChild(iframe);
+ });
+}
+
+// Fake the Cu.waiveXrays, so that we can share the tests with mochitest chrome.
+var Cu = { waiveXrays: (obj) => obj };
+var promises = [];
+SimpleTest.waitForExplicitFinish();
+</script>
+<!-- Test cases for autonomous element -->
+<script type="text/javascript" src="htmlconstructor_autonomous_tests.js"></script>
+<!-- Test cases for customized built-in element -->
+<script type="text/javascript" src="htmlconstructor_builtin_tests.js"></script>
+<script type="text/javascript">
+Promise.all(promises).then(() => {
+ SimpleTest.finish();
+});
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html
new file mode 100644
index 000000000..8c7ec0ac6
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_custom_element_htmlconstructor_chrome.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1274159
+-->
+<head>
+ <title>Test HTMLConstructor for custom elements.</title>
+ <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1274159">Bug 1274159</a>
+<script type="text/javascript">
+function test_with_new_window(f) {
+ return new Promise((aResolve) => {
+ let iframe = document.createElement('iframe');
+ iframe.setAttribute('type', 'content');
+ iframe.setAttribute('src', 'http://example.org/tests/dom/tests/mochitest/webcomponents/dummy_page.html');
+ iframe.onload = function() {
+ f(iframe.contentWindow);
+ aResolve();
+ };
+ document.body.appendChild(iframe);
+ });
+}
+
+var Cu = Components.utils;
+var promises = [];
+SimpleTest.waitForExplicitFinish();
+</script>
+<!-- Test cases for autonomous element -->
+<script type="text/javascript" src="htmlconstructor_autonomous_tests.js"></script>
+<!-- Test cases for customized built-in element -->
+<script type="text/javascript" src="htmlconstructor_builtin_tests.js"></script>
+<script type="text/javascript">
+Promise.all(promises).then(() => {
+ SimpleTest.finish();
+});
+</script>
+</body>
+</html>