diff --git a/Gruntfile.js b/Gruntfile.js index 50a662cba..c05b42546 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -78,6 +78,11 @@ module.exports = function( grunt ) { "qunit/qunit.css": "qunitjs/qunit/qunit.css", "qunit/LICENSE.txt": "qunitjs/LICENSE.txt", + "qunit-assert-step/qunit-assert-step.js": + "qunit-assert-step/qunit-assert-step.js", + "qunit-assert-step/MIT-LICENSE.txt": + "qunit-assert-step/MIT-LICENSE.txt", + "requirejs/require.js": "requirejs/require.js", "sinon/fake_timers.js": "sinon/lib/sinon/util/fake_timers.js", diff --git a/external/qunit-assert-step/MIT-LICENSE.txt b/external/qunit-assert-step/MIT-LICENSE.txt new file mode 100644 index 000000000..aed5dc97e --- /dev/null +++ b/external/qunit-assert-step/MIT-LICENSE.txt @@ -0,0 +1,21 @@ +Copyright jQuery Foundation and other contributors +http://jquery.com/ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/external/qunit-assert-step/qunit-assert-step.js b/external/qunit-assert-step/qunit-assert-step.js new file mode 100644 index 000000000..90bca18cf --- /dev/null +++ b/external/qunit-assert-step/qunit-assert-step.js @@ -0,0 +1,26 @@ +QUnit.extend( QUnit.assert, { + + /** + * Check the sequence/order + * + * @example test('Example unit test', function(assert) { assert.step(1); setTimeout(function () { assert.step(3); start(); }, 100); assert.step(2); stop(); }); + * @param Number expected The excepted step within the test() + * @param String message (optional) + */ + step: function (expected, message) { + // increment internal step counter. + QUnit.config.current.step++; + if (typeof message === "undefined") { + message = "step " + expected; + } + var actual = QUnit.config.current.step; + QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); + } +}); + +/** + * Reset the step counter for every test() + */ +QUnit.testStart(function () { + QUnit.config.current.step = 0; +}); diff --git a/package.json b/package.json index b78f11a13..27ca0757f 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "promises-aplus-tests": "2.1.0", "q": "1.1.2", "qunitjs": "1.17.1", + "qunit-assert-step": "1.0.3", "requirejs": "2.1.17", "sinon": "1.10.3", "sizzle": "2.2.0", diff --git a/src/effects.js b/src/effects.js index 90ac4b1e6..64f9353ef 100644 --- a/src/effects.js +++ b/src/effects.js @@ -345,6 +345,7 @@ function Animation( elem, properties, options ) { // Resolve when we played the last frame; otherwise, reject if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); deferred.resolveWith( elem, [ animation, gotoEnd ] ); } else { deferred.rejectWith( elem, [ animation, gotoEnd ] ); diff --git a/test/index.html b/test/index.html index 0285176d3..54a1ee041 100644 --- a/test/index.html +++ b/test/index.html @@ -13,6 +13,7 @@ + diff --git a/test/unit/effects.js b/test/unit/effects.js index 755b074f8..4d51adbc9 100644 --- a/test/unit/effects.js +++ b/test/unit/effects.js @@ -1832,10 +1832,11 @@ QUnit.test( "non-px animation handles non-numeric start (#11971)", function( ass this.clock.tick( 10 ); } ); -QUnit.test( "Animation callbacks (#11797)", function( assert ) { - assert.expect( 15 ); +QUnit.test("Animation callbacks (#11797)", function( assert ) { + assert.expect( 16 ); - var targets = jQuery( "#foo" ).children(), + var prog = 0, + targets = jQuery( "#foo" ).children(), done = false, expectedProgress = 0; @@ -1845,7 +1846,8 @@ QUnit.test( "Animation callbacks (#11797)", function( assert ) { assert.ok( true, "empty: start" ); }, progress: function( anim, percent ) { - assert.equal( percent, 0, "empty: progress 0" ); + assert.equal( percent, prog, "empty: progress " + prog ); + prog = 1; }, done: function() { assert.ok( true, "empty: done" ); @@ -1917,6 +1919,45 @@ QUnit.test( "Animation callbacks (#11797)", function( assert ) { this.clock.tick( 10 ); } ); +QUnit.test( "Animation callbacks in order (#2292)", function( assert ) { + assert.expect( 9 ); + + var step = 0, + dur = 50; + + // assert? -> github.com/JamesMGreene/qunit-assert-step + jQuery( "#foo" ).animate( { + width: "5px" + }, { + duration: dur, + start: function() { + assert.step( 1 ); + }, + progress: function( anim, p, ms ) { + if ( !( step++ ) ) { + assert.step( 2 ); + assert.strictEqual( p, 0, "first progress callback: progress ratio" ); + assert.strictEqual( ms, dur, "first progress callback: remaining ms" ); + } else { + assert.step( 3 ); + assert.strictEqual( p, 1, "last progress callback: progress ratio" ); + assert.strictEqual( ms, 0, "last progress callback: remaining ms" ); + } + }, + done: function() { + assert.step( 4 ); + }, + fail: function() { + assert.ok( false, "Animation failed" ); + }, + always: function() { + assert.step( 5 ); + } + }).finish(); + + this.clock.tick( dur + 10 ); +} ); + QUnit.test( "Animate properly sets overflow hidden when animating width/height (#12117)", function( assert ) { assert.expect( 8 );