Bug 1274159 - Part 4: Add test cases for HTMLConstructor;

Tag UXP Issue #1344
This commit is contained in:
Gaming4JC 2020-01-02 21:48:12 -05:00 committed by Roy Tam
commit d76a336cd0
8 changed files with 437 additions and 0 deletions

View file

@ -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

View file

@ -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>

View file

@ -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();
})();
}));

View file

@ -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();
})();
}));
});

View file

@ -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]

View file

@ -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>

View file

@ -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>