mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Update web-platform-tests to revision 0d318188757a9c996e20b82db201fd04de5aa255
This commit is contained in:
parent
b2a5225831
commit
1a81b18b9f
12321 changed files with 544385 additions and 6 deletions
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Invoke CALLBACK with ELEMENT as callback this value</title>
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="assert" content="Invoke CALLBACK with ELEMENT as callback this value">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#enqueuing-and-invoking-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
doc.body.innerHTML = '<x-a id="x-a"></x-a>';
|
||||
assert_equals(doc.querySelector('#x-a'), proto.createdCallbackThis,
|
||||
'\'this\' value of the created callback should be the custom element');
|
||||
}, 'Test \'this\' value inside created callback.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
assert_equals(doc.querySelector('#x-element'), proto.attachedCallbackThis,
|
||||
'\'this\' value of the attached callback should be the custom element');
|
||||
}, 'Test \'this\' value inside attached callback.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
doc.body.removeChild(customElement);
|
||||
assert_equals(customElement, proto.detachedCallbackThis,
|
||||
'\'this\' value of the detached callback should be the custom element');
|
||||
}, 'Test \'this\' value inside detached callback.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-b', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(customElement, proto.attributeChangedCallbackThis,
|
||||
'\'this\' value of the attributeChanged callback should be the custom element');
|
||||
}, 'Test \'this\' value inside attributeChanged callback.');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,160 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Attached callback of a custom element should be called if element is moved</title>
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="attached callback ... must be enqueued whenever custom element is inserted into a document and this document has a browsing context.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-a', {prototype: proto});
|
||||
var customElement = doc.createElement('x-a');
|
||||
|
||||
doc.body.appendChild(customElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
|
||||
'should not be called in documents that do not have a browsing context');
|
||||
|
||||
var divElement = doc.createElement('div');
|
||||
doc.body.appendChild(divElement);
|
||||
divElement.appendChild(customElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
|
||||
'should not be called in documents that do not have a browsing context');
|
||||
}, 'Test attached callback if moving custom element inside document ' +
|
||||
'without browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
|
||||
var docNoBrowsingContext = newHTMLDocument();
|
||||
var proto1 = newHTMLElementPrototype();
|
||||
docNoBrowsingContext.registerElement('x-b', {prototype: proto1});
|
||||
|
||||
var customElement = docNoBrowsingContext.createElement('x-b');
|
||||
docNoBrowsingContext.body.appendChild(customElement);
|
||||
assert_equals(proto1.attachedCallbackCalledCounter, 0,
|
||||
'Callback attached should not be called ' +
|
||||
'in documents that do not have a browsing context');
|
||||
|
||||
var proto2 = newHTMLElementPrototype();
|
||||
docWithBrowsingContext.registerElement('x-b', {prototype: proto2});
|
||||
docWithBrowsingContext.body.appendChild(customElement);
|
||||
assert_equals(proto1.attachedCallbackCalledCounter, 1,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
assert_equals(proto2.attachedCallbackCalledCounter, 0,
|
||||
'Callback attached, defined in receiving document, should not be called');
|
||||
}, 'Test attached callback if moving custom element from ' +
|
||||
'document without browsing context to document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
|
||||
var proto1 = newHTMLElementPrototype();
|
||||
docWithBrowsingContext.registerElement('x-c', {prototype: proto1});
|
||||
|
||||
var customElement = docWithBrowsingContext.createElement('x-c');
|
||||
docWithBrowsingContext.body.appendChild(customElement);
|
||||
assert_equals(proto1.attachedCallbackCalledCounter, 1,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
|
||||
var docNoBrowsingContext = newHTMLDocument();
|
||||
var proto2 = newHTMLElementPrototype();
|
||||
docNoBrowsingContext.registerElement('x-c', {prototype: proto2});
|
||||
docNoBrowsingContext.body.appendChild(customElement);
|
||||
assert_equals(proto1.attachedCallbackCalledCounter, 1, 'Callback attached should not be called ' +
|
||||
'in documents that do not have a browsing context');
|
||||
assert_equals(proto2.attachedCallbackCalledCounter, 0,
|
||||
'Callback attached, defined in receiving document, should not be called');
|
||||
}, 'Test attached callback if moving custom element from ' +
|
||||
'document with browsing context to document without browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
|
||||
var customElement = doc.createElement('x-d');
|
||||
doc.body.appendChild(customElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
|
||||
var divElement = doc.createElement('div');
|
||||
doc.body.appendChild(divElement);
|
||||
divElement.appendChild(customElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 2,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
}, 'Test attached callback if moving custom element inside document ' +
|
||||
'with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-e', {prototype: proto});
|
||||
|
||||
var customElement = doc.createElement('x-e');
|
||||
doc.body.appendChild(customElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
|
||||
var divElement = doc.createElement('div');
|
||||
divElement.appendChild(customElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1,
|
||||
'Callback attached should not be called if element is not appended to the document');
|
||||
|
||||
doc.body.appendChild(divElement);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 2,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
}, 'Test attached callback if indirectly moving custom element inside document ' +
|
||||
'with browsing context');
|
||||
|
||||
|
||||
var moveTest = async_test('Test attached callback if moving custom element from ' +
|
||||
'document with browsing context to document with browsing context');
|
||||
|
||||
moveTest.step(function() {
|
||||
var iframe1 = newIFrame('../../resources/blank.html');
|
||||
iframe1.onload = moveTest.step_func(function() {
|
||||
var doc1 = iframe1.contentDocument;
|
||||
|
||||
// register custom element type
|
||||
var proto1 = newHTMLElementPrototype();
|
||||
doc1.registerElement('x-f', {prototype: proto1});
|
||||
|
||||
// create custom element
|
||||
var customElement = doc1.createElement('x-f');
|
||||
doc1.body.appendChild(customElement);
|
||||
assert_equals(proto1.attachedCallbackCalledCounter, 1,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
|
||||
// create second iframe
|
||||
var iframe2 = newIFrame('../../resources/x-element.html');
|
||||
iframe2.onload = moveTest.step_func(function() {
|
||||
var doc2 = iframe2.contentDocument;
|
||||
|
||||
// register custom element type
|
||||
var proto2 = newHTMLElementPrototype();
|
||||
doc2.registerElement('x-f', {prototype: proto2});
|
||||
|
||||
// move element
|
||||
doc2.body.appendChild(customElement);
|
||||
assert_equals(proto1.attachedCallbackCalledCounter, 2,
|
||||
'Callback attached should be called in documents with browsing context');
|
||||
assert_equals(proto2.attachedCallbackCalledCounter, 0,
|
||||
'Callback attached, defined in receiving document, should not be called');
|
||||
|
||||
// test clean up
|
||||
iframe1.remove();
|
||||
iframe2.remove();
|
||||
moveTest.done();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,117 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Attached callback of a custom element should be called </title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="assert" content="attached callback ... must be enqueued whenever custom element is inserted into a document and this document has a browsing context.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
|
||||
'should not be called in documents that do not have a browsing context');
|
||||
}, 'Test attached callback if custom element is instantiated via constructor. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-b></x-b>';
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
|
||||
'should not be called in documents that do not have a browsing context');
|
||||
}, 'Test attached callback if custom element is created via innerHTML property. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
doc.body.innerHTML = '<x-c></x-c>';
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-c', {prototype: proto});
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
|
||||
'should not be called in documents that do not have a browsing context');
|
||||
}, 'Test attached callback if custom element is created via innerHTML property before ' +
|
||||
'registration. Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
doc.body.innerHTML = '<x-d id="x-d"></x-d>';
|
||||
var customElement = doc.querySelector('#x-d');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-d', {prototype: proto});
|
||||
|
||||
customElement.constructor.prototype = proto;
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached should ' +
|
||||
'not be called for unregistered custom element in document without browsing context');
|
||||
}, 'Test attached callback if custom element is unregistered');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should be ' +
|
||||
'called in documents with browsing context');
|
||||
}, 'Test attached callback. Document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var x = doc.createElement('x-element');
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached should not ' +
|
||||
'be called before element is added to document with browsing context');
|
||||
|
||||
doc.body.appendChild(x);
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should be called ' +
|
||||
'in documents with browsing context');
|
||||
}, 'Test attached callback. Registered element is created via document.createElement(). ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var x = doc.createElement('x-element');
|
||||
doc.body.appendChild(x);
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should ' +
|
||||
'be called in documents with browsing context');
|
||||
}, 'Test attached callback. Unregistered element is created via document.createElement(). ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-element></x-element>';
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should ' +
|
||||
'be called in documents with browsing context');
|
||||
}, 'Test attached callback. Registered element is created via innerHTML property. ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
doc.body.innerHTML = '<x-element></x-element>';
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should ' +
|
||||
'be called in documents with browsing context');
|
||||
}, 'Test attached callback. Unresolved element is created via innerHTML property. ' +
|
||||
'Document has browsing context');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,230 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test attributeChanged callback is called if custom element attribute value is changed</title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="attributeChanged callback must be enqueued whenever custom element's attribute is added, changed or removed">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
proto.attributeChangedCallbackCalledCounter = 0;
|
||||
customElement.setAttribute('class', 'someClass2');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is changed by method ' +
|
||||
'setAttribute(). The custom element is created via constructor');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-b id="x-b" class="oldValue"></x-b>';
|
||||
var customElement = doc.querySelector('#x-b');
|
||||
customElement.setAttribute('class', 'newValue');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'oldValue', 'newValue'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is changed by method ' +
|
||||
'setAttribute(). The custom element is created via innerHTML property');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-c', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
proto.attributeChangedCallbackCalledCounter = 0;
|
||||
customElement.classList.add('someClass3');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is changed by method ' +
|
||||
'classList.add(). The custom element is created via constructor');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-d id="x-d" class="oldValue"></x-d>';
|
||||
var customElement = doc.querySelector('#x-d');
|
||||
customElement.classList.add('newestValue');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'oldValue', 'oldValue newestValue'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is changed by method ' +
|
||||
'classList.add(). The custom element is created via innerHTML property');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
proto.attributeChangedCallbackCalledCounter = 0;
|
||||
customElement.id = 'someId';
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is changed as property. ' +
|
||||
'The custom element is created via constructor');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-f', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-f id="x-f" class="oldValue"></x-f>';
|
||||
var customElement = doc.querySelector('#x-f');
|
||||
customElement.className = 'lastValue';
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'oldValue', 'lastValue'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is changed as property. ' +
|
||||
'The custom element is created via innerHTML property');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-g', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
customElement.setAttribute('class', 'someClass someSuperClass');
|
||||
proto.attributeChangedCallbackCalledCounter = 0;
|
||||
customElement.classList.toggle('someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is changed by classList.toggle(). ' +
|
||||
'The custom element is created via constructor');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-h', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-h id="x-h" class="oldValue lastValue"></x-h>';
|
||||
var customElement = doc.querySelector('#x-h');
|
||||
customElement.classList.toggle('lastValue');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'oldValue lastValue', 'oldValue'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is changed by classList.toggle(). ' +
|
||||
'The custom element is created via innerHTML property');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
doc.body.innerHTML = '<x-i id="x-i" class="oldValue"></x-i>';
|
||||
var customElement = doc.querySelector('#x-i');
|
||||
customElement.setAttribute('class', 'newValue');
|
||||
customElement.setAttribute('class', 'newestValue');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-i', {prototype: proto});
|
||||
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
|
||||
'Callback attributeChanged should not be called');
|
||||
|
||||
customElement.setAttribute('class', 'rightValue');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should not be called');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'newestValue', 'rightValue'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback is not called if custom element is not registered');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.setAttribute('class', 'firstValue');
|
||||
customElement.setAttribute('class', 'secondValue');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 2, 'Callback ' +
|
||||
'attributeChanged should be called after call to setAttribute()');
|
||||
|
||||
customElement.classList.add('someClass3');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 3, 'Callback ' +
|
||||
'attributeChanged should be called after call to classList.add()');
|
||||
|
||||
customElement.id = 'someId';
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 4, 'Callback ' +
|
||||
'attributeChanged should be called after changing attribute as property');
|
||||
}, 'Test attributeChanged callback is called if attribute value is changed. ' +
|
||||
'The document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
|
||||
customElement.setAttribute('class', 'firstValue');
|
||||
customElement.setAttribute('class', 'secondValue');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'firstValue', 'secondValue'],
|
||||
'Unexpected callback attributeChanged arguments after call to setAttribute()');
|
||||
|
||||
customElement.classList.add('newestValue');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'secondValue', 'secondValue newestValue'],
|
||||
'Unexpected callback attributeChanged arguments after call to classList.add()');
|
||||
|
||||
customElement.className = 'lastValue';
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'secondValue newestValue', 'lastValue'],
|
||||
'Unexpected callback attributeChanged arguments after changing attribute as property');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is changed. ' +
|
||||
'The document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.setAttribute('class', 'firstValue');
|
||||
customElement.setAttribute('class', 'secondValue');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
customElement.setAttribute('class', 'thirdValue');
|
||||
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'secondValue', 'thirdValue'],
|
||||
'Unexpected callback attributeChanged arguments after setAttribute() call');
|
||||
}, 'Test attributeChanged callback is not called if custom element is not registered. ' +
|
||||
'The document has browsing context');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,167 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test attribute removing to check attributeChanged callback of a custom element</title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="assert" content="attributeChanged callback must be enqueued whenever custom element's attribute is removed">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
//attributeChangedCallback should be called the first time here
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
//attributeChangedCallback should be called the second time here
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 2, 'Callback attributeChanged should be called ' +
|
||||
'after setAttribute() and removeAttribute() calls');
|
||||
}, 'Test attributeChanged callback if attribute is removed. ' +
|
||||
'The custom element created via constructor');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
HTML5_ELEMENTS.forEach(function(element) {
|
||||
var obj = doc.createElement(element);
|
||||
var proto = newCustomElementPrototype(obj.constructor.prototype);
|
||||
var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
|
||||
prototype: proto,
|
||||
extends: element
|
||||
});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
//attributeChangedCallback should be called the first time here
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
//attributeChangedCallback should be called the second time here
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
|
||||
'Callback attributeChanged should be called ' +
|
||||
'after setAttribute() and removeAttribute() calls for "' + element + '"');
|
||||
});
|
||||
}, 'Test attributeChanged callback if attribute is removed. ' +
|
||||
'The custom element created via constructor and extends HTML element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-b id="x-b" class="theClass"></x-b>';
|
||||
var customElement = doc.querySelector('#x-b');
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called ' +
|
||||
'after removeAttribute() call');
|
||||
}, 'Test attributeChanged callback if attribute is removed. ' +
|
||||
'The custom element created via innerHTML property');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-c', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-c id="x-c" class="theClass"></x-c>';
|
||||
var customElement = doc.querySelector('#x-c');
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackArgs[2], null,
|
||||
'Removing an attribute should invoke ' +
|
||||
'the attributeChanged callback with a null new value');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'theClass', null],
|
||||
'Unexpected attributeChanged callback arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute is removed. ' +
|
||||
'The custom element created via innerHTML property');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.body.innerHTML = '<x-d id="x-d" class="theClass"></x-d>';
|
||||
var customElement = doc.querySelector('#x-d');
|
||||
// this should not call or enqueue attributeChangedCallback
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
// this one should not too
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
|
||||
'Callback attributeChanged should not be called');
|
||||
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
// this call invokes attributeChangedCallback
|
||||
customElement.setAttribute('name', 'someName');
|
||||
// and this one
|
||||
customElement.removeAttribute('name');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
|
||||
'Callback attributeChanged should be called ' +
|
||||
'after setAttribute() and removeAttribute() calls');
|
||||
}, 'Test attributeChanged callback is not called if attribute is removed. ' +
|
||||
'The custom element created via innerHTML property and unresolved at first');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
|
||||
'Callback attributeChanged should be called ' +
|
||||
'after setAttribute() and removeAttribute() calls');
|
||||
}, 'Test attributeChanged callback is called if attribute is removed. ' +
|
||||
'The custom element created via constructor and the document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-element id="x-element" class="theClass"></x-element>';
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackArgs[2], null,
|
||||
'Removing an attribute should invoke ' +
|
||||
'the attributeChanged callback with a null new value');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs,
|
||||
['class', 'theClass', null],
|
||||
'Unexpected attributeChanged callback arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute is removed. ' +
|
||||
'The custom element created via innerHTML property and the document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
// this should not call or enqueue attributeChangedCallback
|
||||
customElement.setAttribute('name', 'someName');
|
||||
// this one too
|
||||
customElement.removeAttribute('name');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
|
||||
'Callback attributeChanged should not be called');
|
||||
// this call invokes attributeChangedCallback
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
// this call invokes attributeChangedCallback at second time
|
||||
customElement.removeAttribute('class');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
|
||||
'Callback attributeChanged should be called ' +
|
||||
'after setAttribute() and removeAttribute() calls');
|
||||
}, 'Test attributeChanged callback if attribute is removed. ' +
|
||||
'The custom element created via innerHTML property and unresolved at first. ' +
|
||||
'The document has browsing context');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,339 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test attributeChanged callback is called if custom element attribute value is set</title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="attributeChanged callback ... must be enqueued whenever custom element's attribute is added, changed or removed.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method ' +
|
||||
'setAttribute(). The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-b', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method ' +
|
||||
'setAttribute(). The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-c', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.classList.add('someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method ' +
|
||||
'classList.add(). The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-d', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.classList.add('someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method ' +
|
||||
'classList.add(). The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.classList.toggle('someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method ' +
|
||||
'classList.toggle(). The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-f', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.classList.toggle('someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method ' +
|
||||
'classList.toggle(). The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-g', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.className = 'someClass';
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set as property. ' +
|
||||
'The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-h', {prototype: proto});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.className = 'someClass';
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set as property. '+
|
||||
'The custom element is created via constructor.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-i', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-i id="x-i" class="theClass"></x-i>';
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
|
||||
'Callback attributeChanged should not be called');
|
||||
}, 'Test attributeChanged callback is not called if attribute value is specified in HTML. '+
|
||||
'The custom element is created via innerHTML property.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-j', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-j id="x-j" class="theClass"></x-j>';
|
||||
var customElement = doc.querySelector('#x-j');
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
|
||||
'The custom element is created via innerHTML property.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-k', {prototype: proto});
|
||||
|
||||
doc.body.innerHTML = '<x-k id="x-k"></x-k>';
|
||||
var customElement = doc.querySelector('#x-k');
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
|
||||
'The custom element is created via innerHTML property.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
|
||||
doc.body.innerHTML = '<x-l id="x-l"></x-l>';
|
||||
var customElement = doc.querySelector('#x-l');
|
||||
// this call shouldn't invoke or enqueue the callback
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-l', {prototype: proto});
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
|
||||
'Callback attributeChanged should not be called');
|
||||
// this one should
|
||||
customElement.setAttribute('class', 'someClass2');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is not called if attribute value of unresolved element '+
|
||||
'is set by method setAttribute().');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
HTML5_ELEMENTS.forEach(function(element) {
|
||||
var obj = doc.createElement(element);
|
||||
var proto = newCustomElementPrototype(obj.constructor.prototype);
|
||||
var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
|
||||
prototype: proto,
|
||||
extends: element
|
||||
});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
});
|
||||
}, 'Test attributeChanged callback of the custom element that extends some HTML element. ' +
|
||||
'Test that the callback is called');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
HTML5_ELEMENTS.forEach(function(element) {
|
||||
var obj = doc.createElement(element);
|
||||
var proto = newCustomElementPrototype(obj.constructor.prototype);
|
||||
var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1-1', {
|
||||
prototype: proto,
|
||||
extends: element
|
||||
});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.classList.add('someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
});
|
||||
}, 'Test attributeChanged callback is called if attribute is set by method classList.add(). '+
|
||||
'The custom element extends some HTML element.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
HTML5_ELEMENTS.forEach(function(element) {
|
||||
var obj = doc.createElement(element);
|
||||
var proto = newCustomElementPrototype(obj.constructor.prototype);
|
||||
var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-2', {
|
||||
prototype: proto,
|
||||
extends: element
|
||||
});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
});
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
|
||||
'The custom element extends some HTML element.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
|
||||
'The document has browsing context.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
|
||||
'The document has browsing context.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.classList.add('someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method classList.add(). '+
|
||||
'The document has browsing context.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
customElement.classList.add('someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method classList.add(). '+
|
||||
'The document has browsing context.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
// this call shouldn't invoke or enqueue the callback
|
||||
customElement.setAttribute('name', 'someName');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
|
||||
'Callback attributeChanged should not be called');
|
||||
// this one should
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is not called if attribute value of unresolved element '+
|
||||
'is set by method setAttribute(). The document has browsing context.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
HTML5_ELEMENTS.forEach(function(element) {
|
||||
var obj = doc.createElement(element);
|
||||
var proto = newCustomElementPrototype(obj.constructor.prototype);
|
||||
var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
|
||||
prototype: proto,
|
||||
extends: element
|
||||
});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
|
||||
'Callback attributeChanged should be called');
|
||||
});
|
||||
}, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
|
||||
'The document has browsing context. The custom element extends some HTML element.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
HTML5_ELEMENTS.forEach(function(element) {
|
||||
var obj = doc.createElement(element);
|
||||
var proto = newCustomElementPrototype(obj.constructor.prototype);
|
||||
var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-2', {
|
||||
prototype: proto,
|
||||
extends: element
|
||||
});
|
||||
|
||||
var customElement = new GeneratedConstructor();
|
||||
customElement.setAttribute('class', 'someClass');
|
||||
assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
|
||||
'Unexpected callback attributeChanged arguments');
|
||||
});
|
||||
}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
|
||||
'The document has browsing context. The custom element extends some HTML element.');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,88 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The custom element prototype must be set just prior to invoking created callback</title>
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="assert" content="The custom element prototype must be set just prior to invoking callback.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.body.innerHTML = '<x-a></x-a>';
|
||||
doc.registerElement('x-a', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
|
||||
'The custom element prototype is incorrect inside created callback');
|
||||
}, 'Test custom element prototype inside created callback when custom element is created ' +
|
||||
'in HTML before registration of a custom element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-b></x-b>';
|
||||
assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
|
||||
'The custom element prototype is incorrect inside created callback');
|
||||
}, 'Test custom element prototype inside created callback when custom element is created ' +
|
||||
'in HTML after registration of a custom element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var customElement = doc.createElement('x-c');
|
||||
|
||||
doc.body.appendChild(customElement);
|
||||
doc.registerElement('x-c', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
|
||||
'The custom element prototype is incorrect inside created callback');
|
||||
}, 'Test custom element prototype inside created callback when custom element is created ' +
|
||||
'via document.createElement() before registration of a custom element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
|
||||
var customElement = doc.createElement('x-d');
|
||||
doc.body.appendChild(customElement);
|
||||
assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
|
||||
'The custom element prototype is incorrect inside created callback');
|
||||
}, 'Test custom element prototype inside created callback when custom element is created ' +
|
||||
'via document.createElement() after registration of a custom element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
|
||||
var customElement = new GeneratedConstructor();
|
||||
|
||||
assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
|
||||
'The custom element prototype is incorrect inside created callback');
|
||||
}, 'Test custom element prototype inside created callback when custom element is created ' +
|
||||
'via constructor returned by method registerElement');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
|
||||
'The custom element prototype is incorrect inside created callback');
|
||||
}, 'Test custom element prototype inside created callback when custom element is created ' +
|
||||
'by UA parser before registration of a custom element');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,243 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>All other callbacks must not be enqueued until after the created callback's invocation had started</title>
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="assert" content="All other callbacks must not be enqueued until after the created callback's invocation had started.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
function newPrototypeWithCallbackLog() {
|
||||
var proto = Object.create(HTMLElement.prototype);
|
||||
proto.callbackLog = [];
|
||||
proto.createdCallback = function() {
|
||||
proto.callbackLog.push('created');
|
||||
};
|
||||
proto.attachedCallback = function() {
|
||||
proto.callbackLog.push('attached');
|
||||
};
|
||||
proto.attributeChangedCallback = function() {
|
||||
proto.callbackLog.push('attributeChanged');
|
||||
};
|
||||
proto.detachedCallback = function() {
|
||||
proto.callbackLog.push('detached');
|
||||
};
|
||||
return proto;
|
||||
}
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
doc.registerElement('x-a', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-a></x-a>';
|
||||
|
||||
assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
|
||||
proto.callbackLog[0] + ' should be enqueued after created callback');
|
||||
assert_in_array('attached', proto.callbackLog, 'The callback ' +
|
||||
'attached should be called');
|
||||
}, 'Test attached callback is enqueued after created callback');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-b id="x-b"></x-b>';
|
||||
var customElement = doc.querySelector('#x-b');
|
||||
customElement.setAttribute('key', 'value');
|
||||
|
||||
assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
|
||||
proto.callbackLog[0] + ' should not be enqueued before created callback');
|
||||
assert_in_array('attributeChanged', proto.callbackLog,
|
||||
'The callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is enqueued after created callback. ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
doc.registerElement('x-c', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-c id="x-c"></x-c>';
|
||||
var customElement = doc.querySelector('#x-c');
|
||||
customElement.setAttribute('key', 'value');
|
||||
assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
|
||||
proto.callbackLog[0] + ' should not be enqueued before created callback');
|
||||
assert_in_array('attributeChanged', proto.callbackLog,
|
||||
'The callback attributeChanged should be called');
|
||||
}, 'Test attributeChanged callback is enqueued after created callback. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
doc.body.removeChild(customElement);
|
||||
|
||||
assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
|
||||
proto.callbackLog[0] + ' should not be enqueued before created callback');
|
||||
assert_in_array('detached', proto.callbackLog,
|
||||
'The callback detached should be called');
|
||||
}, 'Test detached callback is enqueued after created callback.');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto1 = newPrototypeWithCallbackLog();
|
||||
proto1.createdCallback = function() {
|
||||
proto1.callbackLog.push('created');
|
||||
var xe = doc.querySelector('#x-e');
|
||||
xe.setAttribute('key', 'value');
|
||||
};
|
||||
var proto2 = newPrototypeWithCallbackLog();
|
||||
|
||||
doc.registerElement('x-d', {prototype: proto1});
|
||||
doc.registerElement('x-e', {prototype: proto2});
|
||||
doc.body.innerHTML = '<x-d><x-e id="x-e"></x-e></x-d>';
|
||||
|
||||
assert_array_equals(proto2.callbackLog, ['created'],
|
||||
'attributeChanged callback should not be enqueued before created callback');
|
||||
}, 'Test attributeChanged callback is not enqueued before created callback started. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto1 = newPrototypeWithCallbackLog();
|
||||
proto1.createdCallback = function() {
|
||||
proto1.callbackLog.push('created');
|
||||
var xe = doc.querySelector('#x-g');
|
||||
xe.setAttribute('key', 'value');
|
||||
};
|
||||
var proto2 = newPrototypeWithCallbackLog();
|
||||
|
||||
doc.registerElement('x-f', {prototype: proto1});
|
||||
doc.registerElement('x-g', {prototype: proto2});
|
||||
doc.body.innerHTML = '<x-f><x-g id="x-g"></x-g></x-f>';
|
||||
|
||||
assert_array_equals(proto2.callbackLog, ['created', 'attached'],
|
||||
'attributeChanged callback should not be called before created callback started');
|
||||
}, 'Test attributeChanged callback is not enqueued before created callback started. ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
proto.createdCallback = function() {
|
||||
proto.callbackLog.push('created');
|
||||
this.setAttribute('key', 'value');
|
||||
};
|
||||
doc.registerElement('x-h', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-h></x-h>';
|
||||
|
||||
assert_array_equals(proto.callbackLog, ['created', 'attributeChanged'],
|
||||
'attributeChanged callback should be enqueued after created callback');
|
||||
}, 'Test attributeChanged callback is enqueued after created callback started. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
|
||||
var docNoBrowsingContext = newHTMLDocument();
|
||||
|
||||
var proto1 = newPrototypeWithCallbackLog();
|
||||
var proto2 = newPrototypeWithCallbackLog();
|
||||
proto1.createdCallback = function() {
|
||||
proto1.callbackLog.push('created');
|
||||
var xk = docNoBrowsingContext.querySelector('#x-k');
|
||||
assert_equals(proto2.callbackLog.length, 0, 'Created callback for x-k ' +
|
||||
'should not be called before created callback for x-i');
|
||||
docWithBrowsingContext.body.appendChild(xk);
|
||||
};
|
||||
|
||||
docNoBrowsingContext.registerElement('x-i', {prototype: proto1});
|
||||
docNoBrowsingContext.registerElement('x-k', {prototype: proto2});
|
||||
docNoBrowsingContext.body.innerHTML = '<x-i><x-k id="x-k"></x-k></x-i>';
|
||||
|
||||
// Though at the moment of inserting <x-k> into docWithBrowsingContext
|
||||
// created callback is not called for <x-k> yet, attached calback is enqueued
|
||||
// anyway. Because specification for setting custom element prototype algorithm reads:
|
||||
// ....
|
||||
// 3. If ELEMENT is in a document and this document has a browsing context:
|
||||
// 1. Enqueue attached callback for ELEMENT
|
||||
//
|
||||
// Changes in the specification will follow, to reflect this exceptional case.
|
||||
assert_array_equals(proto2.callbackLog, ['created', 'attached'],
|
||||
'attached callback should be enqueued when custom element prototype is set');
|
||||
}, 'Test attached callback is enqueued after created callback, but before created callback had started');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
|
||||
var docNoBrowsingContext = newHTMLDocument();
|
||||
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
proto.createdCallback = function() {
|
||||
proto.callbackLog.push('created');
|
||||
docWithBrowsingContext.body.appendChild(this);
|
||||
};
|
||||
|
||||
docNoBrowsingContext.registerElement('x-l', {prototype: proto});
|
||||
docNoBrowsingContext.body.innerHTML = '<x-l></x-l>';
|
||||
assert_array_equals(proto.callbackLog, ['created', 'attached'],
|
||||
'attached callback should be enqueued after created callback had started');
|
||||
}, 'Test attached callback is enqueued after created callback had started');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto1 = newPrototypeWithCallbackLog();
|
||||
var proto2 = newPrototypeWithCallbackLog();
|
||||
proto1.createdCallback = function() {
|
||||
proto1.callbackLog.push('created');
|
||||
var xn = doc.querySelector('#x-n');
|
||||
assert_equals(proto2.callbackLog.length, 0, 'Created callback for x-n ' +
|
||||
'should not be called before created callback for x-m');
|
||||
this.removeChild(xn);
|
||||
};
|
||||
|
||||
doc.registerElement('x-m', {prototype: proto1});
|
||||
doc.registerElement('x-n', {prototype: proto2});
|
||||
doc.body.innerHTML = '<x-m><x-n id="x-n"></x-n></x-m>';
|
||||
assert_array_equals(proto2.callbackLog, ['created'],
|
||||
'detached callback should not be enqueued before created callback had started');
|
||||
}, 'Test detached callback is not enqueued before created callback had started');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
proto.createdCallback = function() {
|
||||
proto.callbackLog.push('created');
|
||||
this.remove();
|
||||
};
|
||||
|
||||
doc.registerElement('x-o', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-o></x-o>';
|
||||
|
||||
assert_array_equals(proto.callbackLog, ['created', 'attached', 'detached'],
|
||||
'detached callback should be enqueued after created callback had started');
|
||||
}, 'Test detached callback is enqueued after created callback had started');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newPrototypeWithCallbackLog();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
// Though at the moment of inserting <x-element> into the document
|
||||
// created callback is not called for <x-element> yet, attached calback is enqueued
|
||||
// anyway. Because specification for setting custom element prototype algorithm reads:
|
||||
// ....
|
||||
// 3. If ELEMENT is in a document and this document has a browsing context:
|
||||
// 1. Enqueue attached callback for ELEMENT
|
||||
//
|
||||
// Changes in the specification will follow, to reflect this exceptional case.
|
||||
assert_array_equals(proto.callbackLog, ['created', 'attached'],
|
||||
'attached callback should be enqueued when custom element prototype is set');
|
||||
}, 'Test attached callback is enqueued after created callback after registration ' +
|
||||
'of custom element type');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,168 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Created callback of a custom element should be invoked after custom element instance is created and its definition is registered</title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="CREATED callback is invoked after custom element instance is created and its definition is registered">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 0,
|
||||
'Callback created should not be called before element instance was created');
|
||||
var customElement = new GeneratedConstructor();
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback when custom element is created by constructor');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 0,
|
||||
'Callback created should not be called before element instance was created');
|
||||
doc.body.innerHTML = '<x-b></x-b>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback when custom element is created in HTML');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-c', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 0,
|
||||
'Callback created should not be called before element instance was created');
|
||||
doc.body.innerHTML = '<div><x-c></x-c></div>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback when custom element is created in HTML as descendant of ' +
|
||||
'another element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 0,
|
||||
'Callback created should not be called before element instance was created');
|
||||
var customElement = doc.createElement('x-d');
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback when custom element is created by createElement');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.body.innerHTML = '<x-e></x-e>';
|
||||
doc.registerElement('x-e', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback when custom element is created in HTML before ' +
|
||||
'registration of a custom element');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-f', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-f-unresolved id="x-f-unresolved"></x-f-unresolved>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 0,
|
||||
'Callback created should not be called if custom element is unresolved');
|
||||
|
||||
var customElement = doc.querySelector('#x-f-unresolved');
|
||||
customElement.constructor.prototype = proto;
|
||||
assert_equals(proto.createdCallbackCalledCounter, 0,
|
||||
'Created callback should not be called if custom element is unresolved');
|
||||
}, 'Test created callback if custom element is unresolved.');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1, 'Callback created should be called');
|
||||
}, 'Test created callback is called after custom element is created and registered. ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/register-and-create-custom-element.html', function(doc) {
|
||||
assert_equals(doc.querySelector('#log').innerText, 'Created callback was called',
|
||||
'Callback created should be called');
|
||||
}, 'Test created callback is called after custom element is registered and created. ' +
|
||||
'Document has browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var customElement = doc.createElement('x-g');
|
||||
|
||||
doc.registerElement('x-g', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called after registration of custom element');
|
||||
}, 'Test created callback when custom element is created by createElement '+
|
||||
'before registration of a custom element');
|
||||
|
||||
|
||||
test(function(){
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
var GeneratedConstructor = doc.registerElement('x-h', {prototype: proto});
|
||||
|
||||
var customElement1 = new GeneratedConstructor();
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1, 'Callback created should be called');
|
||||
|
||||
var customElement2 = doc.createElement('x-h');
|
||||
assert_equals(proto.createdCallbackCalledCounter, 2,
|
||||
'Callback created should be called after element instance was created');
|
||||
|
||||
doc.body.innerHTML = '<x-h></x-h>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 3,
|
||||
'Callback created should be called after element instance was created');
|
||||
|
||||
doc.body.innerHTML = '<div><x-h></x-h></div>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 4,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback. Create several custom elements using different ways');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
var GeneratedConstructor = doc.registerElement('x-element', {prototype: proto});
|
||||
assert_equals(proto.createdCallbackCalledCounter, 1,
|
||||
'Callback created should be called for custom element in loaded document');
|
||||
|
||||
var customElement2 = new GeneratedConstructor();
|
||||
assert_equals(proto.createdCallbackCalledCounter, 2,
|
||||
'Callback created should be called after element instance was created');
|
||||
|
||||
var customElement3 = doc.createElement('x-element');
|
||||
assert_equals(proto.createdCallbackCalledCounter, 3,
|
||||
'Callback created should be called after element instance was created');
|
||||
|
||||
doc.body.innerHTML = '<x-element></x-element>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 4,
|
||||
'Callback created should be called after element instance was created');
|
||||
|
||||
doc.body.innerHTML = '<div><x-element></x-element></div>';
|
||||
assert_equals(proto.createdCallbackCalledCounter, 5,
|
||||
'Callback created should be called after element instance was created');
|
||||
}, 'Test created callback. Create several custom elements using different ways. ' +
|
||||
'Document has browsing context');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,131 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test detached callback of a custom element when moving custom element between different documents</title>
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="detached callback ... must be enqueued whenever custom element is removed from the document and this document has a browsing context.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-a', {prototype: proto});
|
||||
|
||||
var customElement = doc.createElement('x-a');
|
||||
doc.body.appendChild(customElement);
|
||||
|
||||
var divElement = doc.createElement('div');
|
||||
doc.body.appendChild(divElement);
|
||||
divElement.appendChild(customElement);
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called in document without a browsing context');
|
||||
}, 'Test detached callback is not called if moving custom element inside document ' +
|
||||
'without browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
|
||||
var docNoBrowsingContext = newHTMLDocument();
|
||||
var proto1 = newHTMLElementPrototype();
|
||||
docNoBrowsingContext.registerElement('x-b', {prototype: proto1});
|
||||
|
||||
var customElement = docNoBrowsingContext.createElement('x-b');
|
||||
docNoBrowsingContext.body.appendChild(customElement);
|
||||
var proto2 = newHTMLElementPrototype();
|
||||
docWithBrowsingContext.registerElement('x-b', {prototype: proto2});
|
||||
docWithBrowsingContext.body.appendChild(customElement);
|
||||
|
||||
assert_equals(proto1.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called in document without browsing context');
|
||||
assert_equals(proto2.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached, defined in receiving document, should not be called');
|
||||
}, 'Test detached callback is not called if moving custom element from ' +
|
||||
'document without browsing context to document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
|
||||
var proto1 = newHTMLElementPrototype();
|
||||
docWithBrowsingContext.registerElement('x-c', {prototype: proto1});
|
||||
|
||||
var customElement = docWithBrowsingContext.createElement('x-c');
|
||||
docWithBrowsingContext.body.appendChild(customElement);
|
||||
|
||||
var docNoBrowsingContext = newHTMLDocument();
|
||||
var proto2 = newHTMLElementPrototype();
|
||||
docNoBrowsingContext.registerElement('x-c', {prototype: proto2});
|
||||
docNoBrowsingContext.body.appendChild(customElement);
|
||||
assert_equals(proto1.detachedCallbackCalledCounter, 1,
|
||||
'Callback detached should be called in documents with browsing context');
|
||||
assert_equals(proto2.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached, defined in receiving document, should not be called');
|
||||
}, 'Test detached callback if moving custom element from ' +
|
||||
'document with browsing context to document without browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
|
||||
var customElement = doc.createElement('x-d');
|
||||
doc.body.appendChild(customElement);
|
||||
var divElement = doc.createElement('div');
|
||||
doc.body.appendChild(divElement);
|
||||
divElement.appendChild(customElement);
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1,
|
||||
'Callback detached should be called in documents with browsing context');
|
||||
}, 'Test detached callback if moving custom element inside document ' +
|
||||
'with browsing context');
|
||||
|
||||
|
||||
var moveTest = async_test('Test detached callback if moving custom element from ' +
|
||||
'document with browsing context to document with browsing context');
|
||||
|
||||
moveTest.step(function() {
|
||||
var iframe1 = newIFrame('../../resources/blank.html');
|
||||
iframe1.onload = moveTest.step_func(function() {
|
||||
var doc1 = iframe1.contentDocument;
|
||||
|
||||
// register custom element type
|
||||
var proto1 = newHTMLElementPrototype();
|
||||
doc1.registerElement('x-e', {prototype: proto1});
|
||||
|
||||
// create custom element
|
||||
var customElement = doc1.createElement('x-e');
|
||||
doc1.body.appendChild(customElement);
|
||||
assert_equals(proto1.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called when element is created');
|
||||
|
||||
// create second iframe
|
||||
var iframe2 = newIFrame('../../resources/x-element.html');
|
||||
iframe2.onload = moveTest.step_func(function() {
|
||||
var doc2 = iframe2.contentDocument;
|
||||
|
||||
// register custom element type
|
||||
var proto2 = newHTMLElementPrototype();
|
||||
doc2.registerElement('x-e', {prototype: proto2});
|
||||
|
||||
// move element
|
||||
doc2.body.appendChild(customElement);
|
||||
assert_equals(proto1.detachedCallbackCalledCounter, 1,
|
||||
'Callback detached should be called in documents with browsing context');
|
||||
assert_equals(proto2.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached, defined in receiving document, should not be called');
|
||||
|
||||
// test clean up
|
||||
iframe1.remove();
|
||||
iframe2.remove();
|
||||
moveTest.done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,148 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Detached callback of a custom element should not be called if document has no browsing context</title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="detached callback ... must be enqueued whenever custom element is removed from the document and this document has a browsing context.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-a', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-a id="x-a"></x-a>';
|
||||
var customElement = doc.querySelector('#x-a');
|
||||
doc.body.removeChild(customElement);
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
}, 'Test detached callback if custom element is created via innerHTML property. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.body.innerHTML = '<x-b id="x-b"></x-b>';
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
var customElement = doc.querySelector('#x-b');
|
||||
doc.body.removeChild(customElement);
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
}, 'Test detached callback if custom element is via innerHTML property before ' +
|
||||
'registration of a custom element. Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
doc.body.innerHTML = '<x-c id="x-c"></x-c>';
|
||||
var customElement = doc.querySelector('#x-c');
|
||||
|
||||
var proto = newHTMLElementPrototype();
|
||||
customElement.constructor.prototype = proto;
|
||||
doc.body.removeChild(customElement);
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
}, 'Test detached callback if custom element is unregistered. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.registerElement('x-d', {prototype: proto});
|
||||
doc.body.innerHTML = '<x-d id="x-d"></x-d>';
|
||||
doc.body.innerHTML = '';
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
}, 'Test detached callback if removing custom element via innerHTML property. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.registerElement('x-e', {prototype: proto});
|
||||
doc.body.innerHTML = '<div id="customParent"><x-e id="x-e"></x-e></div>';
|
||||
var parent = doc.querySelector('#customParent');
|
||||
doc.body.removeChild(parent);
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
}, 'Test detached callback if removing perent of custom element. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
test(function() {
|
||||
var doc = newHTMLDocument();
|
||||
var proto = newHTMLElementPrototype();
|
||||
|
||||
doc.registerElement('x-f', {prototype: proto});
|
||||
doc.body.innerHTML = '<div><x-f id="x-f"></x-f></div>';
|
||||
doc.body.innerHTML = '';
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
}, 'Test detached callback if removing perent of custom element via innerHTML property. ' +
|
||||
'Document has no browsing context');
|
||||
|
||||
|
||||
var loseBrowsingContextTest = async_test('Test detached callback is not called ' +
|
||||
'if document lose browsing context and custom element is removed');
|
||||
|
||||
loseBrowsingContextTest.step(function() {
|
||||
var iframe = newIFrame('../../resources/x-element.html');
|
||||
iframe.onload = loseBrowsingContextTest.step_func(function(){
|
||||
var doc = iframe.contentDocument;
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
iframe.remove();
|
||||
customElement.remove();
|
||||
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called if the document has no browsing context');
|
||||
loseBrowsingContextTest.done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var navigateTest = async_test('Test detached callback is not called, ' +
|
||||
'if document\'s window is navigated to another document and custom element is removed');
|
||||
|
||||
navigateTest.step(function() {
|
||||
var iframe = newIFrame('../../resources/x-element.html');
|
||||
iframe.onload = navigateTest.step_func(function() {
|
||||
var doc = iframe.contentDocument;
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
customElement = doc.querySelector('#x-element');
|
||||
|
||||
iframe.onload = navigateTest.step_func(function() {
|
||||
customElement.remove();
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 0,
|
||||
'Callback detached should not be called ' +
|
||||
'if the document has no browsing context');
|
||||
navigateTest.done();
|
||||
iframe.remove();
|
||||
});
|
||||
iframe.src = '../../resources/blank.html';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Detached callback of a custom element should be called if document has browsing context</title>
|
||||
<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
|
||||
<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
|
||||
<meta name="assert" content="detached callback ... must be enqueued whenever custom element is removed from the document and this document has a browsing context.">
|
||||
<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../testcommon.js"></script>
|
||||
<link rel="stylesheet" href="/resources/testharness.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
doc.body.removeChild(customElement);
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
|
||||
'called if custom element is removed from the document with browsing context');
|
||||
}, 'Test detached callback is called if custom element is removed by method removeChild() ' +
|
||||
'from document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
doc.body.innerHTML = '<div id="x-a-parent"><x-a id="x-a"></x-a></div>';
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-a', {prototype: proto});
|
||||
var div = doc.querySelector('#x-a-parent');
|
||||
doc.body.removeChild(div);
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
|
||||
'called if custom element is removed from the document with browsing context');
|
||||
}, 'Test detached callback is called if ancestor node of custom element ' +
|
||||
'is removed by method removeChild() from document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
var customElement = doc.querySelector('#x-element');
|
||||
var div = doc.createElement('div');
|
||||
doc.body.replaceChild(div, customElement);
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
|
||||
'called if custom element is removed from the document with browsing context');
|
||||
}, 'Test detached callback is called if custom element is removed by method replaceChild() ' +
|
||||
'from document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-b', {prototype: proto});
|
||||
doc.body.innerHTML = '<div id="x-b-parent"><x-b id="x-b"></x-b></div>';
|
||||
var parent = doc.querySelector('#x-b-parent');
|
||||
var replacement = doc.createElement('div');
|
||||
doc.body.replaceChild(replacement, parent);
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
|
||||
'called if custom element is removed from the document with browsing context');
|
||||
}, 'Test detached callback is called if ancestor node of custom element ' +
|
||||
'is removed by method replaceChild() from document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/x-element.html', function(doc) {
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-element', {prototype: proto});
|
||||
doc.body.innerHTML = '';
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
|
||||
'called if custom element is removed from the document with browsing context');
|
||||
}, 'Test detached callback is called after changing custom element direct parent ' +
|
||||
'innerHTML property in the document with browsing context');
|
||||
|
||||
|
||||
testInIFrame('../../resources/blank.html', function(doc) {
|
||||
doc.body.innerHTML = '<div><x-c></x-c></div>';
|
||||
var proto = newHTMLElementPrototype();
|
||||
doc.registerElement('x-c', {prototype: proto});
|
||||
doc.body.innerHTML = '';
|
||||
assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
|
||||
'called if custom element is removed from the document with browsing context');
|
||||
}, 'Test detached callback is called after changing custom element ancestor ' +
|
||||
'innerHTML property in the document with browsing context');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue