chromium/third_party/blink/web_tests/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-keyboard-events.html

<!DOCTYPE html>
<html>
<head>
<script src="../../../resources/js-test.js"></script>
</head>
<body>
<p id="description"></p>
<p>
Please run this with DumpRenderTree.
</p>
Test following keys:
<ul>
    <li>Digits</li>
    <li>Left/Right - Move focus field inside element</li>
    <li>Up/Down - Increment/decrement value of focus field</li>
    <li>Tab - Move focus field</li>
    <li>Backspace - Make value empty</li>
</ul>
<input id="before">
<input id="input" type="datetime-local">
<input id="after">
<div id="console"></div>
<script>
description('Multiple fields UI of datetime-local input type with keyboard events');
if (window.internals)
    internals.runtimeFlags.langAttributeAwareFormControlUIEnabled = true;
var input = document.getElementById('input');

function keyDown(key, modifiers)
{
    if (!window.eventSender)
        return;
    eventSender.keyDown(key, modifiers);
}

function beginTest(title, opt_value, opt_min, opt_max)
{
    debug('== ' + title + ' ==');
    input.value = opt_value || '';
    input.min = opt_min ? opt_min : '';
    input.max = opt_max ? opt_max : '';
    input.blur();
    input.focus();
}

beginTest('Digit keys');
keyDown('9'); // -> 09/[dd]/yyyy --:-- --
keyDown('2'); // -> 09/[02]/yyyy --:-- --
keyDown('0'); // -> 09/20/[yyyy] --:-- --
keyDown('9'); // -> 09/20/[0009] --:-- --
keyDown('8'); // -> 09/20/[0098] --:-- --
keyDown('7'); // -> 09/20/[0987] --:-- --
keyDown('6'); // -> 09/20/[9876] --:-- --
keyDown('5'); // -> 09/20/98765 [--]:-- --
keyDown('7'); // -> 09/20/98765 07:[--] --
keyDown('5'); // -> 09/20/98765 07:[05] --
keyDown('6'); // -> 09/20/98765 07:56 [--]
keyDown('A'); // -> 09/20/98765 07:56 AM
shouldBeEqualToString('input.value', '98765-09-20T07:56');

beginTest('Digit keys starting with zero', null, null, '9999-12-31T23:59');
keyDown('0'); // -> [00]/dd/yyyy --:-- --
keyDown('2'); // -> 02/[dd]/yyyy --:-- --
keyDown('0'); // -> 02/[00]/yyyy --:-- --
keyDown('3'); // -> 02/03/[yyyy] --:-- --
keyDown('0'); // -> 02/03/[0000] --:-- --
keyDown('0'); // -> 02/03/[0000] --:-- --
keyDown('4'); // -> 02/03/[0044] --:-- --
keyDown('4'); // -> 02/03/[0044] --:-- --
keyDown('0'); // -> 02/03/0044 [00]:-- --
keyDown('5'); // -> 02/03/0044 05:[--] --
keyDown('0'); // -> 02/03/0044 01:[01] --
keyDown('6'); // -> 02/03/0044 05:06 [--]
keyDown('A'); // -> 02/03/0044 05:06 AM
shouldBeEqualToString('input.value', '0044-02-03T05:06');

beginTest('Digit keys and backspace key');
keyDown('1'); // -> [01]/dd/yyyy --:-- --
keyDown("Backspace"); // -> [mm]/20/2012 --:-- --
keyDown('5'); // -> 05/[dd]/yyyy --:-- --
keyDown('6'); // -> 05/06/[yyyy] --:-- --
keyDown("Backspace"); // -> 05/06/[yyyy] --:-- --
keyDown('7'); // -> 05/06/[0007] --:-- --
keyDown("Backspace"); // -> 05/06/[yyyy] --:-- --
keyDown('8'); // -> 05/06/[0008] --:-- --
keyDown('ArrowRight'); // -> 05/06/0008 [--]:-- --
keyDown('9'); // -> 05/06/0008 09:[--] --
keyDown('1'); // -> 05/06/0008 09:[01] --
keyDown('0'); // -> 05/06/0008 09:10 [--]
keyDown('A'); // -> 05/06/0008 09:10 [AM]
shouldBeEqualToString('input.value', '0008-05-06T09:10');

beginTest('Left/Right keys', '2012-09-29T00:00');
keyDown('ArrowRight'); // -> 09/[29]/2012 12:00 AM
keyDown('5'); // -> 09/05/[2012] 12:00 AM
keyDown('ArrowRight'); // -> 09/05/2012 [12]:00 AM
keyDown('7'); // -> 09/05/2012 07:[00] AM
keyDown('ArrowRight'); // -> 09/05/2012 07:00 [AM]
keyDown('P'); // -> 09/05/2012 07:00 [PM]
keyDown('ArrowLeft'); // -> 09/05/2012 07:[00] PM
keyDown('5'); // -> 09/05/2012 07:[05] PM
keyDown('ArrowLeft'); // -> 09/05/2012 [07]:05 PM
keyDown('ArrowLeft'); // -> 09/05/[2012] 07:05 PM
keyDown('4'); // -> 09/05/[0004] 07:05 PM
shouldBeEqualToString('input.value', '0004-09-05T19:05');
keyDown('ArrowLeft'); // -> 09/[05]/0004 07:05 PM
keyDown('ArrowLeft'); // -> [09]/05/0004 07:05 PM
keyDown('ArrowLeft'); // -> [09]/05/0004 07:05 PM
shouldBeEqualToString('document.activeElement.id', 'input');

