Skip to content

Commit 0ff8057

Browse files
committed
Effects: Adding unit tests for jQuery.Animation
Closes gh-2340 (cherry picked from commit b3b2d6c) Conflicts: src/effects.js
1 parent 6b10f9d commit 0ff8057

File tree

4 files changed

+263
-20
lines changed

4 files changed

+263
-20
lines changed

Gruntfile.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,15 @@ module.exports = function( grunt ) {
9090
src: "src/**/*.js",
9191
gruntfile: "Gruntfile.js",
9292

93-
// Right now, check only test helpers
94-
test: [ "test/data/testrunner.js", "test/unit/tween.js" ],
93+
// Check parts of tests that pass
94+
test: [ "test/data/testrunner.js", "test/unit/animation.js", "test/unit/tween.js" ],
9595
release: [ "build/*.js", "!build/release-notes.js" ],
9696
tasks: "build/tasks/*.js"
9797
},
9898
testswarm: {
9999
tests: [
100100
"ajax",
101+
"animation",
101102
"attributes",
102103
"callbacks",
103104
"core",

src/effects.js

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
define([
22
"./core",
33
"./var/rcssNum",
4+
"./var/rnotwhite",
45
"./css/var/cssExpand",
56
"./css/var/isHidden",
67
"./css/var/swap",
@@ -14,20 +15,12 @@ define([
1415
"./manipulation",
1516
"./css",
1617
"./effects/Tween"
17-
], function( jQuery, rcssNum, cssExpand, isHidden, swap, adjustCSS, showHide ) {
18+
], function( jQuery, rcssNum, rnotwhite, cssExpand, isHidden, swap, adjustCSS, showHide ) {
1819

1920
var
2021
fxNow, timerId,
2122
rfxtypes = /^(?:toggle|show|hide)$/,
22-
rrun = /queueHooks$/,
23-
animationPrefilters = [ defaultPrefilter ],
24-
tweeners = {
25-
"*": [ function( prop, value ) {
26-
var tween = this.createTween( prop, value );
27-
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
28-
return tween;
29-
} ]
30-
};
23+
rrun = /queueHooks$/;
3124

3225
function raf() {
3326
if ( timerId ) {
@@ -67,7 +60,7 @@ function genFx( type, includeWidth ) {
6760

6861
function createTween( value, prop, animation ) {
6962
var tween,
70-
collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
63+
collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
7164
index = 0,
7265
length = collection.length;
7366
for ( ; index < length; index++ ) {
@@ -280,7 +273,7 @@ function Animation( elem, properties, options ) {
280273
var result,
281274
stopped,
282275
index = 0,
283-
length = animationPrefilters.length,
276+
length = Animation.prefilters.length,
284277
deferred = jQuery.Deferred().always( function() {
285278
// don't match elem in the :animated selector
286279
delete tick.elem;
@@ -357,8 +350,12 @@ function Animation( elem, properties, options ) {
357350
propFilter( props, animation.opts.specialEasing );
358351

359352
for ( ; index < length ; index++ ) {
360-
result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
353+
result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
361354
if ( result ) {
355+
if ( jQuery.isFunction( result.stop ) ) {
356+
jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
357+
jQuery.proxy( result.stop, result );
358+
}
362359
return result;
363360
}
364361
}
@@ -385,12 +382,24 @@ function Animation( elem, properties, options ) {
385382
}
386383

387384
jQuery.Animation = jQuery.extend( Animation, {
385+
<<<<<<< HEAD
386+
=======
387+
388+
tweeners: {
389+
"*": [ function( prop, value ) {
390+
var tween = this.createTween( prop, value );
391+
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
392+
return tween;
393+
} ]
394+
},
395+
396+
>>>>>>> b3b2d6c... Effects: Adding unit tests for jQuery.Animation
388397
tweener: function( props, callback ) {
389398
if ( jQuery.isFunction( props ) ) {
390399
callback = props;
391400
props = [ "*" ];
392401
} else {
393-
props = props.split(" ");
402+
props = props.match( rnotwhite );
394403
}
395404

396405
var prop,
@@ -399,16 +408,18 @@ jQuery.Animation = jQuery.extend( Animation, {
399408

400409
for ( ; index < length ; index++ ) {
401410
prop = props[ index ];
402-
tweeners[ prop ] = tweeners[ prop ] || [];
403-
tweeners[ prop ].unshift( callback );
411+
Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
412+
Animation.tweeners[ prop ].unshift( callback );
404413
}
405414
},
406415

416+
prefilters: [ defaultPrefilter ],
417+
407418
prefilter: function( callback, prepend ) {
408419
if ( prepend ) {
409-
animationPrefilters.unshift( callback );
420+
Animation.prefilters.unshift( callback );
410421
} else {
411-
animationPrefilters.push( callback );
422+
Animation.prefilters.push( callback );
412423
}
413424
}
414425
});

test/data/testinit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ this.loadTests = function() {
289289
"unit/effects.js",
290290
"unit/offset.js",
291291
"unit/dimensions.js",
292+
"unit/animation.js",
292293
"unit/tween.js"
293294
];
294295

test/unit/animation.js

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
( function() {
2+
3+
// Can't test what ain't there
4+
if ( !jQuery.fx ) {
5+
return;
6+
}
7+
8+
var oldRaf = window.requestAnimationFrame,
9+
defaultPrefilter = jQuery.Animation.prefilters[ 0 ],
10+
defaultTweener = jQuery.Animation.tweeners[ "*" ][ 0 ],
11+
startTime = 505877050;
12+
13+
// This module tests jQuery.Animation and the corresponding 1.8+ effects APIs
14+
module( "animation", {
15+
setup: function() {
16+
window.requestAnimationFrame = null;
17+
this.sandbox = sinon.sandbox.create();
18+
this.clock = this.sandbox.useFakeTimers( startTime );
19+
this._oldInterval = jQuery.fx.interval;
20+
jQuery.fx.step = {};
21+
jQuery.fx.interval = 10;
22+
jQuery.now = Date.now;
23+
jQuery.Animation.prefilters = [ defaultPrefilter ];
24+
jQuery.Animation.tweeners = { "*": [ defaultTweener ] };
25+
},
26+
teardown: function() {
27+
this.sandbox.restore();
28+
jQuery.now = Date.now;
29+
jQuery.fx.stop();
30+
jQuery.fx.interval = this._oldInterval;
31+
window.requestAnimationFrame = oldRaf;
32+
return moduleTeardown.apply( this, arguments );
33+
}
34+
} );
35+
36+
test( "Animation( subject, props, opts ) - shape", function() {
37+
expect( 20 );
38+
39+
var subject = { test: 0 },
40+
props = { test: 1 },
41+
opts = { queue: "fx", duration: 100 },
42+
animation = jQuery.Animation( subject, props, opts );
43+
44+
equal( animation.elem, subject, ".elem is set to the exact object passed" );
45+
equal( animation.originalOptions, opts, ".originalOptions is set to options passed" );
46+
equal( animation.originalProperties, props, ".originalProperties is set to props passed" );
47+
48+
notEqual( animation.props, props, ".props is not the original however" );
49+
deepEqual( animation.props, props, ".props is a copy of the original" );
50+
51+
deepEqual( animation.opts, {
52+
duration: 100,
53+
queue: "fx",
54+
specialEasing: { test: undefined },
55+
easing: jQuery.easing._default
56+
}, ".options is filled with default easing and specialEasing" );
57+
58+
equal( animation.startTime, startTime, "startTime was set" );
59+
equal( animation.duration, 100, ".duration is set" );
60+
61+
equal( animation.tweens.length, 1, ".tweens has one Tween" );
62+
equal( typeof animation.tweens[ 0 ].run, "function", "which has a .run function" );
63+
64+
equal( typeof animation.createTween, "function", ".createTween is a function" );
65+
equal( typeof animation.stop, "function", ".stop is a function" );
66+
67+
equal( typeof animation.done, "function", ".done is a function" );
68+
equal( typeof animation.fail, "function", ".fail is a function" );
69+
equal( typeof animation.always, "function", ".always is a function" );
70+
equal( typeof animation.progress, "function", ".progress is a function" );
71+
72+
equal( jQuery.timers.length, 1, "Added a timers function" );
73+
equal( jQuery.timers[ 0 ].elem, subject, "...with .elem as the subject" );
74+
equal( jQuery.timers[ 0 ].anim, animation, "...with .anim as the animation" );
75+
equal( jQuery.timers[ 0 ].queue, opts.queue, "...with .queue" );
76+
77+
// Cleanup after ourselves by ticking to the end
78+
this.clock.tick( 100 );
79+
} );
80+
81+
test( "Animation.prefilter( fn ) - calls prefilter after defaultPrefilter", function() {
82+
expect( 1 );
83+
84+
var prefilter = this.sandbox.stub(),
85+
defaultSpy = this.sandbox.spy( jQuery.Animation.prefilters, 0 );
86+
87+
jQuery.Animation.prefilter( prefilter );
88+
89+
jQuery.Animation( {}, {}, {} );
90+
ok( prefilter.calledAfter( defaultSpy ), "our prefilter called after" );
91+
} );
92+
93+
test( "Animation.prefilter( fn, true ) - calls prefilter before defaultPrefilter", function() {
94+
expect( 1 );
95+
96+
var prefilter = this.sandbox.stub(),
97+
defaultSpy = this.sandbox.spy( jQuery.Animation.prefilters, 0 );
98+
99+
jQuery.Animation.prefilter( prefilter, true );
100+
101+
jQuery.Animation( {}, {}, {} );
102+
ok( prefilter.calledBefore( defaultSpy ), "our prefilter called before" );
103+
} );
104+
105+
test( "Animation.prefilter - prefilter return hooks", function() {
106+
expect( 34 );
107+
108+
var animation, realAnimation, element,
109+
sandbox = this.sandbox,
110+
ourAnimation = { stop: this.sandbox.spy() },
111+
target = { height: 50 },
112+
props = { height: 100 },
113+
opts = { duration: 100 },
114+
prefilter = this.sandbox.spy( function() {
115+
realAnimation = this;
116+
sandbox.spy( realAnimation, "createTween" );
117+
118+
deepEqual( realAnimation.originalProperties, props, "originalProperties" );
119+
equal( arguments[ 0 ], this.elem, "first param elem" );
120+
equal( arguments[ 1 ], this.props, "second param props" );
121+
equal( arguments[ 2 ], this.opts, "third param opts" );
122+
return ourAnimation;
123+
} ),
124+
defaultSpy = sandbox.spy( jQuery.Animation.prefilters, 0 ),
125+
queueSpy = sandbox.spy( function( next ) {
126+
next();
127+
} ),
128+
TweenSpy = sandbox.spy( jQuery, "Tween" );
129+
130+
jQuery.Animation.prefilter( prefilter, true );
131+
132+
sandbox.stub( jQuery.fx, "timer" );
133+
134+
animation = jQuery.Animation( target, props, opts );
135+
136+
equal( prefilter.callCount, 1, "Called prefilter" );
137+
138+
equal( defaultSpy.callCount, 0,
139+
"Returning something from a prefilter caused remaining prefilters to not run" );
140+
equal( jQuery.fx.timer.callCount, 0, "Returning something never queues a timer" );
141+
equal( animation, ourAnimation, "Returning something returned it from jQuery.Animation" );
142+
equal( realAnimation.createTween.callCount, 0, "Returning something never creates tweens" );
143+
equal( TweenSpy.callCount, 0, "Returning something never creates tweens" );
144+
145+
// Test overriden usage on queues:
146+
prefilter.reset();
147+
element = jQuery( "<div>" )
148+
.css( "height", 50 )
149+
.animate( props, 100 )
150+
.queue( queueSpy )
151+
.animate( props, 100 )
152+
.queue( queueSpy )
153+
.animate( props, 100 )
154+
.queue( queueSpy );
155+
156+
equal( prefilter.callCount, 1, "Called prefilter" );
157+
equal( queueSpy.callCount, 0, "Next function in queue not called" );
158+
159+
realAnimation.opts.complete.call( realAnimation.elem );
160+
equal( queueSpy.callCount, 1, "Next function in queue called after complete" );
161+
162+
equal( prefilter.callCount, 2, "Called prefilter again - animation #2" );
163+
equal( ourAnimation.stop.callCount, 0, ".stop() on our animation hasn't been called" );
164+
165+
element.stop();
166+
equal( ourAnimation.stop.callCount, 1, ".stop() called ourAnimation.stop()" );
167+
ok( !ourAnimation.stop.args[ 0 ][ 0 ], ".stop( falsy ) (undefined or false are both valid)" );
168+
169+
equal( queueSpy.callCount, 2, "Next queue function called" );
170+
ok( queueSpy.calledAfter( ourAnimation.stop ), "After our animation was told to stop" );
171+
172+
// ourAnimation.stop.reset();
173+
equal( prefilter.callCount, 3, "Got the next animation" );
174+
175+
ourAnimation.stop.reset();
176+
177+
// do not clear queue, gotoEnd
178+
element.stop( false, true );
179+
ok( ourAnimation.stop.calledWith( true ), ".stop(true) calls .stop(true)" );
180+
ok( queueSpy.calledAfter( ourAnimation.stop ),
181+
"and the next queue function ran after we were told" );
182+
} );
183+
184+
test( "Animation.tweener( fn ) - unshifts a * tweener", function() {
185+
expect( 2 );
186+
var starTweeners = jQuery.Animation.tweeners[ "*" ];
187+
188+
jQuery.Animation.tweener( jQuery.noop );
189+
equal( starTweeners.length, 2 );
190+
deepEqual( starTweeners, [ jQuery.noop, defaultTweener ] );
191+
} );
192+
193+
test( "Animation.tweener( 'prop', fn ) - unshifts a 'prop' tweener", function() {
194+
expect( 4 );
195+
var tweeners = jQuery.Animation.tweeners,
196+
fn = function() {};
197+
198+
jQuery.Animation.tweener( "prop", jQuery.noop );
199+
equal( tweeners.prop.length, 1 );
200+
deepEqual( tweeners.prop, [ jQuery.noop ] );
201+
202+
jQuery.Animation.tweener( "prop", fn );
203+
equal( tweeners.prop.length, 2 );
204+
deepEqual( tweeners.prop, [ fn, jQuery.noop ] );
205+
} );
206+
207+
test( "Animation.tweener( 'list of props', fn ) - unshifts a tweener to each prop", function() {
208+
expect( 2 );
209+
var tweeners = jQuery.Animation.tweeners,
210+
fn = function() {};
211+
212+
jQuery.Animation.tweener( "list of props", jQuery.noop );
213+
deepEqual( tweeners, {
214+
list: [ jQuery.noop ],
215+
of: [ jQuery.noop ],
216+
props: [ jQuery.noop ],
217+
"*": [ defaultTweener ]
218+
} );
219+
220+
// Test with extra whitespaces
221+
jQuery.Animation.tweener( " list\t of \tprops\n*", fn );
222+
deepEqual( tweeners, {
223+
list: [ fn, jQuery.noop ],
224+
of: [ fn, jQuery.noop ],
225+
props: [ fn, jQuery.noop ],
226+
"*": [ fn, defaultTweener ]
227+
} );
228+
} );
229+
230+
} )();

0 commit comments

Comments
 (0)