michael@0: // This script is used to test elements that implement michael@0: // nsIDOMXULSelectControlElement. This currently is the following elements: michael@0: // listbox, menulist, radiogroup, richlistbox, tabs michael@0: // michael@0: // flag behaviours that differ for certain elements michael@0: // allow-other-value - alternate values for the value property may be used michael@0: // besides those in the list michael@0: // other-value-clears-selection - alternative values for the value property michael@0: // clears the selected item michael@0: // selection-required - an item must be selected in the list, unless there michael@0: // aren't any to select michael@0: // activate-disabled-menuitem - disabled menuitems can be highlighted michael@0: // select-keynav-wraps - key navigation over a selectable list wraps michael@0: // select-extended-keynav - home, end, page up and page down keys work to michael@0: // navigate over a selectable list michael@0: // keynav-leftright - key navigation is left/right rather than up/down michael@0: // The win:, mac: and gtk: or other prefixes may be used for platform specific behaviour michael@0: var behaviours = { michael@0: menu: "win:activate-disabled-menuitem activate-disabled-menuitem-mousemove select-keynav-wraps select-extended-keynav", michael@0: menulist: "allow-other-value other-value-clears-selection", michael@0: listbox: "select-extended-keynav", michael@0: richlistbox: "select-extended-keynav", michael@0: radiogroup: "select-keynav-wraps dont-select-disabled allow-other-value", michael@0: tabs: "select-extended-keynav mac:select-keynav-wraps allow-other-value selection-required keynav-leftright" michael@0: }; michael@0: michael@0: function behaviourContains(tag, behaviour) michael@0: { michael@0: var platform = "none:"; michael@0: if (navigator.platform.indexOf("Mac") >= 0) michael@0: platform = "mac:"; michael@0: else if (navigator.platform.indexOf("Win") >= 0) michael@0: platform = "win:"; michael@0: else if (navigator.platform.indexOf("X") >= 0) michael@0: platform = "gtk:"; michael@0: michael@0: var re = new RegExp("\\s" + platform + behaviour + "\\s|\\s" + behaviour + "\\s"); michael@0: return re.test(" " + behaviours[tag] + " "); michael@0: } michael@0: michael@0: function test_nsIDOMXULSelectControlElement(element, childtag, testprefix) michael@0: { michael@0: var testid = (testprefix) ? testprefix + " " : ""; michael@0: testid += element.localName + " nsIDOMXULSelectControlElement "; michael@0: michael@0: // editable menulists use the label as the value instead michael@0: var firstvalue = "first", secondvalue = "second", fourthvalue = "fourth"; michael@0: if (element.localName == "menulist" && element.editable) { michael@0: firstvalue = "First Item"; michael@0: secondvalue = "Second Item" michael@0: fourthvalue = "Fourth Item"; michael@0: } michael@0: michael@0: // 'initial' - check if the initial state of the element is correct michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "initial", 0, null, -1, ""); michael@0: michael@0: test_nsIDOMXULSelectControlElement_init(element, testid); michael@0: michael@0: // 'appendItem' - check if appendItem works to add a new item michael@0: var firstitem = element.appendItem("First Item", "first"); michael@0: is(firstitem.localName, childtag, michael@0: testid + "appendItem - first item is " + childtag); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "appendItem", 1, null, -1, ""); michael@0: michael@0: is(firstitem.control, element, testid + "control"); michael@0: michael@0: // 'selectedIndex' - check if an item may be selected michael@0: element.selectedIndex = 0; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex", 1, firstitem, 0, firstvalue); michael@0: michael@0: // 'appendItem 2' - check if a second item may be added michael@0: var seconditem = element.appendItem("Second Item", "second"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "appendItem 2", 2, firstitem, 0, firstvalue); michael@0: michael@0: // 'selectedItem' - check if the second item may be selected michael@0: element.selectedItem = seconditem; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "selectedItem", 2, seconditem, 1, secondvalue); michael@0: michael@0: // 'selectedIndex 2' - check if selectedIndex may be set to -1 to deselect items michael@0: var selectionRequired = behaviourContains(element.localName, "selection-required"); michael@0: element.selectedIndex = -1; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex 2", 2, michael@0: selectionRequired ? seconditem : null, selectionRequired ? 1 : -1, michael@0: selectionRequired ? secondvalue : ""); michael@0: michael@0: // 'selectedItem 2' - check if the selectedItem property may be set to null michael@0: element.selectedIndex = 1; michael@0: element.selectedItem = null; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "selectedItem 2", 2, michael@0: selectionRequired ? seconditem : null, selectionRequired ? 1 : -1, michael@0: selectionRequired ? secondvalue : ""); michael@0: michael@0: // 'getIndexOfItem' - check if getIndexOfItem returns the right index michael@0: is(element.getIndexOfItem(firstitem), 0, testid + "getIndexOfItem - first item at index 0"); michael@0: is(element.getIndexOfItem(seconditem), 1, testid + "getIndexOfItem - second item at index 1"); michael@0: michael@0: var otheritem = element.ownerDocument.createElement(childtag); michael@0: is(element.getIndexOfItem(otheritem), -1, testid + "getIndexOfItem - other item not found"); michael@0: michael@0: // 'getItemAtIndex' - check if getItemAtIndex returns the right item michael@0: is(element.getItemAtIndex(0), firstitem, testid + "getItemAtIndex - index 0 is first item"); michael@0: is(element.getItemAtIndex(1), seconditem, testid + "getItemAtIndex - index 0 is second item"); michael@0: is(element.getItemAtIndex(-1), null, testid + "getItemAtIndex - index -1 is null"); michael@0: is(element.getItemAtIndex(2), null, testid + "getItemAtIndex - index 2 is null"); michael@0: michael@0: // check if setting the value changes the selection michael@0: element.value = firstvalue; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "set value 1", 2, firstitem, 0, firstvalue); michael@0: element.value = secondvalue; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "set value 2", 2, seconditem, 1, secondvalue); michael@0: // setting the value attribute to one not in the list doesn't change the selection. michael@0: // The value is only changed for elements which support having a value other than the michael@0: // selection. michael@0: element.value = "other"; michael@0: var allowOtherValue = behaviourContains(element.localName, "allow-other-value"); michael@0: var otherValueClearsSelection = behaviourContains(element.localName, "other-value-clears-selection"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "set value other", 2, michael@0: otherValueClearsSelection ? null : seconditem, michael@0: otherValueClearsSelection ? -1 : 1, michael@0: allowOtherValue ? "other" : secondvalue); michael@0: if (allowOtherValue) michael@0: element.value = ""; michael@0: michael@0: // 'removeItemAt' - check if removeItemAt removes the right item michael@0: if (selectionRequired) michael@0: element.value = secondvalue; michael@0: else michael@0: element.selectedIndex = -1; michael@0: michael@0: var removeditem = element.removeItemAt(0); michael@0: is(removeditem, firstitem, testid + "removeItemAt return value"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt", 1, michael@0: selectionRequired ? seconditem : null, selectionRequired ? 0 : -1, michael@0: selectionRequired ? secondvalue : ""); michael@0: michael@0: is(removeditem.control, null, testid + "control not set"); michael@0: michael@0: var thirditem = element.appendItem("Third Item", "third"); michael@0: var fourthitem = element.appendItem("Fourth Item", fourthvalue); michael@0: var fifthitem = element.appendItem("Fifth Item", "fifth"); michael@0: michael@0: // 'removeItemAt 2' - check if removeItemAt removes the selected item and michael@0: // adjusts the selection to the next item michael@0: element.selectedItem = thirditem; michael@0: is(element.removeItemAt(1), thirditem, testid + "removeItemAt 2 return value"); michael@0: michael@0: // radio buttons don't handle removing quite right due to XBL issues, michael@0: // so disable testing some of these remove tests for now - bug 367400 michael@0: var isnotradio = (element.localName != "radiogroup"); michael@0: // XXXndeakin disable these tests for all widgets for now. They require bug 331513. michael@0: isnotradio = false; michael@0: if (isnotradio) michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 2", 3, fourthitem, 1, fourthvalue); michael@0: michael@0: // 'removeItemAt 3' - check if removeItemAt adjusts the selection michael@0: // if an earlier item is removed michael@0: element.selectedItem = fourthitem; michael@0: element.removeItemAt(0); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 3", 2, fourthitem, 0, fourthvalue); michael@0: michael@0: // 'removeItemAt 4' - check if removeItemAt adjusts the selection if the michael@0: // last item is selected and removed michael@0: element.selectedItem = fifthitem; michael@0: element.removeItemAt(1); michael@0: if (isnotradio) michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 4", 1, fourthitem, 0, fourthvalue); michael@0: michael@0: // 'removeItemAt 5' - check that removeItemAt doesn't fail when removing invalid items michael@0: is(element.removeItemAt(-1), null, testid + "removeItemAt 5 return value"); michael@0: if (isnotradio) michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 5", 1, fourthitem, 0, fourthvalue); michael@0: michael@0: // 'removeItemAt 6' - check that removeItemAt doesn't fail when removing invalid items michael@0: is(element.removeItemAt(1), null, testid + "removeItemAt 6 return value"); michael@0: is("item removed", "item removed", testid + "removeItemAt 6"); michael@0: if (isnotradio) michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "removeItemAt 6", 1, fourthitem, 0, fourthvalue); michael@0: michael@0: // 'insertItemAt' - check if insertItemAt inserts items at the right locations michael@0: element.selectedIndex = 0; michael@0: test_nsIDOMXULSelectControlElement_insertItemAt(element, 0, 0, testid, 5); michael@0: test_nsIDOMXULSelectControlElement_insertItemAt(element, 2, 2, testid, 6); michael@0: test_nsIDOMXULSelectControlElement_insertItemAt(element, -1, 3, testid, 7); michael@0: test_nsIDOMXULSelectControlElement_insertItemAt(element, 6, 4, testid, 8); michael@0: michael@0: element.selectedIndex = 0; michael@0: fourthitem.disabled = true; michael@0: element.selectedIndex = 1; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex disabled", 5, fourthitem, 1, fourthvalue); michael@0: michael@0: element.selectedIndex = 0; michael@0: element.selectedItem = fourthitem; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "selectedIndex disabled", 5, fourthitem, 1, fourthvalue); michael@0: michael@0: // 'removeall' - check if all items are removed michael@0: while (element.itemCount) michael@0: element.removeItemAt(0); michael@0: if (isnotradio) michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "remove all", 0, null, -1, michael@0: allowOtherValue ? "number8" : ""); michael@0: } michael@0: michael@0: function test_nsIDOMXULSelectControlElement_init(element, testprefix) michael@0: { michael@0: // editable menulists use the label as the value michael@0: var isEditable = (element.localName == "menulist" && element.editable); michael@0: michael@0: var id = element.id; michael@0: element = document.getElementById(id + "-initwithvalue"); michael@0: if (element) { michael@0: var seconditem = element.getItemAtIndex(1); michael@0: test_nsIDOMXULSelectControlElement_States(element, testprefix + " value initialization", michael@0: 3, seconditem, 1, michael@0: isEditable ? seconditem.label : seconditem.value); michael@0: } michael@0: michael@0: element = document.getElementById(id + "-initwithselected"); michael@0: if (element) { michael@0: var thirditem = element.getItemAtIndex(2); michael@0: test_nsIDOMXULSelectControlElement_States(element, testprefix + " selected initialization", michael@0: 3, thirditem, 2, michael@0: isEditable ? thirditem.label : thirditem.value); michael@0: } michael@0: } michael@0: michael@0: function test_nsIDOMXULSelectControlElement_States(element, testid, michael@0: expectedcount, expecteditem, michael@0: expectedindex, expectedvalue) michael@0: { michael@0: // need an itemCount property here michael@0: var count = element.itemCount; michael@0: is(count, expectedcount, testid + " item count"); michael@0: is(element.selectedItem, expecteditem, testid + " selectedItem"); michael@0: is(element.selectedIndex, expectedindex, testid + " selectedIndex"); michael@0: is(element.value, expectedvalue, testid + " value"); michael@0: if (element.selectedItem) { michael@0: is(element.selectedItem.selected, true, michael@0: testid + " selectedItem marked as selected"); michael@0: } michael@0: } michael@0: michael@0: function test_nsIDOMXULSelectControlElement_insertItemAt(element, index, expectedindex, testid, number) michael@0: { michael@0: var expectedCount = element.itemCount; michael@0: var expectedSelItem = element.selectedItem; michael@0: var expectedSelIndex = element.selectedIndex; michael@0: var expectedSelValue = element.value; michael@0: michael@0: var newitem = element.insertItemAt(index, "Item " + number, "number" + number); michael@0: is(element.getIndexOfItem(newitem), expectedindex, michael@0: testid + "insertItemAt " + expectedindex + " - get inserted item"); michael@0: expectedCount++; michael@0: if (expectedSelIndex >= expectedindex) michael@0: expectedSelIndex++; michael@0: michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "insertItemAt " + index, michael@0: expectedCount, expectedSelItem, michael@0: expectedSelIndex, expectedSelValue); michael@0: return newitem; michael@0: } michael@0: michael@0: /** test_nsIDOMXULSelectControlElement_UI michael@0: * michael@0: * Test the UI aspects of an element which implements nsIDOMXULSelectControlElement michael@0: * michael@0: * Parameters: michael@0: * element - element to test michael@0: */ michael@0: function test_nsIDOMXULSelectControlElement_UI(element, testprefix) michael@0: { michael@0: var testid = (testprefix) ? testprefix + " " : ""; michael@0: testid += element.localName + " nsIDOMXULSelectControlElement UI "; michael@0: michael@0: while (element.itemCount) michael@0: element.removeItemAt(0); michael@0: michael@0: var firstitem = element.appendItem("First Item", "first"); michael@0: var seconditem = element.appendItem("Second Item", "second"); michael@0: michael@0: // 'mouse select' - check if clicking an item selects it michael@0: synthesizeMouseExpectEvent(firstitem, 2, 2, {}, element, "select", testid + "mouse select"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "mouse select", 2, firstitem, 0, "first"); michael@0: michael@0: synthesizeMouseExpectEvent(seconditem, 2, 2, {}, element, "select", testid + "mouse select 2"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "mouse select 2", 2, seconditem, 1, "second"); michael@0: michael@0: // make sure the element is focused so keyboard navigation will apply michael@0: element.selectedIndex = 1; michael@0: element.focus(); michael@0: michael@0: var navLeftRight = behaviourContains(element.localName, "keynav-leftright"); michael@0: var backKey = navLeftRight ? "VK_LEFT" : "VK_UP"; michael@0: var forwardKey = navLeftRight ? "VK_RIGHT" : "VK_DOWN"; michael@0: michael@0: // 'key select' - check if keypresses move between items michael@0: synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key up", 2, firstitem, 0, "first"); michael@0: michael@0: var keyWrap = behaviourContains(element.localName, "select-keynav-wraps"); michael@0: michael@0: var expectedItem = keyWrap ? seconditem : firstitem; michael@0: var expectedIndex = keyWrap ? 1 : 0; michael@0: var expectedValue = keyWrap ? "second" : "first"; michael@0: synthesizeKeyExpectEvent(backKey, {}, keyWrap ? element : null, "select", testid + "key up 2"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key up 2", 2, michael@0: expectedItem, expectedIndex, expectedValue); michael@0: michael@0: element.selectedIndex = 0; michael@0: synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key down", 2, seconditem, 1, "second"); michael@0: michael@0: expectedItem = keyWrap ? firstitem : seconditem; michael@0: expectedIndex = keyWrap ? 0 : 1; michael@0: expectedValue = keyWrap ? "first" : "second"; michael@0: synthesizeKeyExpectEvent(forwardKey, {}, keyWrap ? element : null, "select", testid + "key down 2"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key down 2", 2, michael@0: expectedItem, expectedIndex, expectedValue); michael@0: michael@0: var thirditem = element.appendItem("Third Item", "third"); michael@0: var fourthitem = element.appendItem("Fourth Item", "fourth"); michael@0: if (behaviourContains(element.localName, "select-extended-keynav")) { michael@0: var fifthitem = element.appendItem("Fifth Item", "fifth"); michael@0: var sixthitem = element.appendItem("Sixth Item", "sixth"); michael@0: michael@0: synthesizeKeyExpectEvent("VK_END", {}, element, "select", testid + "key end"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key end", 6, sixthitem, 5, "sixth"); michael@0: michael@0: synthesizeKeyExpectEvent("VK_HOME", {}, element, "select", testid + "key home"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key home", 6, firstitem, 0, "first"); michael@0: michael@0: synthesizeKeyExpectEvent("VK_PAGE_DOWN", {}, element, "select", testid + "key page down"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key page down", 6, fourthitem, 3, "fourth"); michael@0: synthesizeKeyExpectEvent("VK_PAGE_DOWN", {}, element, "select", testid + "key page down to end"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key page down to end", 6, sixthitem, 5, "sixth"); michael@0: michael@0: synthesizeKeyExpectEvent("VK_PAGE_UP", {}, element, "select", testid + "key page up"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key page up", 6, thirditem, 2, "third"); michael@0: synthesizeKeyExpectEvent("VK_PAGE_UP", {}, element, "select", testid + "key page up to start"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key page up to start", 6, firstitem, 0, "first"); michael@0: michael@0: element.removeItemAt(5); michael@0: element.removeItemAt(4); michael@0: } michael@0: michael@0: // now test whether a disabled item works. michael@0: element.selectedIndex = 0; michael@0: seconditem.disabled = true; michael@0: michael@0: var dontSelectDisabled = (behaviourContains(element.localName, "dont-select-disabled")); michael@0: michael@0: // 'mouse select' - check if clicking an item selects it michael@0: synthesizeMouseExpectEvent(seconditem, 2, 2, {}, element, michael@0: dontSelectDisabled ? "!select" : "select", michael@0: testid + "mouse select disabled"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "mouse select disabled", 4, michael@0: dontSelectDisabled ? firstitem: seconditem, dontSelectDisabled ? 0 : 1, michael@0: dontSelectDisabled ? "first" : "second"); michael@0: michael@0: if (dontSelectDisabled) { michael@0: // test whether disabling an item won't allow it to be selected michael@0: synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down disabled"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key down disabled", 4, thirditem, 2, "third"); michael@0: michael@0: synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up disabled"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled", 4, firstitem, 0, "first"); michael@0: michael@0: element.selectedIndex = 2; michael@0: firstitem.disabled = true; michael@0: michael@0: synthesizeKeyExpectEvent(backKey, {}, keyWrap ? element : null, "select", testid + "key up disabled 2"); michael@0: expectedItem = keyWrap ? fourthitem : thirditem; michael@0: expectedIndex = keyWrap ? 3 : 2; michael@0: expectedValue = keyWrap ? "fourth" : "third"; michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled 2", 4, michael@0: expectedItem, expectedIndex, expectedValue); michael@0: } michael@0: else { michael@0: // in this case, disabled items should behave the same as non-disabled items. michael@0: element.selectedIndex = 0; michael@0: synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down disabled"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key down disabled", 4, seconditem, 1, "second"); michael@0: synthesizeKeyExpectEvent(forwardKey, {}, element, "select", testid + "key down disabled again"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key down disabled again", 4, thirditem, 2, "third"); michael@0: michael@0: synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up disabled"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled", 4, seconditem, 1, "second"); michael@0: synthesizeKeyExpectEvent(backKey, {}, element, "select", testid + "key up disabled again"); michael@0: test_nsIDOMXULSelectControlElement_States(element, testid + "key up disabled again", 4, firstitem, 0, "first"); michael@0: } michael@0: }