beginTest('Up/Down keys', '2012-09-29T00:00');
keyDown('ArrowUp'); // -> [10]/29/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-10-29T00:00');
keyDown('ArrowDown'); // -> [09]/29/2012 12:00 AM
keyDown('ArrowDown'); // -> [08]/29/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-08-29T00:00');

beginTest('Up/Down keys on empty value');
keyDown('ArrowDown'); //  -> [12]/dd/yyyy --:-- --
keyDown('ArrowDown'); //  -> [11]/dd/yyyy --:-- --
keyDown('ArrowRight'); // -> 11/[dd]/yyyy --:-- --
keyDown('ArrowUp'); //    -> 11/[01]/yyyy --:-- --
keyDown('ArrowUp'); //    -> 11/[02]/yyyy --:-- --
keyDown('ArrowDown'); //  -> 11/[01]/yyyy --:-- --
keyDown('ArrowRight'); // -> 11/01/[yyyy] --:-- --
var currentYear = new Date().getFullYear();
keyDown('ArrowUp'); // -> 11/01/[currentYear] --:-- --
keyDown('ArrowRight'); // -> 11/01/currentYear [--]:-- --
keyDown('ArrowUp'); //    -> 11/01/currentYear [01]:-- --
keyDown('ArrowRight'); // -> 11/01/currentYear 01:[--] --
keyDown('ArrowDown'); //  -> 11/01/currentYear 01:[59] --
keyDown('ArrowRight'); // -> 11/01/currentYear 01:59 [--]
keyDown('ArrowUp'); //    -> 11/01/currentYear 01:59 [AM]
shouldBe('input.value', 'currentYear + "-11-01T01:59"');

beginTest('Tab key', '2012-09-30T00:00');
keyDown('\t'); // -> 09/[30]/2012 12:00 AM
keyDown('5'); // -> 09/05/[2012] 12:00 AM
keyDown('\t'); // -> 09/05/2012 [12]:00 AM
keyDown('\t'); // -> 09/05/2012 12:[00] AM
keyDown('\t'); // -> 09/05/2012 12:00 [AM]
keyDown('P'); // -> 09/05/2012 12:00 [PM]
shouldBeEqualToString('input.value', '2012-09-05T12:00');
keyDown('\t'); // -> Focus drop down button.
keyDown('\t'); // -> Focus out.
shouldBeEqualToString('document.activeElement.id', 'after');

beginTest('Shfit+Tab key', '2012-09-30T01:00');
after.focus();
keyDown('\t', ['shiftKey']); // -> 09/30/2012 01:00 AM [drop-down-button]
keyDown('\t', ['shiftKey']); // -> 09/30/2012 01:00 [AM]
keyDown('P'); // -> 09/30/2012 01:00 [PM]
keyDown('\t', ['shiftKey']); // -> 09/30/2012 01:[00] PM
keyDown('3'); // -> 09/30/2012 01:[03] PM
shouldBeEqualToString('input.value', '2012-09-30T13:03');
keyDown('\t', ['shiftKey']); // -> 09/30/2012 [01]:03 PM
keyDown('\t', ['shiftKey']); // -> 09/30/[2012] 01:03 PM
keyDown('\t', ['shiftKey']); // -> 09/[30]/2012 01:03 PM
keyDown('\t', ['shiftKey']); // -> [09]/30/2012 01:03 PM
keyDown('\t', ['shiftKey']); // -> Focus out.
shouldBeEqualToString('document.activeElement.id', 'before');

beginTest('Up key on maximum value', '275760-09-13T00:00');
keyDown('ArrowUp'); // -> [10]/13/275760 12:00 AM
keyDown('\t'); //      -> 10/[13]/275760 12:00 AM
keyDown('ArrowUp'); // -> 10/[14]/275760 12:00 AM
keyDown('\t'); //      -> 10/14/[275760] 12:00 AM
keyDown('ArrowUp'); // -> 10/14/[0001] 12:00 AM
shouldBeEqualToString('input.value', '0001-10-14T00:00');
beginTest('Up key with a maximum attribute', '1999-12-31T00:00', '1000-01-01T00:00', '1999-12-31T23:59');
keyDown('ArrowUp'); // -> [01]/31/1999 12:00 AM
keyDown('\t'); //      -> 01/[31]/1999 12:00 AM
keyDown('ArrowUp'); // -> 01/[01]/1999 12:00 AM
keyDown('\t'); //      -> 01/01/[1999] 12:00 AM
keyDown('ArrowUp'); // -> 01/01/[1000] 12:00 AM
shouldBeEqualToString('input.value', '1000-01-01T00:00');

