Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<title>HTMLSelectListElement 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>
<selectlist id="selectList0">
<div slot="button" behavior="button">
<span behavior="selected-value"></span>
<button id="selectList0-button">selectList0-button</button>
</div>
<option>one</option>
<option>two</option>
<option>three</option>
</selectlist>
<selectlist id="selectList1">
<option>one</option>
<option>
two
<button id="selectList1-button">selectList1-button</button>
</option>
<option>three</option>
</selectlist>
<selectlist id="selectList2">
<option>one</option>
<option>two</option>
<option>three</option>
</selectlist>
<selectlist id="selectList3">
<option>same</option>
<option>same</option>
</selectlist>
<selectlist id="selectList4">
<option>one</option>
<option id="selectList4-option2">two</option>
</selectlist>
<selectlist id="selectList5WithTabIndex" tabindex="1">
<option>one</option>
<option>two</option>
</selectlist>
<input id="input6"/>
<selectlist id="selectList7">
<button slot="button" behavior="button" id="selectList7-button">
selectList7-button
</button>
<option>one</option>
<option>two</option>
</selectlist>
<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 selectList = document.getElementById("selectList0");
const selectListButton = document.getElementById("selectList0-button");
assert_false(selectList.open);
const selectListButtonPromise = new Promise(async resolve => {
selectListButton.addEventListener("click", (e) => {
assert_false(selectList.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 selectListPromise = new Promise(async resolve => {
selectList.addEventListener("click", (e) => {
assert_true(e.defaultPrevented, "Event should have been defaultPrevented by selectListButton click handler");
assert_false(selectList.open, "Listbox shouldn't have opened, because click event was defaultPrevented.");
resolve();
});
});
await clickOn(selectListButton);
return Promise.all([selectListButtonPromise, selectListPromise]);
}, "Button controller code should not run if the click event is preventDefaulted.");
const KEY_CODE_MAP = {
'Tab': '\uE004',
'Enter': '\uE007',
'Space': '\uE00D',
'ArrowUp': '\uE013',
'ArrowDown': '\uE015',
};
promise_test(async () => {
const selectList = document.getElementById("selectList1");
const selectListButton = document.getElementById("selectList1-button");
await clickOn(selectList);
assert_true(selectList.open);
const selectListButtonPromise = new Promise(async resolve => {
selectListButton.addEventListener("click", (e) => {
assert_true(selectList.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 selectListPromise = new Promise(async resolve => {
selectList.addEventListener("click", (e) => {
assert_true(e.defaultPrevented, "Event should have been defaultPrevented by selectListButton click handler");
assert_true(selectList.open, "Listbox shouldn't have closed, because keydown event was defaultPrevented.");
assert_equals(selectList.value, "one", "<selectlist> shouldn't have changed value, because keydown event was defaultPrevented.");
resolve();
});
});
await clickOn(selectListButton);
return Promise.all([selectListButtonPromise, selectListPromise]);
}, "Listbox controller code should not run if the click event is preventDefaulted.");
promise_test(async () => {
const selectList = document.getElementById("selectList2");
const events = [];
selectList.addEventListener("input", (e) => {
assert_true(e.composed, "input event should be composed.");
events.push('input');
});
selectList.addEventListener("change", (e) => {
assert_false(e.composed, "change event should not be composed.");
events.push('change');
});
await clickOn(selectList);
assert_true(selectList.open);
await test_driver.send_keys(selectList, KEY_CODE_MAP.Enter);
assert_false(selectList.open);
assert_equals(selectList.value, "one");
assert_array_equals(events, [], "input and change shouldn't fire if value wansn't changed.");
await clickOn(selectList);
assert_true(selectList.open);
await test_driver.send_keys(selectList, KEY_CODE_MAP.ArrowDown);
assert_equals(selectList.value, "one", "value shouldn't change when user switches options with arrow key.");
assert_array_equals(events, ['input'], "input event should fire when user switches options with arrow key.");
await test_driver.send_keys(selectList, KEY_CODE_MAP.Enter);
assert_equals(selectList.value, "two");
assert_array_equals(events, ['input', 'input', 'change'], "input and change should fire after pressing enter.");
}, "<selectlist> should fire input and change events when new option is selected.");
promise_test(async () => {
const selectList = document.getElementById("selectList3");
const events = [];
selectList.addEventListener("input", (e) => {
assert_true(e.composed, "input event should be composed.");
events.push('input');
});
selectList.addEventListener("change", (e) => {
assert_false(e.composed, "change event should not be composed.");
events.push('change');
});
await clickOn(selectList);
assert_true(selectList.open);
await test_driver.send_keys(selectList, KEY_CODE_MAP.ArrowDown);
assert_array_equals(events, ['input'], "input event should have fired after ArrowDown.");
await test_driver.send_keys(selectList, KEY_CODE_MAP.Enter);
assert_array_equals(events, ['input', 'input', 'change'], "input and change should fire after pressing Enter.");
}, "<selectlist> should fire input and change events even when new selected option has the same value as the old.");
promise_test(async () => {
const selectList = document.getElementById("selectList4");
const selectListOption2 = document.getElementById("selectList4-option2");
let input_event_count = 0;
let change_event_count = 0;
selectList.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++;
});
selectList.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(selectList);
assert_true(selectList.open);
await clickOn(selectListOption2);
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");
}, "<selectlist> should fire input and change events when option in listbox is clicked");
promise_test(async() => {
const selectList = document.getElementById("selectList2");
await test_driver.send_keys(selectList, " ");
assert_true(selectList.open, "<Space> should open selectlist");
await test_driver.send_keys(selectList, KEY_CODE_MAP.Enter);
assert_false(selectList.open, "<Enter> should close selectlist");
}, "Check that <Space> opens <selectlist>.");
promise_test(async() => {
const selectList = document.getElementById("selectList5WithTabIndex");
await test_driver.send_keys(selectList, " ");
assert_true(selectList.open, "<Space> should open selectlist");
await test_driver.send_keys(selectList, KEY_CODE_MAP.Enter);
assert_false(selectList.open, "<Enter> should close selectlist");
}, "Check that <Space> opens <selectlist> when <selectlist> specifies tabindex");
promise_test(async() => {
const input6 = document.getElementById("input6");
const selectList = document.getElementById("selectList7");
const selectListButton = document.getElementById("selectList7-button")
var keydown_count = 0;
selectListButton.addEventListener("keydown", (e) => {
keydown_count++;
});
// Focus selectlist via Tab traversal because focus() does not work when selectlist
// 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(selectList, "a");
assert_equals(keydown_count, 1, "button in shadowroot should have observed keydown");
}, "Test that <selectlist> button slot receives key events.");
</script>