OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <html> |
| 3 <head> |
| 4 <title>Custom Elements: attributeChangedCallback</title> |
| 5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> |
| 6 <meta name="assert" content="attributeChangedCallback must be enqueued whenever
custom element's attribute is added, changed or removed"> |
| 7 <link rel="help" href="https://w3c.github.io/webcomponents/spec/custom/#dfn-attr
ibute-changed-callback"> |
| 8 <script src="/resources/testharness.js"></script> |
| 9 <script src="/resources/testharnessreport.js"></script> |
| 10 </head> |
| 11 <body> |
| 12 <div id="log"></div> |
| 13 <script> |
| 14 |
| 15 var argumentList = []; |
| 16 class MyCustomElement extends HTMLElement { |
| 17 attributeChangedCallback(name, oldValue, newValue, namespace) { |
| 18 argumentList.push({arguments: arguments, value: this.getAttributeNS(name
space, name)}); |
| 19 } |
| 20 } |
| 21 MyCustomElement.observedAttributes = ['title', 'id', 'r']; |
| 22 customElements.define('my-custom-element', MyCustomElement); |
| 23 |
| 24 test(function () { |
| 25 var instance = document.createElement('my-custom-element'); |
| 26 argumentList = []; |
| 27 |
| 28 instance.setAttribute('title', 'foo'); |
| 29 assert_equals(instance.getAttribute('title'), 'foo'); |
| 30 assert_equals(argumentList.length, 1); |
| 31 assert_equals(argumentList[0].value, 'foo'); |
| 32 assert_array_equals(argumentList[0].arguments, ['title', null, 'foo', null])
; |
| 33 |
| 34 instance.removeAttribute('title'); |
| 35 assert_equals(instance.getAttribute('title'), null); |
| 36 assert_equals(argumentList.length, 2); |
| 37 assert_equals(argumentList[1].value, null); |
| 38 assert_array_equals(argumentList[1].arguments, ['title', 'foo', null, null])
; |
| 39 |
| 40 }, 'setAttribute and removeAttribute must enqueue and invoke attributeChangedCal
lback'); |
| 41 |
| 42 test(function () { |
| 43 var instance = document.createElement('my-custom-element'); |
| 44 argumentList = []; |
| 45 |
| 46 instance.setAttributeNS('http://www.w3.org/2000/svg', 'title', 'hello'); |
| 47 assert_equals(instance.getAttribute('title'), 'hello'); |
| 48 assert_equals(argumentList.length, 1); |
| 49 assert_equals(argumentList[0].value, 'hello'); |
| 50 assert_array_equals(argumentList[0].arguments, ['title', null, 'hello', 'htt
p://www.w3.org/2000/svg']); |
| 51 |
| 52 instance.removeAttributeNS('http://www.w3.org/2000/svg', 'title'); |
| 53 assert_equals(instance.getAttribute('title'), null); |
| 54 assert_equals(argumentList.length, 2); |
| 55 assert_equals(argumentList[1].value, null); |
| 56 assert_array_equals(argumentList[1].arguments, ['title', 'hello', null, 'htt
p://www.w3.org/2000/svg']); |
| 57 |
| 58 }, 'setAttributeNS and removeAttributeNS must enqueue and invoke attributeChange
dCallback'); |
| 59 |
| 60 test(function () { |
| 61 var instance = document.createElement('my-custom-element'); |
| 62 argumentList = []; |
| 63 |
| 64 var attr = document.createAttribute('id'); |
| 65 attr.value = 'bar'; |
| 66 instance.setAttributeNode(attr); |
| 67 |
| 68 assert_equals(instance.getAttribute('id'), 'bar'); |
| 69 assert_equals(argumentList.length, 1); |
| 70 assert_equals(argumentList[0].value, 'bar'); |
| 71 assert_array_equals(argumentList[0].arguments, ['id', null, 'bar', null]); |
| 72 |
| 73 instance.removeAttributeNode(attr); |
| 74 assert_equals(instance.getAttribute('id'), null); |
| 75 assert_equals(argumentList.length, 2); |
| 76 assert_equals(argumentList[1].value, null); |
| 77 assert_array_equals(argumentList[1].arguments, ['id', 'bar', null, null]); |
| 78 |
| 79 }, 'setAttributeNode and removeAttributeNS must enqueue and invoke attributeChan
gedCallback'); |
| 80 |
| 81 test(function () { |
| 82 var instance = document.createElement('my-custom-element'); |
| 83 argumentList = []; |
| 84 |
| 85 var attr = document.createAttributeNS('http://www.w3.org/2000/svg', 'r'); |
| 86 attr.value = '100'; |
| 87 instance.setAttributeNode(attr); |
| 88 |
| 89 assert_equals(instance.getAttribute('r'), '100'); |
| 90 assert_equals(argumentList.length, 1); |
| 91 assert_equals(argumentList[0].value, '100'); |
| 92 assert_array_equals(argumentList[0].arguments, ['r', null, '100', 'http://ww
w.w3.org/2000/svg']); |
| 93 |
| 94 instance.removeAttributeNode(attr); |
| 95 assert_equals(instance.getAttribute('r'), null); |
| 96 assert_equals(argumentList.length, 2); |
| 97 assert_equals(argumentList[1].value, null); |
| 98 assert_array_equals(argumentList[1].arguments, ['r', '100', null, 'http://ww
w.w3.org/2000/svg']); |
| 99 }, 'setAttributeNode and removeAttributeNS must enqueue and invoke attributeChan
gedCallback'); |
| 100 |
| 101 test(function () { |
| 102 var callsToOld = []; |
| 103 var callsToNew = []; |
| 104 class CustomElement extends HTMLElement { } |
| 105 CustomElement.prototype.attributeChangedCallback = function () { |
| 106 callsToOld.push(Array.from(arguments)); |
| 107 } |
| 108 CustomElement.observedAttributes = ['title']; |
| 109 customElements.define('element-with-mutated-attribute-changed-callback', Cus
tomElement); |
| 110 CustomElement.prototype.attributeChangedCallback = function () { |
| 111 callsToNew.push(Array.from(arguments)); |
| 112 } |
| 113 |
| 114 var instance = document.createElement('element-with-mutated-attribute-change
d-callback'); |
| 115 instance.setAttribute('title', 'hi'); |
| 116 assert_equals(instance.getAttribute('title'), 'hi'); |
| 117 assert_array_equals(callsToNew, []); |
| 118 assert_equals(callsToOld.length, 1); |
| 119 assert_array_equals(callsToOld[0], ['title', null, 'hi', null]); |
| 120 }, 'Mutating attributeChangedCallback after calling customElements.define must n
ot affect the callback being invoked'); |
| 121 |
| 122 test(function () { |
| 123 var calls = []; |
| 124 class CustomElement extends HTMLElement { |
| 125 attributeChangedCallback() { |
| 126 calls.push(Array.from(arguments)); |
| 127 } |
| 128 } |
| 129 CustomElement.observedAttributes = ['title']; |
| 130 customElements.define('element-not-observing-id-attribute', CustomElement); |
| 131 |
| 132 var instance = document.createElement('element-not-observing-id-attribute'); |
| 133 instance.setAttribute('title', 'hi'); |
| 134 assert_equals(calls.length, 1); |
| 135 assert_array_equals(calls[0], ['title', null, 'hi', null]); |
| 136 instance.setAttribute('id', 'some'); |
| 137 assert_equals(calls.length, 1); |
| 138 }, 'attributedChangedCallback must not be invoked when the observed attributes d
oes not contain the attribute.'); |
| 139 |
| 140 test(function () { |
| 141 var calls = []; |
| 142 class CustomElement extends HTMLElement { } |
| 143 CustomElement.prototype.attributeChangedCallback = function () { |
| 144 calls.push(Array.from(arguments)); |
| 145 } |
| 146 CustomElement.observedAttributes = ['title', 'lang']; |
| 147 customElements.define('element-with-mutated-observed-attributes', CustomElem
ent); |
| 148 CustomElement.observedAttributes = ['title', 'id']; |
| 149 |
| 150 var instance = document.createElement('element-with-mutated-observed-attribu
tes'); |
| 151 instance.setAttribute('title', 'hi'); |
| 152 assert_equals(calls.length, 1); |
| 153 assert_array_equals(calls[0], ['title', null, 'hi', null]); |
| 154 |
| 155 instance.setAttribute('id', 'some'); |
| 156 assert_equals(calls.length, 1); |
| 157 |
| 158 instance.setAttribute('lang', 'en'); |
| 159 assert_equals(calls.length, 2); |
| 160 assert_array_equals(calls[0], ['title', null, 'hi', null]); |
| 161 assert_array_equals(calls[1], ['lang', null, 'en', null]); |
| 162 }, 'Mutating observedAttributes after calling customElements.define must not aff
ect the set of attributes for which attributedChangedCallback is invoked'); |
| 163 |
| 164 test(function () { |
| 165 var calls = []; |
| 166 class CustomElement extends HTMLElement { } |
| 167 CustomElement.prototype.attributeChangedCallback = function () { |
| 168 calls.push(Array.from(arguments)); |
| 169 } |
| 170 CustomElement.observedAttributes = { [Symbol.iterator]: function *() { yield
'lang'; yield 'style'; } }; |
| 171 customElements.define('element-with-generator-observed-attributes', CustomEl
ement); |
| 172 |
| 173 var instance = document.createElement('element-with-generator-observed-attri
butes'); |
| 174 instance.setAttribute('lang', 'en'); |
| 175 assert_equals(calls.length, 1); |
| 176 assert_array_equals(calls[0], ['lang', null, 'en', null]); |
| 177 |
| 178 instance.setAttribute('lang', 'ja'); |
| 179 assert_equals(calls.length, 2); |
| 180 assert_array_equals(calls[1], ['lang', 'en', 'ja', null]); |
| 181 |
| 182 instance.setAttribute('title', 'hello'); |
| 183 assert_equals(calls.length, 2); |
| 184 |
| 185 instance.setAttribute('style', 'font-size: 2rem'); |
| 186 assert_equals(calls.length, 3); |
| 187 assert_array_equals(calls[2], ['style', null, 'font-size: 2rem', null]); |
| 188 }, 'attributedChangedCallback must be enqueued for attributes specified in a non
-Array iterable observedAttributes'); |
| 189 |
| 190 </script> |
| 191 </body> |
| 192 </html> |
OLD | NEW |