summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/editing/dnd/events/events-suite-manual.html
blob: 16c6583dc82a7079efdc071686983d680c9ae387 (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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
<!DOCTYPE html>
<title>drag &amp; drop - event sequence for draggable elements</title>
<script type="text/javascript" src="/resources/testharness.js"></script>
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
<style type="text/css">
  /* use margins instead of padding to make sure the body begins at the top of the page */
  html, body {
    margin: 0;
  }
  body {
    padding: 116px 8px 8px;
  }
  #testhere div {
    height: 100px;
    width: 100px;
    position: absolute;
    top: 8px;
  }
  #orange {
    background-color: orange;
    left: 8px;
  }
  #fuchsia {
    background-color: fuchsia;
    left: 158px;
  }
  #yellow {
    background-color: yellow;
    left: 308px;
  }
  #blue {
    background-color: navy;
    left: 458px;
  }
</style>

<script>
setup(function () {},{explicit_done:true,explicit_timeout:true});
window.onload = function () {
  var orange = document.querySelector('#orange')
  var fuchsia = document.querySelector('#fuchsia')
  var yellow = document.querySelector('#yellow')
  var blue = document.querySelector('#blue')
  var body = document.body;

  var events = new Array

  orange.ondragstart = function (e) {
    events.push('orange.ondragstart');
    e.dataTransfer.effectAllowed = 'copy';
    e.dataTransfer.setData('Text', 'foo');
  };
  orange.ondrag = function () { events.push('orange.ondrag'); };
  orange.ondragenter = function () { events.push('orange.ondragenter'); };
  orange.ondragover = function () { events.push('orange.ondragover'); };
  orange.ondragleave = function () { events.push('orange.ondragleave'); };
  orange.ondrop = function () { events.push('orange.ondrop'); return false; };
  orange.ondragend = function () { events.push('orange.ondragend'); };
  orange.onmousedown = function () { events.push('orange.onmousedown'); };
  orange.onmouseup = function () { events.push('orange.onmouseup'); };

  /* Events for the fuchsia box */
  fuchsia.ondragstart = function () { events.push('pink.ondragstart'); };
  fuchsia.ondrag = function () { events.push('pink.ondrag'); };
  fuchsia.ondragenter = function () { events.push('pink.ondragenter'); };
  fuchsia.ondragover = function () { events.push('pink.ondragover'); };
  fuchsia.ondragleave = function () { events.push('pink.ondragleave'); };
  fuchsia.ondrop = function () { events.push('pink.ondrop'); return false; };
  fuchsia.ondragend = function () { events.push('pink.ondragend'); };
  fuchsia.onmousedown = function () { events.push('pink.onmousedown'); };
  fuchsia.onmouseup = function () { events.push('pink.onmouseup'); };

  /* Events for the fuchsia box */
  yellow.ondragstart = function () { events.push('yellow.ondragstart'); };
  yellow.ondrag = function () { events.push('yellow.ondrag'); };
  yellow.ondragenter = function () { events.push('yellow.ondragenter'); return false; };
  yellow.ondragover = function () { events.push('yellow.ondragover'); return false; };
  yellow.ondragleave = function () { events.push('yellow.ondragleave'); };
  yellow.ondrop = function () { events.push('yellow.ondrop'); return false; };
  yellow.ondragend = function () { events.push('yellow.ondragend'); };
  yellow.onmousedown = function () { events.push('yellow.onmousedown'); };
  yellow.onmouseup = function () { events.push('yellow.onmouseup'); };

  /* Events for the blue box (droppable) */
  blue.ondragstart = function () { events.push('blue.ondragstart'); };
  blue.ondrag = function () { events.push('blue.ondrag'); };
  blue.ondragenter = function () { events.push('blue.ondragenter'); return false; };
  blue.ondragover = function () { events.push('blue.ondragover'); return false; };
  blue.ondragleave = function () { events.push('blue.ondragleave'); };
  blue.ondrop = function () { events.push('blue.ondrop'); return false; };
  blue.ondragend = function () { events.push('blue.ondragend'); };
  blue.onmousedown = function () { events.push('blue.onmousedown'); };
  blue.onmouseup = function () { events.push('blue.onmouseup'); };

  /* Events for the page body */
  body.ondragstart = function (e) { events.push( ( e.target == body ) ? 'body.ondragstart': 'bubble.ondragstart' ); };
  body.ondrag = function (e) { events.push( ( e.target == body ) ? 'body.ondrag': 'bubble.ondrag' ); };
  body.ondragenter = function (e) { events.push( ( e.target == body ) ? 'body.ondragenter': 'bubble.ondragenter' ); };
  body.ondragover = function (e) { events.push( ( e.target == body ) ? 'body.ondragover': 'bubble.ondragover' ); };
  body.ondragleave = function (e) { events.push( ( e.target == body ) ? 'body.ondragleave': 'bubble.ondragleave' ); };
  body.ondrop = function (e) { events.push( ( e.target == body ) ? 'body.ondrop': 'bubble.ondrop' ); };
  body.ondragend = function (e) { events.push( ( e.target == body ) ? 'body.ondragend': 'bubble.ondragend' ); setTimeout(finish,100); };
  body.onmousedown = function (e) { events.push( ( e.target == body ) ? 'body.onmousedown': 'bubble.onmousedown' ); };
  body.onmouseup = function (e) { events.push( ( e.target == body ) ? 'body.onmouseup': 'bubble.onmouseup' ); };

  function finish(e) {
    var i, evindex;
    events = events.join('-');
    /*
      Normalise; reduce repeating event sequences to only 2 occurrences.
      This makes the final event sequence predictable, no matter how many times the drag->dragover sequences repeat.
      Two occurrances are kept in each case to allow testing to make sure the sequence really is repeating.
    */
    //spec compliant - div dragenter is not cancelled, so body dragenter fires and body becomes current target
    //repeats while drag is over orange or fuchsia or the body
    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-body\.ondragover){3,}/g,'$1$1');
    //repeats while dragging over yellow
    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-yellow\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    //repeats while dragging over blue
    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-blue\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    //non-spec-compliant repeats while dragging over orange
    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-orange\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    //non-spec-compliant repeats while dragging over fuchsia
    events = events.replace(/(-orange\.ondrag-bubble\.ondrag-pink\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
    events = events.split(/-/g);

    test(function () {
      assert_array_equals(events,

      [/*  1 */ 'orange.onmousedown', //mouse down
        /*  2 */ 'bubble.onmousedown',

        /*  3 */ 'orange.ondragstart', //dragging begins
        /*  4 */ 'bubble.ondragstart',

        /*  5 */ 'orange.ondrag',      //mouse is over orange
        /*  6 */ 'bubble.ondrag',
        /*  7 */ 'orange.ondragenter', //not cancelled
        /*  8 */ 'bubble.ondragenter',
        /*  9 */ 'body.ondragenter',   //so body becomes current target, and the event fires there as well
        /* 10 */ 'body.ondragover',

        /* 11 */ 'orange.ondrag',      //start repeating (some over orange, some over body)
        /* 12 */ 'bubble.ondrag',
        /* 13 */ 'body.ondragover',
        /* 14 */ 'orange.ondrag',      //...twice to make sure it actually repeats
        /* 15 */ 'bubble.ondrag',
        /* 16 */ 'body.ondragover',    //end repeating

        /* 17 */ 'orange.ondrag',      //mouse moves over pink
        /* 18 */ 'bubble.ondrag',
        /* 19 */ 'pink.ondragenter',   //not cancelled
        /* 20 */ 'bubble.ondragenter',
        /* 21 */ 'body.ondragover',    //so body becomes current target, but since it was already the target, dragenter does not need to fire again

        /* 22 */ 'orange.ondrag',      //start repeating (some over pink, some over body)
        /* 23 */ 'bubble.ondrag',
        /* 24 */ 'body.ondragover',
        /* 25 */ 'orange.ondrag',      //...twice to make sure it actually repeats
        /* 26 */ 'bubble.ondrag',
        /* 27 */ 'body.ondragover',    //end repeating

        /* 28 */ 'orange.ondrag',      //mouse moves over yellow
        /* 29 */ 'bubble.ondrag',
        /* 30 */ 'yellow.ondragenter',
        /* 31 */ 'bubble.ondragenter',
        /* 32 */ 'body.ondragleave',
        /* 33 */ 'yellow.ondragover',
        /* 34 */ 'bubble.ondragover',

        /* 35 */ 'orange.ondrag',      //start repeating (over yellow)
        /* 36 */ 'bubble.ondrag',
        /* 37 */ 'yellow.ondragover',
        /* 38 */ 'bubble.ondragover',
        /* 39 */ 'orange.ondrag',      //...twice to make sure it actually repeats
        /* 40 */ 'bubble.ondrag',
        /* 41 */ 'yellow.ondragover',
        /* 42 */ 'bubble.ondragover',  //end repeating

        /* 43 */ 'orange.ondrag',      //mouse moves over body
        /* 44 */ 'bubble.ondrag',
        /* 45 */ 'body.ondragenter',   //not cancelled
        /* 46 */ 'body.ondragenter',   //so it fires again and sets body as current target
        /* 47 */ 'yellow.ondragleave',
        /* 48 */ 'bubble.ondragleave',
        /* 49 */ 'body.ondragover',

        /* 50 */ 'orange.ondrag',      //start repeating (over body)
        /* 51 */ 'bubble.ondrag',
        /* 52 */ 'body.ondragover',
        /* 53 */ 'orange.ondrag',      //...twice to make sure it actually repeats
        /* 54 */ 'bubble.ondrag',
        /* 55 */ 'body.ondragover',    //end repeating

        /* 56 */ 'orange.ondrag',      //mouse moves over blue
        /* 57 */ 'bubble.ondrag',
        /* 58 */ 'blue.ondragenter',
        /* 59 */ 'bubble.ondragenter',
        /* 60 */ 'body.ondragleave',
        /* 61 */ 'blue.ondragover',
        /* 62 */ 'bubble.ondragover',

        /* 63 */ 'orange.ondrag',      //start repeating (over blue)
        /* 64 */ 'bubble.ondrag',
        /* 65 */ 'blue.ondragover',
        /* 66 */ 'bubble.ondragover',
        /* 67 */ 'orange.ondrag',      //...twice to make sure it actually repeats
        /* 68 */ 'bubble.ondrag',
        /* 69 */ 'blue.ondragover',
        /* 70 */ 'bubble.ondragover',  //end repeating

        /* 71 */ 'blue.ondrop',        //release
        /* 72 */ 'bubble.ondrop',
        /* 73 */ 'orange.ondragend',
        /* 74 */ 'bubble.ondragend']

      );
    }, 'Overall sequence');

    /* ondragstart */
    test(function () { assert_true( events.indexOf('orange.ondragstart') != -1 ); }, "orange.ondragstart should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragstart') return e; }).length, 1); }, "orange.ondragstart should fire 1 time");
    test(function () { assert_equals( events[2], 'orange.ondragstart' ); }, "orange.ondragstart should be event handler #3");
    test(function () { assert_equals( events.indexOf('pink.ondragstart'), -1 ); }, "pink.ondragstart should not fire");
    test(function () { assert_equals( events.indexOf('yellow.ondragstart'), -1 ); }, "yellow.ondragstart should not fire");
    test(function () { assert_equals( events.indexOf('blue.ondragstart'), -1 ); }, "blue.ondragstart should not fire");
    test(function () { assert_equals( events.indexOf('body.ondragstart'), -1 ); }, "ondragstart should not fire at the body");
    test(function () { assert_true( events.indexOf('bubble.ondragstart') != -1 ); }, "ondragstart should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragstart') return e; }).length, 1); }, "ondragstart should only bubble to body 1 time");
    test(function () { assert_equals( events[3], 'bubble.ondragstart' ); }, "ondragstart should bubble to body as event handler #4");

    /* ondrag */
    test(function () { assert_true( events.indexOf('orange.ondrag') != -1 ); }, "orange.ondrag should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondrag') return e; }).length, 15); }, "orange.ondrag should fire 15 times");
    for( var i = 0, evindex = [4,10,13,16,21,24,27,34,38,42,49,52,55,62,66]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'orange.ondrag' ); }, "orange.ondrag should be event handler #"+(evindex[i]+1));
    }
    test(function () { assert_equals( events.indexOf('pink.ondrag'), -1 ); }, "pink.ondrag should not fire");
    test(function () { assert_equals( events.indexOf('yellow.ondrag'), -1 ); }, "yellow.ondrag should not fire");
    test(function () { assert_equals( events.indexOf('blue.ondrag'), -1 ); }, "blue.ondrag should not fire");
    test(function () { assert_equals( events.indexOf('body.ondrag'), -1 ); }, "ondrag should not fire at the body");
    test(function () { assert_true( events.indexOf('bubble.ondrag') != -1 ); }, "ondrag should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondrag') return e; }).length, 15); }, "ondrag should bubble to body 15 times");
    for( var i = 0, evindex = [5,11,14,17,22,25,28,35,39,43,50,53,56,63,67]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'bubble.ondrag' ); }, "ondrag should bubble to body as event handler #"+(evindex[i]+1));
    }

    /* ondragenter */
    test(function () { assert_true( events.indexOf('orange.ondragenter') != -1 ); }, "orange.ondragenter should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragenter') return e; }).length, 1); }, "orange.ondragenter should fire 1 time");
    test(function () { assert_equals( events[6], 'orange.ondragenter' ); }, "orange.ondragenter should be event handler #7");
    test(function () { assert_true( events.indexOf('pink.ondragenter') != -1 ); }, "pink.ondragenter should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'pink.ondragenter') return e; }).length, 1); }, "pink.ondragenter should fire 1 time");
    test(function () { assert_equals( events[18], 'pink.ondragenter' ); }, "pink.ondragenter should be event handler #19");
    test(function () { assert_true( events.indexOf('yellow.ondragenter') != -1 ); }, "yellow.ondragenter should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragenter') return e; }).length, 1); }, "yellow.ondragenter should fire 1 time");
    test(function () { assert_equals( events[29], 'yellow.ondragenter' ); }, "yellow.ondragenter should be event handler #30");
    test(function () { assert_true( events.indexOf('blue.ondragenter') != -1 ); }, "blue.ondragenter should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondragenter') return e; }).length, 1); }, "blue.ondragenter should fire 1 time");
    test(function () { assert_equals( events[57], 'blue.ondragenter' ); }, "blue.ondragenter should be event handler #58");
    test(function () { assert_true( events.indexOf('body.ondragenter') != -1 ); }, "ondragenter should fire at body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragenter') return e; }).length, 3); }, "ondragenter should fire at body 2 times");
    for( var i = 0, evindex = [8,44,45]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'body.ondragenter' ); }, "ondragenter should fire at body as event handler #"+(evindex[i]+1));
    }
    test(function () { assert_true( events.indexOf('bubble.ondragenter') != -1 ); }, "ondragenter should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragenter') return e; }).length, 4); }, "ondragenter should bubble to body 4 times");
    for( var i = 0, evindex = [7,19,30,58]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'bubble.ondragenter' ); }, "ondragenter should bubble to body as event handler #"+(evindex[i]+1));
    }

    /* ondragover */
    test(function () { assert_equals( events.indexOf('orange.ondragover'), -1 ); }, "orange.ondragover should not fire");
    test(function () { assert_equals( events.indexOf('pink.ondragover'), -1 ); }, "pink.ondragover should not fire");
    test(function () { assert_true( events.indexOf('yellow.ondragover') != -1 ); }, "yellow.ondragover should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragover') return e; }).length, 3); }, "yellow.ondragover should fire 3 times");
    for( var i = 0, evindex = [32,36,40]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'yellow.ondragover' ); }, "yellow.ondragover should be event handler #"+(evindex[i]+1));
    }
    test(function () { assert_true( events.indexOf('blue.ondragover') != -1 ); }, "blue.ondragover should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondragover') return e; }).length, 3); }, "blue.ondragover should fire 9 times");
    for( var i = 0, evindex = [60,64,68]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'blue.ondragover' ); }, "blue.ondragover should be event handler #"+(evindex[i]+1));
    }
    test(function () { assert_true( events.indexOf('body.ondragover') != -1 ); }, "ondragover should fire at body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragover') return e; }).length, 9); }, "ondragover should fire at body 2 times");
    for( var i = 0, evindex = [9,12,15,20,23,26,48,51,54]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'body.ondragover' ); }, "ondragover should fire at body as event handler #"+(evindex[i]+1));
    }
    test(function () { assert_true( events.indexOf('bubble.ondragover') != -1 ); }, "ondragover should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragover') return e; }).length, 6); }, "ondragover should bubble to body 6 times");
    for( var i = 0, evindex = [33,37,41,61,65,69]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'bubble.ondragover' ); }, "ondragover should bubble to body as event handler #"+(evindex[i]+1));
    }

    /* ondragleave */
    test(function () { assert_equals( events.indexOf('orange.ondragleave'), -1 ); }, "orange.ondragleave should not fire");
    test(function () { assert_equals( events.indexOf('pink.ondragleave'), -1 ); }, "pink.ondragleave should not fire");
    test(function () { assert_true( events.indexOf('yellow.ondragleave') != -1 ); }, "yellow.ondragleave should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragleave') return e; }).length, 1); }, "yellow.ondragleave should fire 1 time");
    test(function () { assert_equals( events[46], 'yellow.ondragleave' ); }, "yellow.ondragleave should be event handler #47");
    test(function () { assert_equals( events.indexOf('blue.ondragleave'), -1 ); }, "blue.ondragleave should not fire");
    test(function () { assert_true( events.indexOf('body.ondragleave') != -1 ); }, "ondragleave should fire at body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragleave') return e; }).length, 2); }, "ondragleave should fire at body 2 times");
    for( var i = 0, evindex = [31,59]; i < evindex.length; i++ ) {
      test(function () { assert_equals( events[evindex[i]], 'body.ondragleave' ); }, "ondragleave should fire at body as event handler #"+(evindex[i]+1));
    }
    test(function () { assert_true( events.indexOf('bubble.ondragleave') != -1 ); }, "ondragleave should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragleave') return e; }).length, 1); }, "ondragleave should bubble to body 1 time");
    test(function () { assert_equals( events[47], 'bubble.ondragleave' ); }, "ondragleave should bubble to body as event handler #48");

    /* ondrop */
    test(function () { assert_equals( events.indexOf('orange.ondrop'), -1 ); }, "orange.ondrop should not fire");
    test(function () { assert_equals( events.indexOf('pink.ondrop'), -1 ); }, "pink.ondrop should not fire");
    test(function () { assert_equals( events.indexOf('yellow.ondrop'), -1 ); }, "yellow.ondrop should not fire");
    test(function () { assert_true( events.indexOf('blue.ondrop') != -1 ); }, "blue.ondrop should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondrop') return e; }).length, 1); }, "blue.ondrop should fire 1 time");
    test(function () { assert_equals( events[70], 'blue.ondrop' ); }, "blue.ondrop should be event handler #71");
    test(function () { assert_equals( events.indexOf('body.ondrop'), -1 ); }, "ondrop should not fire at body");
    test(function () { assert_true( events.indexOf('bubble.ondrop') != -1 ); }, "ondrop should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondrop') return e; }).length, 1); }, "ondrop should bubble to body 1 time");
    test(function () { assert_equals( events[71], 'bubble.ondrop' ); }, "ondrop should bubble to body as event handler #72");

    /* ondragend */
    test(function () { assert_true( events.indexOf('orange.ondragend') != -1 ); }, "orange.ondragend should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragend') return e; }).length, 1); }, "orange.ondragend should fire 1 time");
    test(function () { assert_equals( events[72], 'orange.ondragend' ); }, "orange.ondragend should be event handler #73");
    test(function () { assert_equals( events.indexOf('pink.ondragend'), -1 ); }, "pink.ondragend should not fire");
    test(function () { assert_equals( events.indexOf('yellow.ondragend'), -1 ); }, "yellow.ondragend should not fire");
    test(function () { assert_equals( events.indexOf('blue.ondragend'), -1 ); }, "blue.ondragend should not fire");
    test(function () { assert_equals( events.indexOf('body.ondragend'), -1 ); }, "ondragend should not fire at body");
    test(function () { assert_true( events.indexOf('bubble.ondragend') != -1 ); }, "ondragend should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragend') return e; }).length, 1); }, "ondragend should bubble to body 1 time");
    test(function () { assert_equals( events[73], 'bubble.ondragend' ); }, "ondragend should bubble to body as event handler #74");

    /* onmousedown */
    test(function () { assert_true( events.indexOf('orange.onmousedown') != -1 ); }, "orange.onmousedown should fire");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.onmousedown') return e; }).length, 1); }, "orange.onmousedown should fire 1 time");
    test(function () { assert_equals( events[0], 'orange.onmousedown' ); }, "orange.onmousedown should be event handler #1");
    test(function () { assert_equals( events.indexOf('pink.onmousedown'), -1 ); }, "pink.onmousedown should not fire");
    test(function () { assert_equals( events.indexOf('yellow.onmousedown'), -1 ); }, "yellow.onmousedown should not fire");
    test(function () { assert_equals( events.indexOf('blue.onmousedown'), -1 ); }, "blue.onmousedown should not fire");
    test(function () { assert_equals( events.indexOf('body.onmousedown'), -1 ); }, "onmousedown should not fire at body");
    test(function () { assert_true( events.indexOf('bubble.onmousedown') != -1 ); }, "onmousedown should bubble to body");
    test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.onmousedown') return e; }).length, 1); }, "onmousedown should bubble to body 1 time");
    test(function () { assert_equals( events[1], 'bubble.onmousedown' ); }, "onmousedown should bubble to body as event handler #1");

    /* onmouseup */
    test(function () { assert_equals( events.indexOf('orange.onmouseup'), -1 ); }, "orange.onmouseup should not fire");
    test(function () { assert_equals( events.indexOf('pink.onmouseup'), -1 ); }, "pink.onmouseup should not fire");
    test(function () { assert_equals( events.indexOf('yellow.onmouseup'), -1 ); }, "yellow.onmouseup should not fire");
    test(function () { assert_equals( events.indexOf('blue.onmouseup'), -1 ); }, "blue.onmouseup should not fire");
    test(function () { assert_equals( events.indexOf('body.onmouseup'), -1 ); }, "onmouseup should not fire at body");
    test(function () { assert_equals( events.indexOf('bubble.onmouseup'), -1 ); }, "onmouseup should not bubble to body");

    done();
  }
};
</script>

<div id="testhere">
<div draggable='true' id='orange'></div>
<div id='fuchsia'></div>
<div id='yellow'></div>
<div id='blue'></div>
</div>

<p>If you have already clicked on this page, reload it.</p>
<p>Use your pointing device to slowly drag the orange square over the pink square then the yellow square, then the blue square, and release it over the blue square (make sure the mouse remains over each square for at least 1 second, and over the gaps between squares for at least 1 second). Fail if no new text appears below.</p>

<div id="log"></div>