beginTest('Down key on minimum value', '0001-01-01T00:00', 'bad min', 'wrong max');
keyDown('ArrowDown'); // -> [12]/01/0001 12:00 AM
keyDown('\t'); //        -> 12/[01]/0001 12:00 AM
keyDown('ArrowDown'); // -> 12/[31]/0001 12:00 AM
keyDown('\t'); //        -> 12/31/[0001] 12:00 AM
keyDown('ArrowDown'); // -> 12/31/[275760] 12:00 AM, which is greater than the hard limit.
shouldBeEqualToString('input.value', '');
beginTest('Down key with a minimum attribute', '1000-01-01T00:00', '1000-01-01T00:00');
keyDown('ArrowDown'); // -> [12]/01/1000 12:00 AM
keyDown('\t'); //        -> 12/[01]/1000 12:00 AM
keyDown('ArrowDown'); // -> 12/[31]/1000 12:00 AM
keyDown('\t'); //        -> 12/31/[1000] 12:00 AM
keyDown('ArrowDown'); // -> 12/31/275760, which is greater than the hard limit.
shouldBeEqualToString('input.value', '');

beginTest('Inconsistent min-max attributes', '1999-12-31T23:59', '1999-12-31T23:59', '1000-01-01T00:00');
keyDown('\t'); // -> 12/[31]/1999 11:59 PM
keyDown('\t'); // -> 12/31/[1999] 11:59 PM
keyDown('ArrowUp'); // -> 12/31/[1000] 11:59 PM.  1000 is the swapped minimum year.
shouldBeEqualToString('input.value', '1000-12-31T23:59');
keyDown('ArrowDown'); // -> 12/31/[1999]
shouldBeEqualToString('input.value', '1999-12-31T23:59');

beginTest('Make an invalid date', '2012-02-01T00:00');
keyDown('\t'); //        -> 02/[01]/2012 12:00 AM
keyDown('ArrowDown'); // -> 02/[31]/2012 12:00 AM
shouldBeEqualToString('input.value', ''); // 2012-02-31 is not a valid date.

beginTest('Backspace key', '2012-09-20T00:00');
keyDown('Backspace'); // -> [mm]/20/2012 12:00 AM
shouldBeEqualToString('input.value', '');

beginTest('Delete key', '2012-09-30T00:00');
keyDown('Delete'); // -> [mm]/30/2012 12:00 AM
shouldBeEqualToString('input.value', '');

beginTest('Typeahead', '2012-12-31T00:00');
keyDown('ArrowRight'); // -> 12/[31]/2012 12:00 AM
keyDown('1'); //          -> 12/[01]/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-12-01T00:00');
keyDown('ArrowLeft'); //  -> [12]/01/2012 12:00 AM
keyDown('ArrowRight'); // -> 12/[01]/2012 12:00 AM
keyDown('2'); //          -> 12/[02]/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-12-02T00:00');

input.setAttribute('lang', 'he-il');
beginTest('RTL focus navigation', '2012-09-28T23:00');
debug('The tests in this block fail on platforms without the lang-attribute-aware-form-control-UI feature.');
// The logicla order: dd/MM/yyyy hh:mm
// The visual order: hh:mm dd/MM/yyyy
keyDown('1'); //          -> 23:00 [01]/09/2012
shouldBeEqualToString('input.value', '2012-09-01T23:00');
keyDown('\t'); //         -> 23:00 01/[09]/2012
keyDown('2'); //          -> 23:00 01/02/[2012]
keyDown('\t'); //         -> [23]:00 2012/09/01
keyDown('1'); //          -> [01]:00 01/09/2012
shouldBeEqualToString('input.value', '2012-02-01T01:00');
keyDown('\t', ['shiftKey']); // -> 01:00 01/09/[2012]
keyDown('8'); //                -> 01:00 01/09/[0008]
keyDown('\t', ['shiftKey']); // -> 01:00 01/[09]/0008
keyDown('3'); //                -> 01:00 01/03/[0008]
shouldBeEqualToString('input.value', '0008-03-01T01:00');
input.removeAttribute('lang');

beginTest('Disabled/readonly', '2012-10-08T00:00');
input.disabled = true;
keyDown('ArrowUp'); // 10/08/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-10-08T00:00');
input.disabled = false;
input.focus();
keyDown('ArrowUp'); // [11]/08/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-11-08T00:00');
input.readOnly = true;
keyDown('ArrowUp'); // 11/08/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-11-08T00:00');
input.readOnly = false;
input.focus();
keyDown('ArrowUp'); // [12]/08/2012 12:00 AM
shouldBeEqualToString('input.value', '2012-12-08T00:00');

</script>
</body>
</html>