Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<link rel=author href="mailto:masonf@chromium.org">
<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>
<div class=wrapper data-description="implicit button">
<select class=select>
<option class=option1>one</option>
<option class=option2>two</option>
<option class=option3>three</option>
</select>
</div>
<div class=wrapper data-description="explicit button">
<select class=select>
<button>Click</button>
<option class=option1>one</option>
<option class=option2>two</option>
<option class=option3>three</option>
</select>
</div>
<style>
select,::picker(select) {
appearance: base-select;
}
</style>
<script>
const events = ['click','keydown','keyup','mousedown','mouseup','pointerdown','pointerup',
'focusin','focusout','input','change','beforetoggle','toggle'];
const keys = {Enter:'\uE007',Escape:'\uE00C',ArrowLeft:'\uE012',ArrowUp:'\uE013',ArrowRight:'\uE014',ArrowDown:'\uE015',Space:' ',Tab:'\uE004',Shift:'\uE008'};
document.querySelectorAll('.wrapper').forEach(wrapper => {
const select = wrapper.querySelector('select');
const option1 = wrapper.querySelector('.option1');
const option2 = wrapper.querySelector('.option2');
const option3 = wrapper.querySelector('.option3');
promise_test(async (t) => {
assert_false(select.matches(':open'),'select should be closed at the start of the test');
let eventList = [];
function assert_events(expectedEvents,message) {
message = message || "Mismatch";
assert_array_equals(eventList,expectedEvents,message);
eventList = [];
}
function getEventHandler(description) {
return (e) => {
let focused = '';
if (e.type == 'keydown' || e.type == 'keyup') {
focused = ` focused: ${document.activeElement.className || document.activeElement.tagName}.`;
}
eventList.push(`${e.type} on ${e.target.className} at ${description}. open: ${select.matches(':open')}.${focused}`);
};
}
events.forEach(evt => wrapper.addEventListener(evt,getEventHandler('wrapper')));
events.forEach(evt => select.addEventListener(evt,getEventHandler('select')));
assert_events([]);
// Open the picker by clicking on it, which will focus the currently selected option.
await test_driver.click(select);
assert_true(select.matches(':open'));
assert_events([
'pointerdown on select at select. open: false.',
'pointerdown on select at wrapper. open: false.',
'mousedown on select at select. open: false.',
'mousedown on select at wrapper. open: false.',
'focusin on option1 at select. open: true.',
'focusin on option1 at wrapper. open: true.',
'pointerup on select at select. open: true.',
'pointerup on select at wrapper. open: true.',
'mouseup on select at select. open: true.',
'mouseup on select at wrapper. open: true.',
'click on select at select. open: true.',
'click on select at wrapper. open: true.'
],'after showing, events from test_driver.click');
// Press arrow-down, and preventDefault
wrapper.addEventListener('keydown',(e) => e.preventDefault(),{once:true});
await test_driver.send_keys(document.activeElement, keys.ArrowDown);
assert_equals(select.selectedOptions[0].innerText,'one');
assert_events([
'keydown on option1 at select. open: true. focused: option1.',
'keydown on option1 at wrapper. open: true. focused: option1.',
'keyup on option1 at select. open: true. focused: option1.',
'keyup on option1 at wrapper. open: true. focused: option1.'
],'arrow down, with preventDefault');
// Press arrow-down, no preventDefault
await test_driver.send_keys(document.activeElement, keys.ArrowDown);
assert_equals(select.selectedOptions[0].innerText,'one','selection does not follow focus');
assert_events([
'keydown on option1 at select. open: true. focused: option1.',
'keydown on option1 at wrapper. open: true. focused: option1.',
'focusout on option1 at select. open: true.',
'focusout on option1 at wrapper. open: true.',
'focusin on option2 at select. open: true.',
'focusin on option2 at wrapper. open: true.',
'keyup on option2 at select. open: true. focused: option2.',
'keyup on option2 at wrapper. open: true. focused: option2.'
],'arrow down, no preventDefault');
// Press escape, and preventDefault
wrapper.addEventListener('keydown',(e) => e.preventDefault(),{once:true});
await test_driver.send_keys(document.activeElement, keys.Escape);
assert_true(select.matches(':open'));
assert_events([
'keydown on option2 at select. open: true. focused: option2.',
'keydown on option2 at wrapper. open: true. focused: option2.',
'keyup on option2 at select. open: true. focused: option2.',
'keyup on option2 at wrapper. open: true. focused: option2.'
],'escape, with preventDefault');
// Press escape, no preventDefault
await test_driver.send_keys(document.activeElement, keys.Escape);
assert_false(select.matches(':open'),'select should be closed escape no preventDefault');
assert_events([
'keydown on option2 at select. open: true. focused: option2.',
'keydown on option2 at wrapper. open: true. focused: option2.',
'focusout on option2 at select. open: false.',
'focusout on option2 at wrapper. open: false.',
'focusin on select at select. open: false.',
'focusin on select at wrapper. open: false.',
'keyup on select at select. open: false. focused: select.',
'keyup on select at wrapper. open: false. focused: select.'
],'escape, no preventDefault');
// Re-open the picker and hit arrow-down again.
await test_driver.click(select);
assert_true(select.matches(':open'));
assert_equals(select.value,'one');
await test_driver.send_keys(document.activeElement, keys.ArrowDown);
assert_equals(select.value,'one','selection does not follow focus');
eventList = [];
// Press enter to select an option, with preventDefault
wrapper.addEventListener('keydown',(e) => e.preventDefault(),{once:true});
await test_driver.send_keys(document.activeElement, keys.Enter);
assert_true(select.matches(':open'));
assert_equals(select.value,'one','value has not changed');
assert_events([
'keydown on option2 at select. open: true. focused: option2.',
'keydown on option2 at wrapper. open: true. focused: option2.',
'keyup on option2 at select. open: true. focused: option2.',
'keyup on option2 at wrapper. open: true. focused: option2.'
],'enter, with preventDefault');
// Press enter to select an option, no preventDefault
await test_driver.send_keys(document.activeElement, keys.Enter);
assert_false(select.matches(':open'),'select should be closed enter no preventDefault');
assert_equals(select.value,'two');
assert_events([
'keydown on option2 at select. open: true. focused: option2.',
'keydown on option2 at wrapper. open: true. focused: option2.',
'input on select at select. open: true.',
'input on select at wrapper. open: true.',
'change on select at select. open: true.',
'change on select at wrapper. open: true.',
'focusout on option2 at select. open: false.',
'focusout on option2 at wrapper. open: false.',
'focusin on select at select. open: false.',
'focusin on select at wrapper. open: false.',
'keyup on select at select. open: false. focused: select.',
'keyup on select at wrapper. open: false. focused: select.'
],'enter, no preventDefault');
// Re-open the picker.
await test_driver.click(select);
assert_true(select.matches(':open'));
eventList = [];
// Click on an option, with preventDefault
wrapper.addEventListener('mouseup',(e) => e.preventDefault(),{once:true});
assert_equals(select.selectedOptions[0].innerText,'two');
await (new test_driver.Actions()
.pointerMove(1, 1, {origin: option1})
.pointerDown()
.pointerUp())
.send();
assert_true(select.matches(':open'),'click should be cancelled');
assert_events([
'pointerdown on option1 at select. open: true.',
'pointerdown on option1 at wrapper. open: true.',
'mousedown on option1 at select. open: true.',
'mousedown on option1 at wrapper. open: true.',
'focusout on option2 at select. open: true.',
'focusout on option2 at wrapper. open: true.',
'focusin on option1 at select. open: true.',
'focusin on option1 at wrapper. open: true.',
'pointerup on option1 at select. open: true.',
'pointerup on option1 at wrapper. open: true.',
'mouseup on option1 at select. open: true.',
'mouseup on option1 at wrapper. open: true.',
'click on option1 at select. open: true.',
'click on option1 at wrapper. open: true.'
],'click option, with preventDefault');
// Click on an option, no preventDefault
assert_equals(select.selectedOptions[0].innerText,'two');
await (new test_driver.Actions()
.pointerMove(1, 1, {origin: option1})
.pointerDown()
.pointerUp())
.send();
assert_false(select.matches(':open'),'select should be closed click option no preventDefault');
assert_events([
'pointerdown on option1 at select. open: true.',
'pointerdown on option1 at wrapper. open: true.',
'mousedown on option1 at select. open: true.',
'mousedown on option1 at wrapper. open: true.',
'pointerup on option1 at select. open: true.',
'pointerup on option1 at wrapper. open: true.',
'mouseup on option1 at select. open: true.',
'mouseup on option1 at wrapper. open: true.',
'input on select at select. open: true.',
'input on select at wrapper. open: true.',
'change on select at select. open: true.',
'change on select at wrapper. open: true.',
'focusout on option1 at select. open: false.',
'focusout on option1 at wrapper. open: false.',
'focusin on select at select. open: false.',
'focusin on select at wrapper. open: false.',
'click on option1 at select. open: false.',
'click on option1 at wrapper. open: false.'
],'click option, no preventDefault');
},`Events, ${wrapper.dataset.description}`);
});
</script>