| <!doctype html> | |
| <title>Support for the :user-valid pseudo-class</title> | |
| <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> | |
| <link rel="help" href="https://drafts.csswg.org/selectors/#user-pseudos"> | |
| <link rel="help" href="https://html.spec.whatwg.org/#selector-user-valid"> | |
| <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> | |
| <style> | |
| :is(input:not([type=submit], [type=reset]), textarea) { | |
| border: 2px solid black; | |
| } | |
| :is(input:not([type=submit], [type=reset]), textarea):user-valid { | |
| border-color: green; | |
| } | |
| :is(input:not([type=submit], [type=reset]), textarea):user-invalid { | |
| border-color: red; | |
| } | |
| </style> | |
| <input id="initially-valid" type="email"> | |
| <p>Test form interactions (reset / submit):</p> | |
| <form id="form"> | |
| <input placeholder="Optional field" id="optional-input"><br> | |
| <textarea placeholder="Optional field" id="optional-textarea"></textarea><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"> | |
| </form> | |
| <script> | |
| promise_test(async () => { | |
| const input = document.querySelector("#initially-valid"); | |
| assert_true(input.validity.valid); | |
| // The selector can't match because no interaction has happened. | |
| assert_false(input.matches(":user-valid"), "Initially does not match :user-valid"); | |
| assert_false(input.matches(":user-invalid"), "Initially does not match :user-invalid"); | |
| await test_driver.click(input); | |
| input.blur(); | |
| assert_false(input.matches(":user-valid"), "No change happened, still does not match :user-valid"); | |
| assert_false(input.matches(":user-invalid"), "No change happened, still does not match :user-invalid"); | |
| await test_driver.click(input); | |
| await test_driver.send_keys(input, "test@example.com"); | |
| input.blur(); | |
| assert_true(input.matches(":user-valid"), "Typed a valid email, :user-valid now matches"); | |
| assert_false(input.matches(":user-invalid"), "Typed a valid email, :user-invalid does not match"); | |
| input.required = true; | |
| input.value = ""; | |
| assert_false(input.matches(":user-valid"), "Cleared required input, :user-valid no longer matches"); | |
| assert_true(input.matches(":user-invalid"), "Cleared required input, :user-invalid now matches"); | |
| }, ":user-valid selector should respond to user action"); | |
| promise_test(async () => { | |
| const form = document.querySelector("#form"); | |
| const optionalInput = document.querySelector("#optional-input"); | |
| const optionalTextarea = document.querySelector("#optional-textarea"); | |
| const submitButton = document.querySelector("#submit-button"); | |
| const resetButton = document.querySelector("#reset-button"); | |
| assert_true(optionalInput.validity.valid); | |
| assert_true(optionalTextarea.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"); | |
| assert_false(optionalTextarea.matches(":user-valid"), "Initially does not match :user-valid"); | |
| assert_false(optionalTextarea.matches(":user-invalid"), "Initially does not match :user-invalid"); | |
| submitButton.click(); | |
| assert_true(optionalInput.matches(":user-valid"), "Submitted the form, input is validated"); | |
| assert_false(optionalInput.matches(":user-invalid"), "Submitted the form, input is validated"); | |
| assert_true(optionalTextarea.matches(":user-valid"), "Submitted the form, textarea is validated"); | |
| assert_false(optionalTextarea.matches(":user-invalid"), "Submitted the form, textarea is validated"); | |
| resetButton.click(); | |
| assert_false(optionalInput.matches(":user-valid"), "Reset the form, user-interacted flag is reset"); | |
| assert_false(optionalInput.matches(":user-invalid"), "Reset the form, user-interacted flag is reset"); | |
| assert_false(optionalTextarea.matches(":user-valid"), "Reset the form, user-interacted flag is reset"); | |
| assert_false(optionalTextarea.matches(":user-invalid"), "Reset the form, user-interacted flag is reset"); | |
| // Test programmatic form submission with constraint validation. | |
| form.requestSubmit(); | |
| assert_true(optionalInput.matches(":user-valid"), "Called form.requestSubmit(), input is validated"); | |
| assert_false(optionalInput.matches(":user-invalid"), "Called form.requestSubmit(), input is validated"); | |
| assert_true(optionalTextarea.matches(":user-valid"), "Called form.requestSubmit(), textarea is validated"); | |
| assert_false(optionalTextarea.matches(":user-invalid"), "Called form.requestSubmit(), textarea is validated"); | |
| }, ":user-valid selector properly interacts with submit & reset buttons"); | |
| </script> |