-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
user-invalid.html
154 lines (120 loc) · 6.89 KB
/
user-invalid.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!doctype html>
<title>Support for the :user-invalid 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-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>
<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-invalid" type="email" value="foo">
<p>Test form interactions (reset / submit):</p>
<form id="form">
<input placeholder="Required field" required id="required-input"><br>
<textarea placeholder="Required field" required id="required-textarea"></textarea><br>
<input type="submit" id="submit-button">
<input type="reset" id="reset-button">
</form>
<script>
promise_test(async () => {
const input = document.querySelector("#initially-invalid");
assert_false(input.validity.valid, "Should be invalid");
// The selector can't match because no interaction has happened.
assert_false(input.matches(':user-invalid'));
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");
input.value = "not an email";
assert_false(input.matches(":user-valid"), "Programatically set value, :user-valid should not match");
assert_false(input.matches(":user-invalid"), "Programatically set value, :user-invalid should not match");
input.value = "";
assert_false(input.matches(":user-valid"), "Programatically cleared value, :user-valid should not match");
assert_false(input.matches(":user-invalid"), "Programatically cleared value, :user-invalid should not match");
await test_driver.click(input);
await test_driver.send_keys(input, "not an email");
input.blur();
assert_true(input.matches(":user-invalid"), "Typed an invalid email, :user-invalid now matches");
assert_false(input.matches(":user-valid"), "Typed an invalid email, :user-valid does not match");
input.value = "";
await test_driver.click(input);
await test_driver.send_keys(input, "[email protected]");
input.blur();
assert_true(input.matches(":user-valid"), "Put a valid email, :user-valid now matches");
assert_false(input.matches(":user-invalid"), "Put an valid email, :user-invalid no longer matches");
}, ':user-invalid selector should respond to user action');
promise_test(async () => {
const form = document.querySelector("#form");
const requiredInput = document.querySelector("#required-input");
const requiredTextarea = document.querySelector("#required-textarea");
const submitButton = document.querySelector("#submit-button");
const resetButton = document.querySelector("#reset-button");
assert_false(requiredInput.validity.valid);
assert_false(requiredTextarea.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");
assert_false(requiredTextarea.matches(":user-valid"), "Initially does not match :user-valid");
assert_false(requiredTextarea.matches(":user-invalid"), "Initially does not match :user-invalid");
submitButton.click();
assert_true(requiredInput.matches(":user-invalid"), "Submitted the form, input is validated");
assert_false(requiredInput.matches(":user-valid"), "Submitted the form, input is validated");
assert_true(requiredTextarea.matches(":user-invalid"), "Submitted the form, textarea is validated");
assert_false(requiredTextarea.matches(":user-valid"), "Submitted the form, textarea is validated");
resetButton.click();
assert_false(requiredInput.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
assert_false(requiredInput.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
assert_false(requiredTextarea.matches(":user-valid"), "Reset the form, user-interacted flag is reset");
assert_false(requiredTextarea.matches(":user-invalid"), "Reset the form, user-interacted flag is reset");
// Test programmatic form submission with constraint validation.
form.requestSubmit();
assert_true(requiredInput.matches(":user-invalid"), "Called form.requestSubmit(), input is validated");
assert_false(requiredInput.matches(":user-valid"), "Called form.requestSubmit(), input is validated");
assert_true(requiredTextarea.matches(":user-invalid"), "Called form.requestSubmit(), textarea is validated");
assert_false(requiredTextarea.matches(":user-valid"), "Called form.requestSubmit(), textarea is validated");
}, ":user-invalid selector properly interacts with submit & reset buttons");
// historical: https://github.com/w3c/csswg-drafts/issues/1329
test(() => {
const input = document.querySelector('input');
// matches() will throw if the selector isn't suppported
assert_throws_dom("SyntaxError", () => input.matches(':user-error'));
}, ':user-error selector should not be supported');
['required-input', 'required-textarea'].forEach(elementId => {
promise_test(async () => {
const resetButton = document.getElementById('reset-button');
const element = document.getElementById(elementId);
element.value = '';
resetButton.click();
assert_false(element.matches(':user-invalid'),
'Element should not match :user-invalid at the start of the test.');
assert_false(element.matches(':user-valid'),
'Element should not match :user-valid at the start of the test.');
const backspace = '\uE003';
element.focus();
await test_driver.send_keys(element, 'a');
await test_driver.send_keys(element, backspace);
assert_false(element.matches(':user-invalid'),
'Element should not match :user-invalid before blurring.');
assert_false(element.matches(':user-valid'),
'Element should not match :user-valid before blurring.');
element.blur();
assert_true(element.matches(':user-invalid'),
'Element should match :user-invalid after typing text and deleting it.');
assert_false(element.matches(':user-valid'),
'Element should not match :user-valid after the test.');
}, `${elementId}: A required input or textarea should match :user-invalid if a user types into it and then clears it before blurring.`);
});
</script>