mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Effects: Adding unit tests for jQuery.Animation
Closes gh-2326
This commit is contained in:
parent
cdaed15c7e
commit
b3b2d6c3dd
@ -103,14 +103,15 @@ module.exports = function( grunt ) {
|
||||
src: "src/**/*.js",
|
||||
gruntfile: "Gruntfile.js",
|
||||
|
||||
// Right now, check only test helpers
|
||||
test: [ "test/data/testrunner.js", "test/unit/tween.js" ],
|
||||
// Check parts of tests that pass
|
||||
test: [ "test/data/testrunner.js", "test/unit/animation.js", "test/unit/tween.js" ],
|
||||
release: [ "build/*.js", "!build/release-notes.js" ],
|
||||
tasks: "build/tasks/*.js"
|
||||
},
|
||||
testswarm: {
|
||||
tests: [
|
||||
"ajax",
|
||||
"animation",
|
||||
"attributes",
|
||||
"callbacks",
|
||||
"core",
|
||||
|
44
src/effects.js
vendored
44
src/effects.js
vendored
@ -2,6 +2,7 @@ define([
|
||||
"./core",
|
||||
"./var/document",
|
||||
"./var/rcssNum",
|
||||
"./var/rnotwhite",
|
||||
"./css/var/cssExpand",
|
||||
"./css/var/isHidden",
|
||||
"./css/var/swap",
|
||||
@ -16,20 +17,13 @@ define([
|
||||
"./manipulation",
|
||||
"./css",
|
||||
"./effects/Tween"
|
||||
], function( jQuery, document, rcssNum, cssExpand, isHidden, swap, adjustCSS, dataPriv, showHide ) {
|
||||
], function( jQuery, document, rcssNum, rnotwhite, cssExpand, isHidden, swap,
|
||||
adjustCSS, dataPriv, showHide ) {
|
||||
|
||||
var
|
||||
fxNow, timerId,
|
||||
rfxtypes = /^(?:toggle|show|hide)$/,
|
||||
rrun = /queueHooks$/,
|
||||
animationPrefilters = [ defaultPrefilter ],
|
||||
tweeners = {
|
||||
"*": [ function( prop, value ) {
|
||||
var tween = this.createTween( prop, value );
|
||||
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
|
||||
return tween;
|
||||
} ]
|
||||
};
|
||||
rrun = /queueHooks$/;
|
||||
|
||||
function raf() {
|
||||
if ( timerId ) {
|
||||
@ -69,7 +63,7 @@ function genFx( type, includeWidth ) {
|
||||
|
||||
function createTween( value, prop, animation ) {
|
||||
var tween,
|
||||
collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
|
||||
collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
|
||||
index = 0,
|
||||
length = collection.length;
|
||||
for ( ; index < length; index++ ) {
|
||||
@ -281,7 +275,7 @@ function Animation( elem, properties, options ) {
|
||||
var result,
|
||||
stopped,
|
||||
index = 0,
|
||||
length = animationPrefilters.length,
|
||||
length = Animation.prefilters.length,
|
||||
deferred = jQuery.Deferred().always( function() {
|
||||
// Don't match elem in the :animated selector
|
||||
delete tick.elem;
|
||||
@ -357,8 +351,12 @@ function Animation( elem, properties, options ) {
|
||||
propFilter( props, animation.opts.specialEasing );
|
||||
|
||||
for ( ; index < length ; index++ ) {
|
||||
result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
|
||||
result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
|
||||
if ( result ) {
|
||||
if ( jQuery.isFunction( result.stop ) ) {
|
||||
jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
|
||||
jQuery.proxy( result.stop, result );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -386,12 +384,20 @@ function Animation( elem, properties, options ) {
|
||||
|
||||
jQuery.Animation = jQuery.extend( Animation, {
|
||||
|
||||
tweeners: {
|
||||
"*": [ function( prop, value ) {
|
||||
var tween = this.createTween( prop, value );
|
||||
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
|
||||
return tween;
|
||||
} ]
|
||||
},
|
||||
|
||||
tweener: function( props, callback ) {
|
||||
if ( jQuery.isFunction( props ) ) {
|
||||
callback = props;
|
||||
props = [ "*" ];
|
||||
} else {
|
||||
props = props.split(" ");
|
||||
props = props.match( rnotwhite );
|
||||
}
|
||||
|
||||
var prop,
|
||||
@ -400,16 +406,18 @@ jQuery.Animation = jQuery.extend( Animation, {
|
||||
|
||||
for ( ; index < length ; index++ ) {
|
||||
prop = props[ index ];
|
||||
tweeners[ prop ] = tweeners[ prop ] || [];
|
||||
tweeners[ prop ].unshift( callback );
|
||||
Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
|
||||
Animation.tweeners[ prop ].unshift( callback );
|
||||
}
|
||||
},
|
||||
|
||||
prefilters: [ defaultPrefilter ],
|
||||
|
||||
prefilter: function( callback, prepend ) {
|
||||
if ( prepend ) {
|
||||
animationPrefilters.unshift( callback );
|
||||
Animation.prefilters.unshift( callback );
|
||||
} else {
|
||||
animationPrefilters.push( callback );
|
||||
Animation.prefilters.push( callback );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -286,6 +286,7 @@ this.loadTests = function() {
|
||||
"unit/effects.js",
|
||||
"unit/offset.js",
|
||||
"unit/dimensions.js",
|
||||
"unit/animation.js",
|
||||
"unit/tween.js"
|
||||
];
|
||||
|
||||
|
230
test/unit/animation.js
Normal file
230
test/unit/animation.js
Normal file
@ -0,0 +1,230 @@
|
||||
( function() {
|
||||
|
||||
// Can't test what ain't there
|
||||
if ( !jQuery.fx ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldRaf = window.requestAnimationFrame,
|
||||
defaultPrefilter = jQuery.Animation.prefilters[ 0 ],
|
||||
defaultTweener = jQuery.Animation.tweeners[ "*" ][ 0 ],
|
||||
startTime = 505877050;
|
||||
|
||||
// This module tests jQuery.Animation and the corresponding 1.8+ effects APIs
|
||||
module( "animation", {
|
||||
setup: function() {
|
||||
window.requestAnimationFrame = null;
|
||||
this.sandbox = sinon.sandbox.create();
|
||||
this.clock = this.sandbox.useFakeTimers( startTime );
|
||||
this._oldInterval = jQuery.fx.interval;
|
||||
jQuery.fx.step = {};
|
||||
jQuery.fx.interval = 10;
|
||||
jQuery.now = Date.now;
|
||||
jQuery.Animation.prefilters = [ defaultPrefilter ];
|
||||
jQuery.Animation.tweeners = { "*": [ defaultTweener ] };
|
||||
},
|
||||
teardown: function() {
|
||||
this.sandbox.restore();
|
||||
jQuery.now = Date.now;
|
||||
jQuery.fx.stop();
|
||||
jQuery.fx.interval = this._oldInterval;
|
||||
window.requestAnimationFrame = oldRaf;
|
||||
return moduleTeardown.apply( this, arguments );
|
||||
}
|
||||
} );
|
||||
|
||||
test( "Animation( subject, props, opts ) - shape", function() {
|
||||
expect( 20 );
|
||||
|
||||
var subject = { test: 0 },
|
||||
props = { test: 1 },
|
||||
opts = { queue: "fx", duration: 100 },
|
||||
animation = jQuery.Animation( subject, props, opts );
|
||||
|
||||
equal( animation.elem, subject, ".elem is set to the exact object passed" );
|
||||
equal( animation.originalOptions, opts, ".originalOptions is set to options passed" );
|
||||
equal( animation.originalProperties, props, ".originalProperties is set to props passed" );
|
||||
|
||||
notEqual( animation.props, props, ".props is not the original however" );
|
||||
deepEqual( animation.props, props, ".props is a copy of the original" );
|
||||
|
||||
deepEqual( animation.opts, {
|
||||
duration: 100,
|
||||
queue: "fx",
|
||||
specialEasing: { test: undefined },
|
||||
easing: jQuery.easing._default
|
||||
}, ".options is filled with default easing and specialEasing" );
|
||||
|
||||
equal( animation.startTime, startTime, "startTime was set" );
|
||||
equal( animation.duration, 100, ".duration is set" );
|
||||
|
||||
equal( animation.tweens.length, 1, ".tweens has one Tween" );
|
||||
equal( typeof animation.tweens[ 0 ].run, "function", "which has a .run function" );
|
||||
|
||||
equal( typeof animation.createTween, "function", ".createTween is a function" );
|
||||
equal( typeof animation.stop, "function", ".stop is a function" );
|
||||
|
||||
equal( typeof animation.done, "function", ".done is a function" );
|
||||
equal( typeof animation.fail, "function", ".fail is a function" );
|
||||
equal( typeof animation.always, "function", ".always is a function" );
|
||||
equal( typeof animation.progress, "function", ".progress is a function" );
|
||||
|
||||
equal( jQuery.timers.length, 1, "Added a timers function" );
|
||||
equal( jQuery.timers[ 0 ].elem, subject, "...with .elem as the subject" );
|
||||
equal( jQuery.timers[ 0 ].anim, animation, "...with .anim as the animation" );
|
||||
equal( jQuery.timers[ 0 ].queue, opts.queue, "...with .queue" );
|
||||
|
||||
// Cleanup after ourselves by ticking to the end
|
||||
this.clock.tick( 100 );
|
||||
} );
|
||||
|
||||
test( "Animation.prefilter( fn ) - calls prefilter after defaultPrefilter", function() {
|
||||
expect( 1 );
|
||||
|
||||
var prefilter = this.sandbox.stub(),
|
||||
defaultSpy = this.sandbox.spy( jQuery.Animation.prefilters, 0 );
|
||||
|
||||
jQuery.Animation.prefilter( prefilter );
|
||||
|
||||
jQuery.Animation( {}, {}, {} );
|
||||
ok( prefilter.calledAfter( defaultSpy ), "our prefilter called after" );
|
||||
} );
|
||||
|
||||
test( "Animation.prefilter( fn, true ) - calls prefilter before defaultPrefilter", function() {
|
||||
expect( 1 );
|
||||
|
||||
var prefilter = this.sandbox.stub(),
|
||||
defaultSpy = this.sandbox.spy( jQuery.Animation.prefilters, 0 );
|
||||
|
||||
jQuery.Animation.prefilter( prefilter, true );
|
||||
|
||||
jQuery.Animation( {}, {}, {} );
|
||||
ok( prefilter.calledBefore( defaultSpy ), "our prefilter called before" );
|
||||
} );
|
||||
|
||||
test( "Animation.prefilter - prefilter return hooks", function() {
|
||||
expect( 34 );
|
||||
|
||||
var animation, realAnimation, element,
|
||||
sandbox = this.sandbox,
|
||||
ourAnimation = { stop: this.sandbox.spy() },
|
||||
target = { height: 50 },
|
||||
props = { height: 100 },
|
||||
opts = { duration: 100 },
|
||||
prefilter = this.sandbox.spy( function() {
|
||||
realAnimation = this;
|
||||
sandbox.spy( realAnimation, "createTween" );
|
||||
|
||||
deepEqual( realAnimation.originalProperties, props, "originalProperties" );
|
||||
equal( arguments[ 0 ], this.elem, "first param elem" );
|
||||
equal( arguments[ 1 ], this.props, "second param props" );
|
||||
equal( arguments[ 2 ], this.opts, "third param opts" );
|
||||
return ourAnimation;
|
||||
} ),
|
||||
defaultSpy = sandbox.spy( jQuery.Animation.prefilters, 0 ),
|
||||
queueSpy = sandbox.spy( function( next ) {
|
||||
next();
|
||||
} ),
|
||||
TweenSpy = sandbox.spy( jQuery, "Tween" );
|
||||
|
||||
jQuery.Animation.prefilter( prefilter, true );
|
||||
|
||||
sandbox.stub( jQuery.fx, "timer" );
|
||||
|
||||
animation = jQuery.Animation( target, props, opts );
|
||||
|
||||
equal( prefilter.callCount, 1, "Called prefilter" );
|
||||
|
||||
equal( defaultSpy.callCount, 0,
|
||||
"Returning something from a prefilter caused remaining prefilters to not run" );
|
||||
equal( jQuery.fx.timer.callCount, 0, "Returning something never queues a timer" );
|
||||
equal( animation, ourAnimation, "Returning something returned it from jQuery.Animation" );
|
||||
equal( realAnimation.createTween.callCount, 0, "Returning something never creates tweens" );
|
||||
equal( TweenSpy.callCount, 0, "Returning something never creates tweens" );
|
||||
|
||||
// Test overriden usage on queues:
|
||||
prefilter.reset();
|
||||
element = jQuery( "<div>" )
|
||||
.css( "height", 50 )
|
||||
.animate( props, 100 )
|
||||
.queue( queueSpy )
|
||||
.animate( props, 100 )
|
||||
.queue( queueSpy )
|
||||
.animate( props, 100 )
|
||||
.queue( queueSpy );
|
||||
|
||||
equal( prefilter.callCount, 1, "Called prefilter" );
|
||||
equal( queueSpy.callCount, 0, "Next function in queue not called" );
|
||||
|
||||
realAnimation.opts.complete.call( realAnimation.elem );
|
||||
equal( queueSpy.callCount, 1, "Next function in queue called after complete" );
|
||||
|
||||
equal( prefilter.callCount, 2, "Called prefilter again - animation #2" );
|
||||
equal( ourAnimation.stop.callCount, 0, ".stop() on our animation hasn't been called" );
|
||||
|
||||
element.stop();
|
||||
equal( ourAnimation.stop.callCount, 1, ".stop() called ourAnimation.stop()" );
|
||||
ok( !ourAnimation.stop.args[ 0 ][ 0 ], ".stop( falsy ) (undefined or false are both valid)" );
|
||||
|
||||
equal( queueSpy.callCount, 2, "Next queue function called" );
|
||||
ok( queueSpy.calledAfter( ourAnimation.stop ), "After our animation was told to stop" );
|
||||
|
||||
// ourAnimation.stop.reset();
|
||||
equal( prefilter.callCount, 3, "Got the next animation" );
|
||||
|
||||
ourAnimation.stop.reset();
|
||||
|
||||
// do not clear queue, gotoEnd
|
||||
element.stop( false, true );
|
||||
ok( ourAnimation.stop.calledWith( true ), ".stop(true) calls .stop(true)" );
|
||||
ok( queueSpy.calledAfter( ourAnimation.stop ),
|
||||
"and the next queue function ran after we were told" );
|
||||
} );
|
||||
|
||||
test( "Animation.tweener( fn ) - unshifts a * tweener", function() {
|
||||
expect( 2 );
|
||||
var starTweeners = jQuery.Animation.tweeners[ "*" ];
|
||||
|
||||
jQuery.Animation.tweener( jQuery.noop );
|
||||
equal( starTweeners.length, 2 );
|
||||
deepEqual( starTweeners, [ jQuery.noop, defaultTweener ] );
|
||||
} );
|
||||
|
||||
test( "Animation.tweener( 'prop', fn ) - unshifts a 'prop' tweener", function() {
|
||||
expect( 4 );
|
||||
var tweeners = jQuery.Animation.tweeners,
|
||||
fn = function() {};
|
||||
|
||||
jQuery.Animation.tweener( "prop", jQuery.noop );
|
||||
equal( tweeners.prop.length, 1 );
|
||||
deepEqual( tweeners.prop, [ jQuery.noop ] );
|
||||
|
||||
jQuery.Animation.tweener( "prop", fn );
|
||||
equal( tweeners.prop.length, 2 );
|
||||
deepEqual( tweeners.prop, [ fn, jQuery.noop ] );
|
||||
} );
|
||||
|
||||
test( "Animation.tweener( 'list of props', fn ) - unshifts a tweener to each prop", function() {
|
||||
expect( 2 );
|
||||
var tweeners = jQuery.Animation.tweeners,
|
||||
fn = function() {};
|
||||
|
||||
jQuery.Animation.tweener( "list of props", jQuery.noop );
|
||||
deepEqual( tweeners, {
|
||||
list: [ jQuery.noop ],
|
||||
of: [ jQuery.noop ],
|
||||
props: [ jQuery.noop ],
|
||||
"*": [ defaultTweener ]
|
||||
} );
|
||||
|
||||
// Test with extra whitespaces
|
||||
jQuery.Animation.tweener( " list\t of \tprops\n*", fn );
|
||||
deepEqual( tweeners, {
|
||||
list: [ fn, jQuery.noop ],
|
||||
of: [ fn, jQuery.noop ],
|
||||
props: [ fn, jQuery.noop ],
|
||||
"*": [ fn, defaultTweener ]
|
||||
} );
|
||||
} );
|
||||
|
||||
} )();
|
Loading…
Reference in New Issue
Block a user