blob: 6ecc2dc694d7486c18523be2d2301d30a306d1bc [file] [log] [blame]
Joey Arhar57e5278f2023-08-09 04:39:441<!doctype html>
2<meta name=variant content="?dialog">
3<meta name=variant content="?CloseWatcher">
4<script src="/resources/testharness.js"></script>
5<script src="/resources/testharnessreport.js"></script>
6<script src="/resources/testdriver.js"></script>
7<script src="/resources/testdriver-vendor.js"></script>
8<script src="/resources/testdriver-actions.js"></script>
9<script src="resources/helpers.js"></script>
10
11<body>
12<script>
13const type = location.search.substring(1);
14const waitForPotentialCloseEvent = () => {
15 // CloseWatchers fire close events synchronously, but dialog elements wait
16 // for a rAF before firing them.
17 return new Promise(resolve => requestAnimationFrame(resolve));
18};
19
20promise_test(async t => {
21 const events = [];
22 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
23 freeWatcher.addEventListener("cancel", e => e.preventDefault());
24
25 await dialogResilientBless(freeWatcher, () => freeWatcher.close());
26 await waitForPotentialCloseEvent();
27
28 assert_array_equals(events, ["freeWatcher close"]);
29}, "Close watchers created without user activation, but close()d via user activation, do not fire cancel");
30
31promise_test(async t => {
32 const events = [];
33 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
34
35 await dialogResilientBless(freeWatcher, () => sendCloseRequest());
36 await waitForPotentialCloseEvent();
37
38 assert_array_equals(events, ["freeWatcher cancel", "freeWatcher close"]);
39}, "Close watchers created without user activation, but closed via a close request after user activation, fires cancel");
40
41promise_test(async t => {
42 const events = [];
43 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
44 freeWatcher.addEventListener("cancel", e => e.preventDefault());
45
46 await dialogResilientBless(freeWatcher, () => sendCloseRequest());
47 await waitForPotentialCloseEvent();
48
49 assert_array_equals(events, ["freeWatcher cancel"]);
50}, "Close watchers created without user activation, but closed via a close request after user activation, fires cancel, which can be preventDefault()ed");
51
52promise_test(async t => {
53 const events = [];
54 createRecordingCloseWatcher(t, events, "freeWatcher", type);
55 createRecordingCloseWatcher(t, events, "watcher1", type);
56 createRecordingCloseWatcher(t, events, "watcher2", type);
57
58 await sendCloseRequest();
59 await waitForPotentialCloseEvent();
60 assert_array_equals(events, ["watcher2 close", "watcher1 close", "freeWatcher close"]);
61}, "Multiple close watchers created without user activation close together (with no cancel)");
62
63promise_test(async t => {
64 const events = [];
65 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
66 await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type, freeWatcher);
67
68 await sendCloseRequest();
69 await waitForPotentialCloseEvent();
70 assert_array_equals(events, ["activationWatcher close"]);
71
72 await sendCloseRequest();
73 await waitForPotentialCloseEvent();
74 assert_array_equals(events, ["activationWatcher close", "freeWatcher close"]);
75}, "Creating a close watcher from user activation keeps it separate from the free close watcher, but they don't fire cancel");
76
77promise_test(async t => {
78 const events = [];
79 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
80 const activationWatcher = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type, freeWatcher);
81
82 await dialogResilientBless(activationWatcher, () => sendCloseRequest());
83 await waitForPotentialCloseEvent();
84 assert_array_equals(events, ["activationWatcher cancel", "activationWatcher close"]);
85
86 await dialogResilientBless(freeWatcher, () => sendCloseRequest());
87 await waitForPotentialCloseEvent();
88 assert_array_equals(events, ["activationWatcher cancel", "activationWatcher close", "freeWatcher cancel", "freeWatcher close"]);
89}, "Creating a close watcher from user activation, and closing close watchers with a close request after user activation, fires cancel");
90
91promise_test(async t => {
92 const events = [];
93 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
94 const activationWatcher1 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher1", type, freeWatcher);
95 await createBlessedRecordingCloseWatcher(t, events, "activationWatcher2", type, activationWatcher1);
96
97 await sendCloseRequest();
98 await waitForPotentialCloseEvent();
99 assert_array_equals(events, ["activationWatcher2 close"]);
100
101 await sendCloseRequest();
102 await waitForPotentialCloseEvent();
103 assert_array_equals(events, ["activationWatcher2 close", "activationWatcher1 close"]);
104}, "Multiple close watchers created with user activation close in reverse order");
105
106promise_test(async t => {
107 const events = [];
108 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
109 const activationWatcher1 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher1", type, freeWatcher);
110 const activationWatcher2 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher2", type, activationWatcher1);
111 await createBlessedRecordingCloseWatcher(t, events, "activationWatcher3", type, activationWatcher2);
112 createRecordingCloseWatcher(t, events, "watcher4", type);
113
114 await sendCloseRequest();
115 await waitForPotentialCloseEvent();
116 assert_array_equals(events, ["watcher4 close", "activationWatcher3 close"]);
117
118 await sendCloseRequest();
119 await waitForPotentialCloseEvent();
120 assert_array_equals(events, ["watcher4 close", "activationWatcher3 close", "activationWatcher2 close"]);
121
122 await sendCloseRequest();
123 await waitForPotentialCloseEvent();
124 assert_array_equals(events, ["watcher4 close", "activationWatcher3 close", "activationWatcher2 close", "activationWatcher1 close"]);
125
126 await sendCloseRequest();
127 await waitForPotentialCloseEvent();
128 assert_array_equals(events, ["watcher4 close", "activationWatcher3 close", "activationWatcher2 close", "activationWatcher1 close", "freeWatcher close"]);
129}, "3 user activations let you have 3 + 1 = 4 ungrouped close watchers/0 cancel events");
130
131promise_test(async t => {
132 const events = [];
133 const freeWatcher1 = createRecordingCloseWatcher(t, events, "freeWatcher1", type);
134
135 await sendCloseRequest();
136 await waitForPotentialCloseEvent();
137 assert_array_equals(events, ["freeWatcher1 close"]);
138
139 const freeWatcher2 = createRecordingCloseWatcher(t, events, "freeWatcher2", type);
140
141 await sendCloseRequest();
142 await waitForPotentialCloseEvent();
143 assert_array_equals(events, ["freeWatcher1 close", "freeWatcher2 close"]);
144}, "closing the free close watcher via a close request allows a new free one to be created without user activation, and it receives a second close request");
145
146promise_test(async t => {
147 const events = [];
148 const activationWatcher = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type);
149 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
150
151 await sendCloseRequest();
152 await waitForPotentialCloseEvent();
153 assert_array_equals(events, ["freeWatcher close"]);
154
155 await sendCloseRequest();
156 await waitForPotentialCloseEvent();
157 assert_array_equals(events, ["freeWatcher close", "activationWatcher close"]);
158}, "The second watcher can be the free watcher, if the first is created with user activation");
159
160promise_test(async t => {
161 const events = [];
162 const activationWatcher1 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher1", type);
163 const activationWatcher2 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher2", type, activationWatcher1);
164 const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
165
166 await sendCloseRequest();
167 await waitForPotentialCloseEvent();
168 assert_array_equals(events, ["freeWatcher close"]);
169
170 await sendCloseRequest();
171 await waitForPotentialCloseEvent();
172 assert_array_equals(events, ["freeWatcher close", "activationWatcher2 close"]);
173
174 await sendCloseRequest();
175 await waitForPotentialCloseEvent();
176 assert_array_equals(events, ["freeWatcher close", "activationWatcher2 close", "activationWatcher1 close"]);
177}, "The third watcher can be the free watcher, if the first two are created with user activation");
178
179promise_test(async t => {
180 const events = [];
181 const freeWatcher1 = createRecordingCloseWatcher(t, events, "freeWatcher1");
182
183 if (freeWatcher1 instanceof HTMLDialogElement) {
184 freeWatcher1.close();
185 } else {
186 freeWatcher1.destroy();
187 }
188 assert_array_equals(events, []);
189
190 const freeWatcher2 = createRecordingCloseWatcher(t, events, "freeWatcher2");
191
192 await sendCloseRequest();
193 assert_array_equals(events, ["freeWatcher2 close"]);
194}, "destroy()ing the free close watcher allows a new free one to be created without user activation, and it receives the close request");
195</script>