UNPKG

elsewhere

Version:

A node project that aims to replicate the functionality of the Google Social Graph API

574 lines (467 loc) 15.4 kB
test("its should be part of Underscore", function() { ok( _.VERSION ); equal( typeof _.Deferred, 'function' ); }); _.each( [ "", " - new operator" ], function( withNew ) { function createDeferred( fn ) { return withNew ? new _.Deferred( fn ) : _.Deferred( fn ); } test("_.Deferred" + withNew, function() { expect( 22 ); createDeferred().resolve().then( function() { ok( true , "Success on resolve" ); ok( this.isResolved(), "Deferred is resolved" ); strictEqual( this.state(), "resolved", "Deferred is resolved (state)" ); }, function() { ok( false , "Error on resolve" ); }).always( function() { ok( true , "Always callback on resolve" ); }); createDeferred().reject().then( function() { ok( false , "Success on reject" ); }, function() { ok( true , "Error on reject" ); ok( this.isRejected(), "Deferred is rejected" ); strictEqual( this.state(), "rejected", "Deferred is rejected (state)" ); }).always( function() { ok( true , "Always callback on reject" ); }); createDeferred( function( defer ) { ok( this === defer , "Defer passed as this & first argument" ); this.resolve( "done" ); }).then( function( value ) { strictEqual( value , "done" , "Passed function executed" ); }); _.each( "resolve reject".split( " " ), function( change ) { createDeferred( function( defer ) { strictEqual( defer.state(), "pending", "pending after creation" ); var checked = 0; defer.progress(function( value ) { strictEqual( value, checked, "Progress: right value (" + value + ") received" ); }); for( checked = 0; checked < 3 ; checked++ ) { defer.notify( checked ); } strictEqual( defer.state(), "pending", "pending after notification" ); defer[ change ](); notStrictEqual( defer.state(), "pending", "not pending after " + change ); defer.notify(); }); }); }); } ); test( "_.Deferred - chainability", function() { var methods = "resolve reject notify resolveWith rejectWith notifyWith done fail progress then always".split( " " ), defer = _.Deferred(); expect( methods.length ); _.each( methods, function( method ) { var object = { m: defer[ method ] }; strictEqual( object.m(), object, method + " is chainable" ); }); }); test( "_.Deferred.pipe - filtering (done)", function() { expect(4); var defer = _.Deferred(), piped = defer.pipe(function( a, b ) { return a * b; }), value1, value2, value3; piped.done(function( result ) { value3 = result; }); defer.done(function( a, b ) { value1 = a; value2 = b; }); defer.resolve( 2, 3 ); strictEqual( value1, 2, "first resolve value ok" ); strictEqual( value2, 3, "second resolve value ok" ); strictEqual( value3, 6, "result of filter ok" ); _.Deferred().reject().pipe(function() { ok( false, "pipe should not be called on reject" ); }); _.Deferred().resolve().pipe( _.noop ).done(function( value ) { strictEqual( value, undefined, "pipe done callback can return undefined/null" ); }); }); test( "_.Deferred.pipe - filtering (fail)", function() { expect(4); var defer = _.Deferred(), piped = defer.pipe( null, function( a, b ) { return a * b; } ), value1, value2, value3; piped.fail(function( result ) { value3 = result; }); defer.fail(function( a, b ) { value1 = a; value2 = b; }); defer.reject( 2, 3 ); strictEqual( value1, 2, "first reject value ok" ); strictEqual( value2, 3, "second reject value ok" ); strictEqual( value3, 6, "result of filter ok" ); _.Deferred().resolve().pipe( null, function() { ok( false, "pipe should not be called on resolve" ); } ); _.Deferred().reject().pipe( null, _.noop ).fail(function( value ) { strictEqual( value, undefined, "pipe fail callback can return undefined/null" ); }); }); test( "_.Deferred.pipe - filtering (progress)", function() { expect(3); var defer = _.Deferred(), piped = defer.pipe( null, null, function( a, b ) { return a * b; } ), value1, value2, value3; piped.progress(function( result ) { value3 = result; }); defer.progress(function( a, b ) { value1 = a; value2 = b; }); defer.notify( 2, 3 ); strictEqual( value1, 2, "first progress value ok" ); strictEqual( value2, 3, "second progress value ok" ); strictEqual( value3, 6, "result of filter ok" ); }); test( "_.Deferred.pipe - deferred (done)", function() { expect(3); var defer = _.Deferred(), piped = defer.pipe(function( a, b ) { return _.Deferred(function( defer ) { defer.reject( a * b ); }); }), value1, value2, value3; piped.fail(function( result ) { value3 = result; }); defer.done(function( a, b ) { value1 = a; value2 = b; }); defer.resolve( 2, 3 ); strictEqual( value1, 2, "first resolve value ok" ); strictEqual( value2, 3, "second resolve value ok" ); strictEqual( value3, 6, "result of filter ok" ); }); test( "_.Deferred.pipe - deferred (fail)", function() { expect(3); var defer = _.Deferred(), piped = defer.pipe( null, function( a, b ) { return _.Deferred(function( defer ) { defer.resolve( a * b ); }); } ), value1, value2, value3; piped.done(function( result ) { value3 = result; }); defer.fail(function( a, b ) { value1 = a; value2 = b; }); defer.reject( 2, 3 ); strictEqual( value1, 2, "first reject value ok" ); strictEqual( value2, 3, "second reject value ok" ); strictEqual( value3, 6, "result of filter ok" ); }); test( "_.Deferred.pipe - deferred (progress)", function() { expect(3); var defer = _.Deferred(), piped = defer.pipe( null, null, function( a, b ) { return _.Deferred(function( defer ) { defer.resolve( a * b ); }); } ), value1, value2, value3; piped.done(function( result ) { value3 = result; }); defer.progress(function( a, b ) { value1 = a; value2 = b; }); defer.notify( 2, 3 ); strictEqual( value1, 2, "first progress value ok" ); strictEqual( value2, 3, "second progress value ok" ); strictEqual( value3, 6, "result of filter ok" ); }); test( "_.Deferred.pipe - context", function() { expect(4); var context = {}; _.Deferred().resolveWith( context, [ 2 ] ).pipe(function( value ) { return value * 3; }).done(function( value ) { strictEqual( this, context, "custom context correctly propagated" ); strictEqual( value, 6, "proper value received" ); }); var defer = _.Deferred(), piped = defer.pipe(function( value ) { return value * 3; }); defer.resolve( 2 ); piped.done(function( value ) { strictEqual( this.promise(), piped, "default context gets updated to latest defer in the chain" ); strictEqual( value, 6, "proper value received" ); }); }); test( "_.when" , function() { expect( 23 ); // Some other objects _.each( { "an empty string": "", "a non-empty string": "some string", "zero": 0, "a number other than zero": 1, "true": true, "false": false, "null": null, "undefined": undefined, "a plain object": {} } , function( value, message ) { ok( _.isFunction( _.when( value ).done(function( resolveValue ) { strictEqual( resolveValue , value , "Test the promise was resolved with " + message ); }).promise ) , "Test " + message + " triggers the creation of a new Promise" ); } ); ok( _.isFunction( _.when().done(function( resolveValue ) { strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" ); }).promise ) , "Test calling when with no parameter triggers the creation of a new Promise" ); var cache, i; for( i = 1 ; i < 4 ; i++ ) { _.when( cache || _.Deferred( function() { this.resolve( i ); }) ).done(function( value ) { strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) ); cache = value; }); } }); test("_.when - joined", function() { expect(53); var deferreds = { value: 1, success: _.Deferred().resolve( 1 ), error: _.Deferred().reject( 0 ), futureSuccess: _.Deferred().notify( true ), futureError: _.Deferred().notify( true ), notify: _.Deferred().notify( true ) }, willSucceed = { value: true, success: true, futureSuccess: true }, willError = { error: true, futureError: true }, willNotify = { futureSuccess: true, futureError: true, notify: true }; _.each( deferreds, function( defer1, id1 ) { _.each( deferreds, function( defer2, id2 ) { var shouldResolve = willSucceed[ id1 ] && willSucceed[ id2 ], shouldError = willError[ id1 ] || willError[ id2 ], shouldNotify = willNotify[ id1 ] || willNotify[ id2 ], expected = shouldResolve ? [ 1, 1 ] : [ 0, undefined ], expectedNotify = shouldNotify && [ willNotify[ id1 ], willNotify[ id2 ] ], code = id1 + "/" + id2; var promise = _.when( defer1, defer2 ).done(function( a, b ) { if ( shouldResolve ) { deepEqual( [ a, b ], expected, code + " => resolve" ); } else { ok( false , code + " => resolve" ); } }).fail(function( a, b ) { if ( shouldError ) { deepEqual( [ a, b ], expected, code + " => reject" ); } else { ok( false , code + " => reject" ); } }).progress(function progress( a, b ) { deepEqual( [ a, b ], expectedNotify, code + " => progress" ); }); } ); } ); deferreds.futureSuccess.resolve( 1 ); deferreds.futureError.reject( 0 ); }); (function() { var output, addToOutput = function( string ) { return function() { output += string; }; }, outputA = addToOutput( "A" ), outputB = addToOutput( "B" ), outputC = addToOutput( "C" ), tests = { "": "XABC X XABCABCC X XBB X XABA X", "once": "XABC X X X X X XABA X", "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC", "unique": "XABC X XABCA X XBB X XAB X", "stopOnFalse": "XABC X XABCABCC X XBB X XA X", "once memory": "XABC XABC X XA X XA XABA XC", "once unique": "XABC X X X X X XAB X", "once stopOnFalse": "XABC X X X X X XA X", "memory unique": "XABC XA XABCA XA XBB XB XAB XC", "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X", "unique stopOnFalse": "XABC X XABCA X XBB X XA X" }, filters = { "no filter": undefined, "filter": function( fn ) { return function() { return fn.apply( this, arguments ); }; } }; _.each( tests, function( resultString, flags ) { _.each( filters, function( filter, filterLabel ) { test( "_.Callbacks( \"" + flags + "\" ) - " + filterLabel, function() { expect( 20 ); // Give qunit a little breathing room stop(); setTimeout( start, 0 ); var cblist; results = resultString.split( /\s+/ ); // Basic binding and firing output = "X"; cblist = _.Callbacks( flags ); cblist.add(function( str ) { output += str; }); cblist.fire( "A" ); strictEqual( output, "XA", "Basic binding and firing" ); strictEqual( cblist.fired(), true, ".fired() detects firing" ); output = "X"; cblist.disable(); cblist.add(function( str ) { output += str; }); strictEqual( output, "X", "Adding a callback after disabling" ); cblist.fire( "A" ); strictEqual( output, "X", "Firing after disabling" ); // Basic binding and firing (context, arguments) output = "X"; cblist = _.Callbacks( flags ); cblist.add(function() { equal( this, window, "Basic binding and firing (context)" ); output += Array.prototype.join.call( arguments, "" ); }); cblist.fireWith( window, [ "A", "B" ] ); strictEqual( output, "XAB", "Basic binding and firing (arguments)" ); // fireWith with no arguments output = ""; cblist = _.Callbacks( flags ); cblist.add(function() { equal( this, window, "fireWith with no arguments (context is window)" ); strictEqual( arguments.length, 0, "fireWith with no arguments (no arguments)" ); }); cblist.fireWith(); // Basic binding, removing and firing output = "X"; cblist = _.Callbacks( flags ); cblist.add( outputA, outputB, outputC ); cblist.remove( outputB, outputC ); cblist.fire(); strictEqual( output, "XA", "Basic binding, removing and firing" ); // Empty output = "X"; cblist = _.Callbacks( flags ); cblist.add( outputA ); cblist.add( outputB ); cblist.add( outputC ); cblist.empty(); cblist.fire(); strictEqual( output, "X", "Empty" ); // Locking output = "X"; cblist = _.Callbacks( flags ); cblist.add( function( str ) { output += str; }); cblist.lock(); cblist.add( function( str ) { output += str; }); cblist.fire( "A" ); cblist.add( function( str ) { output += str; }); strictEqual( output, "X", "Lock early" ); // Ordering output = "X"; cblist = _.Callbacks( flags ); cblist.add( function() { cblist.add( outputC ); outputA(); }, outputB ); cblist.fire(); strictEqual( output, results.shift(), "Proper ordering" ); // Add and fire again output = "X"; cblist.add( function() { cblist.add( outputC ); outputA(); }, outputB ); strictEqual( output, results.shift(), "Add after fire" ); output = "X"; cblist.fire(); strictEqual( output, results.shift(), "Fire again" ); // Multiple fire output = "X"; cblist = _.Callbacks( flags ); cblist.add( function( str ) { output += str; } ); cblist.fire( "A" ); strictEqual( output, "XA", "Multiple fire (first fire)" ); output = "X"; cblist.add( function( str ) { output += str; } ); strictEqual( output, results.shift(), "Multiple fire (first new callback)" ); output = "X"; cblist.fire( "B" ); strictEqual( output, results.shift(), "Multiple fire (second fire)" ); output = "X"; cblist.add( function( str ) { output += str; } ); strictEqual( output, results.shift(), "Multiple fire (second new callback)" ); // Return false output = "X"; cblist = _.Callbacks( flags ); cblist.add( outputA, function() { return false; }, outputB ); cblist.add( outputA ); cblist.fire(); strictEqual( output, results.shift(), "Callback returning false" ); // Add another callback (to control lists with memory do not fire anymore) output = "X"; cblist.add( outputC ); strictEqual( output, results.shift(), "Adding a callback after one returned false" ); }); }); }); })();