Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(630)

Side by Side Diff: third_party/WebKit/LayoutTests/fast/events/inputevents/inputevent-drag-drop.html

Issue 2374743002: [InputEvent] Support |deleteByDrag|, |insertFromDrop| and fire in sequential order (Closed)
Patch Set: Yosin's review 2 Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>InputEvent: beforeinput for Drag and Drop</title>
5 <script src="../../../resources/testharness.js"></script>
6 <script src="../../../resources/testharnessreport.js"></script>
7 <style>
8 div, img {
9 width: 100px;
10 height: 100px;
11 }
12 </style>
13 </head>
14 <body>
15 <div id="editable1" contenteditable><img id="img" src="../resources/greenbox.png "></div>
16 <div id="editable2" contenteditable></div>
17 <textarea id="textarea1">Text</textarea>
18 <textarea id="barrier"></textarea>
19 <script>
20 function simulateDragDrop(dragElement, dropElement) {
21 eventSender.mouseMoveTo(dragElement.offsetLeft + dragElement.offsetWidth / 2 ,
22 dragElement.offsetTop + dragElement.offsetHeight / 2 );
23 eventSender.mouseDown();
24 eventSender.leapForward(600);
25 eventSender.mouseMoveTo(dropElement.offsetLeft + dropElement.offsetWidth / 2 ,
26 dropElement.offsetTop + dropElement.offsetHeight / 2 );
27 eventSender.mouseUp();
28 }
29
30 function assertCleanInitialDOM(logInfo) {
31 const editable1 = document.getElementById('editable1');
32 const editable2 = document.getElementById('editable2');
33 const textarea1 = document.getElementById('textarea1');
34 assert_equals(editable1.children.length, 1, `${logInfo}, DOM is dirty`);
35 assert_equals(editable1.children[0].tagName, 'IMG', `${logInfo}, DOM is dirt y`);
36 assert_equals(editable2.children.length, 0, `${logInfo}, DOM is dirty`);
37 assert_equals(textarea1.value, 'Text', `${logInfo}, DOM is dirty`);
38 }
39
40 test(function() {
41 assertCleanInitialDOM();
42 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe nder.');
43 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn er.');
44
45 const editable1 = document.getElementById('editable1');
46 const editable2 = document.getElementById('editable2');
47 const textarea1 = document.getElementById('textarea1');
48
49 function preventDeleteByDragListener(event) {
50 if (event.inputType == 'deleteByDrag')
51 event.preventDefault();
52 }
53
54 function preventInsertFromDropListener(event) {
55 if (event.inputType == 'insertFromDrop')
56 event.preventDefault();
57 }
58
59 const undoBarrier = document.getElementById('barrier');
60 undoBarrier.focus();
61 document.execCommand('insertText', false, 'abc');
62 function assertBarrierUnchanged() {
63 assert_equals(undoBarrier.value, 'abc');
64 }
65
66 // Normally Drag&Drop requires a single Undo.
67 simulateDragDrop(editable1, editable2);
68 testRunner.execCommand('undo');
69 assertCleanInitialDOM('Normal Drag&Drop');
70 assertBarrierUnchanged();
71
72 // Canceling |DeleteByDrag|, still require a single Undo.
73 editable1.addEventListener('beforeinput', preventDeleteByDragListener);
74 simulateDragDrop(editable1, editable2);
75 testRunner.execCommand('undo');
76 assertCleanInitialDOM('Canceling |DeleteByDrag|');
77 editable1.removeEventListener('beforeinput', preventDeleteByDragListener);
78 assertBarrierUnchanged();
79
80 // Canceling |InsertFromDrop|, still require a single Undo.
81 editable2.addEventListener('beforeinput', preventInsertFromDropListener);
82 simulateDragDrop(editable1, editable2);
83 testRunner.execCommand('undo');
84 assertCleanInitialDOM('Canceling |InsertFromDrop|');
85 editable2.removeEventListener('beforeinput', preventInsertFromDropListener);
86 assertBarrierUnchanged();
87
88 // Canceling both, shouldn't create undo entry.
89 editable1.addEventListener('beforeinput', preventDeleteByDragListener);
90 editable2.addEventListener('beforeinput', preventInsertFromDropListener);
91 simulateDragDrop(editable1, editable2);
92 assertCleanInitialDOM('Canceling both');
93 testRunner.execCommand('undo');
94 assert_equals(undoBarrier.value, '');
95 testRunner.execCommand('redo');
96 assertBarrierUnchanged();
97 editable1.removeEventListener('beforeinput', preventDeleteByDragListener);
98 editable2.removeEventListener('beforeinput', preventInsertFromDropListener);
99
100 // Two Drag&Drop, cancel first |InsertFromDrop| and second |DeleteByDrag|, s hould still create 2 undo entries.
101 editable2.addEventListener('beforeinput', preventInsertFromDropListener);
102 simulateDragDrop(editable1, editable2);
103 editable2.removeEventListener('beforeinput', preventInsertFromDropListener);
104 textarea1.addEventListener('beforeinput', preventDeleteByDragListener);
105 textarea1.select();
106 simulateDragDrop(textarea1, editable2);
107 textarea1.removeEventListener('beforeinput', preventDeleteByDragListener);
108 assert_equals(editable1.children.length, 0);
109 assert_equals(editable2.innerHTML, 'Text');
110 assert_equals(textarea1.value, 'Text');
111 // First undo.
112 testRunner.execCommand('undo');
113 assert_equals(editable1.children.length, 0);
114 assert_equals(editable2.innerHTML, '');
115 assert_equals(textarea1.value, 'Text');
116 // Second undo.
117 testRunner.execCommand('undo');
118 assert_equals(editable1.children.length, 1);
119 assert_equals(editable2.innerHTML, '');
120 assert_equals(textarea1.value, 'Text');
121 // More undo should reach to |undoBarrier|.
122 assertBarrierUnchanged();
123 testRunner.execCommand('undo');
124 assert_equals(undoBarrier.value, '');
125 testRunner.execCommand('redo');
126 }, 'Testing Drag and Drop, preventDefault() and Undo entry');
127
128 test(function() {
129 assertCleanInitialDOM();
130 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe nder.');
131 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn er.');
132
133 const editable1 = document.getElementById('editable1');
134 const editable2 = document.getElementById('editable2');
135 var eventOrderRecorder = [];
136 document.addEventListener('beforeinput', event =>
137 eventOrderRecorder.push(`beforeinput:${event.target.id}:${event.inputTyp e}`));
138 document.addEventListener('input', event =>
139 eventOrderRecorder.push(`input:${event.target.id}:${event.inputType}`));
140 ['drop', 'dragend'].forEach(eventType => document.addEventListener(
141 eventType, () => eventOrderRecorder.push(`${event.target.id}:${event Type}`)));
142
143 function testDragDropEventOrder(dragElement, dropElement, expectedOrder) {
144 assert_equals(dragElement.children.length, 1);
145 eventOrderRecorder = [];
146 simulateDragDrop(dragElement, dropElement);
147 assert_array_equals(eventOrderRecorder, expectedOrder,
148 `Testing drag ${dragElement.id} onto ${dropElement.id} actual order: ${eventOrderRecorder}`);
149 }
150
151 // Test Drag and Drop.
152 testDragDropEventOrder(editable1, editable2,
153 ['editable2:drop', 'beforeinput:img:deleteByDrag', 'input:editable1:dele teByDrag',
154 'beforeinput:editable2:insertFromDrop', 'input:editable2:insertFromDrop' , 'editable1:dragend']);
155 testRunner.execCommand('undo');
156 }, 'Testing Drag and Drop event order');
157
158 test(function() {
159 assertCleanInitialDOM();
160 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe nder.');
161 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn er.');
162
163 const editable1 = document.getElementById('editable1');
164 const editable2 = document.getElementById('editable2');
165 var lastPlainTextData = {};
166 var lastHTMLData = {};
167 document.addEventListener('beforeinput', event => {
168 lastPlainTextData[event.inputType] = event.dataTransfer ? event.dataTran sfer.getData('text/plain') : null;
169 lastHTMLData[event.inputType] = event.dataTransfer ? event.dataTransfer. getData('text/html') : null;
170 });
171
172 function testDragDropDataTransfer(inputType, dragElement, dropElement, expec tedPlainText, expectedHTML) {
173 assert_equals(dragElement.children.length, 1);
174 lastPlainTextData = {};
175 lastHTMLData = {};
176 simulateDragDrop(dragElement, dropElement);
177 assert_equals(lastPlainTextData[inputType], expectedPlainText,
178 `Testing '${inputType}' getData('text/plain')`);
179 if (expectedHTML && expectedHTML.test) {
180 assert_regexp_match(lastHTMLData[inputType], expectedHTML,
181 `Testing '${inputType}' getData('text/html')`);
182 } else {
183 assert_equals(lastHTMLData[inputType], expectedHTML,
184 `Testing '${inputType}' getData('text/html')`);
185 }
186 }
187
188 // Test Drag and Drop.
189 testDragDropDataTransfer('deleteByDrag', editable1, editable2, null, null);
190 testRunner.execCommand('undo');
191 testDragDropDataTransfer('insertFromDrop', editable1, editable2, '', /^<img. *greenbox\.png".*>$/);
192 testRunner.execCommand('undo');
193 }, 'Testing Drag and Drop dataTransfer');
194
195 test(function() {
196 assertCleanInitialDOM();
197 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe nder.');
198 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn er.');
199
200 const editable1 = document.getElementById('editable1');
201 const editable2 = document.getElementById('editable2');
202 var inputTypesToPrevent = [];
203 document.addEventListener('beforeinput', event => {
204 if (inputTypesToPrevent.indexOf(event.inputType) != -1)
205 event.preventDefault();
206 });
207
208 function testDragDropPreventDefault(preventDefaultTypes, dragElement, dropEl ement, expectedDragElementChildren, expectedDropElementChildren) {
209 assert_equals(dragElement.children.length, 1);
210 inputTypesToPrevent = preventDefaultTypes;
211 simulateDragDrop(dragElement, dropElement);
212 assert_equals(dragElement.children.length, expectedDragElementChildren,
213 'Testing preventDefault() on ${preventDefaultTypes} ${dragElement.id } children count');
214 assert_equals(dropElement.children.length, expectedDropElementChildren,
215 'Testing preventDefault() on ${preventDefaultTypes} ${dropElement.id } children count');
216 inputTypesToPrevent = [];
217 }
218
219 // Preventing single 'beforeinput' will only cancel DOM update for one event ,
220 // the remaining DOM update will still update undo stack.
221 testDragDropPreventDefault(['deleteByDrag'], editable1, editable2, 1, 1);
222 testRunner.execCommand('undo');
223 testDragDropPreventDefault(['insertFromDrop'], editable1, editable2, 0, 0);
224 testRunner.execCommand('undo');
225
226 // Adding 'insertHTML' command to undo stack.
227 editable2.focus();
228 document.execCommand('insertHTML', false, '<b>B</b><i>i</i>');
229 assert_equals(editable2.children.length, 2,
230 '"editable2" should have 2 children after "insertHTML" command');
231 // Canceling both |deleteByDrag| and |insertFromDrop| won't modify undo stac k.
232 testDragDropPreventDefault(['deleteByDrag', 'insertFromDrop'], editable1, ed itable2, 1, 2);
233 // |undo| will undo last 'insertHTML' command.
234 testRunner.execCommand('undo');
235 assert_equals(editable2.children.length, 0,
236 '"editable2" should have 0 children after undo "insertHTML"');
237 }, 'Testing Drag and Drop preventDefault()');
238
239 test(function() {
240 assertCleanInitialDOM();
241 assert_not_equals(window.eventSender, undefined, 'This test requires eventSe nder.');
242 assert_not_equals(window.testRunner, undefined, 'This test requires testRunn er.');
243
244 const editable1 = document.getElementById('editable1');
245 const editable2 = document.getElementById('editable2');
246 var eventOrderRecorder = [];
247 [editable1, editable2].forEach(editable => {
248 editable.addEventListener('beforeinput', event =>
249 eventOrderRecorder.push(`beforeinput:${editable.id}:${event.inputTyp e}`));
250 editable.addEventListener('input', event =>
251 eventOrderRecorder.push(`input:${editable.id}:${event.inputType}`));
252 editable.addEventListener('drop', event =>
253 eventOrderRecorder.push(`${editable.id}:drop`));
254 editable.addEventListener('dragend', event =>
255 eventOrderRecorder.push(`${editable.id}:dragend`));
256 });
257
258 function testDragDropEventOrder(dragElement, dropElement, expectedOrder) {
259 assert_equals(dragElement.children.length, 1);
260 eventOrderRecorder = [];
261 simulateDragDrop(dragElement, dropElement);
262 assert_array_equals(eventOrderRecorder, expectedOrder,
263 `Testing drag ${dragElement.id} onto ${dropElement.id} actual order: ${eventOrderRecorder}`);
264 }
265
266 function removeEditable1Listener() {
267 editable1.remove();
268 }
269
270 function removeEditable2Listener() {
271 editable2.remove();
272 }
273
274 // Testing remove drop target, |editable2| won't get 'beforeinput' as it's d isconnected.
275 editable1.addEventListener('beforeinput', removeEditable2Listener);
276 testDragDropEventOrder(editable1, editable2,
277 ['editable2:drop', 'beforeinput:editable1:deleteByDrag', 'input:editable 1:deleteByDrag', 'editable1:dragend']);
278 editable1.removeEventListener('beforeinput', removeEditable2Listener);
279 testRunner.execCommand('undo');
280 document.body.appendChild(editable2);
281
282 // Testing remove drag target, |editable1| won't receive DOM updates after d isconnected.
283 editable1.addEventListener('beforeinput', removeEditable1Listener);
284 testDragDropEventOrder(editable1, editable2,
285 ['editable2:drop', 'beforeinput:editable1:deleteByDrag', 'beforeinput:ed itable2:insertFromDrop',
286 'input:editable2:insertFromDrop', 'editable1:dragend']);
287 editable1.removeEventListener('beforeinput', removeEditable1Listener);
288 testRunner.execCommand('undo');
289 document.body.appendChild(editable1);
290 }, 'Testing element removed by event handler');
291 </script>
292 </body>
293 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698