Data: Separate data & css/effects camelCase implementations
[jquery.git] / test / unit / callbacks.js
blobb440f382278411ef16e745dc6de659812a2f39af
1 QUnit.module( "callbacks", {
2         afterEach: moduleTeardown
3 } );
5 ( function() {
7 var output,
8         addToOutput = function( string ) {
9                 return function() {
10                         output += string;
11                 };
12         },
13         outputA = addToOutput( "A" ),
14         outputB = addToOutput( "B" ),
15         outputC = addToOutput( "C" ),
16         tests = {
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"
28         },
29         filters = {
30                 "no filter": undefined,
31                 "filter": function( fn ) {
32                         return function() {
33                                 return fn.apply( this, arguments );
34                         };
35                 }
36         };
38         function showFlags( flags ) {
39                 if ( typeof flags === "string" ) {
40                         return "'" + flags + "'";
41                 }
42                 var output = [], key;
43                 for ( key in flags ) {
44                         output.push( "'" + key + "': " + flags[ key ] );
45                 }
46                 return "{ " + output.join( ", " ) + " }";
47         }
49 jQuery.each( tests, function( strFlags, resultString ) {
51                 var objectFlags = {};
53                 jQuery.each( strFlags.split( " " ), function() {
54                         if ( this.length ) {
55                                 objectFlags[ this ] = true;
56                         }
57                 } );
59                 jQuery.each( filters, function( filterLabel ) {
61                         jQuery.each( {
62                                 "string": strFlags,
63                                 "object": objectFlags
64                         }, function( flagsTypes, flags ) {
66                                 QUnit.test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function( assert ) {
68                                         assert.expect( 29 );
70                                         var cblist,
71                                                 results = resultString.split( /\s+/ );
73                                         // Basic binding and firing
74                                         output = "X";
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 ) {
80                                                 output += str;
81                                         } );
82                                         assert.strictEqual( cblist.fired(), false, ".fired() still false after .add" );
83                                         cblist.fire( "A" );
84                                         assert.strictEqual( output, "XA", "Basic binding and firing" );
85                                         assert.strictEqual( cblist.fired(), true, ".fired() detects firing" );
86                                         output = "X";
87                                         cblist.disable();
88                                         cblist.add( function( str ) {
89                                                 output += str;
90                                         } );
91                                         assert.strictEqual( output, "X", "Adding a callback after disabling" );
92                                         cblist.fire( "A" );
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" );
102                                         } );
103                                         cblist.fire();
105                                         // Disabling while firing
106                                         cblist = jQuery.Callbacks( flags );
107                                         cblist.add( cblist.disable );
108                                         cblist.add( function() {
109                                                 assert.ok( false, "not disabled" );
110                                         } );
111                                         cblist.fire();
113                                         // Basic binding and firing (context, arguments)
114                                         output = "X";
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, "" );
119                                         } );
120                                         cblist.fireWith( window, [ "A", "B" ] );
121                                         assert.strictEqual( output, "XAB", "Basic binding and firing (arguments)" );
123                                         // fireWith with no arguments
124                                         output = "";
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)" );
129                                         } );
130                                         cblist.fireWith();
132                                         // Basic binding, removing and firing
133                                         output = "X";
134                                         cblist = jQuery.Callbacks( flags );
135                                         cblist.add( outputA, outputB, outputC );
136                                         cblist.remove( outputB, outputC );
137                                         cblist.fire();
138                                         assert.strictEqual( output, "XA", "Basic binding, removing and firing" );
140                                         // Empty
141                                         output = "X";
142                                         cblist = jQuery.Callbacks( flags );
143                                         cblist.add( outputA );
144                                         cblist.add( outputB );
145                                         cblist.add( outputC );
146                                         cblist.empty();
147                                         cblist.fire();
148                                         assert.strictEqual( output, "X", "Empty" );
150                                         // Locking
151                                         output = "X";
152                                         cblist = jQuery.Callbacks( flags );
153                                         cblist.add( function( str ) {
154                                                 output += str;
155                                         } );
156                                         cblist.lock();
157                                         cblist.add( function( str ) {
158                                                 output += str;
159                                         } );
160                                         cblist.fire( "A" );
161                                         cblist.add( function( str ) {
162                                                 output += str;
163                                         } );
164                                         assert.strictEqual( output, "X", "Lock early" );
165                                         assert.strictEqual( cblist.locked(), true, "Locking reflected in accessor" );
167                                         // Locking while firing (gh-1990)
168                                         output = "X";
169                                         cblist = jQuery.Callbacks( flags );
170                                         cblist.add( cblist.lock );
171                                         cblist.add( function( str ) {
172                                                 output += str;
173                                         } );
174                                         cblist.fire( "A" );
175                                         assert.strictEqual( output, "XA", "Locking doesn't abort execution (gh-1990)" );
177                                         // Ordering
178                                         output = "X";
179                                         cblist = jQuery.Callbacks( flags );
180                                         cblist.add( function() {
181                                                 cblist.add( outputC );
182                                                 outputA();
183                                         }, outputB );
184                                         cblist.fire();
185                                         assert.strictEqual( output, results.shift(), "Proper ordering" );
187                                         // Add and fire again
188                                         output = "X";
189                                         cblist.add( function() {
190                                                 cblist.add( outputC );
191                                                 outputA();
192                                         }, outputB );
193                                         assert.strictEqual( output, results.shift(), "Add after fire" );
195                                         output = "X";
196                                         cblist.fire();
197                                         assert.strictEqual( output, results.shift(), "Fire again" );
199                                         // Multiple fire
200                                         output = "X";
201                                         cblist = jQuery.Callbacks( flags );
202                                         cblist.add( function( str ) {
203                                                 output += str;
204                                         } );
205                                         cblist.fire( "A" );
206                                         assert.strictEqual( output, "XA", "Multiple fire (first fire)" );
207                                         output = "X";
208                                         cblist.add( function( str ) {
209                                                 output += str;
210                                         } );
211                                         assert.strictEqual( output, results.shift(), "Multiple fire (first new callback)" );
212                                         output = "X";
213                                         cblist.fire( "B" );
214                                         assert.strictEqual( output, results.shift(), "Multiple fire (second fire)" );
215                                         output = "X";
216                                         cblist.add( function( str ) {
217                                                 output += str;
218                                         } );
219                                         assert.strictEqual( output, results.shift(), "Multiple fire (second new callback)" );
221                                         // Return false
222                                         output = "X";
223                                         cblist = jQuery.Callbacks( flags );
224                                         cblist.add( outputA, function() { return false; }, outputB );
225                                         cblist.add( outputA );
226                                         cblist.fire();
227                                         assert.strictEqual( output, results.shift(), "Callback returning false" );
229                                         // Add another callback (to control lists with memory do not fire anymore)
230                                         output = "X";
231                                         cblist.add( outputC );
232                                         assert.strictEqual( output, results.shift(), "Adding a callback after one returned false" );
234                                         // Callbacks are not iterated
235                                         output = "";
236                                         function handler() {
237                                                 output += "X";
238                                         }
239                                         handler.method = function() {
240                                                 output += "!";
241                                         };
242                                         cblist = jQuery.Callbacks( flags );
243                                         cblist.add( handler );
244                                         cblist.add( handler );
245                                         cblist.fire();
246                                         assert.strictEqual( output, results.shift(), "No callback iteration" );
247                                 } );
248                         } );
249                 } );
250 } );
252 } )();
254 QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert ) {
256         assert.expect( 1 );
258         var options = {
259                         "unique": true
260                 },
261                 cb = jQuery.Callbacks( options ),
262                 count = 0,
263                 fn = function() {
264                         assert.ok( !( count++ ), "called once" );
265                 };
266         options[ "unique" ] = false;
267         cb.add( fn, fn );
268         cb.fire();
269 } );
271 QUnit.test( "jQuery.Callbacks.fireWith - arguments are copied", function( assert ) {
273         assert.expect( 1 );
275         var cb = jQuery.Callbacks( "memory" ),
276                 args = [ "hello" ];
278         cb.fireWith( null, args );
279         args[ 0 ] = "world";
281         cb.add( function( hello ) {
282                 assert.strictEqual( hello, "hello", "arguments are copied internally" );
283         } );
284 } );
286 QUnit.test( "jQuery.Callbacks.remove - should remove all instances", function( assert ) {
288         assert.expect( 1 );
290         var cb = jQuery.Callbacks();
292         function fn() {
293                 assert.ok( false, "function wasn't removed" );
294         }
296         cb.add( fn, fn, function() {
297                 assert.ok( true, "end of test" );
298         } ).remove( fn ).fire();
299 } );
301 QUnit.test( "jQuery.Callbacks.has", function( assert ) {
303         assert.expect( 13 );
305         var cb = jQuery.Callbacks();
306         function getA() {
307                 return "A";
308         }
309         function getB() {
310                 return "B";
311         }
312         function getC() {
313                 return "C";
314         }
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" );
319         cb.remove( getB );
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" );
323         cb.empty();
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" );
330         } ).fire();
332         assert.strictEqual( cb.has(), true, "Callbacks list has callback function(s) after firing" );
334         cb.disable();
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" );
339         cb.add( getA );
340         cb.add( getA );
341         assert.strictEqual( cb.has(), true, "Check if unique list has callback function(s) attached" );
342         cb.lock();
343         assert.strictEqual( cb.has(), false, "locked() list is empty and returns false" );
344 } );
346 QUnit.test( "jQuery.Callbacks() - adding a string doesn't cause a stack overflow", function( assert ) {
348         assert.expect( 1 );
350         jQuery.Callbacks().add( "hello world" );
352         assert.ok( true, "no stack overflow" );
353 } );
355 QUnit.test( "jQuery.Callbacks() - disabled callback doesn't fire (gh-1790)", function( assert ) {
357         assert.expect( 1 );
359         var cb = jQuery.Callbacks(),
360                 fired = false,
361                 shot = function() { fired = true; };
363         cb.disable();
364         cb.empty();
365         cb.add( shot );
366         cb.fire();
367         assert.ok( !fired, "Disabled callback function didn't fire" );
368 } );
370 QUnit.test( "jQuery.Callbacks() - list with memory stays locked (gh-3469)", function( assert ) {
372         assert.expect( 3 );
374         var cb = jQuery.Callbacks( "memory" ),
375                 fired = 0,
376                 count1 = function() { fired += 1; },
377                 count2 = function() { fired += 10; };
379         cb.add( count1 );
380         cb.fire();
381         assert.equal( fired, 1, "Pre-lock() fire" );
383         cb.lock();
384         cb.add( count2 );
385         assert.equal( fired, 11, "Post-lock() add" );
387         cb.fire();
388         assert.equal( fired, 11, "Post-lock() fire ignored" );
389 } );