summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/selectors/user-valid.html
blob: 7a12eb237d34af1645730435f44509a9af882677 (plain)
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-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 type="checkbox" id="optional-checkbox"><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");

  input.value = "test@example.com";

  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, "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 optionalCheckbox = document.querySelector("#optional-checkbox");
  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);
  // 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");

  assert_false(optionalCheckbox.matches(":user-valid"), "Initially does not match :user-valid");
  assert_false(optionalCheckbox.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");

  assert_true(optionalCheckbox.matches(":user-valid"), "Submitted the form, checkbox is validated");
  assert_false(optionalCheckbox.matches(":user-invalid"), "Submitted the form, checkbox 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");

  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");

  // 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");

  assert_true(optionalCheckbox.matches(":user-valid"), "Called form.requestSubmit(), checkbox is validated");
  assert_false(optionalCheckbox.matches(":user-invalid"), "Called form.requestSubmit(), checkbox is validated");
}, ":user-valid selector properly interacts with submit & reset buttons");

promise_test(async () => {
  const checkbox = document.getElementById('optional-checkbox');

  const resetButton = document.getElementById('reset-button');
  resetButton.click();
  assert_false(checkbox.matches(':user-valid'),
    'Checkbox should not match :user-valid at the start of the test.');
  assert_false(checkbox.checked,
    'Checkbox should not be checked at the start of the test.');

  checkbox.checked = true;
  assert_false(checkbox.matches(':user-valid'),
    'Checkbox should not match :user-valid after programatically changing value.');
  checkbox.checked = false;
  assert_false(checkbox.matches(':user-valid'),
    'Checkbox should not match :user-valid after programatically changing value.');

  await test_driver.click(checkbox);
  assert_true(checkbox.checked, 'Checkbox should be checked after clicking once.');

  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.');
</script>