1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
|
<!DOCTYPE html>
<title>HTMLSelectMenuElement Test: events</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<selectmenu id="selectMenu0">
<div slot="button" behavior="button">
<span behavior="selected-value"></span>
<button id="selectMenu0-button">selectMenu0-button</button>
</div>
<option>one</option>
<option>two</option>
<option>three</option>
</selectmenu>
<selectmenu id="selectMenu1">
<option>one</option>
<option>
two
<button id="selectMenu1-button">selectMenu1-button</button>
</option>
<option>three</option>
</selectmenu>
<selectmenu id="selectMenu2">
<option>one</option>
<option>two</option>
<option>three</option>
</selectmenu>
<selectmenu id="selectMenu3">
<option>same</option>
<option>same</option>
</selectmenu>
<selectmenu id="selectMenu4">
<option>one</option>
<option id="selectMenu4-option2">two</option>
</selectmenu>
<selectmenu id="selectMenu5WithTabIndex" tabindex="1">
<option>one</option>
<option>two</option>
</selectmenu>
<input id="input6"/>
<selectmenu id="selectMenu7">
<button slot="button" behavior="button" id="selectMenu7-button">
selectMenu7-button
</button>
<option>one</option>
<option>two</option>
</selectmenu>
<script>
function clickOn(element) {
const actions = new test_driver.Actions();
return actions.pointerMove(0, 0, {origin: element})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
}
promise_test(async () => {
const selectMenu = document.getElementById("selectMenu0");
const selectMenuButton = document.getElementById("selectMenu0-button");
assert_false(selectMenu.open);
const selectMenuButtonPromise = new Promise(async resolve => {
selectMenuButton.addEventListener("click", (e) => {
assert_false(selectMenu.open, "Listbox shouldn't have opened yet");
// PreventDefaulting the event here should prevent UA controller code
// on the button part from opening the listbox.
e.preventDefault();
resolve();
});
});
const selectMenuPromise = new Promise(async resolve => {
selectMenu.addEventListener("click", (e) => {
assert_true(e.defaultPrevented, "Event should have been defaultPrevented by selectMenuButton click handler");
assert_false(selectMenu.open, "Listbox shouldn't have opened, because click event was defaultPrevented.");
resolve();
});
});
await clickOn(selectMenuButton);
return Promise.all([selectMenuButtonPromise, selectMenuPromise]);
}, "Button controller code should not run if the click event is preventDefaulted.");
// See https://w3c.github.io/webdriver/#keyboard-actions
const KEY_CODE_MAP = {
'Tab': '\uE004',
'Enter': '\uE007',
'Space': '\uE00D',
'ArrowUp': '\uE013',
'ArrowDown': '\uE015',
};
promise_test(async () => {
const selectMenu = document.getElementById("selectMenu1");
const selectMenuButton = document.getElementById("selectMenu1-button");
await clickOn(selectMenu);
assert_true(selectMenu.open);
const selectMenuButtonPromise = new Promise(async resolve => {
selectMenuButton.addEventListener("click", (e) => {
assert_true(selectMenu.open, "Listbox shouldn't have closed yet");
// PreventDefaulting the event here should prevent UA controller code
// on the listbox part from selecting the option and closing the listbox.
e.preventDefault();
resolve();
});
});
const selectMenuPromise = new Promise(async resolve => {
selectMenu.addEventListener("click", (e) => {
assert_true(e.defaultPrevented, "Event should have been defaultPrevented by selectMenuButton click handler");
assert_true(selectMenu.open, "Listbox shouldn't have closed, because keydown event was defaultPrevented.");
assert_equals(selectMenu.value, "one", "<selectmenu> shouldn't have changed value, because keydown event was defaultPrevented.");
resolve();
});
});
await clickOn(selectMenuButton);
return Promise.all([selectMenuButtonPromise, selectMenuPromise]);
}, "Listbox controller code should not run if the click event is preventDefaulted.");
promise_test(async () => {
const selectMenu = document.getElementById("selectMenu2");
let input_event_count = 0;
let change_event_count = 0;
selectMenu.addEventListener("input", (e) => {
assert_true(e.composed, "input event should be composed");
assert_equals(input_event_count, 0, "input event should not fire twice");
assert_equals(change_event_count, 0, "input event should not fire before change");
input_event_count++;
});
selectMenu.addEventListener("change", (e) => {
assert_false(e.composed, "change event should not be composed");
assert_equals(input_event_count, 1, "change event should fire after input");
assert_equals(change_event_count, 0, "change event should not fire twice");
change_event_count++;
});
await clickOn(selectMenu);
assert_true(selectMenu.open);
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.Enter);
assert_false(selectMenu.open);
assert_equals(selectMenu.value, "one");
assert_equals(input_event_count, 0, "input event shouldn't fire if value wasn't changed");
assert_equals(change_event_count, 0, "change event shouldn't fire if value wasn't changed");
await clickOn(selectMenu);
assert_true(selectMenu.open);
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.ArrowDown);
assert_equals(selectMenu.value, "two", "value should change when user switches options with arrow key");
assert_equals(input_event_count, 1, "input event should fire when user switches options with arrow key");
assert_equals(change_event_count, 0, "change event shouldn't fire until popover is closed");
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.Enter);
assert_equals(selectMenu.value, "two");
assert_equals(input_event_count, 1, "input event should have fired");
assert_equals(change_event_count, 1, "change event should have fired");
}, "<selectmenu> should fire input and change events when new option is selected");
promise_test(async () => {
const selectMenu = document.getElementById("selectMenu3");
let input_event_count = 0;
let change_event_count = 0;
selectMenu.addEventListener("input", (e) => {
assert_true(e.composed, "input event should be composed");
assert_equals(input_event_count, 0, "input event should not fire twice");
assert_equals(change_event_count, 0, "input event should not fire before change");
input_event_count++;
});
selectMenu.addEventListener("change", (e) => {
assert_false(e.composed, "change event should not be composed");
assert_equals(input_event_count, 1, "change event should fire after input");
assert_equals(change_event_count, 0, "change event should not fire twice");
change_event_count++;
});
await clickOn(selectMenu);
assert_true(selectMenu.open);
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.ArrowDown);
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.Enter);
assert_equals(input_event_count, 1, "input event should have fired");
assert_equals(change_event_count, 1, "change event should have fired");
}, "<selectmenu> should fire input and change events even when new selected option has the same value as the old");
promise_test(async () => {
const selectMenu = document.getElementById("selectMenu4");
const selectMenuOption2 = document.getElementById("selectMenu4-option2");
let input_event_count = 0;
let change_event_count = 0;
selectMenu.addEventListener("input", (e) => {
assert_true(e.composed, "input event should be composed");
assert_equals(input_event_count, 0, "input event should not fire twice");
assert_equals(change_event_count, 0, "input event should not fire before change");
input_event_count++;
});
selectMenu.addEventListener("change", (e) => {
assert_false(e.composed, "change event should not be composed");
assert_equals(input_event_count, 1, "change event should fire after input");
assert_equals(change_event_count, 0, "change event should not fire twice");
change_event_count++;
});
await clickOn(selectMenu);
assert_true(selectMenu.open);
await clickOn(selectMenuOption2);
assert_equals(input_event_count, 1, "input event shouldn't fire when selected option didn't change");
assert_equals(change_event_count, 1, "change event shouldn't fire when selected option didn't change");
}, "<selectmenu> should fire input and change events when option in listbox is clicked");
promise_test(async() => {
const selectMenu = document.getElementById("selectMenu2");
await test_driver.send_keys(selectMenu, " ");
assert_true(selectMenu.open, "<Space> should open selectmenu");
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.Enter);
assert_false(selectMenu.open, "<Enter> should close selectmenu");
}, "Check that <Space> opens <selectmenu>.");
promise_test(async() => {
const selectMenu = document.getElementById("selectMenu5WithTabIndex");
await test_driver.send_keys(selectMenu, " ");
assert_true(selectMenu.open, "<Space> should open selectmenu");
await test_driver.send_keys(selectMenu, KEY_CODE_MAP.Enter);
assert_false(selectMenu.open, "<Enter> should close selectmenu");
}, "Check that <Space> opens <selectmenu> when <selectmenu> specifies tabindex");
promise_test(async() => {
const input6 = document.getElementById("input6");
const selectMenu = document.getElementById("selectMenu7");
const selectMenuButton = document.getElementById("selectMenu7-button")
var keydown_count = 0;
selectMenuButton.addEventListener("keydown", (e) => {
keydown_count++;
});
// Focus selectmenu via Tab traversal because focus() does not work when selectmenu
// has custom slot.
// TODO(http://crbug.com/1440573) Fix this.
await test_driver.send_keys(input6, KEY_CODE_MAP.Tab);
await test_driver.send_keys(selectMenu, "a");
assert_equals(keydown_count, 1, "button in shadowroot should have observed keydown");
}, "Test that <selectmenu> button slot receives key events.");
</script>
|