1 QUnit.module( "callbacks", {
2 teardown: moduleTeardown
8 addToOutput = function( string ) {
13 outputA = addToOutput( "A" ),
14 outputB = addToOutput( "B" ),
15 outputC = addToOutput( "C" ),
17 "": "XABC X XABCABCC X XBB X XABA X XX",
18 "once": "XABC X X X X X XABA X XX",
19 "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC XX",
20 "unique": "XABC X XABCA X XBB X XAB X X",
21 "stopOnFalse": "XABC X XABCABCC X XBB X XA X XX",
22 "once memory": "XABC XABC X XA X XA XABA XC XX",
23 "once unique": "XABC X X X X X XAB X X",
24 "once stopOnFalse": "XABC X X X X X XA X XX",
25 "memory unique": "XABC XA XABCA XA XBB XB XAB XC X",
26 "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X XX",
27 "unique stopOnFalse": "XABC X XABCA X XBB X XA X X"
30 "no filter": undefined,
31 "filter": function( fn ) {
33 return fn.apply( this, arguments );
38 function showFlags( flags ) {
39 if ( typeof flags === "string" ) {
40 return "'" + flags + "'";
43 for ( key in flags ) {
44 output.push( "'" + key + "': " + flags[ key ] );
46 return "{ " + output.join( ", " ) + " }";
49 jQuery.each( tests, function( strFlags, resultString ) {
53 jQuery.each( strFlags.split( " " ), function() {
55 objectFlags[ this ] = true;
59 jQuery.each( filters, function( filterLabel ) {
64 }, function( flagsTypes, flags ) {
66 QUnit.test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function( assert ) {
71 results = resultString.split( /\s+/ );
73 // Basic binding and firing
75 cblist = jQuery.Callbacks( flags );
76 assert.strictEqual( cblist.locked(), false, ".locked() initially false" );
77 assert.strictEqual( cblist.disabled(), false, ".disabled() initially false" );
78 assert.strictEqual( cblist.fired(), false, ".fired() initially false" );
79 cblist.add( function( str ) {
82 assert.strictEqual( cblist.fired(), false, ".fired() still false after .add" );
84 assert.strictEqual( output, "XA", "Basic binding and firing" );
85 assert.strictEqual( cblist.fired(), true, ".fired() detects firing" );
88 cblist.add( function( str ) {
91 assert.strictEqual( output, "X", "Adding a callback after disabling" );
93 assert.strictEqual( output, "X", "Firing after disabling" );
94 assert.strictEqual( cblist.disabled(), true, ".disabled() becomes true" );
95 assert.strictEqual( cblist.locked(), true, "disabling locks" );
97 // Emptying while firing (#13517)
98 cblist = jQuery.Callbacks( flags );
99 cblist.add( cblist.empty );
100 cblist.add( function() {
101 assert.ok( false, "not emptied" );
105 // Disabling while firing
106 cblist = jQuery.Callbacks( flags );
107 cblist.add( cblist.disable );
108 cblist.add( function() {
109 assert.ok( false, "not disabled" );
113 // Basic binding and firing (context, arguments)
115 cblist = jQuery.Callbacks( flags );
116 cblist.add( function() {
117 assert.equal( this, window, "Basic binding and firing (context)" );
118 output += Array.prototype.join.call( arguments, "" );
120 cblist.fireWith( window, [ "A", "B" ] );
121 assert.strictEqual( output, "XAB", "Basic binding and firing (arguments)" );
123 // fireWith with no arguments
125 cblist = jQuery.Callbacks( flags );
126 cblist.add( function() {
127 assert.equal( this, window, "fireWith with no arguments (context is window)" );
128 assert.strictEqual( arguments.length, 0, "fireWith with no arguments (no arguments)" );
132 // Basic binding, removing and firing
134 cblist = jQuery.Callbacks( flags );
135 cblist.add( outputA, outputB, outputC );
136 cblist.remove( outputB, outputC );
138 assert.strictEqual( output, "XA", "Basic binding, removing and firing" );
142 cblist = jQuery.Callbacks( flags );
143 cblist.add( outputA );
144 cblist.add( outputB );
145 cblist.add( outputC );
148 assert.strictEqual( output, "X", "Empty" );
152 cblist = jQuery.Callbacks( flags );
153 cblist.add( function( str ) {
157 cblist.add( function( str ) {
161 cblist.add( function( str ) {
164 assert.strictEqual( output, "X", "Lock early" );
165 assert.strictEqual( cblist.locked(), true, "Locking reflected in accessor" );
167 // Locking while firing (gh-1990)
169 cblist = jQuery.Callbacks( flags );
170 cblist.add( cblist.lock );
171 cblist.add( function( str ) {
175 assert.strictEqual( output, "XA", "Locking doesn't abort execution (gh-1990)" );
179 cblist = jQuery.Callbacks( flags );
180 cblist.add( function() {
181 cblist.add( outputC );
185 assert.strictEqual( output, results.shift(), "Proper ordering" );
187 // Add and fire again
189 cblist.add( function() {
190 cblist.add( outputC );
193 assert.strictEqual( output, results.shift(), "Add after fire" );
197 assert.strictEqual( output, results.shift(), "Fire again" );
201 cblist = jQuery.Callbacks( flags );
202 cblist.add( function( str ) {
206 assert.strictEqual( output, "XA", "Multiple fire (first fire)" );
208 cblist.add( function( str ) {
211 assert.strictEqual( output, results.shift(), "Multiple fire (first new callback)" );
214 assert.strictEqual( output, results.shift(), "Multiple fire (second fire)" );
216 cblist.add( function( str ) {
219 assert.strictEqual( output, results.shift(), "Multiple fire (second new callback)" );
223 cblist = jQuery.Callbacks( flags );
224 cblist.add( outputA, function() { return false; }, outputB );
225 cblist.add( outputA );
227 assert.strictEqual( output, results.shift(), "Callback returning false" );
229 // Add another callback (to control lists with memory do not fire anymore)
231 cblist.add( outputC );
232 assert.strictEqual( output, results.shift(), "Adding a callback after one returned false" );
234 // Callbacks are not iterated
239 handler.method = function() {
242 cblist = jQuery.Callbacks( flags );
243 cblist.add( handler );
244 cblist.add( handler );
246 assert.strictEqual( output, results.shift(), "No callback iteration" );
254 QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert ) {
261 cb = jQuery.Callbacks( options ),
264 assert.ok( !( count++ ), "called once" );
266 options[ "unique" ] = false;
271 QUnit.test( "jQuery.Callbacks.fireWith - arguments are copied", function( assert ) {
275 var cb = jQuery.Callbacks( "memory" ),
278 cb.fireWith( null, args );
281 cb.add( function( hello ) {
282 assert.strictEqual( hello, "hello", "arguments are copied internally" );
286 QUnit.test( "jQuery.Callbacks.remove - should remove all instances", function( assert ) {
290 var cb = jQuery.Callbacks();
293 assert.ok( false, "function wasn't removed" );
296 cb.add( fn, fn, function() {
297 assert.ok( true, "end of test" );
298 } ).remove( fn ).fire();
301 QUnit.test( "jQuery.Callbacks.has", function( assert ) {
305 var cb = jQuery.Callbacks();
315 cb.add( getA, getB, getC );
316 assert.strictEqual( cb.has(), true, "No arguments to .has() returns whether callback function(s) are attached or not" );
317 assert.strictEqual( cb.has( getA ), true, "Check if a specific callback function is in the Callbacks list" );
320 assert.strictEqual( cb.has( getB ), false, "Remove a specific callback function and make sure its no longer there" );
321 assert.strictEqual( cb.has( getA ), true, "Remove a specific callback function and make sure other callback function is still there" );
324 assert.strictEqual( cb.has(), false, "Empty list and make sure there are no callback function(s)" );
325 assert.strictEqual( cb.has( getA ), false, "Check for a specific function in an empty() list" );
327 cb.add( getA, getB, function() {
328 assert.strictEqual( cb.has(), true, "Check if list has callback function(s) from within a callback function" );
329 assert.strictEqual( cb.has( getA ), true, "Check if list has a specific callback from within a callback function" );
332 assert.strictEqual( cb.has(), true, "Callbacks list has callback function(s) after firing" );
335 assert.strictEqual( cb.has(), false, "disabled() list has no callback functions (returns false)" );
336 assert.strictEqual( cb.has( getA ), false, "Check for a specific function in a disabled() list" );
338 cb = jQuery.Callbacks( "unique" );
341 assert.strictEqual( cb.has(), true, "Check if unique list has callback function(s) attached" );
343 assert.strictEqual( cb.has(), false, "locked() list is empty and returns false" );
346 QUnit.test( "jQuery.Callbacks() - adding a string doesn't cause a stack overflow", function( assert ) {
350 jQuery.Callbacks().add( "hello world" );
352 assert.ok( true, "no stack overflow" );
355 QUnit.test( "jQuery.Callbacks() - disabled callback doesn't fire (gh-1790)", function( assert ) {
359 var cb = jQuery.Callbacks(),
361 shot = function() { fired = true; };
367 assert.ok( !fired, "Disabled callback function didn't fire" );
370 QUnit.test( "jQuery.Callbacks() - list with memory stays locked (gh-3469)", function( assert ) {
374 var cb = jQuery.Callbacks( "memory" ),
376 count1 = function() { fired += 1; },
377 count2 = function() { fired += 10; };
381 assert.equal( fired, 1, "Pre-lock() fire" );
385 assert.equal( fired, 11, "Post-lock() add" );
388 assert.equal( fired, 11, "Post-lock() fire ignored" );