Build: replace CRLF with LF during minify
[jquery.git] / test / unit / callbacks.js
blob3f3dc15ec67d192f638ec2bbd923da658a9beed9
1 QUnit.module( "callbacks", {
2 afterEach: moduleTeardown
3 } );
5 ( function() {
7 if ( !includesModule( "callbacks" ) ) {
8 return;
11 ( function() {
13 var output,
14 addToOutput = function( string ) {
15 return function() {
16 output += string;
19 outputA = addToOutput( "A" ),
20 outputB = addToOutput( "B" ),
21 outputC = addToOutput( "C" ),
22 tests = {
23 "": "XABC X XABCABCC X XBB X XABA X XX",
24 "once": "XABC X X X X X XABA X XX",
25 "memory": "XABC XABC XABCABCCC XA XBB XB XABA XC XX",
26 "unique": "XABC X XABCA X XBB X XAB X X",
27 "stopOnFalse": "XABC X XABCABCC X XBB X XA X XX",
28 "once memory": "XABC XABC X XA X XA XABA XC XX",
29 "once unique": "XABC X X X X X XAB X X",
30 "once stopOnFalse": "XABC X X X X X XA X XX",
31 "memory unique": "XABC XA XABCA XA XBB XB XAB XC X",
32 "memory stopOnFalse": "XABC XABC XABCABCCC XA XBB XB XA X XX",
33 "unique stopOnFalse": "XABC X XABCA X XBB X XA X X"
35 filters = {
36 "no filter": undefined,
37 "filter": function( fn ) {
38 return function() {
39 return fn.apply( this, arguments );
44 function showFlags( flags ) {
45 if ( typeof flags === "string" ) {
46 return "'" + flags + "'";
48 var output = [], key;
49 for ( key in flags ) {
50 output.push( "'" + key + "': " + flags[ key ] );
52 return "{ " + output.join( ", " ) + " }";
55 jQuery.each( tests, function( strFlags, resultString ) {
57 var objectFlags = {};
59 jQuery.each( strFlags.split( " " ), function() {
60 if ( this.length ) {
61 objectFlags[ this ] = true;
63 } );
65 jQuery.each( filters, function( filterLabel ) {
67 jQuery.each( {
68 "string": strFlags,
69 "object": objectFlags
70 }, function( flagsTypes, flags ) {
72 QUnit.test( "jQuery.Callbacks( " + showFlags( flags ) + " ) - " + filterLabel, function( assert ) {
74 assert.expect( 29 );
76 var cblist,
77 results = resultString.split( /\s+/ );
79 // Basic binding and firing
80 output = "X";
81 cblist = jQuery.Callbacks( flags );
82 assert.strictEqual( cblist.locked(), false, ".locked() initially false" );
83 assert.strictEqual( cblist.disabled(), false, ".disabled() initially false" );
84 assert.strictEqual( cblist.fired(), false, ".fired() initially false" );
85 cblist.add( function( str ) {
86 output += str;
87 } );
88 assert.strictEqual( cblist.fired(), false, ".fired() still false after .add" );
89 cblist.fire( "A" );
90 assert.strictEqual( output, "XA", "Basic binding and firing" );
91 assert.strictEqual( cblist.fired(), true, ".fired() detects firing" );
92 output = "X";
93 cblist.disable();
94 cblist.add( function( str ) {
95 output += str;
96 } );
97 assert.strictEqual( output, "X", "Adding a callback after disabling" );
98 cblist.fire( "A" );
99 assert.strictEqual( output, "X", "Firing after disabling" );
100 assert.strictEqual( cblist.disabled(), true, ".disabled() becomes true" );
101 assert.strictEqual( cblist.locked(), true, "disabling locks" );
103 // Emptying while firing (trac-13517)
104 cblist = jQuery.Callbacks( flags );
105 cblist.add( cblist.empty );
106 cblist.add( function() {
107 assert.ok( false, "not emptied" );
108 } );
109 cblist.fire();
111 // Disabling while firing
112 cblist = jQuery.Callbacks( flags );
113 cblist.add( cblist.disable );
114 cblist.add( function() {
115 assert.ok( false, "not disabled" );
116 } );
117 cblist.fire();
119 // Basic binding and firing (context, arguments)
120 output = "X";
121 cblist = jQuery.Callbacks( flags );
122 cblist.add( function() {
123 assert.equal( this, window, "Basic binding and firing (context)" );
124 output += Array.prototype.join.call( arguments, "" );
125 } );
126 cblist.fireWith( window, [ "A", "B" ] );
127 assert.strictEqual( output, "XAB", "Basic binding and firing (arguments)" );
129 // fireWith with no arguments
130 output = "";
131 cblist = jQuery.Callbacks( flags );
132 cblist.add( function() {
133 assert.equal( this, window, "fireWith with no arguments (context is window)" );
134 assert.strictEqual( arguments.length, 0, "fireWith with no arguments (no arguments)" );
135 } );
136 cblist.fireWith();
138 // Basic binding, removing and firing
139 output = "X";
140 cblist = jQuery.Callbacks( flags );
141 cblist.add( outputA, outputB, outputC );
142 cblist.remove( outputB, outputC );
143 cblist.fire();
144 assert.strictEqual( output, "XA", "Basic binding, removing and firing" );
146 // Empty
147 output = "X";
148 cblist = jQuery.Callbacks( flags );
149 cblist.add( outputA );
150 cblist.add( outputB );
151 cblist.add( outputC );
152 cblist.empty();
153 cblist.fire();
154 assert.strictEqual( output, "X", "Empty" );
156 // Locking
157 output = "X";
158 cblist = jQuery.Callbacks( flags );
159 cblist.add( function( str ) {
160 output += str;
161 } );
162 cblist.lock();
163 cblist.add( function( str ) {
164 output += str;
165 } );
166 cblist.fire( "A" );
167 cblist.add( function( str ) {
168 output += str;
169 } );
170 assert.strictEqual( output, "X", "Lock early" );
171 assert.strictEqual( cblist.locked(), true, "Locking reflected in accessor" );
173 // Locking while firing (gh-1990)
174 output = "X";
175 cblist = jQuery.Callbacks( flags );
176 cblist.add( cblist.lock );
177 cblist.add( function( str ) {
178 output += str;
179 } );
180 cblist.fire( "A" );
181 assert.strictEqual( output, "XA", "Locking doesn't abort execution (gh-1990)" );
183 // Ordering
184 output = "X";
185 cblist = jQuery.Callbacks( flags );
186 cblist.add( function() {
187 cblist.add( outputC );
188 outputA();
189 }, outputB );
190 cblist.fire();
191 assert.strictEqual( output, results.shift(), "Proper ordering" );
193 // Add and fire again
194 output = "X";
195 cblist.add( function() {
196 cblist.add( outputC );
197 outputA();
198 }, outputB );
199 assert.strictEqual( output, results.shift(), "Add after fire" );
201 output = "X";
202 cblist.fire();
203 assert.strictEqual( output, results.shift(), "Fire again" );
205 // Multiple fire
206 output = "X";
207 cblist = jQuery.Callbacks( flags );
208 cblist.add( function( str ) {
209 output += str;
210 } );
211 cblist.fire( "A" );
212 assert.strictEqual( output, "XA", "Multiple fire (first fire)" );
213 output = "X";
214 cblist.add( function( str ) {
215 output += str;
216 } );
217 assert.strictEqual( output, results.shift(), "Multiple fire (first new callback)" );
218 output = "X";
219 cblist.fire( "B" );
220 assert.strictEqual( output, results.shift(), "Multiple fire (second fire)" );
221 output = "X";
222 cblist.add( function( str ) {
223 output += str;
224 } );
225 assert.strictEqual( output, results.shift(), "Multiple fire (second new callback)" );
227 // Return false
228 output = "X";
229 cblist = jQuery.Callbacks( flags );
230 cblist.add( outputA, function() { return false; }, outputB );
231 cblist.add( outputA );
232 cblist.fire();
233 assert.strictEqual( output, results.shift(), "Callback returning false" );
235 // Add another callback (to control lists with memory do not fire anymore)
236 output = "X";
237 cblist.add( outputC );
238 assert.strictEqual( output, results.shift(), "Adding a callback after one returned false" );
240 // Callbacks are not iterated
241 output = "";
242 function handler() {
243 output += "X";
245 handler.method = function() {
246 output += "!";
248 cblist = jQuery.Callbacks( flags );
249 cblist.add( handler );
250 cblist.add( handler );
251 cblist.fire();
252 assert.strictEqual( output, results.shift(), "No callback iteration" );
253 } );
254 } );
255 } );
256 } );
258 } )();
260 QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert ) {
262 assert.expect( 1 );
264 var options = {
265 "unique": true
267 cb = jQuery.Callbacks( options ),
268 count = 0,
269 fn = function() {
270 assert.ok( !( count++ ), "called once" );
272 options[ "unique" ] = false;
273 cb.add( fn, fn );
274 cb.fire();
275 } );
277 QUnit.test( "jQuery.Callbacks.fireWith - arguments are copied", function( assert ) {
279 assert.expect( 1 );
281 var cb = jQuery.Callbacks( "memory" ),
282 args = [ "hello" ];
284 cb.fireWith( null, args );
285 args[ 0 ] = "world";
287 cb.add( function( hello ) {
288 assert.strictEqual( hello, "hello", "arguments are copied internally" );
289 } );
290 } );
292 QUnit.test( "jQuery.Callbacks.remove - should remove all instances", function( assert ) {
294 assert.expect( 1 );
296 var cb = jQuery.Callbacks();
298 function fn() {
299 assert.ok( false, "function wasn't removed" );
302 cb.add( fn, fn, function() {
303 assert.ok( true, "end of test" );
304 } ).remove( fn ).fire();
305 } );
307 QUnit.test( "jQuery.Callbacks.has", function( assert ) {
309 assert.expect( 13 );
311 var cb = jQuery.Callbacks();
312 function getA() {
313 return "A";
315 function getB() {
316 return "B";
318 function getC() {
319 return "C";
321 cb.add( getA, getB, getC );
322 assert.strictEqual( cb.has(), true, "No arguments to .has() returns whether callback function(s) are attached or not" );
323 assert.strictEqual( cb.has( getA ), true, "Check if a specific callback function is in the Callbacks list" );
325 cb.remove( getB );
326 assert.strictEqual( cb.has( getB ), false, "Remove a specific callback function and make sure its no longer there" );
327 assert.strictEqual( cb.has( getA ), true, "Remove a specific callback function and make sure other callback function is still there" );
329 cb.empty();
330 assert.strictEqual( cb.has(), false, "Empty list and make sure there are no callback function(s)" );
331 assert.strictEqual( cb.has( getA ), false, "Check for a specific function in an empty() list" );
333 cb.add( getA, getB, function() {
334 assert.strictEqual( cb.has(), true, "Check if list has callback function(s) from within a callback function" );
335 assert.strictEqual( cb.has( getA ), true, "Check if list has a specific callback from within a callback function" );
336 } ).fire();
338 assert.strictEqual( cb.has(), true, "Callbacks list has callback function(s) after firing" );
340 cb.disable();
341 assert.strictEqual( cb.has(), false, "disabled() list has no callback functions (returns false)" );
342 assert.strictEqual( cb.has( getA ), false, "Check for a specific function in a disabled() list" );
344 cb = jQuery.Callbacks( "unique" );
345 cb.add( getA );
346 cb.add( getA );
347 assert.strictEqual( cb.has(), true, "Check if unique list has callback function(s) attached" );
348 cb.lock();
349 assert.strictEqual( cb.has(), false, "locked() list is empty and returns false" );
350 } );
352 QUnit.test( "jQuery.Callbacks() - adding a string doesn't cause a stack overflow", function( assert ) {
354 assert.expect( 1 );
356 jQuery.Callbacks().add( "hello world" );
358 assert.ok( true, "no stack overflow" );
359 } );
361 QUnit.test( "jQuery.Callbacks() - disabled callback doesn't fire (gh-1790)", function( assert ) {
363 assert.expect( 1 );
365 var cb = jQuery.Callbacks(),
366 fired = false,
367 shot = function() { fired = true; };
369 cb.disable();
370 cb.empty();
371 cb.add( shot );
372 cb.fire();
373 assert.ok( !fired, "Disabled callback function didn't fire" );
374 } );
376 QUnit.test( "jQuery.Callbacks() - list with memory stays locked (gh-3469)", function( assert ) {
378 assert.expect( 3 );
380 var cb = jQuery.Callbacks( "memory" ),
381 fired = 0,
382 count1 = function() { fired += 1; },
383 count2 = function() { fired += 10; };
385 cb.add( count1 );
386 cb.fire();
387 assert.equal( fired, 1, "Pre-lock() fire" );
389 cb.lock();
390 cb.add( count2 );
391 assert.equal( fired, 11, "Post-lock() add" );
393 cb.fire();
394 assert.equal( fired, 11, "Post-lock() fire ignored" );
395 } );
397 } )();