Data: Separate data & css/effects camelCase implementations
[jquery.git] / test / unit / tween.js
blob9367978774d2cfaf6f94527e10a7926de94237d0
1 ( function() {
3 // Can't test what ain't there
4 if ( !jQuery.fx ) {
5         return;
8 var oldRaf = window.requestAnimationFrame;
10 QUnit.module( "tween", {
11         beforeEach: function() {
12                 this.sandbox = sinon.createSandbox();
13                 this.clock = this.sandbox.useFakeTimers( 505877050 );
14                 this._oldInterval = jQuery.fx.interval;
15                 window.requestAnimationFrame = null;
16                 jQuery.fx.step = {};
17                 jQuery.fx.interval = 10;
18         },
19         afterEach: function() {
20                 this.sandbox.restore();
21                 jQuery.fx.stop();
22                 jQuery.fx.interval = this._oldInterval;
23                 window.requestAnimationFrame = oldRaf;
24                 return moduleTeardown.apply( this, arguments );
25         }
26 } );
28 QUnit.test( "jQuery.Tween - Default propHooks on plain objects", function( assert ) {
29         assert.expect( 8 );
30         var propHooks, defaultHook, testObject, fakeTween, stepSpy;
32         propHooks = jQuery.Tween.propHooks;
33         assert.equal( typeof propHooks, "object", "jQuery.Tween.propHooks exists" );
35         defaultHook = propHooks._default;
36         assert.ok( defaultHook, "_default propHook exists" );
38         testObject = { test: 0 };
39         fakeTween = { elem: testObject, prop: "test", now: 10, unit: "px" };
41         assert.equal( defaultHook.get( fakeTween ), 0, "Can get property of object" );
43         fakeTween.prop = "testMissing";
44         assert.equal( defaultHook.get( fakeTween ), undefined, "Can get missing property on object" );
46         defaultHook.set( fakeTween );
47         assert.equal( testObject.testMissing, 10, "Sets missing value properly on plain object" );
49         fakeTween.prop = "opacity";
50         defaultHook.set( fakeTween );
51         assert.equal( testObject.opacity, 10, "Correctly set opacity on plain object" );
53         fakeTween.prop = "test";
54         stepSpy = jQuery.fx.step.test = this.sandbox.spy();
56         defaultHook.set( fakeTween );
57         assert.ok( stepSpy.calledWith( fakeTween ), "Step function called with Tween" );
58         assert.equal( testObject.test, 0, "Because step didn't set, value is unchanged" );
59 } );
61 QUnit.test( "jQuery.Tween - Default propHooks on elements", function( assert ) {
62         assert.expect( 19 );
63         var propHooks, defaultHook, testElement, fakeTween, cssStub, styleStub, stepSpy;
65         propHooks = jQuery.Tween.propHooks;
66         assert.equal( typeof propHooks, "object", "jQuery.Tween.propHooks exists" );
68         defaultHook = propHooks._default;
69         assert.ok( defaultHook, "_default propHook exists" );
71         testElement = jQuery( "<div>" )[ 0 ];
72         fakeTween = { elem: testElement, prop: "height", now: 10, unit: "px" };
74         cssStub = this.sandbox.stub( jQuery, "css" ).returns( 10 );
76         assert.equal( defaultHook.get( fakeTween ), 10, "Gets expected style value" );
77         assert.ok( cssStub.calledWith( testElement, "height", "" ), "Calls jQuery.css correctly" );
79         fakeTween.prop = "testOpti";
80         testElement.testOpti = 15;
81         cssStub.resetHistory();
83         assert.equal( defaultHook.get( fakeTween ), 15, "Gets expected value not defined on style" );
84         assert.equal( cssStub.callCount, 0, "Did not call jQuery.css" );
86         fakeTween.prop = "testMissing";
87         assert.equal( defaultHook.get( fakeTween ), 10, "Can get missing property on element" );
88         assert.ok( cssStub.calledWith( testElement, "testMissing", "" ), "...using jQuery.css" );
90         cssStub.returns( "" );
91         assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for empty string" );
93         cssStub.returns( "auto" );
94         assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for 'auto'" );
96         cssStub.returns( null );
97         assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for null" );
99         cssStub.returns( undefined );
100         assert.equal( defaultHook.get( fakeTween ), 0, "Uses 0 for undefined" );
102         cssStub.resetHistory();
104         // Setters
105         styleStub = this.sandbox.stub( jQuery, "style" );
106         fakeTween.prop = "height";
108         defaultHook.set( fakeTween );
109         assert.ok( styleStub.calledWith( testElement, "height", "10px" ),
110                 "Calls jQuery.style with elem, prop, now+unit" );
112         styleStub.resetHistory();
113         fakeTween.prop = "testMissing";
115         defaultHook.set( fakeTween );
116         assert.equal( styleStub.callCount, 0, "Did not call jQuery.style for non css property" );
117         assert.equal( testElement.testMissing, 10, "Instead, set value on element directly" );
119         jQuery.cssHooks.testMissing = jQuery.noop;
120         fakeTween.now = 11;
122         defaultHook.set( fakeTween );
123         delete jQuery.cssHooks.testMissing;
125         assert.ok( styleStub.calledWith( testElement, "testMissing", "11px" ),
126                 "Presence of cssHooks causes jQuery.style with elem, prop, now+unit" );
127         assert.equal( testElement.testMissing, 10, "And value was unchanged" );
129         stepSpy = jQuery.fx.step.test = this.sandbox.spy();
130         styleStub.resetHistory();
132         fakeTween.prop = "test";
133         defaultHook.set( fakeTween );
134         assert.ok( stepSpy.calledWith( fakeTween ), "Step function called with Tween" );
135         assert.equal( styleStub.callCount, 0, "Did not call jQuery.style" );
136 } );
138 QUnit.test( "jQuery.Tween - Plain Object", function( assert ) {
139         assert.expect( 13 );
140         var testObject = { test: 100 },
141                 testOptions = { duration: 100 },
142                 tween, easingSpy;
144         tween = jQuery.Tween( testObject, testOptions, "test", 0, "linear" );
145         assert.equal( tween.elem, testObject, "Sets .element" );
146         assert.equal( tween.options, testOptions, "sets .options" );
147         assert.equal( tween.prop, "test", "sets .prop" );
148         assert.equal( tween.end, 0, "sets .end" );
150         assert.equal( tween.easing, "linear", "sets .easing when provided" );
152         assert.equal( tween.start, 100, "Reads .start value during construction" );
153         assert.equal( tween.now, 100, "Reads .now value during construction" );
155         easingSpy = this.sandbox.spy( jQuery.easing, "linear" );
157         assert.equal( tween.run( 0.1 ), tween, ".run() returns this" );
159         assert.equal( tween.now, 90, "Calculated tween" );
161         assert.ok( easingSpy.calledWith( 0.1, 0.1 * testOptions.duration, 0, 1, testOptions.duration ),
162                 "...using jQuery.easing.linear with back-compat arguments" );
163         assert.equal( testObject.test, 90, "Set value" );
165         tween.run( 1 );
166         assert.equal( testObject.test, 0, "Checking another value" );
168         tween.run( 0 );
169         assert.equal( testObject.test, 100, "Can even go back in time" );
170 } );
172 QUnit.test( "jQuery.Tween - Element", function( assert ) {
173         assert.expect( 15 );
174         var testElement = jQuery( "<div>" ).css( "height", 100 )[ 0 ],
175                 testOptions = { duration: 100 },
176                 tween, easingSpy, eased;
178         tween = jQuery.Tween( testElement, testOptions, "height", 0 );
179         assert.equal( tween.elem, testElement, "Sets .element" );
180         assert.equal( tween.options, testOptions, "sets .options" );
181         assert.equal( tween.prop, "height", "sets .prop" );
182         assert.equal( tween.end, 0, "sets .end" );
184         assert.equal(
185                 tween.easing,
186                 jQuery.easing._default,
187                 "sets .easing to default when not provided"
188         );
189         assert.equal( tween.unit, "px", "sets .unit to px when not provided" );
191         assert.equal( tween.start, 100, "Reads .start value during construction" );
192         assert.equal( tween.now, 100, "Reads .now value during construction" );
194         easingSpy = this.sandbox.spy( jQuery.easing, "swing" );
196         assert.equal( tween.run( 0.1 ), tween, ".run() returns this" );
197         assert.equal( tween.pos, jQuery.easing.swing( 0.1 ), "set .pos" );
198         eased = 100 - ( jQuery.easing.swing( 0.1 ) * 100 );
199         assert.equal( tween.now, eased, "Calculated tween" );
201         assert.ok(
202                 easingSpy.calledWith( 0.1, 0.1 * testOptions.duration, 0, 1, testOptions.duration ),
203                 "...using jQuery.easing.linear with back-compat arguments"
204         );
205         assert.equal(
206                 parseFloat( testElement.style.height ).toFixed( 2 ),
207                 eased.toFixed( 2 ), "Set value"
208         );
210         tween.run( 1 );
211         assert.equal( testElement.style.height, "0px", "Checking another value" );
213         tween.run( 0 );
214         assert.equal( testElement.style.height, "100px", "Can even go back in time" );
215 } );
217 QUnit.test( "jQuery.Tween - No duration", function( assert ) {
218         assert.expect( 3 );
220         var testObject = { test: 100 },
221                 testOptions = { duration: 0 },
222                 tween, easingSpy;
224         tween = jQuery.Tween( testObject, testOptions, "test", 0 );
225         easingSpy = this.sandbox.spy( jQuery.easing, "swing" );
226         tween.run( 0.5 );
228         assert.equal( tween.pos, 0.5, "set .pos correctly" );
229         assert.equal( testObject.test, 50, "set value on object correctly" );
230         assert.equal( easingSpy.callCount, 0, "didn't ease the value" );
231 } );
233 QUnit.test( "jQuery.Tween - step function option", function( assert ) {
234         assert.expect( 4 );
236         var testObject = { test: 100 },
237                 testOptions = { duration: 100, step: this.sandbox.spy() },
238                 tween, propHookSpy;
240         propHookSpy = this.sandbox.spy( jQuery.Tween.propHooks._default, "set" );
242         tween = jQuery.Tween( testObject, testOptions, "test", 0, "linear" );
243         assert.equal( testOptions.step.callCount, 0, "didn't call step on create" );
245         tween.run( 0.5 );
246         assert.ok(
247                 testOptions.step.calledOn( testObject ),
248                 "Called step function in context of animated object"
249         );
250         assert.ok(
251                 testOptions.step.calledWith( 50, tween ),
252                 "Called step function with correct parameters"
253         );
254         assert.ok(
255                 testOptions.step.calledBefore( propHookSpy ),
256                 "Called step function before calling propHook.set"
257         );
259 } );
261 QUnit.test( "jQuery.Tween - custom propHooks", function( assert ) {
262         assert.expect( 3 );
264         var testObject = {},
265                 testOptions = { duration: 100, step: this.sandbox.spy() },
266                 propHook = {
267                         get: sinon.stub().returns( 100 ),
268                         set: sinon.stub()
269                 },
270                 tween;
272         jQuery.Tween.propHooks.testHooked = propHook;
274         tween = jQuery.Tween( testObject, testOptions, "testHooked", 0, "linear" );
275         assert.ok( propHook.get.calledWith( tween ), "called propHook.get on create" );
276         assert.equal( tween.now, 100, "Used return value from propHook.get" );
278         tween.run( 0.5 );
279         assert.ok(
280                 propHook.set.calledWith( tween ),
281                 "Called propHook.set function with correct parameters"
282         );
284         delete jQuery.Tween.propHooks.testHooked;
285 } );
287 QUnit.test( "jQuery.Tween - custom propHooks - advanced values", function( assert ) {
288         assert.expect( 5 );
290         var testObject = {},
291                 testOptions = { duration: 100, step: this.sandbox.spy() },
292                 propHook = {
293                         get: sinon.stub().returns( [ 0, 0 ] ),
294                         set: sinon.spy()
295                 },
296                 tween;
298         jQuery.Tween.propHooks.testHooked = propHook;
300         tween = jQuery.Tween( testObject, testOptions, "testHooked", [ 1, 1 ], "linear" );
301         assert.ok( propHook.get.calledWith( tween ), "called propHook.get on create" );
302         assert.deepEqual( tween.start, [ 0, 0 ], "Used return value from get" );
304         tween.run( 0.5 );
306         // Some day this NaN assumption might change - perhaps add a "calc" helper to the hooks?
307         assert.ok( isNaN( tween.now ), "Used return value from propHook.get" );
308         assert.equal( tween.pos, 0.5, "But the eased percent is still available" );
309         assert.ok(
310                 propHook.set.calledWith( tween ),
311                 "Called propHook.set function with correct parameters"
312         );
314         delete jQuery.Tween.propHooks.testHooked;
315 } );
317 } )();