| <!DOCTYPE html> |
| <html> |
| |
| <head> |
| <meta http-equiv="Expire" content="0" /> |
| <meta charset="utf-8"> |
| <title>select_test.html</title> |
| <link rel="stylesheet" href="/filez/_main/third_party/js/qunit/qunit.css"> |
| <script src="/filez/_main/third_party/js/qunit/qunit.js"></script> |
| <script src="/filez/_main/third_party/js/qunit/qunit_test_runner.js"></script> |
| <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.events'); |
| goog.require('goog.userAgent'); |
| </script> |
| <script type="text/javascript"> |
| var singleSelect, multiSelect, radioButtons, checkboxes, changeCount; |
| var gotPointerCaptureCount, lostPointerCaptureCount; |
| |
| 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(assert, expectedCount) { |
| assert.strictEqual(changeCount, expectedCount, 'Unexpected number of changes'); |
| } |
| |
| function expectPointerCaptures(target) { |
| gotPointerCaptureCount = 0; |
| lostPointerCaptureCount = 0; |
| goog.events.listen(target, goog.events.EventType.MSGOTPOINTERCAPTURE, |
| function (e) { |
| gotPointerCaptureCount++; |
| }); |
| goog.events.listen(target, goog.events.EventType.MSLOSTPOINTERCAPTURE, |
| function (e) { |
| lostPointerCaptureCount++; |
| }); |
| } |
| |
| function assertPointerCaptures(assert, expectedCount) { |
| assert.strictEqual(gotPointerCaptureCount, expectedCount, 'Unexpected number of got captures'); |
| assert.strictEqual(lostPointerCaptureCount, expectedCount, 'Unexpected number of lost captures'); |
| } |
| |
| function firesChangeEventIfNotToggled() { |
| if (goog.userAgent.product.CHROME && bot.userAgent.isProductVersion(45)) { |
| return false; |
| } else if (goog.userAgent.WEBKIT || bot.userAgent.IE_DOC_9 || |
| goog.userAgent.EDGE) { |
| return true; |
| } |
| return false; |
| } |
| |
| QUnit.testStart(function() { |
| singleSelect = bot.locators.findElement({ id: 'singleSelect' }); |
| multiSelect = bot.locators.findElement({ id: 'multiSelect' }); |
| checkboxes = bot.locators.findElements({ name: 'checkbox' }); |
| radioButtons = bot.locators.findElements({ name: 'radio' }); |
| |
| goog.events.removeAll(singleSelect); |
| goog.events.removeAll(multiSelect); |
| for (var i = 0; i < checkboxes.length; ++i) { |
| goog.events.removeAll(checkboxes[i]); |
| } |
| for (var i = 0; i < radioButtons.length; ++i) { |
| goog.events.removeAll(radioButtons[i]); |
| } |
| 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 canSelectAnOptionFromASingleSelect(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| assert.notOk(bot.dom.isSelected(singleSelect.options[1])); |
| expectChanges(singleSelect); |
| if (bot.userAgent.IE_DOC_10) { |
| expectPointerCaptures(singleSelect); |
| } |
| action(singleSelect.options[1]); |
| |
| assertChanges(assert, 1); |
| if (bot.userAgent.IE_DOC_10) { |
| assertPointerCaptures(assert, 1); |
| } |
| assert.ok(bot.dom.isSelected(singleSelect.options[1])); |
| } |
| |
| QUnit.test('click can select an option from a single select', function(assert) { |
| canSelectAnOptionFromASingleSelect(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can select an option from a single select', function(assert) { |
| canSelectAnOptionFromASingleSelect(assert, bot.action.tap); |
| }); |
| |
| function cannotDeselectAnOptionFromASingleSelect(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| assert.ok(bot.dom.isSelected(singleSelect.options[0])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[0]); |
| |
| assertChanges(assert, 0); |
| assert.ok(bot.dom.isSelected(singleSelect.options[0])); |
| } |
| |
| QUnit.test('click cannot deselect an option from a single select', function(assert) { |
| cannotDeselectAnOptionFromASingleSelect(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap cannot deselect an option from a single select', function(assert) { |
| cannotDeselectAnOptionFromASingleSelect(assert, bot.action.tap); |
| }); |
| |
| function cannotSelectAnOptionFromADisabledSelect(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| singleSelect.disabled = true; |
| assert.notOk(bot.dom.isSelected(singleSelect.options[1])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[1]); |
| |
| assertChanges(assert, 0); |
| assert.notOk(bot.dom.isSelected(singleSelect.options[1])); |
| singleSelect.disabled = false; |
| } |
| |
| QUnit.test('click cannot select an option from a disabled select', function(assert) { |
| cannotSelectAnOptionFromADisabledSelect(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap cannot select an option from a disabled select', function(assert) { |
| cannotSelectAnOptionFromADisabledSelect(assert, bot.action.tap); |
| }); |
| |
| function canSelectAnEnabledOptionFromASelectWithADisabledOption(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| singleSelect.options[1].disabled = true; |
| assert.notOk(bot.dom.isSelected(singleSelect.options[2])); |
| expectChanges(singleSelect); |
| |
| action(singleSelect.options[2]); |
| |
| assertChanges(assert, 1); |
| assert.ok(bot.dom.isSelected(singleSelect.options[2])); |
| singleSelect.options[1].disabled = false; |
| } |
| |
| QUnit.test('click can select an enabled option from a select with a disabled option', function(assert) { |
| canSelectAnEnabledOptionFromASelectWithADisabledOption(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can select an enabled option from a select with a disabled option', function(assert) { |
| canSelectAnEnabledOptionFromASelectWithADisabledOption(assert, bot.action.tap); |
| }); |
| |
| function canToggleOptionsInAMultiSelect(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| multiSelect.options[0].selected = true; |
| expectChanges(multiSelect); |
| |
| action(multiSelect.options[0]); |
| action(multiSelect.options[1]); |
| action(multiSelect.options[2]); |
| |
| assertChanges(assert, 3); |
| assert.notOk(bot.dom.isSelected(multiSelect.options[0])); |
| assert.ok(bot.dom.isSelected(multiSelect.options[1])); |
| assert.ok(bot.dom.isSelected(multiSelect.options[2])); |
| } |
| |
| QUnit.test('click can toggle options in a multi select', function(assert) { |
| if (goog.userAgent.product.CHROME || goog.userAgent.product.SAFARI) { |
| assert.ok(true, 'Skipping: disabled due to Chrome/Safari issues'); |
| return; |
| } |
| canToggleOptionsInAMultiSelect(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can toggle options in a multi select', function(assert) { |
| if (goog.userAgent.product.CHROME || goog.userAgent.product.SAFARI) { |
| assert.ok(true, 'Skipping: disabled due to Chrome/Safari issues'); |
| return; |
| } |
| canToggleOptionsInAMultiSelect(assert, bot.action.tap); |
| }); |
| |
| function canToggleCheckboxes(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| checkboxes[0].checked = true; |
| expectChanges(checkboxes[0]); |
| action(checkboxes[0]); |
| assertChanges(assert, 1); |
| |
| if (!bot.userAgent.IE_DOC_PRE9) { |
| expectChanges(checkboxes[1]); |
| } |
| action(checkboxes[1]); |
| assertChanges(assert, 1); |
| |
| expectChanges(checkboxes[2]); |
| action(checkboxes[2]); |
| assertChanges(assert, 1); |
| |
| assert.notOk(bot.dom.isSelected(checkboxes[0])); |
| assert.ok(bot.dom.isSelected(checkboxes[1])); |
| assert.ok(bot.dom.isSelected(checkboxes[2])); |
| } |
| |
| QUnit.test('click can toggle checkboxes', function(assert) { |
| canToggleCheckboxes(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can toggle checkboxes', function(assert) { |
| canToggleCheckboxes(assert, bot.action.tap); |
| }); |
| |
| function canSelectRadioButtons(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| expectChanges(radioButtons[0]); |
| action(radioButtons[0]); |
| assertChanges(assert, 1); |
| |
| assert.ok(bot.dom.isSelected(radioButtons[0])); |
| |
| if (!bot.userAgent.IE_DOC_PRE9) { |
| expectChanges(radioButtons[1]); |
| } |
| action(radioButtons[1]); |
| assertChanges(assert, 1); |
| assert.ok(bot.dom.isSelected(radioButtons[1])); |
| |
| expectChanges(radioButtons[2]); |
| action(radioButtons[2]); |
| assertChanges(assert, 1); |
| assert.ok(bot.dom.isSelected(radioButtons[2])); |
| } |
| |
| QUnit.test('click can select radio buttons', function(assert) { |
| canSelectRadioButtons(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can select radio buttons', function(assert) { |
| canSelectRadioButtons(assert, bot.action.tap); |
| }); |
| |
| function cannotDeselectRadioButtons(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| radioButtons[0].checked = true; |
| expectChanges(radioButtons[0]); |
| |
| action(radioButtons[0]); |
| assertChanges(assert, 0); |
| assert.ok(bot.dom.isSelected(radioButtons[0])); |
| } |
| |
| QUnit.test('click cannot deselect radio buttons', function(assert) { |
| cannotDeselectRadioButtons(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap cannot deselect radio buttons', function(assert) { |
| cannotDeselectRadioButtons(assert, bot.action.tap); |
| }); |
| |
| function cannotSelectDisabledElements(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| function assertCannotSelectWhenDisabled(elem, isOption) { |
| elem.disabled = true; |
| expectChanges(isOption ? elem.parentNode : elem); |
| |
| action(elem); |
| |
| assertChanges(assert, 0); |
| assert.notOk(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); |
| } |
| |
| QUnit.test('click cannot select disabled elements', function(assert) { |
| cannotSelectDisabledElements(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap cannot select disabled elements', function(assert) { |
| cannotSelectDisabledElements(assert, bot.action.tap); |
| }); |
| |
| function canSelectOptionWhenDefaultPrevented(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| function assertCanSelectWhenDefaultPrevented(elem) { |
| goog.events.listen(elem, 'click', function (e) { |
| e.preventDefault(); |
| }); |
| expectChanges(elem.parentNode); |
| |
| action(elem); |
| |
| assertChanges(assert, 1); |
| assert.ok(bot.dom.isSelected(elem)); |
| } |
| |
| assertCanSelectWhenDefaultPrevented(singleSelect.options[1]); |
| assertCanSelectWhenDefaultPrevented(multiSelect.options[0]); |
| } |
| |
| QUnit.test('click can select option when default prevented', function(assert) { |
| if (goog.userAgent.product.SAFARI) { |
| assert.ok(true, 'Skipping: disabled on Safari'); |
| return; |
| } |
| canSelectOptionWhenDefaultPrevented(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can select option when default prevented', function(assert) { |
| if (goog.userAgent.product.CHROME || goog.userAgent.product.SAFARI) { |
| assert.ok(true, 'Skipping: disabled due to Chrome/Safari issues'); |
| return; |
| } |
| canSelectOptionWhenDefaultPrevented(assert, bot.action.tap); |
| }); |
| |
| function cannotSelectCheckboxWhenDefaultPrevented(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| var elem = checkboxes[0]; |
| goog.events.listen(elem, 'click', function (e) { |
| e.preventDefault(); |
| }); |
| expectChanges(elem); |
| |
| action(elem); |
| |
| assertChanges(assert, firesChangeEventIfNotToggled() ? 1 : 0); |
| assert.notOk(bot.dom.isSelected(elem)); |
| } |
| |
| QUnit.test('click cannot select checkbox when default prevented', function(assert) { |
| cannotSelectCheckboxWhenDefaultPrevented(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap cannot select checkbox when default prevented', function(assert) { |
| cannotSelectCheckboxWhenDefaultPrevented(assert, bot.action.tap); |
| }); |
| |
| function maybeSelectRadioButtonWhenDefaultPrevented(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| var elem = radioButtons[0]; |
| goog.events.listen(elem, 'click', function (e) { |
| e.preventDefault(); |
| }); |
| expectChanges(elem); |
| |
| action(elem); |
| |
| if ((goog.userAgent.product.CHROME && |
| !bot.userAgent.isProductVersion(39)) || |
| (goog.userAgent.WEBKIT && !goog.userAgent.product.CHROME)) { |
| assertChanges(assert, 1); |
| assert.ok(bot.dom.isSelected(elem)); |
| } else { |
| assertChanges(assert, firesChangeEventIfNotToggled() ? 1 : 0); |
| assert.notOk(bot.dom.isSelected(elem)); |
| } |
| } |
| |
| QUnit.test('click maybe select radio button when default prevented', function(assert) { |
| maybeSelectRadioButtonWhenDefaultPrevented(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap maybe select radio button when default prevented', function(assert) { |
| maybeSelectRadioButtonWhenDefaultPrevented(assert, bot.action.tap); |
| }); |
| |
| function canSelectOptionFromTransparentSelect(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| var style = singleSelect.style; |
| style['opacity'] = '0'; |
| style['filter'] = 'alpha(opacity=0)'; |
| assert.strictEqual(bot.dom.getOpacity(singleSelect), 0); |
| assert.notOk(bot.dom.isSelected(singleSelect.options[1])); |
| expectChanges(singleSelect); |
| |
| bot.action.click(singleSelect.options[1]); |
| |
| assertChanges(assert, 1); |
| assert.ok(bot.dom.isSelected(singleSelect.options[1])); |
| style['opacity'] = ''; |
| style['filter'] = ''; |
| assert.strictEqual(bot.dom.getOpacity(singleSelect), 1); |
| } |
| |
| QUnit.test('click can select option from transparent select', function(assert) { |
| canSelectOptionFromTransparentSelect(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap can select option from transparent select', function(assert) { |
| canSelectOptionFromTransparentSelect(assert, bot.action.tap); |
| }); |
| |
| function noErrorAfterSelectWhenOnChangePreventsDefault(assert, action) { |
| if (!checkActionCompatibility(action) || |
| (goog.userAgent.IE && !bot.userAgent.isProductVersion(7))) { |
| assert.ok(true, 'Skipping: not supported'); |
| return; |
| } |
| goog.events.listen(radioButtons[1], 'change', function (e) { |
| e.preventDefault(); |
| }); |
| action(radioButtons[1]); |
| assert.ok(bot.dom.isSelected(radioButtons[1])); |
| |
| action(radioButtons[2]); |
| assert.ok(true); |
| } |
| |
| QUnit.test('click no error after select when on change prevents default', function(assert) { |
| noErrorAfterSelectWhenOnChangePreventsDefault(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap no error after select when on change prevents default', function(assert) { |
| noErrorAfterSelectWhenOnChangePreventsDefault(assert, bot.action.tap); |
| }); |
| |
| function selectOptionTriggersJQueryChangeHandler(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| var changes = 0; |
| $('#singleSelect').change(function () { |
| changes++; |
| }); |
| |
| action(singleSelect.options[1]); |
| |
| assert.strictEqual(changes, 1); |
| $('#singleSelect').unbind(); |
| } |
| |
| QUnit.test('click select option triggers jQuery change handler', function(assert) { |
| selectOptionTriggersJQueryChangeHandler(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap select option triggers jQuery change handler', function(assert) { |
| selectOptionTriggersJQueryChangeHandler(assert, bot.action.tap); |
| }); |
| |
| function pointerCaptureFiresOnCheckboxToggle(assert, action) { |
| if (!bot.userAgent.IE_DOC_10) { |
| assert.ok(true, 'Skipping: only for IE10'); |
| return; |
| } |
| checkboxes[0].checked = true; |
| expectPointerCaptures(checkboxes[0]); |
| action(checkboxes[0]); |
| if (action == bot.action.tap) { |
| assertPointerCaptures(assert, 1); |
| } else { |
| assertPointerCaptures(assert, 0); |
| } |
| assert.notOk(bot.dom.isSelected(checkboxes[0])); |
| } |
| |
| QUnit.test('click pointer capture fires on checkbox toggle', function(assert) { |
| pointerCaptureFiresOnCheckboxToggle(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap pointer capture fires on checkbox toggle', function(assert) { |
| pointerCaptureFiresOnCheckboxToggle(assert, bot.action.tap); |
| }); |
| |
| function togglesByTheTimeChangeEventFires(assert, action) { |
| if (!checkActionCompatibility(action)) { |
| assert.ok(true, 'Action not supported, skipping'); |
| return; |
| } |
| |
| singleSelect.options[0].selected = true; |
| checkToggleAtChange(action, singleSelect, singleSelect.options[1]); |
| |
| multiSelect.options[0].selected = false; |
| checkToggleAtChange(action, multiSelect, multiSelect.options[0]); |
| |
| radioButtons[0].checked = false; |
| checkToggleAtChange(action, radioButtons[0], radioButtons[0]); |
| |
| checkboxes[0].checked = false; |
| checkToggleAtChange(action, checkboxes[0], checkboxes[0]); |
| |
| function checkToggleAtChange(action, targetElem, toggleElem) { |
| var preState = bot.dom.isSelected(toggleElem); |
| var postState = null; |
| goog.events.listen(targetElem, 'change', function (e) { |
| postState = bot.dom.isSelected(toggleElem); |
| }); |
| action(toggleElem); |
| assert.ok(postState !== null, 'change event did not fire'); |
| assert.notStrictEqual(postState, preState, 'element did not toggle'); |
| } |
| } |
| |
| QUnit.test('click toggles by the time change event fires', function(assert) { |
| if (goog.userAgent.product.SAFARI) { |
| assert.ok(true, 'Skipping: disabled on Safari'); |
| return; |
| } |
| togglesByTheTimeChangeEventFires(assert, bot.action.click); |
| }); |
| |
| QUnit.test('tap toggles by the time change event fires', function(assert) { |
| if (goog.userAgent.product.CHROME || goog.userAgent.product.SAFARI) { |
| assert.ok(true, 'Skipping: disabled due to Chrome/Safari issues'); |
| return; |
| } |
| togglesByTheTimeChangeEventFires(assert, bot.action.tap); |
| }); |
| </script> |
| </head> |
| |
| <body> |
| <div id="qunit"></div> |
| <div id="qunit-fixture"></div> |
| <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> |