blob: 721ad1f4ced84b8c81291fe92fa402e7b6384358 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>Custom Elements: CEReactions on Document interface</title>
<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
<meta name="assert" content="importNode and adoptNode of Document interface must have CEReactions">
<meta name="help" content="https://dom.spec.whatwg.org/#document">
<meta name="help" content="https://html.spec.whatwg.org/#document">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../resources/custom-elements-helpers.js"></script>
<script src="./resources/reactions.js"></script>
</head>
<body>
<div id="log"></div>
<script>
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
const instance = contentDocument.createElement('custom-element');
assert_array_equals(element.takeLog().types(), ['constructed']);
const newDoc = contentDocument.implementation.createHTMLDocument();
newDoc.importNode(instance);
assert_array_equals(element.takeLog().types(), []);
}, 'importNode on Document must not construct a new custom element when importing a custom element into a window-less document');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
const template = contentDocument.createElement('template');
template.innerHTML = '<custom-element></custom-element>';
assert_array_equals(element.takeLog().types(), []);
contentDocument.importNode(template.content, true);
assert_array_equals(element.takeLog().types(), ['constructed']);
}, 'importNode on Document must construct a new custom element when importing a custom element from a template');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
const instance = contentDocument.createElement('custom-element');
assert_array_equals(element.takeLog().types(), ['constructed']);
const newDoc = contentDocument.implementation.createHTMLDocument();
newDoc.adoptNode(instance);
const logEntries = element.takeLog();
assert_array_equals(logEntries.types(), ['adopted']);
assert_equals(logEntries.last().oldDocument, contentDocument);
assert_equals(logEntries.last().newDocument, newDoc);
}, 'adoptNode on Document must enqueue an adopted reaction when importing a custom element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
const instance = contentDocument.createElement('custom-element');
const container = contentDocument.createElement('div');
container.contentEditable = true;
container.appendChild(instance);
contentDocument.body.appendChild(container);
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
container.focus();
contentDocument.execCommand('delete', false, null);
assert_array_equals(element.takeLog().types(), ['disconnected']);
}, 'execCommand on Document must enqueue a disconnected reaction when deleting a custom element from a contenteditable element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentDocument.title = '';
const title = contentDocument.querySelector('title');
const instance = contentDocument.createElement('custom-element');
title.appendChild(instance);
instance.textContent = 'hello';
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
assert_equals(title.innerHTML, '<custom-element>hello</custom-element>');
title.text = 'world';
assert_equals(title.innerHTML, 'world');
assert_array_equals(element.takeLog().types(), ['disconnected']);
}, 'title on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
const body = contentDocument.body;
body.innerHTML = '<custom-element>hello</custom-element>';
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
assert_equals(body.innerHTML, '<custom-element>hello</custom-element>');
contentDocument.body = contentDocument.createElement('body');
assert_array_equals(element.takeLog().types(), ['disconnected']);
}, 'body on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
const instance = contentDocument.createElement('custom-element');
const body = contentDocument.createElement('body');
body.appendChild(instance);
assert_array_equals(element.takeLog().types(), ['constructed']);
assert_equals(body.innerHTML, '<custom-element></custom-element>');
contentDocument.body = body;
assert_array_equals(element.takeLog().types(), ['connected']);
}, 'body on Document must enqueue connectedCallback when inserting a custom element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentDocument.body.innerHTML = '<custom-element></custom-element>';
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
contentDocument.open();
assert_array_equals(element.takeLog().types(), ['disconnected']);
}, 'open on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentDocument.body.innerHTML = '<custom-element></custom-element>';
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
contentDocument.write('');
assert_array_equals(element.takeLog().types(), ['disconnected']);
}, 'write on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow, contentDocument) {
contentWindow.document.open();
// document.open()'s spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698.
// However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641
// the custom element registry will be replaced after document.open() call,
// So call customElements.define() after that in order to register defintion
// to correct custom elements registry.
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentWindow.document.write('<custom-element></custom-element>');
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
}, 'write on Document must enqueue connectedCallback after constructing a custom element');
test_with_window(function (contentWindow, contentDocument) {
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentDocument.body.innerHTML = '<custom-element></custom-element>';
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
contentDocument.writeln('');
assert_array_equals(element.takeLog().types(), ['disconnected']);
}, 'writeln on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow) {
contentWindow.document.open();
// document.open()'s spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698.
// However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641
// the custom element registry will be replaced after document.open() call,
// So call customElements.define() after that in order to register defintion
// to correct custom elements registry.
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentWindow.document.writeln('<custom-element></custom-element>');
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
}, 'writeln on Document must enqueue connectedCallback after constructing a custom element');
</script>
</body>
</html>