зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1892346 [wpt PR 45792] - Support :user-valid/:user-invalid on multifield inputs, a=testonly
Automatic update from web-platform-tests Support :user-valid/:user-invalid on multifield inputs This patch makes :user-valid and :user-invalid start working on inputs with type date, datetime-local, and time. I matched the webkit behavior for when to start matching in response to keyboard input, and added a separate tentative test for that behavior. Fixed: 328674226 Change-Id: If3c394e43043a0b3d27eac22d0671c6b45b82bc6 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5463293 Reviewed-by: Di Zhang <dizhangg@chromium.org> Commit-Queue: Joey Arhar <jarhar@chromium.org> Cr-Commit-Position: refs/heads/main@{#1294002} -- wpt-commits: 6a7c427b1e2f8c5542e4515ae7d73afaa6e0f236 wpt-pr: 45792
This commit is contained in:
Родитель
d52a52dc4a
Коммит
3286fe8859
|
@ -29,6 +29,7 @@
|
|||
<input placeholder="Required field" required id="required-input"><br>
|
||||
<textarea placeholder="Required field" required id="required-textarea"></textarea><br>
|
||||
<input type="checkbox" required id="required-checkbox"><br>
|
||||
<input type="date" required id="required-date"><br>
|
||||
<input type="submit" id="submit-button">
|
||||
<input type="reset" id="reset-button">
|
||||
</form>
|
||||
|
@ -80,12 +81,14 @@ promise_test(async () => {
|
|||
const requiredInput = document.querySelector("#required-input");
|
||||
const requiredTextarea = document.querySelector("#required-textarea");
|
||||
const requiredCheckbox = document.querySelector("#required-checkbox");
|
||||
const requiredDate = document.querySelector("#required-date");
|
||||
const submitButton = document.querySelector("#submit-button");
|
||||
const resetButton = document.querySelector("#reset-button");
|
||||
|
||||
assert_false(requiredInput.validity.valid);
|
||||
assert_false(requiredTextarea.validity.valid);
|
||||
assert_false(requiredCheckbox.validity.valid);
|
||||
assert_false(requiredDate.validity.valid);
|
||||
// The selector can't match because no interaction has happened.
|
||||
assert_false(requiredInput.matches(":user-valid"), "Initially does not match :user-valid");
|
||||
assert_false(requiredInput.matches(":user-invalid"), "Initially does not match :user-invalid");
|
||||
|
@ -96,6 +99,9 @@ promise_test(async () => {
|
|||
assert_false(requiredCheckbox.matches(":user-valid"), "Initially does not match :user-valid");
|
||||
assert_false(requiredCheckbox.matches(":user-invalid"), "Initially does not match :user-invalid");
|
||||
|
||||
assert_false(requiredDate.matches(":user-valid"), "Initially does not match :user-valid");
|
||||
assert_false(requiredDate.matches(":user-invalid"), "Initially does not match :user-invalid");
|
||||
|
||||
submitButton.click();
|
||||
|
||||
assert_true(requiredInput.matches(":user-invalid"), "Submitted the form, input is validated");
|
||||
|
@ -107,6 +113,9 @@ promise_test(async () => {
|
|||
assert_true(requiredCheckbox.matches(":user-invalid"), "Submitted the form, checkbox is validated");
|
||||
assert_false(requiredCheckbox.matches(":user-valid"), "Submitted the form, checkbox is validated");
|
||||
|
||||
assert_true(requiredDate.matches(":user-invalid"), "Submitted the form, date input is validated");
|
||||
assert_false(requiredDate.matches(":user-valid"), "Submitted the form, date input is validated");
|
||||
|
||||
resetButton.click();
|
||||
|
||||
assert_false(requiredInput.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
|
||||
|
@ -118,6 +127,9 @@ promise_test(async () => {
|
|||
assert_false(requiredCheckbox.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
|
||||
assert_false(requiredCheckbox.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
|
||||
|
||||
assert_false(requiredDate.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
|
||||
assert_false(requiredDate.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
|
||||
|
||||
// Test programmatic form submission with constraint validation.
|
||||
form.requestSubmit();
|
||||
|
||||
|
@ -129,6 +141,9 @@ promise_test(async () => {
|
|||
|
||||
assert_true(requiredCheckbox.matches(":user-invalid"), "Called form.requestSubmit(), checkbox is validated");
|
||||
assert_false(requiredCheckbox.matches(":user-valid"), "Called form.requestSubmit(), checkbox is validated");
|
||||
|
||||
assert_true(requiredDate.matches(":user-invalid"), "Called form.requestSubmit(), date input is validated");
|
||||
assert_false(requiredDate.matches(":user-valid"), "Called form.requestSubmit(), date input is validated");
|
||||
}, ":user-invalid selector properly interacts with submit & reset buttons");
|
||||
|
||||
// historical: https://github.com/w3c/csswg-drafts/issues/1329
|
||||
|
@ -193,4 +208,38 @@ promise_test(async () => {
|
|||
assert_true(checkbox.matches(':user-invalid'),
|
||||
'Checkbox should match :user-invalid after clicking twice.');
|
||||
}, 'A required checkbox should match :user-invalid if the user unchecks it and blurs.');
|
||||
|
||||
promise_test(async () => {
|
||||
const date = document.getElementById('required-date');
|
||||
|
||||
const resetButton = document.getElementById('reset-button');
|
||||
resetButton.click();
|
||||
assert_false(date.matches(':user-invalid'),
|
||||
'date input should not match :user-invalid at the start of the test.');
|
||||
assert_equals(date.value, '',
|
||||
'date input should not have a value at the start of the test.');
|
||||
|
||||
date.value = '2024-04-15';
|
||||
assert_false(date.matches(':user-invalid'),
|
||||
'date should not match :user-invalid after programatically changing value.');
|
||||
date.value = '';
|
||||
assert_false(date.matches(':user-invalid'),
|
||||
'date should not match :user-invalid after programatically changing value.');
|
||||
|
||||
const tabKey = '\uE004';
|
||||
const backspace = '\uE003';
|
||||
date.focus();
|
||||
// Press tab twice at the end to make sure that focus has left the input.
|
||||
await test_driver.send_keys(date, `1${tabKey}1${tabKey}1234${tabKey}${tabKey}`);
|
||||
assert_not_equals(document.activeElement, date,
|
||||
'Pressing tab twice after typing in the date should have blurred the input.');
|
||||
assert_equals(date.value, '1234-01-01',
|
||||
'Date input value should match the testdriver input.');
|
||||
date.focus();
|
||||
await test_driver.send_keys(date, backspace);
|
||||
assert_equals(date.value, '',
|
||||
'Date input value should be cleared when deleting one of the sub-values.');
|
||||
assert_true(date.matches(':user-invalid'),
|
||||
'Date input should match :user-invalid after typing in an invalid value.');
|
||||
}, 'A required date should match :user-invalid if the user unchecks it and blurs.');
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel=author href="mailto:jarhar@chromium.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/selectors/#user-pseudos">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/#selector-user-invalid">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
|
||||
<!-- This test asserts specifics of keyboard behavior in multifield inputs,
|
||||
like type=date and type=time, in ways that are not specified. -->
|
||||
|
||||
<form>
|
||||
<input id=date type=date required>
|
||||
<input id=time type=time required>
|
||||
<input id=datetime-local type=datetime-local required>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const tabKey = '\uE004';
|
||||
const backspace = '\uE003';
|
||||
|
||||
promise_test(async () => {
|
||||
const date = document.getElementById('date');
|
||||
assert_false(date.matches(':user-valid'),
|
||||
'Date input should not match :user-valid at the start of the test.');
|
||||
assert_false(date.matches(':user-invalid'),
|
||||
'Date input should not match :user-invalid at the start of the test.');
|
||||
assert_equals(date.value, '',
|
||||
'Date input should not have a value at the start of the test.');
|
||||
|
||||
date.focus();
|
||||
await test_driver.send_keys(date, `1${tabKey}`);
|
||||
assert_equals(date.value, '',
|
||||
'Date input value should not be set after partially inputting the date.');
|
||||
assert_false(date.matches(':user-valid'),
|
||||
'Date input should not match :user-valid after partially inputting the date.');
|
||||
assert_false(date.matches(':user-invalid'),
|
||||
'Date input should not match :user-invalid after partially inputting the date.');
|
||||
|
||||
await test_driver.send_keys(date, `1${tabKey}1234${tabKey}`);
|
||||
assert_equals(date.value, '1234-01-01',
|
||||
'Date input value should match the testdriver input.');
|
||||
assert_true(date.matches(':user-valid'),
|
||||
'Date input should match :user-valid after typing in a complete value.');
|
||||
assert_false(date.matches(':user-invalid'),
|
||||
'Date input should not match :user-invalid after typing in a complete value.');
|
||||
|
||||
date.blur();
|
||||
date.focus();
|
||||
await test_driver.send_keys(date, backspace);
|
||||
assert_equals(date.value, '',
|
||||
'Date input value should be cleared when deleting one of the sub-values.');
|
||||
assert_false(date.matches(':user-valid'),
|
||||
'Date input should not match :user-valid after typing in an invalid value.');
|
||||
assert_true(date.matches(':user-invalid'),
|
||||
'Date input should match :user-invalid after typing in an invalid value.');
|
||||
}, '<input type=date> keyboard behavior for :user-valid/:user-invalid.');
|
||||
|
||||
promise_test(async () => {
|
||||
const time = document.getElementById('time');
|
||||
assert_false(time.matches(':user-valid'),
|
||||
'Time input should not match :user-valid at the start of the test.');
|
||||
assert_false(time.matches(':user-invalid'),
|
||||
'Time input should not match :user-invalid at the start of the test.');
|
||||
assert_equals(time.value, '',
|
||||
'Time input should not have a value at the start of the test.');
|
||||
|
||||
time.focus();
|
||||
await test_driver.send_keys(time, `1${tabKey}`);
|
||||
assert_equals(time.value, '',
|
||||
'Time input value should not be set after partially inputting the time.');
|
||||
assert_false(time.matches(':user-valid'),
|
||||
'Time input should not match :user-valid after partially inputting the time.');
|
||||
assert_false(time.matches(':user-invalid'),
|
||||
'Time input should not match :user-invalid after partially inputting the time.');
|
||||
|
||||
await test_driver.send_keys(time, `2${tabKey}a${tabKey}`);
|
||||
assert_equals(time.value, '01:02',
|
||||
'Time input value should match the testdriver input.');
|
||||
assert_true(time.matches(':user-valid'),
|
||||
'Time input should match :user-valid after typing in a complete value.');
|
||||
assert_false(time.matches(':user-invalid'),
|
||||
'Time input should not match :user-invalid after typing in a complete value.');
|
||||
|
||||
time.blur();
|
||||
time.focus();
|
||||
await test_driver.send_keys(time, backspace);
|
||||
assert_equals(time.value, '',
|
||||
'Time input value should be cleared when deleting one of the sub-values.');
|
||||
assert_false(time.matches(':user-valid'),
|
||||
'Time input should not match :user-valid after typing in an invalid value.');
|
||||
assert_true(time.matches(':user-invalid'),
|
||||
'Time input should match :user-invalid after typing in an invalid value.');
|
||||
}, '<input type=time> keyboard behavior for :user-valid/:user-invalid.');
|
||||
|
||||
promise_test(async () => {
|
||||
const dateTimeLocal = document.getElementById('datetime-local');
|
||||
assert_false(dateTimeLocal.matches(':user-valid'),
|
||||
'Datetime input should not match :user-valid at the start of the test.');
|
||||
assert_false(dateTimeLocal.matches(':user-invalid'),
|
||||
'Datetime input should not match :user-invalid at the start of the test.');
|
||||
assert_equals(dateTimeLocal.value, '',
|
||||
'Datetime input should not have a value at the start of the test.');
|
||||
|
||||
dateTimeLocal.focus();
|
||||
await test_driver.send_keys(dateTimeLocal, `1${tabKey}`);
|
||||
assert_equals(dateTimeLocal.value, '',
|
||||
'Datetime input value should not be set after partially inputting the dateTimeLocal.');
|
||||
assert_false(dateTimeLocal.matches(':user-valid'),
|
||||
'Datetime input should not match :user-valid after partially inputting the dateTimeLocal.');
|
||||
assert_false(dateTimeLocal.matches(':user-invalid'),
|
||||
'Datetime input should not match :user-invalid after partially inputting the dateTimeLocal.');
|
||||
|
||||
await test_driver.send_keys(dateTimeLocal, `1${tabKey}1234${tabKey}1${tabKey}2${tabKey}a${tabKey}`);
|
||||
assert_equals(dateTimeLocal.value, '1234-01-01T01:02',
|
||||
'Datetime input value should match the testdriver input.');
|
||||
assert_true(dateTimeLocal.matches(':user-valid'),
|
||||
'Datetime input should match :user-valid after typing in a complete value.');
|
||||
assert_false(dateTimeLocal.matches(':user-invalid'),
|
||||
'Datetime input should not match :user-invalid after typing in a complete value.');
|
||||
|
||||
dateTimeLocal.blur();
|
||||
dateTimeLocal.focus();
|
||||
await test_driver.send_keys(dateTimeLocal, backspace);
|
||||
assert_equals(dateTimeLocal.value, '',
|
||||
'Datetime input value should be cleared when deleting one of the sub-values.');
|
||||
assert_false(dateTimeLocal.matches(':user-valid'),
|
||||
'Datetime input should not match :user-valid after typing in an invalid value.');
|
||||
assert_true(dateTimeLocal.matches(':user-invalid'),
|
||||
'Datetime input should match :user-invalid after typing in an invalid value.');
|
||||
}, '<input type=datetime-local> keyboard behavior for :user-valid/:user-invalid.');
|
||||
</script>
|
|
@ -29,6 +29,7 @@
|
|||
<input placeholder="Optional field" id="optional-input"><br>
|
||||
<textarea placeholder="Optional field" id="optional-textarea"></textarea><br>
|
||||
<input type="checkbox" id="optional-checkbox"><br>
|
||||
<input type="date" id="optional-date"><br>
|
||||
<input required placeholder="Required field"> <!-- Prevent the form from navigating with this invalid input -->
|
||||
<input type="submit" id="submit-button">
|
||||
<input type="reset" id="reset-button">
|
||||
|
@ -77,12 +78,14 @@ promise_test(async () => {
|
|||
const optionalInput = document.querySelector("#optional-input");
|
||||
const optionalTextarea = document.querySelector("#optional-textarea");
|
||||
const optionalCheckbox = document.querySelector("#optional-checkbox");
|
||||
const optionalDate = document.querySelector("#optional-date");
|
||||
const submitButton = document.querySelector("#submit-button");
|
||||
const resetButton = document.querySelector("#reset-button");
|
||||
|
||||
assert_true(optionalInput.validity.valid);
|
||||
assert_true(optionalTextarea.validity.valid);
|
||||
assert_true(optionalCheckbox.validity.valid);
|
||||
assert_true(optionalDate.validity.valid);
|
||||
// The selector can't match because no interaction has happened.
|
||||
assert_false(optionalInput.matches(":user-valid"), "Initially does not match :user-valid");
|
||||
assert_false(optionalInput.matches(":user-invalid"), "Initially does not match :user-invalid");
|
||||
|
@ -93,6 +96,9 @@ promise_test(async () => {
|
|||
assert_false(optionalCheckbox.matches(":user-valid"), "Initially does not match :user-valid");
|
||||
assert_false(optionalCheckbox.matches(":user-invalid"), "Initially does not match :user-invalid");
|
||||
|
||||
assert_false(optionalDate.matches(":user-valid"), "Initially does not match :user-valid");
|
||||
assert_false(optionalDate.matches(":user-invalid"), "Initially does not match :user-invalid");
|
||||
|
||||
submitButton.click();
|
||||
|
||||
assert_true(optionalInput.matches(":user-valid"), "Submitted the form, input is validated");
|
||||
|
@ -104,6 +110,9 @@ promise_test(async () => {
|
|||
assert_true(optionalCheckbox.matches(":user-valid"), "Submitted the form, checkbox is validated");
|
||||
assert_false(optionalCheckbox.matches(":user-invalid"), "Submitted the form, checkbox is validated");
|
||||
|
||||
assert_true(optionalDate.matches(":user-valid"), "Submitted the form, date is validated");
|
||||
assert_false(optionalDate.matches(":user-invalid"), "Submitted the form, date is validated");
|
||||
|
||||
resetButton.click();
|
||||
|
||||
assert_false(optionalInput.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
|
||||
|
@ -115,6 +124,9 @@ promise_test(async () => {
|
|||
assert_false(optionalCheckbox.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
|
||||
assert_false(optionalCheckbox.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
|
||||
|
||||
assert_false(optionalDate.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
|
||||
assert_false(optionalDate.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
|
||||
|
||||
// Test programmatic form submission with constraint validation.
|
||||
form.requestSubmit();
|
||||
|
||||
|
@ -126,6 +138,9 @@ promise_test(async () => {
|
|||
|
||||
assert_true(optionalCheckbox.matches(":user-valid"), "Called form.requestSubmit(), checkbox is validated");
|
||||
assert_false(optionalCheckbox.matches(":user-invalid"), "Called form.requestSubmit(), checkbox is validated");
|
||||
|
||||
assert_true(optionalDate.matches(":user-valid"), "Called form.requestSubmit(), date is validated");
|
||||
assert_false(optionalDate.matches(":user-invalid"), "Called form.requestSubmit(), date is validated");
|
||||
}, ":user-valid selector properly interacts with submit & reset buttons");
|
||||
|
||||
promise_test(async () => {
|
||||
|
@ -151,4 +166,33 @@ promise_test(async () => {
|
|||
assert_true(checkbox.matches(':user-valid'),
|
||||
'Checkbox should match :user-valid after clicking once.');
|
||||
}, 'Checkboxes should match :user-valid after the user clicks on it.');
|
||||
|
||||
promise_test(async () => {
|
||||
const date = document.getElementById('optional-date');
|
||||
|
||||
const resetButton = document.getElementById('reset-button');
|
||||
resetButton.click();
|
||||
assert_false(date.matches(':user-valid'),
|
||||
'Date input should not match :user-valid at the start of the test.');
|
||||
assert_equals(date.value, '',
|
||||
'Date input should not have a value at the start of the test.');
|
||||
|
||||
date.value = '2024-04-15';
|
||||
assert_false(date.matches(':user-valid'),
|
||||
'Date input should not match :user-valid after programatically changing value.');
|
||||
date.value = '';
|
||||
assert_false(date.matches(':user-valid'),
|
||||
'Date input should not match :user-valid after programatically changing value.');
|
||||
|
||||
const tabKey = '\uE004';
|
||||
date.focus();
|
||||
// Press tab twice at the end to make sure that focus has left the input.
|
||||
await test_driver.send_keys(date, `1${tabKey}1${tabKey}1234${tabKey}${tabKey}`);
|
||||
assert_not_equals(document.activeElement, date,
|
||||
'Pressing tab twice after typing in the date should have blurred the input.');
|
||||
assert_equals(date.value, '1234-01-01',
|
||||
'Date input value should match the testdriver input.');
|
||||
assert_true(date.matches(':user-valid'),
|
||||
'Date input should match :user-valid after typing in a value.');
|
||||
}, 'Date inputs should match :user-valid after the user types a value into it.');
|
||||
</script>
|
||||
|
|
Загрузка…
Ссылка в новой задаче