2010-09-27 Erik Arvidsson <arv@chromium.org>
[WebKit.git] / LayoutTests / fast / dom / HTMLElement / script-tests / class-list.js
1 description('Tests the classList attribute and its properties.');
2
3 var element;
4
5 function createElement(className)
6 {
7     element = document.createElement('p');
8     element.className = className;
9 }
10
11 debug('Tests from http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/');
12
13 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/setting/001.htm
14 // Firefox throws here but WebKit does not throw on setting readonly idl
15 // attributes.
16 createElement('x');
17 try {
18     element.classList = 'y';
19     shouldBeEqualToString('String(element.classList)', 'x');
20 } catch (ex) {
21     testPassed('Throwing on set is acceptable');
22 }
23
24 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/001.htm
25 createElement('');
26 shouldEvaluateTo('element.classList.length', 0);
27
28 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/002.htm
29 createElement('x');
30 shouldEvaluateTo('element.classList.length', 1);
31
32 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/003.htm
33 createElement('x x');
34 shouldEvaluateTo('element.classList.length', 2);
35
36 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/004.htm
37 createElement('x y');
38 shouldEvaluateTo('element.classList.length', 2);
39
40 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/005.htm
41 createElement('');
42 element.classList.add('x');
43 shouldBeEqualToString('element.className', 'x');
44
45 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/006.htm
46 createElement('x');
47 element.classList.add('x');
48 shouldBeEqualToString('element.className', 'x');
49
50 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/007.htm
51 createElement('x  x');
52 element.classList.add('x');
53 shouldBeEqualToString('element.className', 'x  x');
54
55 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/008.htm
56 createElement('y');
57 element.classList.add('x');
58 shouldBeEqualToString('element.className', 'y x');
59
60 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/009.htm
61 createElement('');
62 element.classList.remove('x');
63 shouldBeEqualToString('element.className', '');
64
65 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/010.htm
66 createElement('x');
67 element.classList.remove('x');
68 shouldBeEqualToString('element.className', '');
69
70 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/011.htm
71 createElement(' y x  y ');
72 element.classList.remove('x');
73 shouldBeEqualToString('element.className', ' y y ');
74
75 // http://simon.html5.org/test/html/dom/reflecting/DOMTokenList/getting/012.htm
76 createElement(' x y  x ');
77 element.classList.remove('x');
78 shouldBeEqualToString('element.className', 'y');
79
80 debug('Testing add in presence of trailing white spaces.');
81
82 createElement('x ');
83 element.classList.add('y');
84 shouldBeEqualToString('element.className', 'x y');
85
86 createElement('x\t');
87 element.classList.add('y');
88 shouldBeEqualToString('element.className', 'x\t y');
89
90 createElement(' ');
91 element.classList.add('y');
92 shouldBeEqualToString('element.className', ' y');
93
94
95 debug('Test invalid tokens');
96
97 // Testing exception due to invalid token
98
99 // shouldThrow from js-test-pre.js is not sufficient.
100 function shouldThrowDOMException(f, ec)
101 {
102     try {
103         f();
104         testFailed('Expected an exception');
105     } catch (ex) {
106         if (!(ex instanceof DOMException)) {
107             testFailed('Exception is not an instance of DOMException, found: ' +
108                        Object.toString.call(ex));
109             return;
110         }
111         if (ec !== ex.code) {
112             testFailed('Wrong exception code: ' + ex.code);
113             return;
114         }
115     }
116     var formattedFunction = String(f).replace(/^function.+\{\s*/m, '').
117         replace(/;?\s+\}/m, '');
118     testPassed(formattedFunction + ' threw expected DOMException with code ' + ec);
119 }
120
121 createElement('x');
122 shouldThrowDOMException(function() {
123     element.classList.contains('');
124 }, DOMException.SYNTAX_ERR);
125
126 createElement('x y');
127 shouldThrowDOMException(function() {
128     element.classList.contains('x y');
129 }, DOMException.INVALID_CHARACTER_ERR);
130
131 createElement('');
132 shouldThrowDOMException(function() {
133     element.classList.add('');
134 }, DOMException.SYNTAX_ERR);
135
136 createElement('');
137 shouldThrowDOMException(function() {
138     element.classList.add('x y');
139 }, DOMException.INVALID_CHARACTER_ERR);
140
141 createElement('');
142 shouldThrowDOMException(function() {
143     element.classList.remove('');
144 }, DOMException.SYNTAX_ERR);
145
146 createElement('');
147 shouldThrowDOMException(function() {
148     element.classList.remove('x y');
149 }, DOMException.INVALID_CHARACTER_ERR);
150
151 createElement('');
152 shouldThrowDOMException(function() {
153     element.classList.toggle('');
154 }, DOMException.SYNTAX_ERR);
155
156 createElement('x y');
157 shouldThrowDOMException(function() {
158     element.classList.toggle('x y');
159 }, DOMException.INVALID_CHARACTER_ERR);
160
161
162 debug('Indexing');
163
164 createElement('x');
165 shouldBeEqualToString('element.classList[0]', 'x');
166 shouldBeEqualToString('element.classList.item(0)', 'x');
167
168 createElement('x x');
169 shouldBeEqualToString('element.classList[1]', 'x');
170 shouldBeEqualToString('element.classList.item(1)', 'x');
171
172 createElement('x y');
173 shouldBeEqualToString('element.classList[1]', 'y');
174 shouldBeEqualToString('element.classList.item(1)', 'y');
175
176 createElement('');
177 shouldBeNull('element.classList[0]');
178 shouldBeNull('element.classList.item(0)');
179
180 createElement('x y z');
181 shouldBeNull('element.classList[4]');
182 shouldBeNull('element.classList.item(4)');
183 shouldBeUndefined('element.classList[-1]');  // Not a valid index so should not trigger item().
184 shouldBeNull('element.classList.item(-1)');
185
186 debug('Test case since DOMTokenList is case sensitive');
187
188 createElement('x');
189 shouldBeTrue('element.classList.contains(\'x\')');
190 shouldBeFalse('element.classList.contains(\'X\')');
191 shouldBeEqualToString('element.classList[0]', 'x');
192
193 createElement('X');
194 shouldBeTrue('element.classList.contains(\'X\')');
195 shouldBeFalse('element.classList.contains(\'x\')');
196 shouldBeEqualToString('element.classList[0]', 'X');
197
198
199 debug('Testing whitespace');
200 // U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF),
201 // U+000C FORM FEED (FF), and U+000D CARRIAGE RETURN (CR)
202
203 createElement('x\u0020y');
204 shouldEvaluateTo('element.classList.length', 2);
205
206 createElement('x\u0009y');
207 shouldEvaluateTo('element.classList.length', 2);
208
209 createElement('x\u000Ay');
210 shouldEvaluateTo('element.classList.length', 2);
211
212 createElement('x\u000Cy');
213 shouldEvaluateTo('element.classList.length', 2);
214
215 createElement('x\u000Dy');
216 shouldEvaluateTo('element.classList.length', 2);
217
218
219 debug('DOMTokenList presence and type');
220
221
222 // Safari returns object
223 // Firefox returns object
224 // IE8 returns object
225 // Chrome returns function
226 // assertEquals('object', typeof DOMTokenList);
227 shouldBeTrue('\'undefined\' != typeof DOMTokenList');
228
229 shouldBeEqualToString('typeof DOMTokenList.prototype', 'object');
230
231 createElement('x');
232 shouldBeEqualToString('typeof element.classList', 'object');
233
234 shouldEvaluateTo('element.classList.constructor', 'DOMTokenList');
235
236 shouldBeTrue('element.classList === element.classList');
237
238 var successfullyParsed = true;