CSSStyleDeclaration should be annotated with CEReactions
[WebKit-https.git] / LayoutTests / fast / custom-elements / reactions / CSSStyleDeclaration.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Custom Elements: CEReactions on CSSStyleDeclaration interface</title>
5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
6 <meta name="assert" content="cssText, setProperty, setPropertyValue, setPropertyPriority, removeProperty, cssFloat, and all camel cased attributes of CSSStyleDeclaration interface must have CEReactions">
7 <meta name="help" content="https://dom.spec.whatwg.org/#node">
8 <script src="../../../resources/testharness.js"></script>
9 <script src="../../../resources/testharnessreport.js"></script>
10 <script src="../../../imported/w3c/web-platform-tests/custom-elements/resources/custom-elements-helpers.js"></script>
11 <script src="../../../imported/w3c/web-platform-tests/custom-elements/reactions/resources/reactions.js"></script>
12 <script src="../resources/additional-helpers.js"></script>
13 </head>
14 <body>
15 <div id="log"></div>
16 <script>
17
18 function test_mutating_style_property_value(testFunction, name, options) {
19     const propertyName = (options || {}).propertyName || 'color';
20     const idlName = (options || {}).idlName || 'color';
21     const value1 = (options || {}).value1 || 'blue';
22     const rule1 = `${propertyName}: ${value1};`;
23     const value2 = (options || {}).value2 || 'red';
24     const rule2 = `${propertyName}: ${value2};`;
25
26     test(function () {
27         var element = define_new_custom_element(['style']);
28         var instance = document.createElement(element.name);
29         assert_array_equals(element.takeLog().types(), ['constructed']);
30         testFunction(instance, propertyName, idlName, value1);
31         assert_equals(instance.getAttribute('style'), rule1);
32         var logEntries = element.takeLog();
33         assert_array_equals(logEntries.types(), ['attributeChanged']);
34         assert_attribute_log_entry(logEntries.last(), {name: 'style', oldValue: null, newValue: rule1, namespace: null});
35     }, name + ' must enqueue an attributeChanged reaction when it adds the observed style attribute');
36
37     test(function () {
38         var element = define_new_custom_element(['title']);
39         var instance = document.createElement(element.name);
40         assert_array_equals(element.takeLog().types(), ['constructed']);
41         testFunction(instance, propertyName, idlName, value1);
42         assert_equals(instance.getAttribute('style'), rule1);
43         assert_array_equals(element.takeLog().types(), []);
44     }, name + ' must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed');
45
46     test(function () {
47         var element = define_new_custom_element(['style']);
48         var instance = document.createElement(element.name);
49         testFunction(instance, propertyName, idlName, value1);
50         assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
51         testFunction(instance, propertyName, idlName, value2);
52         assert_equals(instance.getAttribute('style'), rule2);
53         var logEntries = element.takeLog();
54         assert_array_equals(logEntries.types(), ['attributeChanged']);
55         assert_attribute_log_entry(logEntries.last(), {name: 'style', oldValue: rule1, newValue: rule2, namespace: null});
56     }, name + ' must enqueue an attributeChanged reaction when it mutates the observed style attribute');
57
58     test(function () {
59         var element = define_new_custom_element([]);
60         var instance = document.createElement(element.name);
61         testFunction(instance, propertyName, idlName, value1);
62         assert_array_equals(element.takeLog().types(), ['constructed']);
63         testFunction(instance, propertyName, idlName, value2);
64         assert_equals(instance.getAttribute('style'), rule2);
65         assert_array_equals(element.takeLog().types(), []);
66     }, name + ' must not enqueue an attributeChanged reaction when it mutates the style attribute but the style attribute is not observed');
67 }
68
69 function test_removing_style_property_value(testFunction, name) {
70     test(function () {
71         var element = define_new_custom_element(['style']);
72         var instance = document.createElement(element.name);
73         instance.setAttribute('style', 'color: red; display: none;');
74         assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
75         testFunction(instance, 'color', 'color');
76         assert_equals(instance.getAttribute('style'), 'display: none;'); // Don't make this empty since browser behaviors are inconsistent now.
77         var logEntries = element.takeLog();
78         assert_array_equals(logEntries.types(), ['attributeChanged']);
79         assert_attribute_log_entry(logEntries.last(), {name: 'style', oldValue: 'color: red; display: none;', newValue: 'display: none;', namespace: null});
80     }, name + ' must enqueue an attributeChanged reaction when it removes a property from the observed style attribute');
81
82     test(function () {
83         var element = define_new_custom_element(['class']);
84         var instance = document.createElement(element.name);
85         instance.setAttribute('style', 'color: red; display: none;');
86         assert_array_equals(element.takeLog().types(), ['constructed']);
87         testFunction(instance, 'color', 'color');
88         assert_equals(instance.getAttribute('style'), 'display: none;'); // Don't make this empty since browser behaviors are inconsistent now.
89         assert_array_equals(element.takeLog().types(), []);
90     }, name + ' must not enqueue an attributeChanged reaction when it removes a property from the style attribute but the style attribute is not observed');
91 }
92
93 function test_mutating_style_property_priority(testFunction, name) {
94     test(function () {
95         var element = define_new_custom_element(['style']);
96         var instance = document.createElement(element.name);
97         instance.setAttribute('style', 'color: red');
98         assert_array_equals(element.takeLog().types(), ['constructed', 'attributeChanged']);
99         testFunction(instance, 'color', 'color', true);
100         assert_equals(instance.getAttribute('style'), 'color: red !important;');
101         var logEntries = element.takeLog();
102         assert_array_equals(logEntries.types(), ['attributeChanged']);
103         assert_attribute_log_entry(logEntries.last(), {name: 'style', oldValue: 'color: red', newValue: 'color: red !important;', namespace: null});
104     }, name + ' must enqueue an attributeChanged reaction when it makes a property important and the style attribute is observed');
105
106     test(function () {
107         var element = define_new_custom_element(['id']);
108         var instance = document.createElement(element.name);
109         instance.setAttribute('style', 'color: red');
110         assert_array_equals(element.takeLog().types(), ['constructed']);
111         testFunction(instance, 'color', 'color', true);
112         assert_equals(instance.getAttribute('style'), 'color: red !important;');
113         assert_array_equals(element.takeLog().types(), []);
114     }, name + ' must enqueue an attributeChanged reaction when it makes a property important but the style attribute is not observed');
115 }
116
117 test_mutating_style_property_value(function (instance, propertyName, idlName, value) {
118     instance.style.cssText = `${propertyName}: ${value}`;
119 }, 'cssText on CSSStyleDeclaration');
120
121 test_mutating_style_property_value(function (instance, propertyName, idlName, value) {
122     instance.style.setProperty(propertyName, value);
123 }, 'setProperty on CSSStyleDeclaration');
124
125 test_mutating_style_property_priority(function (instance, propertyName, idlName, isImportant) {
126     instance.style.setProperty(propertyName, instance.style[idlName], isImportant ? 'important': '');
127 }, 'setProperty on CSSStyleDeclaration');
128
129 test_removing_style_property_value(function (instance, propertyName, idlName) {
130     instance.style.removeProperty(propertyName);
131 }, 'removeProperty on CSSStyleDeclaration');
132
133 test(function () {
134     var element = define_new_custom_element(['style']);
135     var instance = document.createElement(element.name);
136     assert_array_equals(element.takeLog().types(), ['constructed']);
137     instance.style.cssFloat = 'left';
138     assert_equals(instance.getAttribute('style'), 'float: left;');
139     var logEntries = element.takeLog();
140     assert_array_equals(logEntries.types(), ['attributeChanged']);
141     assert_attribute_log_entry(logEntries.last(), {name: 'style', oldValue: null, newValue: 'float: left;', namespace: null});
142 }, 'cssFloat on CSSStyleDeclaration must enqueue an attributeChanged reaction when it adds the observed style attribute');
143
144 test(function () {
145     var element = define_new_custom_element([]);
146     var instance = document.createElement(element.name);
147     assert_array_equals(element.takeLog().types(), ['constructed']);
148     instance.style.cssFloat = 'left';
149     assert_equals(instance.getAttribute('style'), 'float: left;');
150     assert_array_equals(element.takeLog().types(), []);
151 }, 'cssFloat on CSSStyleDeclaration must not enqueue an attributeChanged reaction when it adds the style attribute but the style attribute is not observed');
152
153 test_mutating_style_property_value(function (instance, propertyName, idlName, value) {
154     assert_equals(idlName, 'borderWidth');
155     instance.style.borderWidth = value;
156 }, 'A camel case attribute (borderWidth) on CSSStyleDeclaration',
157     {propertyName: 'border-width', idlName: 'borderWidth', value1: '2px', value2: '4px'});
158
159 test_mutating_style_property_value(function (instance, propertyName, idlName, value) {
160     assert_equals(propertyName, 'border-width');
161     instance.style['border-width'] = value;
162 }, 'A dashed property (border-width) on CSSStyleDeclaration',
163     {propertyName: 'border-width', idlName: 'borderWidth', value1: '1px', value2: '5px'});
164
165 test_mutating_style_property_value(function (instance, propertyName, idlName, value) {
166     instance.style.webkitFilter = value;
167 }, 'A webkit prefixed camel case attribute (webkitFilter) on CSSStyleDeclaration',
168     {propertyName: 'filter', idlName: 'filter', value1: 'grayscale(20%)', value2: 'grayscale(30%)'});
169
170 test_mutating_style_property_value(function (instance, propertyName, idlName, value) {
171     instance.style['-webkit-filter'] = value;
172 }, 'A webkit prefixed dashed property (-webkit-filter) on CSSStyleDeclaration',
173     {propertyName: 'filter', idlName: 'filter', value1: 'grayscale(20%)', value2: 'grayscale(30%)'});
174
175 </script>
176 </body>
177 </html>