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
155
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test for valid state with autocomplete</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="satchel_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<style>
input:invalid {
border: red 1px solid;
}
</style>
</head>
<body>
<p id="display"></p>
<div id="content">
<form id="form1">
<input type="email" name="field1">
<button type="submit">Submit</button>
</form>
</div>
<pre id="test">
<script class="testbody">
var input = document.querySelector("input[name=field1]");
async function runTest() {
const kSetUserInputCancelable = SpecialPowers.getBoolPref("dom.input_event.allow_to_cancel_set_user_input");
let resolveFunc = null;
function onPopup() {
if (resolveFunc) {
resolveFunc();
resolveFunc = null;
}
}
registerPopupShownListener(onPopup);
function promisePopup() {
return new Promise(resolve => {
resolveFunc = resolve;
});
}
let beforeInputFired = false;
let inputFired = false;
let waitForPopup = promisePopup();
input.focus();
input.addEventListener("beforeinput", (event) => {
ok(!beforeInputFired, '"input" event should be fired only once at typing');
beforeInputFired = true;
ok(event.cancelable,
'"beforeinput" event for "insertText" should be cancelable');
is(event.inputType, "insertText",
"inputType of \"beforeinput\" event should be \"insertText\"");
ok(input.validity.valid,
"Should be valid immediately before inserting a character");
ok(!input.matches(":invalid"),
"Shouldn't match \":invalid\" immediately before inserting a character");
}, {once: true});
input.addEventListener("input", (event) => {
ok(!inputFired, '"input" event should be fired only once at typing');
inputFired = true;
is(event.inputType, "insertText",
"inputType of \"input\" event should be \"insertText\"");
ok(!input.validity.valid,
"Should be invalid immediately after inserting a character");
ok(input.matches(":invalid"),
"Should match \":invalid\" immediately after inserting a character");
}, {once: true});
beforeInputFired = false;
inputFired = false;
synthesizeKey("e");
ok(beforeInputFired, '"beforeinput" event should have been fired at typing "e"');
ok(inputFired, '"input" event should have been fired at typing "e"');
await waitForPopup;
synthesizeKey("KEY_ArrowDown");
input.addEventListener("beforeinput", (event) => {
ok(!beforeInputFired, '"input" event should be fired only once at typing');
beforeInputFired = true;
is(event.cancelable, kSetUserInputCancelable,
`"beforeinput" event for "insertReplacementText" should be cancelable unless it's suppressed by the pref`);
is(event.inputType, "insertReplacementText",
"inputType of \"beforeinput\" event should be \"insertReplacementText\"");
ok(!input.validity.valid,
"Should be invalid immediately before selecting valid item in autocomplete list");
ok(input.matches(":invalid"),
"Should match \":invalid\" immediately before selecting valid item in autocomplete list");
}, {once: true});
input.addEventListener("input", (event) => {
ok(!inputFired, '"input" event should be fired only once at typing');
inputFired = true;
is(event.inputType, "insertReplacementText",
"inputType of \"input\" event should be \"insertReplacementText\"");
ok(input.validity.valid,
"Should be valid immediately after selecting valid item in autocomplete list");
ok(!input.matches(":invalid"),
"Shouldn't match \":invalid\" immediately after selecting valid item in autocomplete list");
}, {once: true});
beforeInputFired = false;
inputFired = false;
synthesizeKey("KEY_Enter"); // Select valid item
ok(beforeInputFired, '"beforeinput" event should have been fired at selecting valid item');
ok(inputFired, '"input" event should have been fired at selecting valid item');
waitForPopup = promisePopup();
synthesizeKey("KEY_Backspace");
await waitForPopup;
synthesizeKey("KEY_ArrowDown");
synthesizeKey("KEY_ArrowDown");
input.addEventListener("beforeinput", (event) => {
ok(!beforeInputFired, '"input" event should be fired only once at typing');
beforeInputFired = true;
is(event.cancelable, kSetUserInputCancelable,
`"beforeinput" event for "insertReplacementText" should be cancelable unless it's suppressed by the pref`);
is(event.inputType, "insertReplacementText",
"inputType of \"beforeinput\" event should be \"insertReplacementText\"");
ok(input.validity.valid,
"Should be valid immediately before selecting invalid item in autocomplete list");
ok(!input.matches(":invalid"),
"Shouldn't match \":invalid\" immediately after selecting invalid item in autocomplete list");
}, {once: true});
input.addEventListener("input", (event) => {
ok(!inputFired, '"input" event should be fired only once at typing');
inputFired = true;
is(event.inputType, "insertReplacementText",
"inputType of \"input\" event should be \"insertReplacementText\"");
ok(!input.validity.valid,
"Should be invalid immediately after selecting invalid item in autocomplete list");
ok(input.matches(":invalid"),
"Should match \":invalid\" immediately after selecting invalid item in autocomplete list");
}, {once: true});
beforeInputFired = false;
inputFired = false;
synthesizeKey("KEY_Enter"); // Select invalid item
ok(beforeInputFired, '"beforeinput" event should have been fired at selecting invalid item');
ok(inputFired, '"input" event should have been fired at selecting invalid item');
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(() => {
updateFormHistory([
{ op: "remove" },
{ op: "add", fieldname: "field1", value: "email@example.com" },
{ op: "add", fieldname: "field1", value: "email@example.com." },
], runTest);
});
</script>
</pre>
</body>
|