Revert "Export"
[framework/web/web-ui-fw.git] / libs / js / jquery-mobile-1.1.0 / tests / unit / event / event_core.js
1 /*
2  * mobile event unit tests
3  */
4
5 (function($){
6         var libName = "jquery.mobile.event.js",
7                         absFn = Math.abs,
8                         originalEventFn = $.Event.prototype.originalEvent,
9                         preventDefaultFn = $.Event.prototype.preventDefault,
10                         events = ("touchstart touchmove touchend orientationchange tap taphold " +
11                                                                 "swipe swipeleft swiperight scrollstart scrollstop").split( " " );
12
13         module(libName, {
14                 setup: function(){
15
16                         // ensure bindings are removed
17                         $.each(events + "vmouseup vmousedown".split(" "), function(i, name){
18                                 $("#qunit-fixture").unbind();
19                         });
20
21                         //NOTE unmock
22                         Math.abs = absFn;
23                         $.Event.prototype.originalEvent = originalEventFn;
24                         $.Event.prototype.preventDefault = preventDefaultFn;
25
26                         // make sure the event objects respond to touches to simulate
27                         // the collections existence in non touch enabled test browsers
28                         $.Event.prototype.touches = [{pageX: 1, pageY: 1 }];
29
30                         $($.mobile.pageContainer).unbind( "throttledresize" );
31                 }
32         });
33
34         $.testHelper.excludeFileProtocol(function(){
35                 test( "new events defined on the jquery object", function(){
36                         $.each(events, function( i, name ) {
37                                 delete $.fn[name];
38                                 same($.fn[name], undefined);
39                         });
40
41                         $.testHelper.reloadLib(libName);
42
43                         $.each(events, function( i, name ) {
44                                 ok($.fn[name] !== undefined, name + " is not undefined");
45                         });
46                 });
47         });
48
49         asyncTest( "defined event functions bind a closure when passed", function(){
50                 expect( 1 );
51
52                 $('#qunit-fixture').bind(events[0], function(){
53                         ok(true, "event fired");
54                         start();
55                 });
56
57                 $('#qunit-fixture').trigger(events[0]);
58         });
59
60         asyncTest( "defined event functions trigger the event with no arguments", function(){
61                 expect( 1 );
62
63                 $('#qunit-fixture').bind('touchstart', function(){
64                         ok(true, "event fired");
65                         start();
66                 });
67
68                 $('#qunit-fixture').touchstart();
69         });
70
71         test( "defining event functions sets the attrFn to true", function(){
72                 $.each(events, function(i, name){
73                         ok($.attrFn[name], "attribute function is true");
74                 });
75         });
76
77         test( "scrollstart enabled defaults to true", function(){
78                 $.event.special.scrollstart.enabled = false;
79                 $.testHelper.reloadLib(libName);
80                 ok($.event.special.scrollstart.enabled, "scrollstart enabled");
81         });
82
83         asyncTest( "scrollstart setup binds a function that returns when its disabled", function(){
84                 expect( 1 );
85                 $.event.special.scrollstart.enabled = false;
86
87                 $( "#qunit-fixture" ).bind("scrollstart", function(){
88                         ok(false, "scrollstart fired");
89                 });
90
91                 $( "#qunit-fixture" ).bind("touchmove", function(){
92                         ok(true, "touchmove fired");
93                         start();
94                 });
95
96                 $( "#qunit-fixture" ).trigger("touchmove");
97         });
98
99         asyncTest( "scrollstart setup binds a function that triggers scroll start when enabled", function(){
100                 $.event.special.scrollstart.enabled = true;
101
102                 $( "#qunit-fixture" ).bind("scrollstart", function(){
103                         ok(true, "scrollstart fired");
104                         start();
105                 });
106
107                 $( "#qunit-fixture" ).trigger("touchmove");
108         });
109
110         asyncTest( "scrollstart setup binds a function that triggers scroll stop after 50 ms", function(){
111                 var triggered = false;
112                 $.event.special.scrollstart.enabled = true;
113
114                 $( "#qunit-fixture" ).bind("scrollstop", function(){
115                         triggered = true;
116                 });
117
118                 ok(!triggered, "not triggered");
119
120                 $( "#qunit-fixture" ).trigger("touchmove");
121
122                 setTimeout(function(){
123                         ok(triggered, "triggered");
124                         start();
125                 }, 50);
126         });
127
128         var forceTouchSupport = function(){
129                 $.support.touch = true;
130                 $.testHelper.reloadLib(libName);
131
132                 //mock originalEvent information
133                 $.Event.prototype.originalEvent = {
134                         touches: [{ 'pageX' : 0 }, { 'pageY' : 0 }]
135                 };
136         };
137
138         asyncTest( "long press fires tap hold after 750 ms", function(){
139                 var taphold = false,
140                         target;
141
142                 forceTouchSupport();
143
144                 $( "#qunit-fixture" ).bind("taphold", function( e ){
145                         taphold = true;
146                         target = e.target;
147                 });
148
149                 $( "#qunit-fixture" ).trigger("vmousedown");
150
151                 setTimeout(function(){
152                         ok( taphold );
153                         equal( target, $( "#qunit-fixture" ).get( 0 ), "taphold target should be #qunit-fixture" );
154                         start();
155                 }, 751);
156         });
157
158         //NOTE used to simulate movement when checked
159         //TODO find a better way ...
160         var mockAbs = function(value){
161                 Math.abs = function(){
162                         return value;
163                 };
164         };
165
166         asyncTest( "move prevents taphold", function(){
167                 expect( 1 );
168                 var taphold = false;
169
170                 forceTouchSupport();
171                 mockAbs(100);
172
173                 //NOTE record taphold event
174                 $( "#qunit-fixture" ).bind("taphold", function(){
175                         ok(false, "taphold fired");
176                         taphold = true;
177                 });
178
179                 //NOTE start the touch events
180                 $( "#qunit-fixture" ).trigger("vmousedown");
181
182                 //NOTE fire touchmove to push back taphold
183                 setTimeout(function(){
184                         $( "#qunit-fixture" ).trigger("vmousecancel");
185                 }, 100);
186
187                 //NOTE verify that the taphold hasn't been fired
188                 //               with the normal timing
189                 setTimeout(function(){
190                         ok(!taphold, "taphold not fired");
191                         start();
192                 }, 751);
193         });
194
195         asyncTest( "tap event fired without movement", function(){
196                 expect( 1 );
197                 var tap = false,
198                                 checkTap = function(){
199                                         ok(true, "tap fired");
200                                 };
201
202                 forceTouchSupport();
203
204                 //NOTE record the tap event
205                 $( "#qunit-fixture" ).bind("tap", checkTap);
206
207                 $( "#qunit-fixture" ).trigger("vmousedown");
208                 $( "#qunit-fixture" ).trigger("vmouseup");
209                 $( "#qunit-fixture" ).trigger("vclick");
210
211                 setTimeout(function(){
212                         start();
213                 }, 400);
214         });
215
216         asyncTest( "tap event not fired when there is movement", function(){
217                 expect( 1 );
218                 var tap = false;
219                 forceTouchSupport();
220
221                 //NOTE record tap event
222                 $( "#qunit-fixture" ).bind("tap", function(){
223                         ok(false, "tap fired");
224                         tap = true;
225                 });
226
227                 //NOTE make sure movement is recorded
228                 mockAbs(100);
229
230                 //NOTE start and move right away
231                 $( "#qunit-fixture" ).trigger("touchstart");
232                 $( "#qunit-fixture" ).trigger("touchmove");
233
234                 //NOTE end touch sequence after 20 ms
235                 setTimeout(function(){
236                         $( "#qunit-fixture" ).trigger("touchend");
237                 }, 20);
238
239                 setTimeout(function(){
240                         ok(!tap, "not tapped");
241                         start();
242                 }, 40);
243         });
244
245         asyncTest( "tap event propagates up DOM tree", function(){
246                 var tap = 0,
247                         $qf = $( "#qunit-fixture" ),
248                         $doc = $( document ),
249                         docTapCB = function(){
250                                 same(++tap, 2, "document tap callback called once after #qunit-fixture callback");
251                         };
252
253                 $qf.bind( "tap", function() {
254                         same(++tap, 1, "#qunit-fixture tap callback called once");
255                 });
256
257                 $doc.bind( "tap", docTapCB );
258
259                 $qf.trigger( "vmousedown" )
260                         .trigger( "vmouseup" )
261                         .trigger( "vclick" );
262
263                 // tap binding should be triggered twice, once for
264                 // #qunit-fixture, and a second time for document.
265                 same( tap, 2, "final tap callback count is 2" );
266
267                 $doc.unbind( "tap", docTapCB );
268
269                 start();
270         });
271
272         asyncTest( "stopPropagation() prevents tap from propagating up DOM tree", function(){
273                 var tap = 0,
274                         $qf = $( "#qunit-fixture" ),
275                         $doc = $( document ),
276                         docTapCB = function(){
277                                 ok(false, "tap should NOT be triggered on document");
278                         };
279
280                 $qf.bind( "tap", function(e) {
281                         same(++tap, 1, "tap callback 1 triggered once on #qunit-fixture");
282                         e.stopPropagation();
283                 })
284                 .bind( "tap", function(e) {
285                         same(++tap, 2, "tap callback 2 triggered once on #qunit-fixture");
286                 });
287
288                 $doc.bind( "tap", docTapCB);
289
290                 $qf.trigger( "vmousedown" )
291                         .trigger( "vmouseup" )
292                         .trigger( "vclick" );
293
294                 // tap binding should be triggered twice.
295                 same( tap, 2, "final tap count is 2" );
296
297                 $doc.unbind( "tap", docTapCB );
298
299                 start();
300         });
301
302         asyncTest( "stopImmediatePropagation() prevents tap propagation and execution of 2nd handler", function(){
303                 var tap = 0,
304                         $cf = $( "#qunit-fixture" );
305                         $doc = $( document ),
306                         docTapCB = function(){
307                                 ok(false, "tap should NOT be triggered on document");
308                         };
309
310                 // Bind 2 tap callbacks on qunit-fixture. Only the first
311                 // one should ever be called.
312                 $cf.bind( "tap", function(e) {
313                         same(++tap, 1, "tap callback 1 triggered once on #qunit-fixture");
314                         e.stopImmediatePropagation();
315                 })
316                 .bind( "tap", function(e) {
317                         ok(false, "tap callback 2 should NOT be triggered on #qunit-fixture");
318                 });
319
320                 $doc.bind( "tap", docTapCB);
321
322                 $cf.trigger( "vmousedown" )
323                         .trigger( "vmouseup" )
324                         .trigger( "vclick" );
325
326                 // tap binding should be triggered once.
327                 same( tap, 1, "final tap count is 1" );
328
329                 $doc.unbind( "tap", docTapCB );
330
331                 start();
332         });
333
334         var swipeTimedTest = function(opts){
335                 var swipe = false;
336
337                 forceTouchSupport();
338
339                 $( "#qunit-fixture" ).bind('swipe', function(){
340                         swipe = true;
341                 });
342
343                 //NOTE bypass the trigger source check
344                 $.Event.prototype.originalEvent = {
345                         touches: false
346                 };
347
348                 $( "#qunit-fixture" ).trigger("touchstart");
349
350                 //NOTE make sure the coordinates are calculated within range
351                 //               to be registered as a swipe
352                 mockAbs(opts.coordChange);
353
354                 setTimeout(function(){
355                         $( "#qunit-fixture" ).trigger("touchmove");
356                         $( "#qunit-fixture" ).trigger("touchend");
357                 }, opts.timeout + 100);
358
359                 setTimeout(function(){
360                         same(swipe, opts.expected, "swipe expected");
361                         start();
362                 }, opts.timeout + 200);
363
364                 stop();
365         };
366
367         test( "swipe fired when coordinate change in less than a second", function(){
368                 swipeTimedTest({ timeout: 10, coordChange: 35, expected: true });
369         });
370
371         test( "swipe not fired when coordinate change takes more than a second", function(){
372                 swipeTimedTest({ timeout: 1000, coordChange: 35, expected: false });
373         });
374
375         test( "swipe not fired when coordinate change <= 30", function(){
376                 swipeTimedTest({ timeout: 1000, coordChange: 30, expected: false });
377         });
378
379         test( "swipe not fired when coordinate change >= 75", function(){
380                 swipeTimedTest({ timeout: 1000, coordChange: 75, expected: false });
381         });
382
383         asyncTest( "scrolling prevented when coordinate change > 10", function(){
384                 expect( 1 );
385
386                 forceTouchSupport();
387
388                 // ensure the swipe custome event is setup
389                 $( "#qunit-fixture" ).bind('swipe', function(){});
390
391                 //NOTE bypass the trigger source check
392                 $.Event.prototype.originalEvent = {
393                         touches: false
394                 };
395
396                 $.Event.prototype.preventDefault = function(){
397                         ok(true, "prevent default called");
398                         start();
399                 };
400
401                 mockAbs(11);
402
403                 $( "#qunit-fixture" ).trigger("touchstart");
404                 $( "#qunit-fixture" ).trigger("touchmove");
405         });
406
407         asyncTest( "move handler returns when touchstart has been fired since touchstop", function(){
408                 expect( 1 );
409
410                 // bypass triggered event check
411                 $.Event.prototype.originalEvent = {
412                         touches: false
413                 };
414
415                 forceTouchSupport();
416
417                 // ensure the swipe custome event is setup
418                 $( "#qunit-fixture" ).bind('swipe', function(){});
419
420                 $( "#qunit-fixture" ).trigger("touchstart");
421                 $( "#qunit-fixture" ).trigger("touchend");
422
423                 $( "#qunit-fixture" ).bind("touchmove", function(){
424                         ok(true, "touchmove bound functions are fired");
425                         start();
426                 });
427
428                 Math.abs = function(){
429                         ok(false, "shouldn't compare coordinates");
430                 };
431
432                 $( "#qunit-fixture" ).trigger("touchmove");
433         });
434
435         var nativeSupportTest = function(opts){
436                 $.support.orientation = opts.orientationSupport;
437                 same($.event.special.orientationchange[opts.method](), opts.returnValue);
438         };
439
440         test( "orientation change setup should do nothing when natively supported", function(){
441                 nativeSupportTest({
442                         method: 'setup',
443                         orientationSupport: true,
444                         returnValue: false
445                 });
446         });
447
448         test( "orientation change setup should bind resize when not supported natively", function(){
449                 nativeSupportTest({
450                         method: 'setup',
451                         orientationSupport: false,
452                         returnValue: undefined //NOTE result of bind function call
453                 });
454         });
455
456         test( "orientation change teardown should do nothing when natively supported", function(){
457                 nativeSupportTest({
458                         method: 'teardown',
459                         orientationSupport: true,
460                         returnValue: false
461                 });
462         });
463
464         test( "orientation change teardown should unbind resize when not supported natively", function(){
465                 nativeSupportTest({
466                         method: 'teardown',
467                         orientationSupport: false,
468                         returnValue: undefined //NOTE result of unbind function call
469                 });
470         });
471
472         /* The following 4 tests are async so that the throttled event triggers don't interfere with subsequent tests */
473
474         asyncTest( "throttledresize event proxies resize events", function(){
475                 $( window ).one( "throttledresize", function(){
476                         ok( true, "throttledresize called");
477                         start();
478                 });
479
480                 $( window ).trigger( "resize" );
481         });
482
483         asyncTest( "throttledresize event prevents resize events from firing more frequently than 250ms", function(){
484                 var called = 0;
485
486                 $(window).bind( "throttledresize", function(){
487                         called++;
488                 });
489
490                 // NOTE 250 ms * 3 = 750ms which is plenty of time
491                 // for the events to trigger before the next test, but
492                 // not so much time that the second resize will be triggered
493                 // before the call to same() is made
494                 $.testHelper.sequence([
495                         function(){
496                                 $(window).trigger( "resize" ).trigger( "resize" );
497                         },
498
499                         // verify that only one throttled resize was called after 250ms
500                         function(){ same( called, 1 ); },
501
502                         function(){
503                                 start();
504                         }
505                 ], 250);
506         });
507
508         asyncTest( "throttledresize event promises that a held call will execute only once after throttled timeout", function(){
509                 var called = 0;
510
511                 expect( 2 );
512
513                 $.testHelper.eventSequence( "throttledresize", [
514                         // ignore the first call
515                         $.noop,
516
517                         function(){
518                                 ok( true, "second throttled resize should run" );
519                         },
520
521                         function(timedOut){
522                                 ok( timedOut, "third throttled resize should not run");
523                                 start();
524                         }
525                 ]);
526
527                 $.mobile.pageContainer
528                         .trigger( "resize" )
529                         .trigger( "resize" )
530                         .trigger( "resize" );
531         });
532
533         asyncTest( "mousedown mouseup and click events should add a which when its not defined", function() {
534                 var whichDefined = function( event ){
535                         same(event.which, 1);
536                 };
537
538                 $( document ).bind( "vclick", whichDefined);
539                 $( document ).trigger( "click" );
540
541                 $( document ).bind( "vmousedown", whichDefined);
542                 $( document ).trigger( "mousedown" );
543
544                 $( document ).bind( "vmouseup", function( event ){
545                         same(event.which, 1);
546                         start();
547                 });
548
549                 $( document ).trigger( "mouseup" );
550         });
551 })(jQuery);