select-events.optional.html (11124B)
1 <!DOCTYPE html> 2 <link rel=author href="mailto:masonf@chromium.org"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/resources/testdriver.js"></script> 6 <script src="/resources/testdriver-actions.js"></script> 7 <script src="/resources/testdriver-vendor.js"></script> 8 9 <!-- This test is optional because the HTML spec does not require that specific 10 behaviors are mapped to specific keyboard buttons. --> 11 12 <div class=wrapper data-description="implicit button"> 13 <select class=select> 14 <option class=option1>one</option> 15 <option class=option2>two</option> 16 <option class=option3>three</option> 17 </select> 18 </div> 19 20 <div class=wrapper data-description="explicit button"> 21 <select class=select> 22 <button>Click</button> 23 <option class=option1>one</option> 24 <option class=option2>two</option> 25 <option class=option3>three</option> 26 </select> 27 </div> 28 29 <style> 30 select,::picker(select) { 31 appearance: base-select; 32 } 33 </style> 34 35 <script> 36 const events = ['click','keydown','keyup','mousedown','mouseup','pointerdown','pointerup', 37 'focusin','focusout','input','change','beforetoggle','toggle']; 38 const keys = {Enter:'\uE007',Escape:'\uE00C',ArrowLeft:'\uE012',ArrowUp:'\uE013',ArrowRight:'\uE014',ArrowDown:'\uE015',Space:' ',Tab:'\uE004',Shift:'\uE008'}; 39 40 document.querySelectorAll('.wrapper').forEach(wrapper => { 41 const select = wrapper.querySelector('select'); 42 const option1 = wrapper.querySelector('.option1'); 43 const option2 = wrapper.querySelector('.option2'); 44 const option3 = wrapper.querySelector('.option3'); 45 promise_test(async (t) => { 46 assert_false(select.matches(':open'),'select should be closed at the start of the test'); 47 let eventList = []; 48 function assert_events(expectedEvents,message) { 49 message = message || "Mismatch"; 50 assert_array_equals(eventList,expectedEvents,message); 51 eventList = []; 52 } 53 function getEventHandler(description) { 54 return (e) => { 55 let focused = ''; 56 if (e.type == 'keydown' || e.type == 'keyup') { 57 focused = ` focused: ${document.activeElement.className || document.activeElement.tagName}.`; 58 } 59 eventList.push(`${e.type} on ${e.target.className} at ${description}. open: ${select.matches(':open')}.${focused}`); 60 }; 61 } 62 events.forEach(evt => wrapper.addEventListener(evt,getEventHandler('wrapper'))); 63 events.forEach(evt => select.addEventListener(evt,getEventHandler('select'))); 64 assert_events([]); 65 66 // Open the picker by clicking on it, which will focus the currently selected option. 67 await test_driver.click(select); 68 assert_true(select.matches(':open')); 69 assert_events([ 70 'pointerdown on select at select. open: false.', 71 'pointerdown on select at wrapper. open: false.', 72 'mousedown on select at select. open: false.', 73 'mousedown on select at wrapper. open: false.', 74 'focusin on option1 at select. open: true.', 75 'focusin on option1 at wrapper. open: true.', 76 'pointerup on select at select. open: true.', 77 'pointerup on select at wrapper. open: true.', 78 'mouseup on select at select. open: true.', 79 'mouseup on select at wrapper. open: true.', 80 'click on select at select. open: true.', 81 'click on select at wrapper. open: true.' 82 ],'after showing, events from test_driver.click'); 83 84 // Press arrow-down, and preventDefault 85 wrapper.addEventListener('keydown',(e) => e.preventDefault(),{once:true}); 86 await test_driver.send_keys(document.activeElement, keys.ArrowDown); 87 assert_equals(select.selectedOptions[0].innerText,'one'); 88 assert_events([ 89 'keydown on option1 at select. open: true. focused: option1.', 90 'keydown on option1 at wrapper. open: true. focused: option1.', 91 'keyup on option1 at select. open: true. focused: option1.', 92 'keyup on option1 at wrapper. open: true. focused: option1.' 93 ],'arrow down, with preventDefault'); 94 95 // Press arrow-down, no preventDefault 96 await test_driver.send_keys(document.activeElement, keys.ArrowDown); 97 assert_equals(select.selectedOptions[0].innerText,'one','selection does not follow focus'); 98 assert_events([ 99 'keydown on option1 at select. open: true. focused: option1.', 100 'keydown on option1 at wrapper. open: true. focused: option1.', 101 'focusout on option1 at select. open: true.', 102 'focusout on option1 at wrapper. open: true.', 103 'focusin on option2 at select. open: true.', 104 'focusin on option2 at wrapper. open: true.', 105 'keyup on option2 at select. open: true. focused: option2.', 106 'keyup on option2 at wrapper. open: true. focused: option2.' 107 ],'arrow down, no preventDefault'); 108 109 // Press escape, and preventDefault 110 wrapper.addEventListener('keydown',(e) => e.preventDefault(),{once:true}); 111 await test_driver.send_keys(document.activeElement, keys.Escape); 112 assert_true(select.matches(':open')); 113 assert_events([ 114 'keydown on option2 at select. open: true. focused: option2.', 115 'keydown on option2 at wrapper. open: true. focused: option2.', 116 'keyup on option2 at select. open: true. focused: option2.', 117 'keyup on option2 at wrapper. open: true. focused: option2.' 118 ],'escape, with preventDefault'); 119 120 // Press escape, no preventDefault 121 await test_driver.send_keys(document.activeElement, keys.Escape); 122 assert_false(select.matches(':open'),'select should be closed escape no preventDefault'); 123 assert_events([ 124 'keydown on option2 at select. open: true. focused: option2.', 125 'keydown on option2 at wrapper. open: true. focused: option2.', 126 'focusout on option2 at select. open: false.', 127 'focusout on option2 at wrapper. open: false.', 128 'focusin on select at select. open: false.', 129 'focusin on select at wrapper. open: false.', 130 'keyup on select at select. open: false. focused: select.', 131 'keyup on select at wrapper. open: false. focused: select.' 132 ],'escape, no preventDefault'); 133 134 // Re-open the picker and hit arrow-down again. 135 await test_driver.click(select); 136 assert_true(select.matches(':open')); 137 assert_equals(select.value,'one'); 138 await test_driver.send_keys(document.activeElement, keys.ArrowDown); 139 assert_equals(select.value,'one','selection does not follow focus'); 140 eventList = []; 141 142 // Press enter to select an option, with preventDefault 143 wrapper.addEventListener('keydown',(e) => e.preventDefault(),{once:true}); 144 await test_driver.send_keys(document.activeElement, keys.Enter); 145 assert_true(select.matches(':open')); 146 assert_equals(select.value,'one','value has not changed'); 147 assert_events([ 148 'keydown on option2 at select. open: true. focused: option2.', 149 'keydown on option2 at wrapper. open: true. focused: option2.', 150 'keyup on option2 at select. open: true. focused: option2.', 151 'keyup on option2 at wrapper. open: true. focused: option2.' 152 ],'enter, with preventDefault'); 153 154 // Press enter to select an option, no preventDefault 155 await test_driver.send_keys(document.activeElement, keys.Enter); 156 assert_false(select.matches(':open'),'select should be closed enter no preventDefault'); 157 assert_equals(select.value,'two'); 158 assert_events([ 159 'keydown on option2 at select. open: true. focused: option2.', 160 'keydown on option2 at wrapper. open: true. focused: option2.', 161 'input on select at select. open: true.', 162 'input on select at wrapper. open: true.', 163 'change on select at select. open: true.', 164 'change on select at wrapper. open: true.', 165 'focusout on option2 at select. open: false.', 166 'focusout on option2 at wrapper. open: false.', 167 'focusin on select at select. open: false.', 168 'focusin on select at wrapper. open: false.', 169 'keyup on select at select. open: false. focused: select.', 170 'keyup on select at wrapper. open: false. focused: select.' 171 ],'enter, no preventDefault'); 172 173 // Re-open the picker. 174 await test_driver.click(select); 175 assert_true(select.matches(':open')); 176 eventList = []; 177 178 // Click on an option, with preventDefault 179 wrapper.addEventListener('mouseup',(e) => e.preventDefault(),{once:true}); 180 assert_equals(select.selectedOptions[0].innerText,'two'); 181 await (new test_driver.Actions() 182 .pointerMove(1, 1, {origin: option1}) 183 .pointerDown() 184 .pointerUp()) 185 .send(); 186 assert_true(select.matches(':open'),'click should be cancelled'); 187 assert_events([ 188 'pointerdown on option1 at select. open: true.', 189 'pointerdown on option1 at wrapper. open: true.', 190 'mousedown on option1 at select. open: true.', 191 'mousedown on option1 at wrapper. open: true.', 192 'focusout on option2 at select. open: true.', 193 'focusout on option2 at wrapper. open: true.', 194 'focusin on option1 at select. open: true.', 195 'focusin on option1 at wrapper. open: true.', 196 'pointerup on option1 at select. open: true.', 197 'pointerup on option1 at wrapper. open: true.', 198 'mouseup on option1 at select. open: true.', 199 'mouseup on option1 at wrapper. open: true.', 200 'click on option1 at select. open: true.', 201 'click on option1 at wrapper. open: true.' 202 ],'click option, with preventDefault'); 203 204 // Click on an option, no preventDefault 205 assert_equals(select.selectedOptions[0].innerText,'two'); 206 await (new test_driver.Actions() 207 .pointerMove(1, 1, {origin: option1}) 208 .pointerDown() 209 .pointerUp()) 210 .send(); 211 assert_false(select.matches(':open'),'select should be closed click option no preventDefault'); 212 assert_events([ 213 'pointerdown on option1 at select. open: true.', 214 'pointerdown on option1 at wrapper. open: true.', 215 'mousedown on option1 at select. open: true.', 216 'mousedown on option1 at wrapper. open: true.', 217 'pointerup on option1 at select. open: true.', 218 'pointerup on option1 at wrapper. open: true.', 219 'mouseup on option1 at select. open: true.', 220 'mouseup on option1 at wrapper. open: true.', 221 'input on select at select. open: true.', 222 'input on select at wrapper. open: true.', 223 'change on select at select. open: true.', 224 'change on select at wrapper. open: true.', 225 'focusout on option1 at select. open: false.', 226 'focusout on option1 at wrapper. open: false.', 227 'focusin on select at select. open: false.', 228 'focusin on select at wrapper. open: false.', 229 'click on option1 at select. open: false.', 230 'click on option1 at wrapper. open: false.' 231 ],'click option, no preventDefault'); 232 },`Events, ${wrapper.dataset.description}`); 233 }); 234 </script>