| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta http-equiv="Expire" content="0"/> |
| <title>select_test.html</title> |
| <script type="text/javascript" src="test_bootstrap.js"></script> |
| <script type="text/javascript" src="jquery.min.js"></script> |
| <script type="text/javascript"> |
| goog.require('bot.action'); |
| goog.require('bot.locators'); |
| goog.require('bot.userAgent'); |
| goog.require('goog.array'); |
| goog.require('goog.dom'); |
| goog.require('goog.events'); |
| goog.require('goog.testing.jsunit'); |
| goog.require('goog.userAgent'); |
| </script> |
| <script type="text/javascript"> |
| var singleSelect, multiSelect, radioButtons, checkboxes, changeCount; |
| |
| function setUpPage() { |
| singleSelect = bot.locators.findElement({id: 'singleSelect'}); |
| multiSelect = bot.locators.findElement({id: 'multiSelect'}); |
| checkboxes = bot.locators.findElements({name: 'checkbox'}); |
| radioButtons = bot.locators.findElements({name: 'radio'}); |
| } |
| |
| function setUp() { |
| goog.events.removeAll(); |
| singleSelect.selectedIndex = 0; |
| goog.array.forEach(multiSelect.options, function(e) { |
| e.selected = false; |
| }); |
| goog.array.forEach(checkboxes, function(e) { |
| e.checked = false; |
| }); |
| goog.array.forEach(radioButtons, function(e) { |
| e.checked = false; |
| }); |
| } |
| |
| function checkActionCompatibility(action) { |
| if (action == bot.action.tap) { |
| return bot.events.SUPPORTS_TOUCH_EVENTS; |
| } |
| return true; |
| } |
| |
| function expectChanges(target) { |
| changeCount = 0; |
| goog.events.listen(target, 'change', function(e) { |
| changeCount++; |
| }); |
| } |
| |
| function assertChanges(expectedCount) { |
| assertEquals('Unexpected number of changes', expectedCount, changeCount); |
| } |
| |
| function canSelectAnOptionFromASingleSelect(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| assertFalse(bot.dom.isSelected(singleSelect.options[1])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[1]); |
| |
| assertChanges(1); |
| assertTrue(bot.dom.isSelected(singleSelect.options[1])); |
| } |
| |
| var testClickCanSelectAnOptionFromASingleSelect = |
| goog.partial(canSelectAnOptionFromASingleSelect, bot.action.click); |
| |
| var testTapCanSelectAnOptionFromASingleSelect = |
| goog.partial(canSelectAnOptionFromASingleSelect, bot.action.tap); |
| |
| function cannotDeselectAnOptionFromASingleSelect(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| assertTrue(bot.dom.isSelected(singleSelect.options[0])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[0]); |
| |
| assertChanges(0); |
| assertTrue(bot.dom.isSelected(singleSelect.options[0])); |
| } |
| |
| var testClickCannotDeselectAnOptionFromASingleSelect = |
| goog.partial(cannotDeselectAnOptionFromASingleSelect, bot.action.click); |
| |
| var testTapCannotDeselectAnOptionFromASingleSelect = |
| goog.partial(cannotDeselectAnOptionFromASingleSelect, bot.action.tap); |
| |
| function cannotSelectAnOptionFromADisabledSelect(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| singleSelect.disabled = true; |
| assertFalse(bot.dom.isSelected(singleSelect.options[1])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[1]); |
| |
| assertChanges(0); |
| assertFalse(bot.dom.isSelected(singleSelect.options[1])); |
| singleSelect.disabled = false; |
| } |
| |
| var testClickCannotSelectAnOptionFromADisabled = |
| goog.partial(cannotSelectAnOptionFromADisabledSelect, bot.action.click); |
| |
| var testTapCannotSelectAnOptionFromADisabled = |
| goog.partial(cannotSelectAnOptionFromADisabledSelect, bot.action.tap); |
| |
| function canSelectAnEnabledOptionFromASelectWithADisabledOption(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| singleSelect.options[1].disabled = true; |
| assertFalse(bot.dom.isSelected(singleSelect.options[2])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[2]); |
| |
| assertChanges(1); |
| assertTrue(bot.dom.isSelected(singleSelect.options[2])); |
| singleSelect.options[1].disabled = false; |
| } |
| |
| var testClickCanSelectAnEnabledOptionFromASelectWithADisabledOption = |
| goog.partial(canSelectAnEnabledOptionFromASelectWithADisabledOption, |
| bot.action.click); |
| |
| var testTapCanSelectAnEnabledOptionFromASelectWithADisabledOption = |
| goog.partial(canSelectAnEnabledOptionFromASelectWithADisabledOption, |
| bot.action.tap); |
| |
| function canToggleOptionsInAMultiSelect(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| multiSelect.options[0].selected = true; |
| expectChanges(multiSelect); |
| |
| action(multiSelect.options[0]); |
| action(multiSelect.options[1]); |
| action(multiSelect.options[2]); |
| |
| assertChanges(3); |
| assertFalse(bot.dom.isSelected(multiSelect.options[0])); |
| assertTrue(bot.dom.isSelected(multiSelect.options[1])); |
| assertTrue(bot.dom.isSelected(multiSelect.options[2])); |
| } |
| |
| var testClickCanToggleOptionsInAMultiSelect = |
| goog.partial(canToggleOptionsInAMultiSelect, bot.action.click); |
| |
| var testTapCanToggleOptionsInAMultiSelect = |
| goog.partial(canToggleOptionsInAMultiSelect, bot.action.tap); |
| |
| function canToggleCheckboxes(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| // IE fires a change event on the next click after the change. |
| checkboxes[0].checked = true; |
| expectChanges(checkboxes[0]); |
| action(checkboxes[0]); |
| assertChanges(bot.userAgent.IE_DOC_PRE9 ? 0 : 1); |
| |
| if (!goog.userAgent.IE) { |
| expectChanges(checkboxes[1]); |
| } |
| action(checkboxes[1]); |
| assertChanges(1); |
| |
| expectChanges(checkboxes[bot.userAgent.IE_DOC_PRE9 ? 1 : 2]); |
| action(checkboxes[2]); |
| assertChanges(1); |
| |
| assertFalse(bot.dom.isSelected(checkboxes[0])); |
| assertTrue(bot.dom.isSelected(checkboxes[1])); |
| assertTrue(bot.dom.isSelected(checkboxes[2])); |
| } |
| |
| var testClickCanToggleCheckboxes = |
| goog.partial(canToggleCheckboxes, bot.action.click); |
| |
| var testTapCanToggleCheckboxes = |
| goog.partial(canToggleCheckboxes, bot.action.tap); |
| |
| function canSelectRadioButtons(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| // IE fires a change event on the next click after the change. |
| expectChanges(radioButtons[0]); |
| action(radioButtons[0]); |
| assertChanges(bot.userAgent.IE_DOC_PRE9 ? 0 : 1); |
| |
| assertTrue(bot.dom.isSelected(radioButtons[0])); |
| |
| if (!goog.userAgent.IE) { |
| expectChanges(radioButtons[1]); |
| } |
| action(radioButtons[1]); |
| assertChanges(1); |
| assertTrue(bot.dom.isSelected(radioButtons[1])); |
| |
| expectChanges(radioButtons[bot.userAgent.IE_DOC_PRE9 ? 1 : 2]); |
| action(radioButtons[2]); |
| assertChanges(1); |
| assertTrue(bot.dom.isSelected(radioButtons[2])); |
| } |
| |
| var testClickCanSelectRadioButtons = |
| goog.partial(canSelectRadioButtons, bot.action.click); |
| |
| var testTapCanSelectRadioButtons = |
| goog.partial(canSelectRadioButtons, bot.action.tap); |
| |
| function cannotDeselectRadioButtons(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| radioButtons[0].checked = true; |
| expectChanges(radioButtons[0]); |
| |
| action(radioButtons[0]); |
| |
| assertChanges(0); |
| assertTrue(bot.dom.isSelected(radioButtons[0])); |
| } |
| |
| var testClickCannotDeselectRadioButtons = |
| goog.partial(cannotDeselectRadioButtons, bot.action.click); |
| |
| var testTapCannotDeselectRadioButtons = |
| goog.partial(cannotDeselectRadioButtons, bot.action.tap); |
| |
| function cannotSelectDisabledElements(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| function assertCannotSelectWhenDisabled(elem, isOption) { |
| elem.disabled = true; |
| expectChanges(isOption ? elem.parentNode : elem); |
| |
| action(elem); |
| |
| assertChanges(0); |
| assertFalse(bot.dom.isSelected(elem)); |
| elem.disabled = false; |
| } |
| |
| assertCannotSelectWhenDisabled(singleSelect.options[1], true); |
| assertCannotSelectWhenDisabled(multiSelect.options[0], true); |
| assertCannotSelectWhenDisabled(checkboxes[0], false); |
| assertCannotSelectWhenDisabled(radioButtons[0], false); |
| } |
| |
| var testClickCannotSelectDisabledElements = |
| goog.partial(cannotSelectDisabledElements, bot.action.click); |
| |
| var testTapCannotSelectDisabledElements = |
| goog.partial(cannotSelectDisabledElements, bot.action.tap); |
| |
| function canSelectOptionWhenDefaultPrevented(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| function assertCanSelectWhenDefaultPrevented(elem) { |
| goog.events.listen(elem, 'click', function(e) { |
| e.preventDefault(); |
| }); |
| expectChanges(elem.parentNode); |
| |
| action(elem); |
| |
| assertChanges(1); |
| assertTrue(bot.dom.isSelected(elem)); |
| } |
| |
| assertCanSelectWhenDefaultPrevented(singleSelect.options[1]); |
| assertCanSelectWhenDefaultPrevented(multiSelect.options[0]); |
| } |
| |
| var testClickCanSelectOptionWhenDefaultPrevented = |
| goog.partial(canSelectOptionWhenDefaultPrevented, bot.action.click); |
| |
| var testTapCanSelectOptionWhenDefaultPrevented = |
| goog.partial(canSelectOptionWhenDefaultPrevented, bot.action.tap); |
| |
| function cannotSelectCheckboxWhenDefaultPrevented(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| var elem = checkboxes[0]; |
| goog.events.listen(elem, 'click', function(e) { |
| e.preventDefault(); |
| }); |
| expectChanges(elem); |
| |
| action(elem); |
| |
| // WebKit and IE9 standards mode fire change events when the |
| // checkbox isn't toggled. |
| assertChanges( |
| goog.userAgent.WEBKIT || bot.userAgent.IE_DOC_9 ? 1 : 0); |
| assertFalse(bot.dom.isSelected(elem)); |
| } |
| |
| var testClickCannotSelectCheckboxWhenDefaultPrevented = |
| goog.partial(cannotSelectCheckboxWhenDefaultPrevented, |
| bot.action.click); |
| |
| var testTapCannotSelectCheckboxWhenDefaultPrevented = |
| goog.partial(cannotSelectCheckboxWhenDefaultPrevented, bot.action.tap); |
| |
| function maybeSelectRadioButtonWhenDefaultPrevented(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| var elem = radioButtons[0]; |
| goog.events.listen(elem, 'click', function(e) { |
| e.preventDefault(); |
| }); |
| expectChanges(elem); |
| |
| action(elem); |
| |
| // WebKit and Firefox < 11 select a radio button even when the handler |
| // prevents the default; IE and Opera do not. |
| if (goog.userAgent.WEBKIT || |
| (goog.userAgent.GECKO && !bot.userAgent.isEngineVersion(11))) { |
| // Gecko does toggle the radio button, but doesn't fire a change event. |
| assertChanges(goog.userAgent.GECKO ? 0 : 1); |
| assertTrue(bot.dom.isSelected(elem)); |
| } else { |
| // IE9 standards mode still fires the change event. |
| assertChanges(bot.userAgent.IE_DOC_9 ? 1 : 0); |
| assertFalse(bot.dom.isSelected(elem)); |
| } |
| } |
| |
| var testClickMaybeSelectRadioButtonWhenDefaultPrevented = |
| goog.partial(maybeSelectRadioButtonWhenDefaultPrevented, |
| bot.action.click); |
| |
| var testTapMaybeSelectRadioButtonWhenDefaultPrevented = |
| goog.partial(maybeSelectRadioButtonWhenDefaultPrevented, |
| bot.action.tap); |
| |
| /** @see http://code.google.com/p/selenium/issues/detail?id=1941 */ |
| function canSelectOptionFromTransparentSelect(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| var style = singleSelect.style; |
| style['opacity'] = '0'; |
| style['filter'] = 'alpha(opacity=0)'; |
| assertEquals(0, bot.dom.getOpacity(singleSelect)); |
| assertFalse(bot.dom.isSelected(singleSelect.options[1])); |
| expectChanges(singleSelect); |
| |
| bot.action.click(singleSelect.options[1]); |
| |
| assertChanges(1); |
| assertTrue(bot.dom.isSelected(singleSelect.options[1])); |
| style['opacity'] = ''; |
| style['filter'] = ''; |
| assertEquals(1, bot.dom.getOpacity(singleSelect)); |
| } |
| |
| var testClickCanSelectOptionFromTransparentSelect = |
| goog.partial(canSelectOptionFromTransparentSelect, bot.action.click); |
| |
| var testTapCanSelectOptionFromTransparentSelect = |
| goog.partial(canSelectOptionFromTransparentSelect, bot.action.tap); |
| |
| function noErrorAfterSelectWhenOnChangePreventsDefault(action) { |
| if (!checkActionCompatibility(action) || |
| (goog.userAgent.IE && !bot.userAgent.isProductVersion(7))) { |
| return; |
| } |
| goog.events.listen(radioButtons[1], 'change', function(e) { |
| e.preventDefault(); |
| }); |
| action(radioButtons[1]); |
| assertTrue(bot.dom.isSelected(radioButtons[1])); |
| |
| // In IE, this second click used to throw an "Unspecified error". |
| action(radioButtons[2]); |
| } |
| |
| var testClickNoErrorAfterSelectWhenOnChangePreventsDefault = |
| goog.partial(noErrorAfterSelectWhenOnChangePreventsDefault, |
| bot.action.click); |
| |
| var testTapNoErrorAfterSelectWhenOnChangePreventsDefault = |
| goog.partial(noErrorAfterSelectWhenOnChangePreventsDefault, |
| bot.action.tap); |
| |
| function selectOptionTriggersJQueryChangeHandler(action) { |
| if (!checkActionCompatibility(action)) { |
| return; |
| } |
| var changes = 0; |
| $('#singleSelect').change(function() { |
| changes++; |
| }); |
| |
| action(singleSelect.options[1]); |
| |
| assertEquals(1, changes); |
| $('#singleSelect').unbind(); |
| } |
| |
| var testClickSelectOptionTriggersJQueryChangeHandler = |
| goog.partial(selectOptionTriggersJQueryChangeHandler, bot.action.click); |
| |
| var testTapSelectOptionTriggersJQueryChangeHandler = |
| goog.partial(selectOptionTriggersJQueryChangeHandler, bot.action.tap); |
| |
| </script> |
| </head> |
| <body> |
| <form action="#" method="get"> |
| <select id="singleSelect"> |
| <option id="singleOption1" value="foo">foo</option> |
| <option id="singleOption2" value="bar">bar</option> |
| <option id="singleOption3" value="baz">baz</option> |
| </select> |
| <br> |
| <select id="multiSelect" multiple> |
| <option id="multiOption1" value="apples">apples</option> |
| <option id="multiOption2" value="oranges">oranges</option> |
| <option id="multiOption3" value="cherries">cherries</option> |
| </select> |
| <br> |
| <input type="checkbox" name="checkbox" value="peas">peas |
| <input type="checkbox" name="checkbox" value="spinach">spinach |
| <input type="checkbox" name="checkbox" value="broccoli">broccoli |
| <br> |
| <input type="radio" name="radio" value="cheese">cheese |
| <input type="radio" name="radio" value="water">water |
| <input type="radio" name="radio" value="bread">bread |
| </form> |
| </body> |
| </html> |