View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.event;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.annotation.Alerts;
19  import org.htmlunit.junit.annotation.BuggyWebDriver;
20  import org.htmlunit.junit.annotation.HtmlUnitNYI;
21  import org.junit.jupiter.api.Test;
22  import org.openqa.selenium.By;
23  import org.openqa.selenium.Keys;
24  import org.openqa.selenium.WebDriver;
25  import org.openqa.selenium.WebElement;
26  
27  /**
28   * Tests for {@link KeyboardEvent}.
29   *
30   * @author Ahmed Ashour
31   * @author Marc Guillemot
32   * @author Frank Danek
33   * @author Ronald Brill
34   * @author Joerg Werner
35   */
36  public class KeyboardEventTest extends WebDriverTestCase {
37  
38      private static final String DUMP_EVENT_FUNCTION = "  function dump(event) {\n"
39              + "    log(event);\n"
40              + "    log(event.type);\n"
41              + "    log(event.bubbles);\n"
42              + "    log(event.cancelable);\n"
43              + "    log(event.composed);\n"
44  
45              + "    var details = [event.key, event.code, event.location, event.ctrlKey,\n"
46              + "                 event.shiftKey, event.altKey, event.metaKey, event.repeat, \n"
47              + "                 event.isComposing, event.charCode, event.which].join(',');\n"
48              + "    log(details);\n"
49              + "  }\n";
50  
51      /**
52       * @throws Exception if the test fails
53       */
54      @Test
55      @Alerts({"[object KeyboardEvent]", "type", "false", "false", "false",
56               ",,0,false,false,false,false,false,false,0,0"})
57      public void create_ctor() throws Exception {
58          final String html = DOCTYPE_HTML
59                  + "<html><head><script>\n"
60                  + LOG_TITLE_FUNCTION
61                  + "  function test() {\n"
62                  + "    try {\n"
63                  + "      var event = new KeyboardEvent('type');\n"
64                  + "      dump(event);\n"
65                  + "    } catch(e) { logEx(e) }\n"
66                  + "  }\n"
67                  + DUMP_EVENT_FUNCTION
68                  + "</script></head><body onload='test()'>\n"
69                  + "</body></html>";
70  
71          loadPageVerifyTitle2(html);
72      }
73  
74      /**
75       * @throws Exception if the test fails
76       */
77      @Test
78      @Alerts("TypeError")
79      @HtmlUnitNYI(CHROME = {"[object KeyboardEvent]", "undefined", "false", "false", "false",
80                             ",,0,false,false,false,false,false,false,0,0"},
81              EDGE = {"[object KeyboardEvent]", "undefined", "false", "false", "false",
82                      ",,0,false,false,false,false,false,false,0,0"},
83              FF = {"[object KeyboardEvent]", "undefined", "false", "false", "false",
84                    ",,0,false,false,false,false,false,false,0,0"},
85              FF_ESR = {"[object KeyboardEvent]", "undefined", "false", "false", "false",
86                        ",,0,false,false,false,false,false,false,0,0"})
87      public void create_ctorWithoutType() throws Exception {
88          final String html = DOCTYPE_HTML
89              + "<html><head><script>\n"
90              + LOG_TITLE_FUNCTION
91              + "  function test() {\n"
92              + "    try {\n"
93              + "      var event = new KeyboardEvent();\n"
94              + "      dump(event);\n"
95              + "    } catch(e) { logEx(e) }\n"
96              + "  }\n"
97              + DUMP_EVENT_FUNCTION
98              + "</script></head><body onload='test()'>\n"
99              + "</body></html>";
100 
101         loadPageVerifyTitle2(html);
102     }
103 
104     /**
105      * @throws Exception if the test fails
106      */
107     @Test
108     @Alerts({"[object KeyboardEvent]", "42", "false", "false", "false",
109              ",,0,false,false,false,false,false,false,0,0"})
110     public void create_ctorNumericType() throws Exception {
111         final String html = DOCTYPE_HTML
112             + "<html><head><script>\n"
113             + LOG_TITLE_FUNCTION
114             + "  function test() {\n"
115             + "    try {\n"
116             + "      var event = new KeyboardEvent(42);\n"
117             + "      dump(event);\n"
118             + "    } catch(e) { logEx(e) }\n"
119             + "  }\n"
120             + DUMP_EVENT_FUNCTION
121             + "</script></head><body onload='test()'>\n"
122             + "</body></html>";
123 
124         loadPageVerifyTitle2(html);
125     }
126 
127     /**
128      * @throws Exception if the test fails
129      */
130     @Test
131     @Alerts({"[object KeyboardEvent]", "null", "false", "false", "false",
132              ",,0,false,false,false,false,false,false,0,0"})
133     public void create_ctorNullType() throws Exception {
134         final String html = DOCTYPE_HTML
135             + "<html><head><script>\n"
136             + LOG_TITLE_FUNCTION
137             + "  function test() {\n"
138             + "    try {\n"
139             + "      var event = new KeyboardEvent(null);\n"
140             + "      dump(event);\n"
141             + "    } catch(e) { logEx(e) }\n"
142             + "  }\n"
143             + DUMP_EVENT_FUNCTION
144             + "</script></head><body onload='test()'>\n"
145             + "</body></html>";
146 
147         loadPageVerifyTitle2(html);
148     }
149 
150     /**
151      * @throws Exception if the test fails
152      */
153     @Test
154     @Alerts("ReferenceError")
155     public void create_ctorUnknownType() throws Exception {
156         final String html = DOCTYPE_HTML
157             + "<html><head><script>\n"
158             + LOG_TITLE_FUNCTION
159             + "  function test() {\n"
160             + "    try {\n"
161             + "      var event = new KeyboardEvent(unknown);\n"
162             + "      dump(event);\n"
163             + "    } catch(e) { logEx(e) }\n"
164             + "  }\n"
165             + DUMP_EVENT_FUNCTION
166             + "</script></head><body onload='test()'>\n"
167             + "</body></html>";
168 
169         loadPageVerifyTitle2(html);
170     }
171 
172     /**
173      * @throws Exception if the test fails
174      */
175     @Test
176     @Alerts({"[object KeyboardEvent]", "HtmlUnitEvent", "false", "false", "false",
177              ",,0,false,false,false,false,false,false,0,0"})
178     public void create_ctorArbitraryType() throws Exception {
179         final String html = DOCTYPE_HTML
180             + "<html><head><script>\n"
181             + LOG_TITLE_FUNCTION
182             + "  function test() {\n"
183             + "    try {\n"
184             + "      var event = new KeyboardEvent('HtmlUnitEvent');\n"
185             + "      dump(event);\n"
186             + "    } catch(e) { logEx(e) }\n"
187             + "  }\n"
188             + DUMP_EVENT_FUNCTION
189             + "</script></head><body onload='test()'>\n"
190             + "</body></html>";
191 
192         loadPageVerifyTitle2(html);
193     }
194 
195     /**
196      * @throws Exception if the test fails
197      */
198     @Test
199     @Alerts(DEFAULT = {"[object KeyboardEvent]", "keyboard", "false", "false", "false",
200                        "key,code,123,true,true,true,true,true,true,456,789"},
201             CHROME = {"[object KeyboardEvent]", "keyboard", "false", "false", "false",
202                       "key,code,123,true,true,true,true,true,true,456,0"},
203             EDGE = {"[object KeyboardEvent]", "keyboard", "false", "false", "false",
204                     "key,code,123,true,true,true,true,true,true,456,0"})
205     public void create_ctorAllDetails() throws Exception {
206         final String html = DOCTYPE_HTML
207             + "<html><head><script>\n"
208             + LOG_TITLE_FUNCTION
209             + "  function test() {\n"
210             + "    try {\n"
211             + "      var event = new KeyboardEvent('keyboard', "
212                              + "{ key: 'key', code: 'code', location: 123, "
213                              + "ctrlKey: true, shiftKey: true, altKey: true, metaKey: true,"
214                              + "repeat: true, isComposing: true, charCode: 456, which: 789 });\n"
215             + "      dump(event);\n"
216             + "    } catch(e) { logEx(e) }\n"
217             + "  }\n"
218             + DUMP_EVENT_FUNCTION
219             + "</script></head><body onload='test()'>\n"
220             + "</body></html>";
221 
222         loadPageVerifyTitle2(html);
223     }
224 
225     /**
226      * @throws Exception if the test fails
227      */
228     @Test
229     @Alerts({"[object KeyboardEvent]", "keyboard", "false", "false", "false",
230              "null,,0,true,false,false,false,false,false,456,0"})
231     public void create_ctorSomeDetails() throws Exception {
232         final String html = DOCTYPE_HTML
233             + "<html><head><script>\n"
234             + LOG_TITLE_FUNCTION
235             + "  function test() {\n"
236             + "    try {\n"
237             + "      var event = new KeyboardEvent('keyboard', "
238                              + "{ key: null, code: undefined, ctrlKey: true, charCode: 456 });\n"
239             + "      dump(event);\n"
240             + "    } catch(e) { logEx(e) }\n"
241             + "  }\n"
242             + DUMP_EVENT_FUNCTION
243             + "</script></head><body onload='test()'>\n"
244             + "</body></html>";
245 
246         loadPageVerifyTitle2(html);
247     }
248 
249     /**
250      * @throws Exception if the test fails
251      */
252     @Test
253     @Alerts({"[object KeyboardEvent]", "keyboard", "false", "false", "false",
254              ",,0,false,false,false,false,false,false,0,0"})
255     public void create_ctorMissingData() throws Exception {
256         final String html = DOCTYPE_HTML
257             + "<html><head><script>\n"
258             + LOG_TITLE_FUNCTION
259             + "  function test() {\n"
260             + "    try {\n"
261             + "      var event = new KeyboardEvent('keyboard', {\n"
262             + "      });\n"
263             + "      dump(event);\n"
264             + "    } catch(e) { logEx(e) }\n"
265             + "  }\n"
266             + DUMP_EVENT_FUNCTION
267             + "</script></head><body onload='test()'>\n"
268             + "</body></html>";
269 
270         loadPageVerifyTitle2(html);
271     }
272 
273     /**
274      * @throws Exception if the test fails
275      */
276     @Test
277     @Alerts({"[object KeyboardEvent]", "keyboard", "false", "false", "false",
278              ",,0,false,false,false,false,false,false,0,0"})
279     public void create_ctorNullData() throws Exception {
280         final String html = DOCTYPE_HTML
281             + "<html><head><script>\n"
282             + LOG_TITLE_FUNCTION
283             + "  function test() {\n"
284             + "    try {\n"
285             + "      var event = new KeyboardEvent('keyboard', null);\n"
286             + "      dump(event);\n"
287             + "    } catch(e) { logEx(e) }\n"
288             + "  }\n"
289             + DUMP_EVENT_FUNCTION
290             + "</script></head><body onload='test()'>\n"
291             + "</body></html>";
292 
293         loadPageVerifyTitle2(html);
294     }
295 
296     /**
297      * @throws Exception if the test fails
298      */
299     @Test
300     @Alerts({"[object KeyboardEvent]", "keyboard", "false", "false", "false",
301              ",,0,false,false,false,false,false,false,0,0"})
302     public void create_ctorUndefinedData() throws Exception {
303         final String html = DOCTYPE_HTML
304             + "<html><head><script>\n"
305             + LOG_TITLE_FUNCTION
306             + "  function test() {\n"
307             + "    try {\n"
308             + "      var event = new KeyboardEvent('keyboard', undefined);\n"
309             + "      dump(event);\n"
310             + "    } catch(e) { logEx(e) }\n"
311             + "  }\n"
312             + DUMP_EVENT_FUNCTION
313             + "</script></head><body onload='test()'>\n"
314             + "</body></html>";
315 
316         loadPageVerifyTitle2(html);
317     }
318 
319     /**
320      * @throws Exception if the test fails
321      */
322     @Test
323     @Alerts({"[object KeyboardEvent]", "keyboard", "false", "false", "false",
324              ",,0,false,false,false,false,false,false,0,0"})
325     public void create_ctorWrongData() throws Exception {
326         final String html = DOCTYPE_HTML
327             + "<html><head><script>\n"
328             + LOG_TITLE_FUNCTION
329             + "  function test() {\n"
330             + "    try {\n"
331             + "      var event = new KeyboardEvent('keyboard', {\n"
332             + "        'data': ['Html', 'Unit']\n"
333             + "      });\n"
334             + "      dump(event);\n"
335             + "    } catch(e) { logEx(e) }\n"
336             + "  }\n"
337             + DUMP_EVENT_FUNCTION
338             + "</script></head><body onload='test()'>\n"
339             + "</body></html>";
340 
341         loadPageVerifyTitle2(html);
342     }
343 
344     /**
345      * @throws Exception if the test fails
346      */
347     @Test
348     @Alerts({"DOM3: [object KeyboardEvent]", "vendor: exception"})
349     public void createEvent() throws Exception {
350         final String html = DOCTYPE_HTML
351             + "<html><head><script>\n"
352             + LOG_TITLE_FUNCTION
353             + "  function test() {\n"
354             + "    try {\n"
355             + "      log('DOM3: ' + document.createEvent('KeyboardEvent'));\n"
356             + "    } catch(e) {log('DOM3: exception')}\n"
357             + "    try {\n"
358             + "      log('vendor: ' + document.createEvent('KeyEvents'));\n"
359             + "    } catch(e) {log('vendor: exception')}\n"
360             + "  }\n"
361             + "</script></head><body onload='test()'>\n"
362             + "</body></html>";
363         loadPageVerifyTitle2(html);
364     }
365 
366     /**
367      * @throws Exception if the test fails
368      */
369     @Test
370     @Alerts({"NotSupportedError/DOMException", "0-0", "undefined-undefined"})
371     public void keyCode() throws Exception {
372         final String html = DOCTYPE_HTML
373             + "<html><head><script>\n"
374             + LOG_TITLE_FUNCTION
375             + "  function test() {\n"
376             + "    try {\n"
377             + "      var keyEvent = document.createEvent('KeyEvents');\n"
378             + "      log(keyEvent.keyCode + '-' + keyEvent.charCode);\n"
379             + "    } catch(e) { logEx(e) }\n"
380             + "    try {\n"
381             + "      var keyEvent = document.createEvent('KeyboardEvent');\n"
382             + "      log(keyEvent.keyCode + '-' + keyEvent.charCode);\n"
383             + "    } catch(e) { logEx(e) }\n"
384             + "    try {\n"
385             + "      var mouseEvent = document.createEvent('MouseEvents');\n"
386             + "      log(mouseEvent.keyCode + '-' + mouseEvent.charCode);\n"
387             + "    } catch(e) { logEx(e) }\n"
388             + "  }\n"
389             + "</script></head><body onload='test()'>\n"
390             + "</body></html>";
391         loadPageVerifyTitle2(html);
392     }
393 
394     /**
395      * @throws Exception if the test fails
396      */
397     @Test
398     @Alerts({"NotSupportedError/DOMException", "TypeError"})
399     public void initKeyEvent() throws Exception {
400         final String html = DOCTYPE_HTML
401             + "<html><head><script>\n"
402             + LOG_TITLE_FUNCTION
403             + "  var properties = ['type', 'bubbles', 'cancelable', /*'view',*/ 'ctrlKey', 'altKey',\n"
404             + "        'shiftKey', 'metaKey', 'keyCode', 'charCode'];\n"
405             + "  function dumpEvent(e) {\n"
406             + "    var str = '';\n"
407             + "    for (var i = 0; i < properties.length; i++) str += ', ' + e[properties[i]];\n"
408             + "    log(str.substring(2));\n"
409             + "  }\n"
410             + "  function test() {\n"
411             + "    try {\n"
412             + "      var keyEvent = document.createEvent('KeyEvents');\n"
413             + "      keyEvent.initKeyEvent('keydown', true, true, null, true, true, true, true, 65, 65);\n"
414             + "      dumpEvent(keyEvent);\n"
415             + "      keyEvent = document.createEvent('KeyEvents');\n"
416             + "      keyEvent.initKeyEvent('keyup', false, false, null, false, false, false, false, 32, 32);\n"
417             + "      dumpEvent(keyEvent);\n"
418             + "    } catch(e) { logEx(e) }\n"
419             + "    try {\n"
420             + "      var keyEvent = document.createEvent('KeyboardEvent');\n"
421             + "      keyEvent.initKeyEvent('keydown', true, true, null, true, true, true, true, 65, 65);\n"
422             + "      dumpEvent(keyEvent);\n"
423             + "      keyEvent = document.createEvent('KeyboardEvent');\n"
424             + "      keyEvent.initKeyEvent('keyup', false, false, null, false, false, false, false, 32, 32);\n"
425             + "      dumpEvent(keyEvent);\n"
426             + "    } catch(e) { logEx(e) }\n"
427             + "  }\n"
428             + "</script></head><body onload='test()'>\n"
429             + "</body></html>";
430         loadPageVerifyTitle2(html);
431     }
432 
433     /**
434      * @throws Exception if the test fails
435      */
436     @Test
437     @Alerts(DEFAULT = {"NotSupportedError/DOMException",
438                        "keydown, true, true, , 0, true, true, true, true, 0, 0",
439                        "keyup, false, false, , 7, false, false, false, false, 0, 0"},
440             FF = {"NotSupportedError/DOMException",
441                   "keydown, true, true, Fn, 0, true, true, true, true, 0, 0",
442                   "keyup, false, false, , 7, false, false, false, false, 0, 0"},
443             FF_ESR = {"NotSupportedError/DOMException",
444                       "keydown, true, true, Fn, 0, true, true, true, true, 0, 0",
445                       "keyup, false, false, , 7, false, false, false, false, 0, 0"})
446     @HtmlUnitNYI(CHROME = {"NotSupportedError/DOMException",
447                            "keydown, true, true, Fn, 0, true, true, true, true, 0, 0",
448                            "keyup, false, false, , 7, false, false, false, false, 0, 0"},
449                  EDGE = {"NotSupportedError/DOMException",
450                          "keydown, true, true, Fn, 0, true, true, true, true, 0, 0",
451                          "keyup, false, false, , 7, false, false, false, false, 0, 0"})
452     public void initKeyboardEvent() throws Exception {
453         final String html = DOCTYPE_HTML
454             + "<html><head><script>\n"
455             + LOG_TITLE_FUNCTION
456             + "  var properties = ['type', 'bubbles', 'cancelable', /*'view',*/ 'key', 'location',"
457             + "        'ctrlKey', 'altKey', 'shiftKey', 'metaKey', 'keyCode', 'charCode'];\n"
458             + "  function dumpEvent(e) {\n"
459             + "    var str = '';\n"
460             + "    for (var i = 0; i < properties.length; i++) str += ', ' + e[properties[i]];\n"
461             + "    log(str.substring(2));\n"
462             + "  }\n"
463             + "  function test() {\n"
464             + "    try {\n"
465             + "      var keyEvent = document.createEvent('KeyEvents');\n"
466             + "      keyEvent.initKeyboardEvent('keydown', true, true, null, 'Fn', 0, true, true, true, true);\n"
467             + "      dumpEvent(keyEvent);\n"
468             + "      keyEvent = document.createEvent('KeyEvents');\n"
469             + "      keyEvent.initKeyboardEvent('keyup', false, false, null, '', 7, false, false, false, false);\n"
470             + "      dumpEvent(keyEvent);\n"
471             + "    } catch(e) { logEx(e) }\n"
472             + "    try {\n"
473             + "      var keyEvent = document.createEvent('KeyboardEvent');\n"
474             + "      keyEvent.initKeyboardEvent('keydown', true, true, null, 'Fn', 0, true, true, true, true);\n"
475             + "      dumpEvent(keyEvent);\n"
476             + "      keyEvent = document.createEvent('KeyboardEvent');\n"
477             + "      keyEvent.initKeyboardEvent('keyup', false, false, null, '', 7, false, false, false, false);\n"
478             + "      dumpEvent(keyEvent);\n"
479             + "    } catch(e) { logEx(e) }\n"
480             + "  }\n"
481             + "</script></head><body onload='test()'>\n"
482             + "</body></html>";
483         loadPageVerifyTitle2(html);
484     }
485 
486     /**
487      * @throws Exception if the test fails
488      */
489     @Test
490     @Alerts({"32", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57"})
491     public void keyCodes_keyup() throws Exception {
492         final String html = DOCTYPE_HTML
493             + "<html><head>\n"
494             + "<script>\n"
495             + LOG_TEXTAREA_FUNCTION
496             + "</script>\n"
497             + "</head>\n"
498             + "<body>\n"
499             + "  <input id='t' onkeyup='log(event.keyCode)'/>\n"
500             + LOG_TEXTAREA
501             + "</body></html>";
502 
503         final WebDriver driver = loadPage2(html);
504         final WebElement field = driver.findElement(By.id("t"));
505 
506         field.sendKeys(" 0123456789");
507         verifyTextArea2(driver, getExpectedAlerts());
508     }
509 
510     /**
511      * @throws Exception if the test fails
512      */
513     @Test
514     @Alerts({"65", "66", "67", "68", "69",
515              "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
516              "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90"})
517     public void keyCodes2_keyup() throws Exception {
518         final String html = DOCTYPE_HTML
519             + "<html><head>\n"
520             + "<script>\n"
521             + LOG_TEXTAREA_FUNCTION
522             + "</script>\n"
523             + "</head>\n"
524             + "<body>\n"
525             + "  <input id='t' onkeyup='log(event.keyCode)'/>\n"
526             + LOG_TEXTAREA
527             + "</body></html>";
528 
529         final WebDriver driver = loadPage2(html);
530         final WebElement field = driver.findElement(By.id("t"));
531 
532         field.sendKeys("abcdefghijklmnopqrstuvwxyz");
533 
534         verifyTextArea2(driver, getExpectedAlerts());
535     }
536 
537     /**
538      * @throws Exception if the test fails
539      */
540     @Test
541     @Alerts({"32", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57"})
542     public void keyCodes_keydown() throws Exception {
543         final String html = DOCTYPE_HTML
544             + "<html><head>\n"
545             + "<script>\n"
546             + LOG_TEXTAREA_FUNCTION
547             + "</script>\n"
548             + "</head>\n"
549             + "<body>\n"
550             + "  <input id='t' onkeydown='log(event.keyCode)'/>\n"
551             + LOG_TEXTAREA
552             + "</body></html>";
553 
554         final WebDriver driver = loadPage2(html);
555         final WebElement field = driver.findElement(By.id("t"));
556 
557         field.sendKeys(" 0123456789");
558 
559         verifyTextArea2(driver, getExpectedAlerts());
560     }
561 
562     /**
563      * @throws Exception if the test fails
564      */
565     @Test
566     @Alerts({"65", "66", "67", "68", "69",
567              "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
568              "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90"})
569     public void keyCodes2_keydown() throws Exception {
570         final String html = DOCTYPE_HTML
571             + "<html><head>\n"
572             + "<script>\n"
573             + LOG_TEXTAREA_FUNCTION
574             + "</script>\n"
575             + "</head>\n"
576             + "<body>\n"
577             + "  <input id='t' onkeydown='log(event.keyCode)'/>\n"
578             + LOG_TEXTAREA
579             + "</body></html>";
580 
581         final WebDriver driver = loadPage2(html);
582         final WebElement field = driver.findElement(By.id("t"));
583 
584         field.sendKeys("abcdefghijklmnopqrstuvwxyz");
585 
586         verifyTextArea2(driver, getExpectedAlerts());
587     }
588 
589     /**
590      * @throws Exception if the test fails
591      */
592     @Test
593     @Alerts({"32", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57"})
594     public void keyCodes_keypress() throws Exception {
595         final String html = DOCTYPE_HTML
596             + "<html><head>\n"
597             + "<script>\n"
598             + LOG_TEXTAREA_FUNCTION
599             + "</script>\n"
600             + "</head>\n"
601             + "<body>\n"
602             + "  <input id='t' onkeypress='log(event.charCode)'/>\n"
603             + LOG_TEXTAREA
604             + "</body></html>";
605 
606         final WebDriver driver = loadPage2(html);
607         final WebElement field = driver.findElement(By.id("t"));
608 
609         field.sendKeys(" 0123456789");
610 
611         verifyTextArea2(driver, getExpectedAlerts());
612     }
613 
614     /**
615      * @throws Exception if the test fails
616      */
617     @Test
618     @Alerts({"97", "98", "99",
619              "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
620              "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
621              "120", "121", "122"})
622     public void keyCodes2_keypress() throws Exception {
623         final String html = DOCTYPE_HTML
624             + "<html><head>\n"
625             + "<script>\n"
626             + LOG_TEXTAREA_FUNCTION
627             + "</script>\n"
628             + "</head>\n"
629             + "<body>\n"
630             + "  <input id='t' onkeypress='log(event.charCode)'/>\n"
631             + LOG_TEXTAREA
632             + "</body></html>";
633 
634         final WebDriver driver = loadPage2(html);
635         final WebElement field = driver.findElement(By.id("t"));
636 
637         field.sendKeys("abcdefghijklmnopqrstuvwxyz");
638 
639         verifyTextArea2(driver, getExpectedAlerts());
640     }
641 
642     /**
643      * @throws Exception if the test fails
644      */
645     @Test
646     @Alerts({"13", "13", "13"})
647     public void keyCodeEnter_keypress() throws Exception {
648         final String html = DOCTYPE_HTML
649             + "<html>\n"
650             + "<head>\n"
651             + "<script>\n"
652             + LOG_TITLE_FUNCTION
653             + "function handleKey(e) {\n"
654             + "  log(e.charCode);\n"
655             + "  log(e.keyCode);\n"
656             + "  log(e.which);\n"
657             + "}\n"
658             + "</script>\n"
659             + "</head>\n"
660             + "<body>\n"
661             + "  <textarea id='t' onkeypress='handleKey(event)'></textarea>\n"
662             + "</body>\n"
663             + "</html>";
664 
665         final WebDriver driver = loadPage2(html);
666         final WebElement field = driver.findElement(By.id("t"));
667 
668         field.sendKeys(Keys.ENTER);
669 
670         verifyTitle2(driver, getExpectedAlerts());
671     }
672 
673     /**
674      * @throws Exception if the test fails
675      */
676     @Test
677     @Alerts({"keydown:16,0,16,Shift,undefined,ShiftLeft,true",
678              "keydown:65,0,65,A,undefined,KeyA,true",
679              "keypress:65,65,65,A,undefined,KeyA,true",
680              "keyup:65,0,65,A,undefined,KeyA,true",
681              "keyup:16,0,16,Shift,undefined,ShiftLeft,false",
682              "keydown:65,0,65,a,undefined,KeyA,false",
683              "keypress:97,97,97,a,undefined,KeyA,false",
684              "keyup:65,0,65,a,undefined,KeyA,false",
685              "keydown:190,0,190,.,undefined,Period,false",
686              "keypress:46,46,46,.,undefined,Period,false",
687              "keyup:190,0,190,.,undefined,Period,false",
688              "keydown:13,0,13,Enter,undefined,Enter,false",
689              "keypress:13,13,13,Enter,undefined,Enter,false",
690              "keyup:13,0,13,Enter,undefined,Enter,false"})
691     // https://github.com/SeleniumHQ/selenium/issues/2531
692     @BuggyWebDriver(CHROME = {"keydown:16,0,16,Shift,undefined,ShiftLeft,false",
693                               "keydown:65,0,65,A,undefined,KeyA,true",
694                               "keypress:65,65,65,A,undefined,KeyA,true",
695                               "keyup:65,0,65,A,undefined,KeyA,true",
696                               "keyup:16,0,16,Shift,undefined,ShiftLeft,false",
697                               "keydown:65,0,65,a,undefined,KeyA,false",
698                               "keypress:97,97,97,a,undefined,KeyA,false",
699                               "keyup:65,0,65,a,undefined,KeyA,false",
700                               "keydown:190,0,190,.,undefined,Period,false",
701                               "keypress:46,46,46,.,undefined,Period,false",
702                               "keyup:190,0,190,.,undefined,Period,false",
703                               "keydown:13,0,13,Enter,undefined,Enter,false",
704                               "keypress:13,13,13,Enter,undefined,Enter,false",
705                               "keyup:13,0,13,Enter,undefined,Enter,false"},
706                     EDGE = {"keydown:16,0,16,Shift,undefined,ShiftLeft,false",
707                             "keydown:65,0,65,A,undefined,KeyA,true",
708                             "keypress:65,65,65,A,undefined,KeyA,true",
709                             "keyup:65,0,65,A,undefined,KeyA,true",
710                             "keyup:16,0,16,Shift,undefined,ShiftLeft,false",
711                             "keydown:65,0,65,a,undefined,KeyA,false",
712                             "keypress:97,97,97,a,undefined,KeyA,false",
713                             "keyup:65,0,65,a,undefined,KeyA,false",
714                             "keydown:190,0,190,.,undefined,Period,false",
715                             "keypress:46,46,46,.,undefined,Period,false",
716                             "keyup:190,0,190,.,undefined,Period,false",
717                             "keydown:13,0,13,Enter,undefined,Enter,false",
718                             "keypress:13,13,13,Enter,undefined,Enter,false",
719                             "keyup:13,0,13,Enter,undefined,Enter,false"},
720                     FF_ESR = {"keydown:65,0,65,A,undefined,KeyA,false",
721                               "keypress:65,65,65,A,undefined,KeyA,false",
722                               "keyup:65,0,65,A,undefined,KeyA,false",
723                               "keydown:65,0,65,a,undefined,KeyA,false",
724                               "keypress:97,97,97,a,undefined,KeyA,false",
725                               "keyup:65,0,65,a,undefined,KeyA,false",
726                               "keydown:190,0,190,.,undefined,Period,false",
727                               "keypress:46,46,46,.,undefined,Period,false",
728                               "keyup:190,0,190,.,undefined,Period,false",
729                               "keydown:13,0,13,Enter,undefined,Enter,false",
730                               "keypress:13,13,13,Enter,undefined,Enter,false",
731                               "keyup:13,0,13,Enter,undefined,Enter,false"},
732                     FF = {"keydown:65,0,65,A,undefined,KeyA,false",
733                           "keypress:65,65,65,A,undefined,KeyA,false",
734                           "keyup:65,0,65,A,undefined,KeyA,false",
735                           "keydown:65,0,65,a,undefined,KeyA,false",
736                           "keypress:97,97,97,a,undefined,KeyA,false",
737                           "keyup:65,0,65,a,undefined,KeyA,false",
738                           "keydown:190,0,190,.,undefined,Period,false",
739                           "keypress:46,46,46,.,undefined,Period,false",
740                           "keyup:190,0,190,.,undefined,Period,false",
741                           "keydown:13,0,13,Enter,undefined,Enter,false",
742                           "keypress:13,13,13,Enter,undefined,Enter,false",
743                           "keyup:13,0,13,Enter,undefined,Enter,false"})
744     public void which() throws Exception {
745         final String html = DOCTYPE_HTML
746             + "<html><head></head><body>\n"
747             + "<input type='text' id='keyId'>\n"
748             + "<script>\n"
749             + LOG_TEXTAREA_FUNCTION
750             + "function handler(e) {\n"
751             + "  e = e ? e : window.event;\n"
752             + "  var msg = e.type + ':' + e.keyCode + ',' + e.charCode + ',' + e.which + ',' "
753                             + "+ e.key + ',' + e.char + ',' + e.code + ',' + e.shiftKey;\n"
754             + "  msg = msg.replace(/\\r/g, '\\\\r');\n"
755             + "  msg = msg.replace(/\\n/g, '\\\\n');\n"
756             + "  log(msg);"
757             + "}\n"
758             + "document.getElementById('keyId').onkeyup = handler;\n"
759             + "document.getElementById('keyId').onkeydown = handler;\n"
760             + "document.getElementById('keyId').onkeypress = handler;\n"
761             + "</script>\n"
762             + LOG_TEXTAREA
763             + "</body></html>";
764 
765         final String keysToSend = "Aa." + Keys.RETURN;
766         final WebDriver driver = loadPage2(html);
767         driver.findElement(By.id("keyId")).sendKeys(keysToSend);
768 
769         verifyTextArea2(driver, getExpectedAlerts());
770     }
771 }