|
1 // This script is used to test elements that implement |
|
2 // nsIDOMXULSelectControlElement. This currently is the following elements: |
|
3 // listbox, menulist, radiogroup, richlistbox, tabs |
|
4 // |
|
5 // flag behaviours that differ for certain elements |
|
6 // allow-other-value - alternate values for the value property may be used |
|
7 // besides those in the list |
|
8 // other-value-clears-selection - alternative values for the value property |
|
9 // clears the selected item |
|
10 // selection-required - an item must be selected in the list, unless there |
|
11 // aren't any to select |
|
12 // activate-disabled-menuitem - disabled menuitems can be highlighted |
|
13 // select-keynav-wraps - key navigation over a selectable list wraps |
|
14 // select-extended-keynav - home, end, page up and page down keys work to |
|
15 // navigate over a selectable list |
|
16 // keynav-leftright - key navigation is left/right rather than up/down |
|
17 // The win:, mac: and gtk: or other prefixes may be used for platform specific behaviour |
|
18 var behaviours = { |
|
19 menu: "win:activate-disabled-menuitem activate-disabled-menuitem-mousemove select-keynav-wraps select-extended-keynav", |
|
20 menulist: "allow-other-value other-value-clears-selection", |
|
21 listbox: "select-extended-keynav", |
|
22 richlistbox: "select-extended-keynav", |
|
23 radiogroup: "select-keynav-wraps dont-select-disabled allow-other-value", |
|
24 tabs: "select-extended-keynav mac:select-keynav-wraps allow-other-value selection-required keynav-leftright" |
|
25 }; |
|
26 |
|
27 function behaviourContains(tag, behaviour) |
|
28 { |
|
29 var platform = "none:"; |
|
30 if (navigator.platform.indexOf("Mac") >= 0) |
|
31 platform = "mac:"; |
|
32 else if (navigator.platform.indexOf("Win") >= 0) |
|
33 platform = "win:"; |
|
34 else if (navigator.platform.indexOf("X") >= 0) |
|
35 platform = "gtk:"; |
|
36 |
|
37 var re = new RegExp("\\s" + platform + behaviour + "\\s|\\s" + behaviour + "\\s"); |
|
38 return re.test(" " + behaviours[tag] + " "); |
|
39 } |
|
40 |
|
41 function test_nsIDOMXULSelectControlElement(element, childtag, testprefix) |
|
42 { |
|
43 var testid = (testprefix) ? testprefix + " " : ""; |
|
44 testid += element.localName + " nsIDOMXULSelectControlElement "; |
|
45 |
|
46 // editable menulists use the label as the value instead |
|
47 var firstvalue = "first", secondvalue = "second", fourthvalue = "fourth"; |
|
48 if (element.localName == "menulist" && element.editable) { |
|
49 firstvalue = "First Item"; |
|
50 secondvalue = "Second Item" |
|
51 fourthvalue = "Fourth Item"; |
|
52 } |
|
53 |
|
54 // 'initial' - check if the initial state of the element is correct |
|
55 test_nsIDOMXULSelectControlElement_States(element, testid + "initial", 0, null, -1, ""); |
|
56 |
|
57 test_nsIDOMXULSelectControlElement_init(element, testid); |
|
58 |
|
59 // 'appendItem' - check if appendItem works to add a new item |
|
60 var firstitem = element.appendItem("First Item", "first"); |
|
61 is(firstitem.localName, childtag, |
|
62 testid + "appendItem - first item is " + childtag); |
|
63 test_nsIDOMXULSelectControlElement_States(element, testid + "appendItem", 1, null, -1, ""); |
|
64 |
|
65 is(firstitem.control, element, testid + "control"); |
|
66 |
|
67 // 'selectedIndex' - check if an item may be selected |
|
68 element.selectedIndex = 0; |
|
69 test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex", 1, firstitem, 0, firstvalue); |
|
70 |
|
71 // 'appendItem 2' - check if a second item may be added |
|
72 var seconditem = element.appendItem("Second Item", "second"); |
|
73 test_nsIDOMXULSelectControlElement_States(element, testid + "appendItem 2", 2, firstitem, 0, firstvalue); |
|
74 |
|
75 // 'selectedItem' - check if the second item may be selected |
|
76 element.selectedItem = seconditem; |
|
77 test_nsIDOMXULSelectControlElement_States(element, testid + "selectedItem", 2, seconditem, 1, secondvalue); |
|
78 |
|
79 // 'selectedIndex 2' - check if selectedIndex may be set to -1 to deselect items |
|
80 var selectionRequired = behaviourContains(element.localName, "selection-required"); |
|
81 element.selectedIndex = -1; |
|
82 test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex 2", 2, |
|
83 selectionRequired ? seconditem : null, selectionRequired ? 1 : -1, |
|
84 selectionRequired ? secondvalue : ""); |
|
85 |
|
86 // 'selectedItem 2' - check if the selectedItem property may be set to null |
|
87 element.selectedIndex = 1; |
|
88 element.selectedItem = null; |
|
89 test_nsIDOMXULSelectControlElement_States(element, testid + "selectedItem 2", 2, |
|
90 selectionRequired ? seconditem : null, selectionRequired ? 1 : -1, |
|
91 selectionRequired ? secondvalue : ""); |
|
92 |
|
93 // 'getIndexOfItem' - check if getIndexOfItem returns the right index |
|
94 is(element.getIndexOfItem(firstitem), 0, testid + "getIndexOfItem - first item at index 0"); |
|
95 is(element.getIndexOfItem(seconditem), 1, testid + "getIndexOfItem - second item at index 1"); |
|
96 |
|
97 var otheritem = element.ownerDocument.createElement(childtag); |
|
98 is(element.getIndexOfItem(otheritem), -1, testid + "getIndexOfItem - other item not found"); |
|
99 |
|
100 // 'getItemAtIndex' - check if getItemAtIndex returns the right item |
|
101 is(element.getItemAtIndex(0), firstitem, testid + "getItemAtIndex - index 0 is first item"); |
|
102 is(element.getItemAtIndex(1), seconditem, testid + "getItemAtIndex - index 0 is second item"); |
|
103 is(element.getItemAtIndex(-1), null, testid + "getItemAtIndex - index -1 is null"); |
|
104 is(element.getItemAtIndex(2), null, testid + "getItemAtIndex - index 2 is null"); |
|
105 |
|
106 // check if setting the value changes the selection |
|
107 element.value = firstvalue; |
|
108 test_nsIDOMXULSelectControlElement_States(element, testid + "set value 1", 2, firstitem, 0, firstvalue); |
|
109 element.value = secondvalue; |
|
110 test_nsIDOMXULSelectControlElement_States(element, testid + "set value 2", 2, seconditem, 1, secondvalue); |
|
111 // setting the value attribute to one not in the list doesn't change the selection. |
|
112 // The value is only changed for elements which support having a value other than the |
|
113 // selection. |
|
114 element.value = "other"; |
|
115 var allowOtherValue = behaviourContains(element.localName, "allow-other-value"); |
|
116 var otherValueClearsSelection = behaviourContains(element.localName, "other-value-clears-selection"); |
|
117 test_nsIDOMXULSelectControlElement_States(element, testid + "set value other", 2, |
|
118 otherValueClearsSelection ? null : seconditem, |
|
119 otherValueClearsSelection ? -1 : 1, |
|
120 allowOtherValue ? "other" : secondvalue); |
|
121 if (allowOtherValue) |
|
122 element.value = ""; |
|
123 |
|
124 // 'removeItemAt' - check if removeItemAt removes the right item |
|
125 if (selectionRequired) |
|
126 element.value = secondvalue; |
|
127 else |
|
128 element.selectedIndex = -1; |
|
129 |
|
130 var removeditem = element.removeItemAt(0); |
|
131 is(removeditem, firstitem, testid + "removeItemAt return value"); |
|
132 test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt", 1, |
|
133 selectionRequired ? seconditem : null, selectionRequired ? 0 : -1, |
|
134 selectionRequired ? secondvalue : ""); |
|
135 |
|
136 is(removeditem.control, null, testid + "control not set"); |
|
137 |
|
138 var thirditem = element.appendItem("Third Item", "third"); |
|
139 var fourthitem = element.appendItem("Fourth Item", fourthvalue); |
|
140 var fifthitem = element.appendItem("Fifth Item", "fifth"); |
|
141 |
|
142 // 'removeItemAt 2' - check if removeItemAt removes the selected item and |
|
143 // adjusts the selection to the next item |
|
144 element.selectedItem = thirditem; |
|
145 is(element.removeItemAt(1), thirditem, testid + "removeItemAt 2 return value"); |
|
146 |
|
147 // radio buttons don't handle removing quite right due to XBL issues, |
|
148 // so disable testing some of these remove tests for now - bug 367400 |
|
149 var isnotradio = (element.localName != "radiogroup"); |
|
150 // XXXndeakin disable these tests for all widgets for now. They require bug 331513. |
|
151 isnotradio = false; |
|
152 if (isnotradio) |
|
153 test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 2", 3, fourthitem, 1, fourthvalue); |
|
154 |
|
155 // 'removeItemAt 3' - check if removeItemAt adjusts the selection |
|
156 // if an earlier item is removed |
|
157 element.selectedItem = fourthitem; |
|
158 element.removeItemAt(0); |
|
159 test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 3", 2, fourthitem, 0, fourthvalue); |
|
160 |
|
161 // 'removeItemAt 4' - check if removeItemAt adjusts the selection if the |
|
162 // last item is selected and removed |
|
163 element.selectedItem = fifthitem; |
|
164 element.removeItemAt(1); |
|
165 if (isnotradio) |
|
166 test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 4", 1, fourthitem, 0, fourthvalue); |
|
167 |
|
168 // 'removeItemAt 5' - check that removeItemAt doesn't fail when removing invalid items |
|
169 is(element.removeItemAt(-1), null, testid + "removeItemAt 5 return value"); |
|
170 if (isnotradio) |
|
171 test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 5", 1, fourthitem, 0, fourthvalue); |
|
172 |
|
173 // 'removeItemAt 6' - check that removeItemAt doesn't fail when removing invalid items |
|
174 is(element.removeItemAt(1), null, testid + "removeItemAt 6 return value"); |
|
175 is("item removed", "item removed", testid + "removeItemAt 6"); |
|
176 if (isnotradio) |
|
177 test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 6", 1, fourthitem, 0, fourthvalue); |
|
178 |
|
179 // 'insertItemAt' - check if insertItemAt inserts items at the right locations |
|
180 element.selectedIndex = 0; |
|
181 test_nsIDOMXULSelectControlElement_insertItemAt(element, 0, 0, testid, 5); |
|
182 test_nsIDOMXULSelectControlElement_insertItemAt(element, 2, 2, testid, 6); |
|
183 test_nsIDOMXULSelectControlElement_insertItemAt(element, -1, 3, testid, 7); |
|
184 test_nsIDOMXULSelectControlElement_insertItemAt(element, 6, 4, testid, 8); |
|
185 |
|
186 element.selectedIndex = 0; |
|
187 fourthitem.disabled = true; |
|
188 element.selectedIndex = 1; |
|
189 test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex disabled", 5, fourthitem, 1, fourthvalue); |
|
190 |
|
191 element.selectedIndex = 0; |
|
192 element.selectedItem = fourthitem; |
|
193 test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex disabled", 5, fourthitem, 1, fourthvalue); |
|
194 |
|
195 // 'removeall' - check if all items are removed |
|
196 while (element.itemCount) |
|
197 element.removeItemAt(0); |
|
198 if (isnotradio) |
|
199 test_nsIDOMXULSelectControlElement_States(element, testid + "remove all", 0, null, -1, |
|
200 allowOtherValue ? "number8" : ""); |
|
201 } |
|
202 |
|
203 function test_nsIDOMXULSelectControlElement_init(element, testprefix) |
|
204 { |
|
205 // editable menulists use the label as the value |
|
206 var isEditable = (element.localName == "menulist" && element.editable); |
|
207 |
|
208 var id = element.id; |
|
209 element = document.getElementById(id + "-initwithvalue"); |
|
210 if (element) { |
|
211 var seconditem = element.getItemAtIndex(1); |
|
212 test_nsIDOMXULSelectControlElement_States(element, testprefix + " value initialization", |
|
213 3, seconditem, 1, |
|
214 isEditable ? seconditem.label : seconditem.value); |
|
215 } |
|
216 |
|
217 element = document.getElementById(id + "-initwithselected"); |
|
218 if (element) { |
|
219 var thirditem = element.getItemAtIndex(2); |
|
220 test_nsIDOMXULSelectControlElement_States(element, testprefix + " selected initialization", |
|
221 3, thirditem, 2, |
|
222 isEditable ? thirditem.label : thirditem.value); |
|
223 } |
|
224 } |
|
225 |
|
226 function test_nsIDOMXULSelectControlElement_States(element, testid, |
|
227 expectedcount, expecteditem, |
|
228 expectedindex, expectedvalue) |
|
229 { |
|
230 // need an itemCount property here |
|
231 var count = element.itemCount; |
|
232 is(count, expectedcount, testid + " item count"); |
|
233 is(element.selectedItem, expecteditem, testid + " selectedItem"); |
|
234 is(element.selectedIndex, expectedindex, testid + " selectedIndex"); |
|
235 is(element.value, expectedvalue, testid + " value"); |
|
236 if (element.selectedItem) { |
|
237 is(element.selectedItem.selected, true, |
|
238 testid + " selectedItem marked as selected"); |
|
239 } |
|
240 } |
|
241 |
|
242 function test_nsIDOMXULSelectControlElement_insertItemAt(element, index, expectedindex, testid, number) |
|
243 { |
|
244 var expectedCount = element.itemCount; |
|
245 var expectedSelItem = element.selectedItem; |
|
246 var expectedSelIndex = element.selectedIndex; |
|
247 var expectedSelValue = element.value; |
|
248 |
|
249 var newitem = element.insertItemAt(index, "Item " + number, "number" + number); |
|
250 is(element.getIndexOfItem(newitem), expectedindex, |
|
251 testid + "insertItemAt " + expectedindex + " - get inserted item"); |
|
252 expectedCount++; |
|
253 if (expectedSelIndex >= expectedindex) |
|
254 expectedSelIndex++; |
|
255 |
|
256 test_nsIDOMXULSelectControlElement_States(element, testid + "insertItemAt " + index, |
|
257 expectedCount, expectedSelItem, |
|
258 expectedSelIndex, expectedSelValue); |
|
259 return newitem; |
|
260 } |
|
261 |
|
262 /** test_nsIDOMXULSelectControlElement_UI |
|
263 * |
|
264 * Test the UI aspects of an element which implements nsIDOMXULSelectControlElement |
|
265 * |
|
266 * Parameters: |
|
267 * element - element to test |
|
268 */ |
|
269 function test_nsIDOMXULSelectControlElement_UI(element, testprefix) |
|
270 { |
|
271 var testid = (testprefix) ? testprefix + " " : ""; |
|
272 testid += element.localName + " nsIDOMXULSelectControlElement UI "; |
|
273 |
|
274 while (element.itemCount) |
|
275 element.removeItemAt(0); |
|
276 |
|
277 var firstitem = element.appendItem("First Item", "first"); |
|
278 var seconditem = element.appendItem("Second Item", "second"); |
|
279 |
|
280 // 'mouse select' - check if clicking an item selects it |
|
281 synthesizeMouseExpectEvent(firstitem, 2, 2, {}, element, "select", testid + "mouse select"); |
|
282 test_nsIDOMXULSelectControlElement_States(element, testid + "mouse select", 2, firstitem, 0, "first"); |
|
283 |
|
284 synthesizeMouseExpectEvent(seconditem, 2, 2, {}, element, "select", testid + "mouse select 2"); |
|
285 test_nsIDOMXULSelectControlElement_States(element, testid + "mouse select 2", 2, seconditem, 1, "second"); |
|
286 |
|
287 // make sure the element is focused so keyboard navigation will apply |
|
288 element.selectedIndex = 1; |
|
289 element.focus(); |
|
290 |
|
291 var navLeftRight = behaviourContains(element.localName, "keynav-leftright"); |
|
292 var backKey = navLeftRight ? "VK_LEFT" : "VK_UP"; |
|
293 var forwardKey = navLeftRight ? "VK_RIGHT" : "VK_DOWN"; |
|
294 |
|
295 // 'key select' - check if keypresses move between items |
|
296 synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up"); |
|
297 test_nsIDOMXULSelectControlElement_States(element, testid + "key up", 2, firstitem, 0, "first"); |
|
298 |
|
299 var keyWrap = behaviourContains(element.localName, "select-keynav-wraps"); |
|
300 |
|
301 var expectedItem = keyWrap ? seconditem : firstitem; |
|
302 var expectedIndex = keyWrap ? 1 : 0; |
|
303 var expectedValue = keyWrap ? "second" : "first"; |
|
304 synthesizeKeyExpectEvent(backKey, {}, keyWrap ? element : null, "select", testid + "key up 2"); |
|
305 test_nsIDOMXULSelectControlElement_States(element, testid + "key up 2", 2, |
|
306 expectedItem, expectedIndex, expectedValue); |
|
307 |
|
308 element.selectedIndex = 0; |
|
309 synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down"); |
|
310 test_nsIDOMXULSelectControlElement_States(element, testid + "key down", 2, seconditem, 1, "second"); |
|
311 |
|
312 expectedItem = keyWrap ? firstitem : seconditem; |
|
313 expectedIndex = keyWrap ? 0 : 1; |
|
314 expectedValue = keyWrap ? "first" : "second"; |
|
315 synthesizeKeyExpectEvent(forwardKey, {}, keyWrap ? element : null, "select", testid + "key down 2"); |
|
316 test_nsIDOMXULSelectControlElement_States(element, testid + "key down 2", 2, |
|
317 expectedItem, expectedIndex, expectedValue); |
|
318 |
|
319 var thirditem = element.appendItem("Third Item", "third"); |
|
320 var fourthitem = element.appendItem("Fourth Item", "fourth"); |
|
321 if (behaviourContains(element.localName, "select-extended-keynav")) { |
|
322 var fifthitem = element.appendItem("Fifth Item", "fifth"); |
|
323 var sixthitem = element.appendItem("Sixth Item", "sixth"); |
|
324 |
|
325 synthesizeKeyExpectEvent("VK_END", {}, element, "select", testid + "key end"); |
|
326 test_nsIDOMXULSelectControlElement_States(element, testid + "key end", 6, sixthitem, 5, "sixth"); |
|
327 |
|
328 synthesizeKeyExpectEvent("VK_HOME", {}, element, "select", testid + "key home"); |
|
329 test_nsIDOMXULSelectControlElement_States(element, testid + "key home", 6, firstitem, 0, "first"); |
|
330 |
|
331 synthesizeKeyExpectEvent("VK_PAGE_DOWN", {}, element, "select", testid + "key page down"); |
|
332 test_nsIDOMXULSelectControlElement_States(element, testid + "key page down", 6, fourthitem, 3, "fourth"); |
|
333 synthesizeKeyExpectEvent("VK_PAGE_DOWN", {}, element, "select", testid + "key page down to end"); |
|
334 test_nsIDOMXULSelectControlElement_States(element, testid + "key page down to end", 6, sixthitem, 5, "sixth"); |
|
335 |
|
336 synthesizeKeyExpectEvent("VK_PAGE_UP", {}, element, "select", testid + "key page up"); |
|
337 test_nsIDOMXULSelectControlElement_States(element, testid + "key page up", 6, thirditem, 2, "third"); |
|
338 synthesizeKeyExpectEvent("VK_PAGE_UP", {}, element, "select", testid + "key page up to start"); |
|
339 test_nsIDOMXULSelectControlElement_States(element, testid + "key page up to start", 6, firstitem, 0, "first"); |
|
340 |
|
341 element.removeItemAt(5); |
|
342 element.removeItemAt(4); |
|
343 } |
|
344 |
|
345 // now test whether a disabled item works. |
|
346 element.selectedIndex = 0; |
|
347 seconditem.disabled = true; |
|
348 |
|
349 var dontSelectDisabled = (behaviourContains(element.localName, "dont-select-disabled")); |
|
350 |
|
351 // 'mouse select' - check if clicking an item selects it |
|
352 synthesizeMouseExpectEvent(seconditem, 2, 2, {}, element, |
|
353 dontSelectDisabled ? "!select" : "select", |
|
354 testid + "mouse select disabled"); |
|
355 test_nsIDOMXULSelectControlElement_States(element, testid + "mouse select disabled", 4, |
|
356 dontSelectDisabled ? firstitem: seconditem, dontSelectDisabled ? 0 : 1, |
|
357 dontSelectDisabled ? "first" : "second"); |
|
358 |
|
359 if (dontSelectDisabled) { |
|
360 // test whether disabling an item won't allow it to be selected |
|
361 synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down disabled"); |
|
362 test_nsIDOMXULSelectControlElement_States(element, testid + "key down disabled", 4, thirditem, 2, "third"); |
|
363 |
|
364 synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up disabled"); |
|
365 test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled", 4, firstitem, 0, "first"); |
|
366 |
|
367 element.selectedIndex = 2; |
|
368 firstitem.disabled = true; |
|
369 |
|
370 synthesizeKeyExpectEvent(backKey, {}, keyWrap ? element : null, "select", testid + "key up disabled 2"); |
|
371 expectedItem = keyWrap ? fourthitem : thirditem; |
|
372 expectedIndex = keyWrap ? 3 : 2; |
|
373 expectedValue = keyWrap ? "fourth" : "third"; |
|
374 test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled 2", 4, |
|
375 expectedItem, expectedIndex, expectedValue); |
|
376 } |
|
377 else { |
|
378 // in this case, disabled items should behave the same as non-disabled items. |
|
379 element.selectedIndex = 0; |
|
380 synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down disabled"); |
|
381 test_nsIDOMXULSelectControlElement_States(element, testid + "key down disabled", 4, seconditem, 1, "second"); |
|
382 synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down disabled again"); |
|
383 test_nsIDOMXULSelectControlElement_States(element, testid + "key down disabled again", 4, thirditem, 2, "third"); |
|
384 |
|
385 synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up disabled"); |
|
386 test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled", 4, seconditem, 1, "second"); |
|
387 synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up disabled again"); |
|
388 test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled again", 4, firstitem, 0, "first"); |
|
389 } |
|
390 } |