From d31cef38f2aa76ca71ed18aa97d035a84c7e33e6 Mon Sep 17 00:00:00 2001 From: jaubourg Date: Mon, 26 Nov 2012 03:31:19 +0100 Subject: [PATCH] Total revamping of the ajax unit tests --- test/.jshintrc | 2 + test/data/testinit.js | 71 + test/data/testrunner.js | 30 +- test/unit/ajax.js | 3734 +++++++++++++++------------------------ 4 files changed, 1523 insertions(+), 2314 deletions(-) diff --git a/test/.jshintrc b/test/.jshintrc index 7a39e47d8..3513666d5 100644 --- a/test/.jshintrc +++ b/test/.jshintrc @@ -38,6 +38,7 @@ "stop": true, "expect": true, "raises": true, + "ajaxTest": true, "testIframe": true, "testIframeWithCallback": true, "createDashboardXML": true, @@ -50,6 +51,7 @@ "q": true, "amdDefined": true, "fireNative": true, + "Globals": true, "hasPHP": true, "isLocal": true, "originaljQuery": true, diff --git a/test/data/testinit.js b/test/data/testinit.js index 046763fbb..b16b0be3d 100644 --- a/test/data/testinit.js +++ b/test/data/testinit.js @@ -143,6 +143,77 @@ function url( value ) { return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random() * 100000, 10); } +// Ajax testing helper +var ajaxTest = (function() { + + var resolved = $.Deferred().resolve(); + + function getRequests( options ) { + var requests = options.requests || options.request || options || []; + if ( !jQuery.isArray(requests) ) { + requests = [ requests ]; + } + return requests; + } + + return function( title, expect, options ) { + if ( jQuery.isFunction(options) ) { + options = options(); + } + options = options || []; + asyncTest( title, expect, function() { + setTimeout(function() { + if ( options.setup ) { + options.setup(); + } + var ajaxSettings = jQuery.ajaxSetup( {}, {} ); + aborted = false, + abort = function( reason ) { + if ( !aborted ) { + aborted = true; + ok( false, "unexpected " + reason ); + jQuery.each( requests, function( _, request ) { + request.abort(); + }); + } + }, + requestOptions = getRequests( options ), + requests = jQuery.map( requestOptions, function( options ) { + var request = ( options.create || jQuery.ajax )( options ); + if ( options.afterSend ) { + options.afterSend( request ); + } + return request; + }); + requests = jQuery.map( requests, function( request, index ) { + function callIfDefined( type, type2 ) { + var handler = requestOptions[ index ][ type ] || !!requestOptions[ index ][ type2 ]; + return handler ? function() { + if ( !aborted && jQuery.isFunction( handler ) ) { + handler.apply( this, arguments ); + } + return resolved; + } : function() { + abort( type ); + return resolved; + } + } + var promise = request.then( callIfDefined( "done", "success" ), callIfDefined( "fail", "error" ) ); + promise.abort = request.abort; + return promise; + }); + jQuery.when.apply( jQuery, requests ).done( + options.teardown, + function() { + jQuery.ajaxSetup( ajaxSettings ); + setTimeout( start, 0 ); + } + ); + }, 0 ); + }); + }; +})(); + (function () { this.testIframe = function( fileName, name, fn ) { diff --git a/test/data/testrunner.js b/test/data/testrunner.js index 6304d5142..6041e4bd4 100644 --- a/test/data/testrunner.js +++ b/test/data/testrunner.js @@ -134,6 +134,31 @@ function testSubproject( label, url, risTests ) { } } +// Register globals for cleanup and the cleanup code itself +// Explanation at http://perfectionkills.com/understanding-delete/#ie_bugs +var Globals = (function() { + var globals = {}; + return QUnit.config.noglobals ? { + register: function( name ) { + globals[ name ] = true; + jQuery.globalEval( "var " + name ); + }, + cleanup: function() { + var name, + current = globals; + globals = {}; + for ( name in current ) { + jQuery.globalEval( "try { " + + "delete " + ( jQuery.support.deleteExpando ? "window['" + name + "']" : name ) + + "; } catch( x ) {}" ); + } + } + } : { + register: jQuery.noop, + cleanup: jQuery.noop + }; +})(); + /** * QUnit hooks */ @@ -292,10 +317,13 @@ function testSubproject( label, url, risTests ) { // Reset internal jQuery state jQuery.event.global = {}; if ( ajaxSettings ) { - jQuery.ajaxSettings = jQuery.extend( {}, ajaxSettings ); + jQuery.ajaxSettings = jQuery.extend( true, {}, ajaxSettings ); } else { delete jQuery.ajaxSettings; } + + // Cleanup globals + Globals.cleanup(); // Let QUnit reset the fixture reset.apply( this, arguments ); diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 86ded7f3f..b9cff112f 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -1,104 +1,31 @@ -(function() { - - var isOpera = !!window.opera, - jsonpCallbacks = [], - jsonpCallback = jQuery.ajaxSettings.jsonpCallback, - deleteExpando = jQuery.support.deleteExpando, - - // Ensure that we can cleanup generated JSONP callback functions if checking globals - newjsonpCallback = jsonpCallback && function() { +module( "ajax", { + setup: function() { + var jsonpCallback = this.jsonpCallback = jQuery.ajaxSettings.jsonpCallback; + jQuery.ajaxSettings.jsonpCallback = function() { var callback = jsonpCallback.apply( this, arguments ); - - // Explanation at http://perfectionkills.com/understanding-delete/#ie_bugs - jQuery.globalEval( "var " + callback ); - + Globals.register( callback ); return callback; }; + }, + teardown: function() { + moduleTeardown.apply( this, arguments ); + } +}); - module( "ajax", { - setup: deleteExpando ? - function() {} : - function() { - if ( QUnit.config.noglobals ) { - jQuery.ajaxSettings.jsonpCallback = newjsonpCallback; - } - }, - teardown: function() { - // Cleanup JSONP callback functions - jsonpCallbacks = jQuery.map( jsonpCallbacks, QUnit.config.noglobals ? - function( callback ) { - jQuery.globalEval( "try { " + - "delete " + ( deleteExpando ? "window['" + callback + "']" : callback ) + - "; } catch( x ) {}" ); - } : - function() {} - ); - jQuery.ajaxSettings.jsonpCallback = jsonpCallback; - - moduleTeardown.apply( this, arguments ); - } - }); +(function() { if ( !jQuery.ajax || ( isLocal && !hasPHP ) ) { return; } - test( "jQuery.ajax() - success callbacks", function() { - expect( 8 ); - - jQuery.ajaxSetup({ - timeout: 0 - }); - - stop(); - - jQuery("#foo").ajaxStart(function() { - ok( true, "ajaxStart" ); - }).ajaxStop(function() { - ok( true, "ajaxStop" ); - start(); - }).ajaxSend(function() { - ok( true, "ajaxSend" ); - }).ajaxComplete(function() { - ok( true, "ajaxComplete" ); - }).ajaxError(function() { - ok( false, "ajaxError" ); - }).ajaxSuccess(function() { - ok( true, "ajaxSuccess" ); - }); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( true, "success" ); - }, - error: function() { - ok( false, "error" ); - }, - complete: function() { - ok( true, "complete"); - } - }); - }); - - test( "jQuery.ajax() - success callbacks - (url, options) syntax", function() { - expect( 8 ); - - jQuery.ajaxSetup({ - timeout: 0 - }); +//----------- jQuery.ajax() - stop(); - - setTimeout(function() { + ajaxTest( "jQuery.ajax() - success callbacks", 8, { + setup: function() { jQuery("#foo").ajaxStart(function() { ok( true, "ajaxStart" ); }).ajaxStop(function() { ok( true, "ajaxStop" ); - start(); }).ajaxSend(function() { ok( true, "ajaxSend" ); }).ajaxComplete(function() { @@ -108,39 +35,55 @@ }).ajaxSuccess(function() { ok( true, "ajaxSuccess" ); }); + }, + url: url("data/name.html"), + beforeSend: function() { + ok( true, "beforeSend" ); + }, + success: function() { + ok( true, "success" ); + }, + complete: function() { + ok( true, "complete"); + } + }); - jQuery.ajax( url("data/name.html"), { - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( true, "success" ); - }, - error: function() { - ok( false, "error" ); - }, - complete: function() { - ok( true, "complete" ); - } + ajaxTest( "jQuery.ajax() - success callbacks - (url, options) syntax", 8, { + setup: function() { + jQuery("#foo").ajaxStart(function() { + ok( true, "ajaxStart" ); + }).ajaxStop(function() { + ok( true, "ajaxStop" ); + }).ajaxSend(function() { + ok( true, "ajaxSend" ); + }).ajaxComplete(function() { + ok( true, "ajaxComplete" ); + }).ajaxError(function() { + ok( false, "ajaxError" ); + }).ajaxSuccess(function() { + ok( true, "ajaxSuccess" ); }); - }, 13 ); + }, + create: function( options ) { + return jQuery.ajax( url("data/name.html"), options ); + }, + beforeSend: function() { + ok( true, "beforeSend" ); + }, + success: function() { + ok( true, "success" ); + }, + complete: function() { + ok( true, "complete" ); + } }); - test( "jQuery.ajax() - success callbacks (late binding)", function() { - expect( 8 ); - - jQuery.ajaxSetup({ - timeout: 0 - }); - - stop(); - - setTimeout(function() { + ajaxTest( "jQuery.ajax() - success callbacks (late binding)", 8, { + setup: function() { jQuery("#foo").ajaxStart(function() { ok( true, "ajaxStart" ); }).ajaxStop(function() { ok( true, "ajaxStop" ); - start(); }).ajaxSend(function() { ok( true, "ajaxSend" ); }).ajaxComplete(function() { @@ -150,32 +93,25 @@ }).ajaxSuccess(function() { ok( true, "ajaxSuccess" ); }); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - } - }).complete(function() { + }, + url: url("data/name.html"), + beforeSend: function() { + ok( true, "beforeSend" ); + }, + success: true, + afterSend: function( request ) { + request.complete(function() { ok( true, "complete" ); }).success(function() { ok( true, "success" ); }).error(function() { ok( false, "error" ); }); - }, 13 ); + } }); - test( "jQuery.ajax() - success callbacks (oncomplete binding)", function() { - expect( 8 ); - - jQuery.ajaxSetup({ - timeout: 0 - }); - - stop(); - - setTimeout(function() { + ajaxTest( "jQuery.ajax() - success callbacks (oncomplete binding)", 8, { + setup: function() { jQuery("#foo").ajaxStart(function() { ok( true, "ajaxStart" ); }).ajaxStop(function() { @@ -189,37 +125,25 @@ }).ajaxSuccess(function() { ok( true, "ajaxSuccess" ); }); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - complete: function( xhr ) { - xhr.complete(function() { - ok( true, "complete" ); - }).success(function() { - ok( true, "success" ); - }).error(function() { - ok( false, "error" ); - }).complete(function() { - start(); - }); - } + }, + url: url("data/name.html"), + beforeSend: function() { + ok( true, "beforeSend" ); + }, + success: true, + complete: function( xhr ) { + xhr.complete(function() { + ok( true, "complete" ); + }).success(function() { + ok( true, "success" ); + }).error(function() { + ok( false, "error" ); }); - }, 13 ); + } }); - test( "jQuery.ajax() - success callbacks (very late binding)", function() { - expect( 8 ); - - jQuery.ajaxSetup({ - timeout: 0 - }); - - stop(); - - setTimeout(function() { + ajaxTest( "jQuery.ajax() - error callbacks", 8, { + setup: function() { jQuery("#foo").ajaxStart(function() { ok( true, "ajaxStart" ); }).ajaxStop(function() { @@ -229,210 +153,59 @@ }).ajaxComplete(function() { ok( true, "ajaxComplete" ); }).ajaxError(function() { - ok( false, "ajaxError" ); + ok( true, "ajaxError" ); }).ajaxSuccess(function() { - ok( true, "ajaxSuccess" ); - }); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - ok(true, "beforeSend"); - }, - complete: function( xhr ) { - setTimeout (function() { - xhr.complete(function() { - ok( true, "complete" ); - }).success(function() { - ok( true, "success" ); - }).error(function() { - ok( false, "error" ); - }).complete(function() { - start(); - }); - }, 100 ); - } - }); - }, 13 ); - }); - - test( "jQuery.ajax() - success callbacks (order)", function() { - expect( 1 ); - - jQuery.ajaxSetup({ - timeout: 0 - }); - - stop(); - - var testString = ""; - - setTimeout(function() { - jQuery.ajax({ - url: url("data/name.html"), - success: function( _1, _2, xhr ) { - xhr.success(function() { - xhr.success(function() { - testString += "E"; - }); - testString += "D"; - }); - testString += "A"; - }, - complete: function() { - strictEqual( testString, "ABCDE", "Proper order" ); - start(); - } - }).success(function() { - testString += "B"; - }).success(function() { - testString += "C"; + ok( false, "ajaxSuccess" ); }); - }, 13 ); - }); - - test( "jQuery.ajax() - error callbacks", function() { - expect( 8 ); - stop(); - - jQuery("#foo").ajaxStart(function() { - ok( true, "ajaxStart" ); - }).ajaxStop(function() { - ok( true, "ajaxStop" ); - start(); - }).ajaxSend(function() { - ok( true, "ajaxSend" ); - }).ajaxComplete(function() { - ok( true, "ajaxComplete" ); - }).ajaxError(function() { - ok( true, "ajaxError" ); - }).ajaxSuccess(function() { - ok( false, "ajaxSuccess" ); - }); - - jQuery.ajaxSetup({ - timeout: 500 - }); - - jQuery.ajax({ - url: url("data/name.php?wait=5"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( false, "success" ); - }, - error: function() { - ok( true, "error" ); - }, - complete: function() { - ok( true, "complete" ); - } - }); - }); - - test( "jQuery.ajax - multiple method signatures introduced in 1.5 ( #8107)", function() { - - expect( 4 ); - - stop(); - - jQuery.when( - /* jQuery.when arguments start */ - jQuery.ajax().success(function() { - ok( true, "With no arguments" ); - }), - jQuery.ajax("data/name.html").success(function() { - ok( true, "With only string URL argument" ); - }), - jQuery.ajax( "data/name.html", {}).success(function() { - ok( true, "With string URL param and map" ); - }), - jQuery.ajax({ - url: "data/name.html" - }).success(function() { - ok( true, "With only map" ); - }) - /* jQuery.when arguments end */ - ).always(function() { - start(); - }); - - }); - - test( "jQuery.ajax() - textStatus and errorThrown values", function() { - - var nb = 2; - - expect( 2 * nb ); - stop(); - - function startN() { - if ( !( --nb ) ) { - start(); - } + }, + url: url("data/name.php?wait=5"), + beforeSend: function() { + ok( true, "beforeSend" ); + }, + afterSend: function( request ) { + request.abort(); + }, + error: function() { + ok( true, "error" ); + }, + complete: function() { + ok( true, "complete" ); } + }); - /* - Safari 3.x returns "OK" instead of "Not Found" - Safari 4.x doesn't have this issue so the test should be re-instated once - we drop support for 3.x - - jQuery.ajax({ - url: url("data/nonExistingURL"), - error: function( _, textStatus, errorThrown ) { - strictEqual( textStatus, "error", "textStatus is 'error' for 404" ); - strictEqual( errorThrown, "Not Found", "errorThrown is 'Not Found' for 404"); - startN(); - } - }); - */ - - jQuery.ajax({ + ajaxTest( "jQuery.ajax() - textStatus and errorThrown values", 4, [ + { url: url("data/name.php?wait=5"), error: function( _, textStatus, errorThrown ) { strictEqual( textStatus, "abort", "textStatus is 'abort' for abort" ); strictEqual( errorThrown, "abort", "errorThrown is 'abort' for abort" ); - startN(); + }, + afterSend: function( request ) { + request.abort(); } - }).abort(); - - jQuery.ajax({ + }, + { url: url("data/name.php?wait=5"), error: function( _, textStatus, errorThrown ) { strictEqual( textStatus, "mystatus", "textStatus is 'mystatus' for abort('mystatus')" ); strictEqual( errorThrown, "mystatus", "errorThrown is 'mystatus' for abort('mystatus')" ); - startN(); - } - }).abort("mystatus"); - }); - - test( "jQuery.ajax() - responseText on error", function() { - - expect( 1 ); - - stop(); - - jQuery.ajax({ - url: url("data/errorWithText.php"), - error: function( xhr ) { - strictEqual( xhr.responseText, "plain text message", "Test jqXHR.responseText is filled for HTTP errors" ); }, - complete: function() { - start(); + afterSend: function( request ) { + request.abort("mystatus"); } - }); - }); - - test( ".ajax() - retry with jQuery.ajax( this )", function() { - - expect( 2 ); + } + ]); - stop(); + ajaxTest( "jQuery.ajax() - responseText on error", 1, { + url: url("data/errorWithText.php"), + error: function( xhr ) { + strictEqual( xhr.responseText, "plain text message", "Test jqXHR.responseText is filled for HTTP errors" ); + } + }); + asyncTest( "jQuery.ajax() - retry with jQuery.ajax( this )", 2, function() { var previousUrl, firstTime = true; - jQuery.ajax({ url: url("data/errorWithText.php"), error: function() { @@ -464,151 +237,99 @@ }); }); - test( ".ajax() - headers", function() { - - expect( 4 ); - - stop(); - - jQuery("#foo").ajaxSend(function( evt, xhr ) { - xhr.setRequestHeader( "ajax-send", "test" ); - }); - - var i, - requestHeaders = { - "siMPle": "value", - "SometHing-elsE": "other value", - "OthEr": "something else" - }, - list = []; - - for ( i in requestHeaders ) { - list.push( i ); + ajaxTest( "jQuery.ajax() - headers", 4, { + setup: function() { + jQuery("#foo").ajaxSend(function( evt, xhr ) { + xhr.setRequestHeader( "ajax-send", "test" ); + }); + }, + url: url("data/headers.php?keys=siMPle_SometHing-elsE_OthEr_ajax-send"), + headers: { + "siMPle": "value", + "SometHing-elsE": "other value", + "OthEr": "something else" + }, + success: function( data, _, xhr ) { + var i, emptyHeader, + requestHeaders = jQuery.extend( this.headers, { + "ajax-send": "test" + }), + tmp = []; + for ( i in requestHeaders ) { + tmp.push( i, ": ", requestHeaders[ i ], "\n" ); + } + tmp = tmp.join(""); + + strictEqual( data, tmp, "Headers were sent" ); + strictEqual( xhr.getResponseHeader("Sample-Header"), "Hello World", "Sample header received" ); + + emptyHeader = xhr.getResponseHeader("Empty-Header"); + if ( emptyHeader === null ) { + ok( true, "Firefox doesn't support empty headers" ); + } else { + strictEqual( emptyHeader, "", "Empty header received" ); + } + strictEqual( xhr.getResponseHeader("Sample-Header2"), "Hello World 2", "Second sample header received" ); } - list.push("ajax-send"); - - jQuery.ajax( url("data/headers.php?keys=" + list.join("_")), { + }); - headers: requestHeaders, - success: function( data, _, xhr ) { - var i, emptyHeader, - tmp = []; - for ( i in requestHeaders ) { - tmp.push( i, ": ", requestHeaders[ i ], "\n" ); - } - tmp.push("ajax-send: test\n"); - tmp = tmp.join(""); + ajaxTest( "jQuery.ajax() - Accept header", 1, { + url: url("data/headers.php?keys=accept"), + headers: { + Accept: "very wrong accept value" + }, + beforeSend: function( xhr ) { + xhr.setRequestHeader("Accept", "*/*"); + }, + success: function( data ) { + strictEqual( data, "accept: */*\n", "Test Accept header is set to last value provided" ); + } + }); - strictEqual( data, tmp, "Headers were sent" ); - strictEqual( xhr.getResponseHeader("Sample-Header"), "Hello World", "Sample header received" ); - - emptyHeader = xhr.getResponseHeader("Empty-Header"); - if ( emptyHeader === null ) { - ok( true, "Firefox doesn't support empty headers" ); - } else { - strictEqual( emptyHeader, "", "Empty header received" ); - } - strictEqual( xhr.getResponseHeader("Sample-Header2"), "Hello World 2", "Second sample header received" ); - }, - error: function() { - ok( false, "error" ); - } - }).always(function() { - start(); - }); - }); - - test( ".ajax() - Accept header", function() { - - expect( 1 ); - - stop(); - - jQuery.ajax( url("data/headers.php?keys=accept"), { - headers: { - Accept: "very wrong accept value" - }, - beforeSend: function( xhr ) { - xhr.setRequestHeader("Accept", "*/*"); - }, - success: function( data ) { - strictEqual( data, "accept: */*\n", "Test Accept header is set to last value provided" ); - start(); - }, - error: function() { - ok( false, "error" ); - } - }); - }); - - test( ".ajax() - contentType", function() { - - expect( 2 ); - - stop(); - - var count = 2; - - function restart() { - if ( ! --count ) { - start(); - } - } - - jQuery.ajax( url("data/headers.php?keys=content-type"), { + ajaxTest( "jQuery.ajax() - contentType", 2, [ + { + url: url("data/headers.php?keys=content-type"), contentType: "test", success: function( data ) { strictEqual( data, "content-type: test\n", "Test content-type is sent when options.contentType is set" ); - }, - complete: function() { - restart(); } - }); - - jQuery.ajax( url("data/headers.php?keys=content-type" ), { + }, + { + url: url("data/headers.php?keys=content-type"), contentType: false, success: function( data ) { strictEqual( data, "content-type: \n", "Test content-type is not sent when options.contentType===false" ); - }, - complete: function() { - restart(); } - }); - - }); - - test( ".ajax() - protocol-less urls", function() { - expect( 1 ); + } + ]); - jQuery.ajax({ - url: "//somedomain.com", - beforeSend: function( xhr, settings ) { - equal( settings.url, location.protocol + "//somedomain.com", "Make sure that the protocol is added." ); - return false; - } - }); + ajaxTest( "jQuery.ajax() - protocol-less urls", 1, { + url: "//somedomain.com", + beforeSend: function( xhr, settings ) { + equal( settings.url, location.protocol + "//somedomain.com", "Make sure that the protocol is added." ); + return false; + }, + error: true }); - test( ".ajax() - hash", function() { - expect( 3 ); - - jQuery.ajax({ + ajaxTest( "jQuery.ajax() - hash", 3, [ + { url: "data/name.html#foo", beforeSend: function( xhr, settings ) { equal( settings.url, "data/name.html", "Make sure that the URL is trimmed." ); return false; - } - }); - - jQuery.ajax({ + }, + error: true + }, + { url: "data/name.html?abc#foo", beforeSend: function( xhr, settings ) { - equal( settings.url, "data/name.html?abc", "Make sure that the URL is trimmed." ); + equal( settings.url, "data/name.html?abc", "Make sure that the URL is trimmed." ); return false; - } - }); - - jQuery.ajax({ + }, + error: true + }, + { url: "data/name.html?abc#foo", data: { "test": 123 @@ -616,150 +337,94 @@ beforeSend: function( xhr, settings ) { equal( settings.url, "data/name.html?abc&test=123", "Make sure that the URL is trimmed." ); return false; - } - }); - }); - - test( "jQuery ajax - cross-domain detection", function() { + }, + error: true + } + ]); - expect( 7 ); + ajaxTest( "jQuery.ajax() - cross-domain detection", 7, function() { + function request( url, title, crossDomainOrOptions ) { + return jQuery.extend( { + dataType: "jsonp", + url: url, + beforeSend: function( _, s ) { + ok( crossDomainOrOptions === false ? !s.crossDomain : s.crossDomain, title ); + return false; + }, + error: true + }, crossDomainOrOptions ); + } var loc = document.location, samePort = loc.port || ( loc.protocol === "http:" ? 80 : 443 ), otherPort = loc.port === 666 ? 667 : 666, otherProtocol = loc.protocol === "http:" ? "https:" : "http:"; - - jQuery.ajax({ - dataType: "jsonp", - url: loc.protocol + "//" + loc.host + ":" + samePort, - beforeSend: function( _, s ) { - ok( !s.crossDomain, "Test matching ports are not detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); - - jQuery.ajax({ - dataType: "jsonp", - url: otherProtocol + "//" + loc.host, - beforeSend: function( _, s ) { - ok( s.crossDomain, "Test different protocols are detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); - - jQuery.ajax({ - dataType: "jsonp", - url: "app:/path", - beforeSend: function( _, s ) { - ok( s.crossDomain, "Adobe AIR app:/ URL detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); - - jQuery.ajax({ - dataType: "jsonp", - url: loc.protocol + "//example.invalid:" + ( loc.port || 80 ), - beforeSend: function( _, s ) { - ok( s.crossDomain, "Test different hostnames are detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); - - jQuery.ajax({ - dataType: "jsonp", - url: loc.protocol + "//" + loc.hostname + ":" + otherPort, - beforeSend: function( _, s ) { - ok( s.crossDomain, "Test different ports are detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); - - jQuery.ajax({ - dataType: "jsonp", - url: "about:blank", - beforeSend: function( _, s ) { - ok( s.crossDomain, "Test about:blank is detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); - - jQuery.ajax({ - dataType: "jsonp", - url: loc.protocol + "//" + loc.host, - crossDomain: true, - beforeSend: function( _, s ) { - ok( s.crossDomain, "Test forced crossDomain is detected as cross-domain" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - return false; - } - }); + + return [ + request( + loc.protocol + "//" + loc.host + ":" + samePort, + "Test matching ports are not detected as cross-domain", + false + ), + request( + otherProtocol + "//" + loc.host, + "Test different protocols are detected as cross-domain" + ), + request( + "app:/path", + "Adobe AIR app:/ URL detected as cross-domain" + ), + request( + loc.protocol + "//example.invalid:" + ( loc.port || 80 ), + "Test different hostnames are detected as cross-domain" + ), + request( + loc.protocol + "//" + loc.hostname + ":" + otherPort, + "Test different ports are detected as cross-domain" + ), + request( + "about:blank", + "Test about:blank is detected as cross-domain" + ), + request( + loc.protocol + "//" + loc.host, + "Test forced crossDomain is detected as cross-domain", + { + crossDomain: true + } + ) + ]; }); - test( ".load() - 404 error callbacks", function() { - expect( 6 ); - stop(); - - jQuery("#foo").ajaxStart(function() { - ok( true, "ajaxStart" ); - }).ajaxStop(function() { - ok( true, "ajaxStop" ); - start(); - }).ajaxSend(function() { - ok( true, "ajaxSend" ); - }).ajaxComplete(function() { - ok( true, "ajaxComplete" ); - }).ajaxError(function() { - ok( true, "ajaxError" ); - }).ajaxSuccess(function() { - ok( false, "ajaxSuccess" ); - }); - - jQuery("
").load( "data/404.html", function() { + ajaxTest( "jQuery.ajax() - abort", 8, { + setup: function() { + jQuery("#foo").ajaxStart(function() { + ok( true, "ajaxStart" ); + }).ajaxStop(function() { + ok( true, "ajaxStop" ); + }).ajaxSend(function() { + ok( true, "ajaxSend" ); + }).ajaxComplete(function() { + ok( true, "ajaxComplete" ); + }); + }, + url: url("data/name.php?wait=5"), + beforeSend: function() { + ok( true, "beforeSend" ); + }, + afterSend: function( xhr ) { + strictEqual( xhr.readyState, 1, "XHR readyState indicates successful dispatch" ); + xhr.abort(); + strictEqual( xhr.readyState, 0, "XHR readyState indicates successful abortion" ); + }, + error: true, + complete: function() { ok( true, "complete" ); - }); - }); - - test( "jQuery.ajax() - abort", function() { - expect( 8 ); - stop(); - - jQuery("#foo").ajaxStart(function() { - ok( true, "ajaxStart" ); - }).ajaxStop(function() { - ok( true, "ajaxStop" ); - start(); - }).ajaxSend(function() { - ok( true, "ajaxSend" ); - }).ajaxComplete(function() { - ok( true, "ajaxComplete" ); - }); - - var xhr = jQuery.ajax({ - url: url("data/name.php?wait=5"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - complete: function() { - ok( true, "complete" ); - } - }); - - equal( xhr.readyState, 1, "XHR readyState indicates successful dispatch" ); - - xhr.abort(); - equal( xhr.readyState, 0, "XHR readyState indicates successful abortion" ); + } }); - test( "Ajax events with context", function() { - expect( 14 ); + ajaxTest( "jQuery.ajax() - events with context", 12, function() { - stop(); var context = document.createElement("div"); function event( e ) { @@ -772,342 +437,224 @@ }; } + return { + setup: function() { + jQuery( context ).appendTo("#foo") + .ajaxSend( event ) + .ajaxComplete( event ) + .ajaxError( event ) + .ajaxSuccess( event ); + }, + requests: [{ + url: url("data/name.html"), + context: context, + beforeSend: callback("beforeSend"), + success: callback("success"), + complete: callback("complete") + }, { + url: url("data/404.html"), + context: context, + beforeSend: callback("beforeSend"), + error: callback("error"), + complete: callback("complete") + }] + }; + }); + + ajaxTest( "jQuery.ajax() - events without context", 3, function() { function nocallback( msg ) { return function() { equal( typeof this.url, "string", "context is settings on callback " + msg ); }; } + return { + url: url("data/404.html"), + beforeSend: nocallback("beforeSend"), + error: nocallback("error"), + complete: nocallback("complete") + }; + }); - jQuery("#foo").add( context ) - .ajaxSend( event ) - .ajaxComplete( event ) - .ajaxError( event ) - .ajaxSuccess( event ); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: callback("beforeSend"), - success: callback("success"), - error: callback("error"), - complete: function() { - callback("complete").call( this ); - - jQuery.ajax({ - url: url("data/404.html"), - context: context, - beforeSend: callback("beforeSend"), - error: callback("error"), - complete: function() { - callback("complete").call( this ); - - jQuery("#foo").add( context ).unbind(); + ajaxTest( "jQuery.ajax() - context modification", 1, { + url: url("data/name.html"), + context: {}, + beforeSend: function() { + this.test = "foo"; + }, + afterSend: function() { + strictEqual( this.context.test, "foo", "Make sure the original object is maintained." ); + }, + success: true + }); - jQuery.ajax({ - url: url("data/404.html"), - beforeSend: nocallback("beforeSend"), - error: nocallback("error"), - complete: function() { - nocallback("complete").call( this ); - start(); - } - }); - } + ajaxTest( "jQuery.ajax() - context modification through ajaxSetup", 3, function() { + var obj = {}; + return { + setup: function() { + jQuery.ajaxSetup({ + context: obj }); + strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." ); }, - context: context - }); + requests: [{ + url: url("data/name.html"), + success: function() { + strictEqual( this, obj, "Make sure the original object is maintained." ); + } + }, { + url: url("data/name.html"), + context: {}, + success: function() { + ok( this !== obj, "Make sure overidding context is possible." ); + } + }] + }; }); - test( "jQuery.ajax context modification", function() { - expect( 1 ); + ajaxTest( "jQuery.ajax() - disabled globals", 3, { + setup: function() { + jQuery("#foo").ajaxStart(function() { + ok( false, "ajaxStart" ); + }).ajaxStop(function() { + ok( false, "ajaxStop" ); + }).ajaxSend(function() { + ok( false, "ajaxSend" ); + }).ajaxComplete(function() { + ok( false, "ajaxComplete" ); + }).ajaxError(function() { + ok( false, "ajaxError" ); + }).ajaxSuccess(function() { + ok( false, "ajaxSuccess" ); + }); + }, + global: false, + url: url("data/name.html"), + beforeSend: function() { + ok( true, "beforeSend" ); + }, + success: function() { + ok( true, "success" ); + }, + complete: function() { + ok( true, "complete" ); + } + }); - stop(); + ajaxTest( "jQuery.ajax() - xml: non-namespace elements inside namespaced elements", 3, { + url: url("data/with_fries.xml"), + dataType: "xml", + success: function( resp ) { + equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); + equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); + equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); + } + }); - var obj = {}; + ajaxTest( "jQuery.ajax() - xml: non-namespace elements inside namespaced elements (over JSONP)", 3, { + url: url("data/with_fries_over_jsonp.php"), + dataType: "jsonp xml", + success: function( resp ) { + equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); + equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); + equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); + } + }); - jQuery.ajax({ + ajaxTest( "jQuery.ajax() - HEAD requests", 2, [ + { url: url("data/name.html"), - context: obj, - beforeSend: function() { - this.test = "foo"; + type: "HEAD", + success: function( data, status, xhr ) { + ok( /Date/i.test( xhr.getAllResponseHeaders() ), "No Date in HEAD response" ); + } + }, + { + url: url("data/name.html"), + data: { + "whip_it": "good" }, - complete: function() { - start(); + type: "HEAD", + success: function( data, status, xhr ) { + ok( /Date/i.test( xhr.getAllResponseHeaders() ), "No Date in HEAD response with data" ); } - }); + } + ]); - equal( obj.test, "foo", "Make sure the original object is maintained." ); + ajaxTest( "jQuery.ajax() - beforeSend", 1, { + url: url("data/name.html"), + beforeSend: function( xml ) { + this.check = true; + }, + success: function( data ) { + ok( this.check, "check beforeSend was executed" ); + } }); - test( "jQuery.ajax context modification through ajaxSetup", function() { - expect( 4 ); - - stop(); - - var obj = {}; - - jQuery.ajaxSetup({ - context: obj - }); - - strictEqual( jQuery.ajaxSettings.context, obj, "Make sure the context is properly set in ajaxSettings." ); - - jQuery.ajax({ - url: url("data/name.html"), - complete: function() { - strictEqual( this, obj, "Make sure the original object is maintained." ); - jQuery.ajax({ - url: url("data/name.html"), - context: {}, - complete: function() { - ok( this !== obj, "Make sure overidding context is possible." ); - jQuery.ajaxSetup({ - context: false - }); - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - this.test = "foo2"; - }, - complete: function() { - ok( this !== obj, "Make sure unsetting context is possible." ); - start(); - } - }); - } - }); - } - }); - }); - - test( "jQuery.ajax() - disabled globals", function() { - expect( 3 ); - stop(); - - jQuery("#foo").ajaxStart(function() { - ok( false, "ajaxStart" ); - }).ajaxStop(function() { - ok( false, "ajaxStop" ); - }).ajaxSend(function() { - ok( false, "ajaxSend" ); - }).ajaxComplete(function() { - ok( false, "ajaxComplete" ); - }).ajaxError(function() { - ok( false, "ajaxError" ); - }).ajaxSuccess(function() { - ok( false, "ajaxSuccess" ); - }); - - jQuery.ajax({ - global: false, - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend" ); - }, - success: function() { - ok( true, "success" ); - }, - error: function() { - ok( false, "error" ); - }, - complete: function() { - ok( true, "complete" ); - setTimeout(function() { - start(); - }, 13 ); - } - }); - }); - - test( "jQuery.ajax - xml: non-namespace elements inside namespaced elements", function() { - expect( 3 ); - - stop(); - - jQuery.ajax({ - url: url("data/with_fries.xml"), - dataType: "xml", - success: function( resp ) { - equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); - equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); - equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); - start(); - } - }); - }); - - test( "jQuery.ajax - xml: non-namespace elements inside namespaced elements (over JSONP)", function() { - expect( 3 ); - stop(); - jQuery.ajax({ - url: url("data/with_fries_over_jsonp.php"), - dataType: "jsonp xml", - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( resp ) { - equal( jQuery( "properties", resp ).length, 1, "properties in responseXML" ); - equal( jQuery( "jsconf", resp ).length, 1, "jsconf in responseXML" ); - equal( jQuery( "thing", resp ).length, 2, "things in responseXML" ); - start(); - }, - error: function( _1, _2, error ) { - ok( false, error ); - start(); - } - }); - }); - - test( "jQuery.ajax - HEAD requests", function() { - expect( 2 ); - - stop(); - jQuery.ajax({ - url: url("data/name.html"), - type: "HEAD", - success: function( data, status, xhr ) { - var h = xhr.getAllResponseHeaders(); - ok( /Date/i.test( h ), "No Date in HEAD response" ); - - jQuery.ajax({ - url: url("data/name.html"), - data: { - "whip_it": "good" - }, - type: "HEAD", - success: function( data, status, xhr ) { - var h = xhr.getAllResponseHeaders(); - ok( /Date/i.test( h ), "No Date in HEAD response with data" ); - start(); - } - }); - } - }); - - }); - - test( "jQuery.ajax - beforeSend", function() { - expect( 1 ); - stop(); - - var check = false; - - jQuery.ajaxSetup({ - timeout: 0 - }); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function( xml ) { - check = true; - }, - success: function( data ) { - ok( check, "check beforeSend was executed" ); - start(); - } - }); - }); - - test( "jQuery.ajax - beforeSend, cancel request (#2688)", function() { - expect( 2 ); - - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function() { - ok( true, "beforeSend got called, canceling" ); - return false; - }, - success: function() { - ok( false, "request didn't get canceled" ); - }, - complete: function() { - ok( false, "request didn't get canceled" ); - }, - error: function() { - ok( false, "request didn't get canceled" ); - } - }).fail(function( _, reason ) { + ajaxTest( "jQuery.ajax() - beforeSend, cancel request manually", 2, { + create: function() { + return jQuery.ajax({ + url: url("data/name.html"), + beforeSend: function( xhr ) { + ok( true, "beforeSend got called, canceling" ); + xhr.abort(); + }, + success: function() { + ok( false, "request didn't get canceled" ); + }, + complete: function() { + ok( false, "request didn't get canceled" ); + }, + error: function() { + ok( false, "request didn't get canceled" ); + } + }); + }, + fail: function( _, reason ) { strictEqual( reason, "canceled", "canceled request must fail with 'canceled' status text" ); - }); - }); - - test( "jQuery.ajax - beforeSend, cancel request manually", function() { - expect( 2 ); - jQuery.ajax({ - url: url("data/name.html"), - beforeSend: function( xhr ) { - ok( true, "beforeSend got called, canceling" ); - xhr.abort(); - }, - success: function() { - ok( false, "request didn't get canceled" ); - }, - complete: function() { - ok( false, "request didn't get canceled" ); - }, - error: function() { - ok( false, "request didn't get canceled" ); - } - }).fail(function( _, reason ) { - strictEqual( reason, "canceled", "manually canceled request must fail with 'canceled' status text" ); - }); + } }); - window["foobar"] = null; - window["testFoo"] = undefined; - - test( "jQuery.ajax - dataType html", function() { - expect( 5 ); - stop(); - - var verifyEvaluation = function() { - equal( window["testFoo"], "foo", "Check if script was evaluated for datatype html" ); - equal( window["foobar"], "bar", "Check if script src was evaluated for datatype html" ); - - start(); - }; - - jQuery.ajax({ - dataType: "html", - url: url("data/test.html"), - success: function( data ) { - jQuery("#ap").html( data ); - ok( data.match( /^html text/ ), "Check content for datatype html" ); - setTimeout( verifyEvaluation, 600 ); - } - }); + ajaxTest( "jQuery.ajax() - dataType html", 5, { + setup: function() { + Globals.register("testFoo"); + Globals.register("foobar"); + }, + dataType: "html", + url: url("data/test.html"), + success: function( data ) { + ok( data.match( /^html text/ ), "Check content for datatype html" ); + jQuery("#ap").html( data ); + strictEqual( window["testFoo"], "foo", "Check if script was evaluated for datatype html" ); + strictEqual( window["foobar"], "bar", "Check if script src was evaluated for datatype html" ); + } }); - test( "synchronous request", function() { - expect( 1 ); - var response = jQuery.ajax({ - url: url("data/json_obj.js"), - dataType: "text", - async: false - }).responseText; - - ok( /^\{ "data"/.test( response ), "check returned text" ); + ajaxTest( "jQuery.ajax() - synchronous request", 1, { + url: url("data/json_obj.js"), + dataType: "text", + async: false, + success: true, + afterSend: function( xhr ) { + ok( /^\{ "data"/.test( xhr.responseText ), "check returned text" ); + } }); - test( "synchronous request with callbacks", function() { - expect( 2 ); - var result; - jQuery.ajax({ - url: url("data/json_obj.js"), - async: false, - dataType: "text", - success: function(data) { - ok( true, "sucess callback executed" ); + ajaxTest( "jQuery.ajax() - synchronous request with callbacks", 2, { + url: url("data/json_obj.js"), + async: false, + dataType: "text", + success: true, + afterSend: function( xhr ) { + var result; + xhr.done(function( data ) { + ok( true, "success callback executed" ); result = data; - } - }); - ok( /^\{ "data"/.test( result ), "check returned text" ); + }); + ok( /^\{ "data"/.test( result ), "check returned text" ); + } }); - test( "pass-through request object", function() { - expect( 8 ); - stop(); - + asyncTest( "jQuery.ajax(), jQuery.get[Script|JSON](), jQuery.post(), pass-through request object", 8, function() { var target = "data/name.html"; var successCount = 0; var errorCount = 0; @@ -1123,7 +670,6 @@ equal( successCount, 5, "Check all ajax calls successful" ); equal( errorCount, 0, "Check no ajax errors (status" + errorEx + ")" ); jQuery("#foo").unbind("ajaxError"); - start(); }); @@ -1137,1221 +683,353 @@ }), "generic" ); }); - test( "ajax cache", function() { - expect( 18 ); - - stop(); - - var count = 0; - - jQuery("#firstp").bind( "ajaxSuccess", function( e, xml, s ) { - var re = /_=(.*?)(&|$)/g; - var oldOne = null; - for ( var i = 0; i < 6; i++ ) { - var ret = re.exec( s.url ); - if ( !ret ) { - break; - } - oldOne = ret[ 1 ]; - } - equal( i, 1, "Test to make sure only one 'no-cache' parameter is there" ); - ok( oldOne != "tobereplaced555", "Test to be sure parameter (if it was there) was replaced" ); - if ( ++count === 6 ) { - start(); - } - }); - - ok( jQuery.ajax({ - url: "data/text.php", - cache: false - }), "test with no parameters" ); - ok( jQuery.ajax({ - url: "data/text.php?pizza=true", - cache: false - }), "test with 1 parameter" ); - ok( jQuery.ajax({ - url: "data/text.php?_=tobereplaced555", - cache: false - }), "test with _= parameter" ); - ok( jQuery.ajax({ - url: "data/text.php?pizza=true&_=tobereplaced555", - cache: false - }), "test with 1 parameter plus _= one" ); - ok( jQuery.ajax({ - url: "data/text.php?_=tobereplaced555&tv=false", - cache: false - }), "test with 1 parameter plus _= one before it" ); - ok( jQuery.ajax({ - url: "data/text.php?name=David&_=tobereplaced555&washere=true", - cache: false - }), "test with 2 parameters surrounding _= one" ); - }); - - /* - * Test disabled. - * The assertions expect that the passed-in object will be modified, - * which shouldn't be the case. Fixes #5439. - test( "global ajaxSettings", function() { - expect( 2 ); - - var t, - tmp = jQuery.extend({}, jQuery.ajaxSettings ), - orig = { - url: "data/with_fries.xml" + ajaxTest( "jQuery.ajax() - cache", 12, function() { + + var re = /_=(.*?)(&|$)/g; + + function request( url, title ) { + return { + url: url, + cache: false, + beforeSend: function() { + var parameter, tmp; + while(( tmp = re.exec( this.url ) )) { + strictEqual( parameter, undefined, title + ": only one 'no-cache' parameter" ); + parameter = tmp[ 1 ]; + notStrictEqual( parameter, "tobereplaced555", title + ": parameter (if it was there) was replaced" ); + } + return false; + }, + error: true }; - - jQuery.ajaxSetup({ - data: { - foo: "bar", - bar: "BAR" - } - }); - - t = jQuery.extend({}, orig ); - t.data = {}; - jQuery.ajax( t ); - ok( t.url.indexOf("foo") > -1 && t.url.indexOf("bar") > -1, "Check extending {}" ); - - t = jQuery.extend({}, orig ); - t.data = { - zoo: "a", - ping: "b" - }; - jQuery.ajax( t ); - ok( t.url.indexOf("ping") > -1 && t.url.indexOf("zoo") > -1 && t.url.indexOf("foo") > -1 && t.url.indexOf("bar") > -1, "Check extending { zoo: "a", ping: "b" }" ); - - jQuery.ajaxSettings = tmp; - }); - */ - - test( "load(String)", function() { - expect( 2 ); - stop(); // check if load can be called with only url - jQuery.ajaxSetup({ - beforeSend: function() { - strictEqual( this.type, "GET", "no data means GET request" ); - } - }); - jQuery("#first").load( "data/name.html", function() { - start(); - }); - jQuery.ajaxSetup({ - beforeSend: null - }); + } + + return [ + request( + "data/text.php", + "no parameter" + ), + request( + "data/text.php?pizza=true", + "1 parameter" + ), + request( + "data/text.php?_=tobereplaced555", + "_= parameter" + ), + request( + "data/text.php?pizza=true&_=tobereplaced555", + "1 parameter and _=" + ), + request( + "data/text.php?_=tobereplaced555&tv=false", + "_= and 1 parameter" + ), + request( + "data/text.php?name=David&_=tobereplaced555&washere=true", + "2 parameters surrounding _=" + ) + ]; }); - test( "load(String,null)", function() { - expect( 2 ); - stop(); // check if load can be called with url and null data - jQuery.ajaxSetup({ - beforeSend: function() { - strictEqual( this.type, "GET", "no data means GET request" ); - } - }); - jQuery("#first").load( "data/name.html", null, function() { - start(); - }); - }); + jQuery.each( [ " - Same Domain", " - Cross Domain" ], function( crossDomain, label ) { - test( "load(String,undefined)", function() { - expect( 2 ); - stop(); // check if load can be called with url and null data - jQuery.ajaxSetup({ - beforeSend: function() { - strictEqual( this.type, "GET", "no data means GET request" ); + ajaxTest( "jQuery.ajax() - JSONP - Query String (?n)" + label, 4, [ + { + url: "data/jsonp.php?callback=?", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data.data, "JSON results returned (GET, url callback)" ); + } + }, + { + url: "data/jsonp.php?callback=??", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data.data, "JSON results returned (GET, url context-free callback)" ); + } + }, + { + url: "data/jsonp.php/??", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data.data, "JSON results returned (GET, REST-like)" ); + } + }, + { + url: "data/jsonp.php/???json=1", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + strictEqual( jQuery.type( data ), "array", "JSON results returned (GET, REST-like with param)" ); + } } - }); - jQuery("#first").load( "data/name.html", undefined, function() { - start(); - }); - }); - - test( "load('url selector')", function() { - expect( 1 ); - stop(); // check if load can be called with only url - jQuery("#first").load( "data/test3.html div.user", function() { - equal( jQuery( this ).children("div").length, 2, "Verify that specific elements were injected" ); - start(); - }); - }); + ]); - test( "load(String, Function) with ajaxSetup on dataType json, see #2046", function() { - expect( 1 ); - stop(); - jQuery.ajaxSetup({ - dataType: "json" - }); - jQuery("#first").ajaxComplete(function( e, xml, s ) { - equal( s.dataType, "html", "Verify the load() dataType was html" ); - jQuery("#first").unbind("ajaxComplete"); - jQuery.ajaxSetup({ - dataType: "" - }); - start(); - }); - jQuery("#first").load("data/test3.html"); - }); - - test( "load(String, Function) - simple: inject text into DOM", function() { - expect( 2 ); - stop(); - jQuery("#first").load( url("data/name.html"), function() { - ok( /^ERROR/.test( jQuery("#first").text() ), "Check if content was injected into the DOM" ); - start(); - }); - }); - - test( "load(String, Function) - check scripts", function() { - expect( 7 ); - stop(); - - var verifyEvaluation = function() { - equal( window["foobar"], "bar", "Check if script src was evaluated after load" ); - equal( jQuery("#ap").html(), "bar", "Check if script evaluation has modified DOM"); - - start(); - }; - jQuery("#first").load( url("data/test.html"), function() { - ok( jQuery("#first").html().match( /^html text/ ), "Check content after loading html" ); - equal( jQuery("#foo").html(), "foo", "Check if script evaluation has modified DOM" ); - equal( window["testFoo"], "foo", "Check if script was evaluated after load" ); - setTimeout( verifyEvaluation, 600 ); - }); - }); - - test( "load(String, Function) - check file with only a script tag", function() { - expect( 3 ); - stop(); - - jQuery("#first").load( url("data/test2.html"), function() { - equal( jQuery("#foo").html(), "foo", "Check if script evaluation has modified DOM"); - equal( window["testFoo"], "foo", "Check if script was evaluated after load" ); - - start(); - }); - }); - - test( "load(String, Function) - dataFilter in ajaxSettings", function() { - expect( 2 ); - stop(); - jQuery.ajaxSetup({ - dataFilter: function() { - return "Hello World"; - } - }); - var div = jQuery("
").load( url("data/name.html"), function( responseText ) { - strictEqual( div.html(), "Hello World", "Test div was filled with filtered data" ); - strictEqual( responseText, "Hello World", "Test callback receives filtered data" ); - jQuery.ajaxSetup({ - dataFilter: 0 - }); - start(); - }); - }); - - test( "load(String, Object, Function)", function() { - expect( 2 ); - stop(); - - jQuery("
").load( url("data/params_html.php"), { - "foo": 3, - "bar": "ok" - }, function() { - var $post = jQuery( this ).find("#post"); - equal( $post.find("#foo").text(), "3", "Check if a hash of data is passed correctly" ); - equal( $post.find("#bar").text(), "ok", "Check if a hash of data is passed correctly" ); - start(); - }); - }); - - test( "load(String, String, Function)", function() { - expect( 2 ); - stop(); - - jQuery("
").load( url("data/params_html.php"), "foo=3&bar=ok", function() { - var $get = jQuery( this ).find("#get"); - equal( $get.find("#foo").text(), "3", "Check if a string of data is passed correctly" ); - equal( $get.find("#bar").text(), "ok", "Check if a of data is passed correctly" ); - start(); - }); - }); - - asyncTest( "load() - data specified in ajaxSettings is merged in (#10524)", 1, function() { - jQuery.ajaxSetup({ - data: { - "foo": "bar" - } - }); - - var data = { - "baz": 1 - }; - - jQuery("#foo") - .load( "data/echoQuery.php", data ) - .ajaxComplete(function( event, jqXHR, options ) { - ok( ~options.data.indexOf("foo=bar"), "Data from ajaxSettings was used" ); - jQuery.ajaxSetup({ - data: null - }); - start(); - }); - }); - - asyncTest( "load() - callbacks get the correct parameters", 8, function() { - var slice = [].slice, - completeArgs = {}; - - jQuery.ajaxSetup({ - success: function( _, status, jqXHR ) { - completeArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ]; + ajaxTest( "jQuery.ajax() - JSONP - Explicit callback param" + label, 9, { + setup: function() { + Globals.register("functionToCleanUp"); + Globals.register("XXX"); + Globals.register("jsonpResults"); + window["jsonpResults"] = function( data ) { + ok( data["data"], "JSON results returned (GET, custom callback function)" ); + }; }, - error: function( jqXHR, status ) { - completeArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ]; - } - }); - - jQuery.when.apply( - /* jQuery.when.apply arguments start */ - jQuery, - jQuery.map([ - { - type: "success", - url: "data/echoQuery.php?arg=pop" - }, - { - type: "error", - url: "data/404.php" - } - ], - function( options ) { - return jQuery.Deferred(function( defer ) { - jQuery("#foo").load( options.url, function() { - var args = arguments; - strictEqual( completeArgs[ options.url ].length, args.length, "same number of arguments (" + options.type + ")" ); - jQuery.each( completeArgs[ options.url ], function( i, value ) { - strictEqual( args[ i ], value, "argument #" + i + " is the same (" + options.type + ")" ); - }); - defer.resolve(); - }); - }); - }) - /* jQuery.when.apply arguments end*/ - ).always(function() { - jQuery.ajaxSetup({ - success: null, - error: null - }); - start(); - }); - }); - - test( "jQuery.get(String, Function) - data in ajaxSettings (#8277)", function() { - expect( 1 ); - stop(); - jQuery.ajaxSetup({ - data: "helloworld" - }); - jQuery.get( url("data/echoQuery.php"), function( data ) { - ok( /helloworld$/.test( data ), "Data from ajaxSettings was used" ); - jQuery.ajaxSetup({ - data: null - }); - start(); - }); - }); - - test( "jQuery.get(String, Hash, Function) - parse xml and use text() on nodes", function() { - expect( 2 ); - stop(); - jQuery.get( url("data/dashboard.xml"), function( xml ) { - var content = []; - jQuery( "tab", xml ).each(function() { - content.push( jQuery( this ).text() ); - }); - equal( content[ 0 ], "blabla", "Check first tab" ); - equal( content[ 1 ], "blublu", "Check second tab" ); - start(); - }); - }); - - test( "jQuery.getScript(String, Function) - with callback", function() { - expect( 3 ); - stop(); - jQuery.getScript( url("data/test.js"), function( data, _, jqXHR ) { - equal( foobar, "bar", "Check if script was evaluated" ); - strictEqual( data, jqXHR.responseText, "Same-domain script requests returns the source of the script (#8082)" ); - start(); - }); - }); - - test( "jQuery.getScript(String, Function) - no callback", function() { - expect( 1 ); - stop(); - jQuery.getScript( url("data/test.js"), function() { - start(); - }); - }); - - - jQuery.each( [ "Same Domain", "Cross Domain" ], function( crossDomain, label ) { - - asyncTest( "jQuery.ajax() - JSONP, Query String (?n)" + label, function() { - expect( 4 ); - - var count = 0; - function plus() { - if ( ++count === 4 ) { - start(); - } - } - - jQuery.ajax({ - url: "data/jsonp.php?callback=?", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, "JSON results returned (GET, url callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, url callback)" ); - plus(); - } - }); - - jQuery.ajax({ - url: "data/jsonp.php?callback=??", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, "JSON results returned (GET, url context-free callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, url context-free callback)" ); - plus(); - } - }); - - jQuery.ajax({ - url: "data/jsonp.php/??", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/jsonp\.php\/([^?]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, "JSON results returned (GET, REST-like)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, REST-like)" ); - plus(); - } - }); - - jQuery.ajax({ - url: "data/jsonp.php/???json=1", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/jsonp\.php\/([^?]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - strictEqual( jQuery.type( data ), "array", "JSON results returned (GET, REST-like with param)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, REST-like with param)" ); - plus(); - } - }); - }); - - asyncTest( "jQuery.ajax() - JSONP, Explicit jsonp/Callback param " + label, function() { - expect( 9 ); - - var count = 0; - function plus() { - if ( ++count === 7 ) { - start(); - } - } - - jQuery.ajax({ + requests: [{ url: "data/jsonp.php", dataType: "jsonp", crossDomain: crossDomain, jsonp: "callback", - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, success: function( data ) { ok( data["data"], "JSON results returned (GET, data obj callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, data obj callback)" ); - plus(); } - }); - - jQuery.globalEval("var jsonpResults;"); - window["jsonpResults"] = function( data ) { - ok( data["data"], "JSON results returned (GET, custom callback function)" ); - jQuery.globalEval("delete jsonpResults;"); - plus(); - }; - - jQuery.ajax({ + }, { url: "data/jsonp.php", dataType: "jsonp", crossDomain: crossDomain, jsonpCallback: "jsonpResults", success: function( data ) { ok( data.data, "JSON results returned (GET, custom callback name)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, custom callback name)" ); - plus(); } - }); - - jQuery.globalEval("var functionToCleanUp;"); - jQuery.ajax({ + }, { url: "data/jsonp.php", dataType: "jsonp", crossDomain: crossDomain, - jsonpCallback: "functionToCleanUp", - beforeSend: function() { - jsonpCallbacks.push("functionToCleanUp"); - }, - success: function( data ) { - ok( data["data"], "JSON results returned (GET, custom callback name to be cleaned up)" ); - strictEqual( window["functionToCleanUp"], undefined, "Callback was removed (GET, custom callback name to be cleaned up)" ); - plus(); - var xhr; - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - jsonpCallback: "functionToCleanUp", - beforeSend: function( jqXHR ) { - xhr = jqXHR; - return false; - } - }); - xhr.error(function() { - ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" ); - strictEqual( window["functionToCleanUp"], undefined, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" ); - plus(); - }); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, custom callback name to be cleaned up)" ); - plus(); - plus(); - } - }); - - jQuery.globalEval("var XXX;"); - jQuery.ajax({ - url: "data/jsonp.php?callback=XXX", - dataType: "jsonp", - jsonp: false, - jsonpCallback: "XXX", - crossDomain: crossDomain, - beforeSend: function() { - ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ), "The URL wasn't messed with (GET, custom callback name with no url manipulation)" ); - jsonpCallbacks.push("XXX"); - plus(); - }, - success: function( data ) { - ok( data["data"], "JSON results returned (GET, custom callback name with no url manipulation)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" ); - plus(); - } - }); - }); - - asyncTest( "jQuery.ajax() - JSONP, Callback in data, " + label, function() { - expect( 2 ); - - var count = 0; - function plus() { - if ( ++count === 2 ) { - start(); - } - } - - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - data: "callback=?", - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, "JSON results returned (GET, data callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, data callback)" ); - plus(); - } - }); - - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - data: "callback=??", - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, "JSON results returned (GET, data context-free callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, data context-free callback)" ); - plus(); - } - }); - }); - - - asyncTest( "jQuery.ajax() - JSONP, POST, " + label, function() { - expect( 3 ); - - var count = 0; - function plus() { - if ( ++count === 3 ) { - start(); - } - } - - jQuery.ajax({ - type: "POST", - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data["data"], "JSON results returned (POST, no callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, data obj callback)" ); - plus(); - } - }); - - jQuery.ajax({ - type: "POST", - url: "data/jsonp.php", - data: "callback=?", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( crossDomain ? s.url : s.data ) || [])[1] ); - }, - success: function( data ) { - ok( data["data"], "JSON results returned (POST, data callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (POST, data callback)" ); - plus(); - } - }); - - jQuery.ajax({ - type: "POST", - url: "data/jsonp.php", - jsonp: "callback", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data["data"], "JSON results returned (POST, data obj callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (POST, data obj callback)" ); - plus(); - } - }); - }); - - asyncTest( "jQuery.ajax() - JSONP, " + label, function() { - expect( 3 ); - - var count = 0; - function plus() { - if ( ++count === 2 ) { - start(); - } - } - - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, "JSON results returned (GET, no callback)" ); - plus(); - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, no callback)" ); - plus(); - } - }); - - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - }, - success: function( data ) { - ok( data.data, ( this.alreadyDone ? "this re-used" : "first request" ) + ": JSON results returned (GET, no callback)" ); - if ( !this.alreadyDone ) { - this.alreadyDone = true; - - // NOTE: "this" will create another request identical - // to the CALLING request - jQuery.ajax( this ); - } else { - plus(); - } - }, - error: function( data ) { - ok( false, "Ajax error JSON (GET, no callback)" ); - plus(); - } - }); - }); - - asyncTest( "jQuery.ajax() - #7578, " + label, function() { - expect( 1 ); - - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - strictEqual( this.cache, false, "cache must be false on JSON request" ); - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - start(); - return false; - } - }); - }); - - asyncTest( "jQuery.ajax() - #8205, " + label, function() { - expect( 2 ); - - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function( jqXHR, s ) { - s.callback = s.jsonpCallback; - jsonpCallbacks.push( (/callback=([^&]*)/.exec( s.url ) || [])[1] ); - } - }).pipe(function() { - var previous = this; - strictEqual( previous.jsonpCallback, undefined, "jsonpCallback option is set back to default in callbacks" ); - jQuery.ajax({ - url: "data/jsonp.php", - dataType: "jsonp", - crossDomain: crossDomain, - beforeSend: function() { - strictEqual( this.jsonpCallback, previous.callback, "JSONP callback name is re-used" ); - return false; - } - }); - }).always(function() { - start(); - }); - }); - }); - - test( "jQuery.ajax() - script, Remote", function() { - expect( 2 ); - - var base = window.location.href.replace( /[^\/]*$/, "" ); - - stop(); - - jQuery.ajax({ - url: base + "data/test.js", - dataType: "script", - success: function( data ) { - ok( window["foobar"], "Script results returned (GET, no callback)" ); - start(); - } - }); - }); - - test( "jQuery.ajax() - script, Remote with POST", function() { - expect( 3 ); - - var base = window.location.href.replace( /[^\/]*$/, "" ); - - stop(); - - jQuery.ajax({ - url: base + "data/test.js", - type: "POST", - dataType: "script", - success: function( data, status ) { - ok( window["foobar"], "Script results returned (POST, no callback)" ); - equal( status, "success", "Script results returned (POST, no callback)" ); - start(); - }, - error: function( xhr ) { - ok( false, "ajax error, status code: " + xhr.status ); - start(); - } - }); - }); - - test( "jQuery.ajax() - script, Remote with scheme-less URL", function() { - expect( 2 ); - - var base = window.location.href.replace( /[^\/]*$/, "" ); - base = base.replace( /^.*?\/\//, "//" ); - - stop(); - - jQuery.ajax({ - url: base + "data/test.js", - dataType: "script", - success: function( data ) { - ok( window["foobar"], "Script results returned (GET, no callback)" ); - start(); - } - }); - }); - - test( "jQuery.ajax() - malformed JSON", function() { - expect( 2 ); - - stop(); - - jQuery.ajax({ - url: "data/badjson.js", - dataType: "json", - success: function() { - ok( false, "Success." ); - start(); - }, - error: function( xhr, msg, detailedMsg ) { - equal( "parsererror", msg, "A parse error occurred." ); - ok( /(invalid|error|exception)/i.test( detailedMsg ), "Detailed parsererror message provided" ); - start(); - } - }); - }); - - test( "jQuery.ajax() - script, throws exception (#11743)", function() { - expect( 1 ); - - raises(function() { - jQuery.ajax({ - url: "data/badjson.js", - dataType: "script", - throws: true, - // TODO find a way to test this asynchronously, too - async: false, - // Global events get confused by the exception - global: false, - success: function() { - ok( false, "Success." ); - }, - error: function() { - ok( false, "Error." ); - } - }); - }, "exception bubbled" ); - }); - - test( "jQuery.ajax() - script by content-type", function() { - expect( 2 ); - - stop(); - - jQuery.when( - /* jQuery.when arguments start */ - jQuery.ajax({ - url: "data/script.php", - data: { - "header": "script" - } - }), - jQuery.ajax({ - url: "data/script.php", - data: { - "header": "ecma" - } - }) - /* jQuery.when arguments end */ - ).always(function() { - start(); - }); - }); - - test( "jQuery.ajax() - json by content-type", function() { - expect( 5 ); - - stop(); - - jQuery.ajax({ - url: "data/json.php", - data: { - "header": "json", - "json": "array" - }, - success: function( json ) { - ok( json.length >= 2, "Check length" ); - equal( json[ 0 ]["name"], "John", "Check JSON: first, name" ); - equal( json[ 0 ]["age"], 21, "Check JSON: first, age" ); - equal( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); - equal( json[ 1 ]["age"], 25, "Check JSON: second, age" ); - start(); - } - }); - }); - - test( "jQuery.ajax() - json by content-type disabled with options", function() { - expect( 6 ); - - stop(); - - jQuery.ajax({ - url: url("data/json.php"), - data: { - "header": "json", - "json": "array" - }, - contents: { - "json": false - }, - success: function( text ) { - equal( typeof text, "string", "json wasn't auto-determined" ); - var json = jQuery.parseJSON( text ); - ok( json.length >= 2, "Check length"); - equal( json[ 0 ]["name"], "John", "Check JSON: first, name" ); - equal( json[ 0 ]["age"], 21, "Check JSON: first, age" ); - equal( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); - equal( json[ 1 ]["age"], 25, "Check JSON: second, age" ); - start(); - } - }); - }); - - test( "jQuery.getJSON(String, Hash, Function) - JSON array", function() { - expect( 5 ); - stop(); - jQuery.getJSON( - /* jQuery.getJSON arguments start */ - url("data/json.php"), - { - "json": "array" - }, - function( json ) { - ok( json.length >= 2, "Check length" ); - equal( json[ 0 ]["name"], "John", "Check JSON: first, name" ); - equal( json[ 0 ]["age"], 21, "Check JSON: first, age" ); - equal( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); - equal( json[ 1 ]["age"], 25, "Check JSON: second, age" ); - start(); - } - /* jQuery.getJSON arguments end */ - ); - }); - - test( "jQuery.getJSON(String, Function) - JSON object", function() { - expect( 2 ); - stop(); - jQuery.getJSON( url("data/json.php"), function( json ) { - if ( json && json["data"] ) { - equal( json["data"]["lang"], "en", "Check JSON: lang" ); - equal( json["data"].length, 25, "Check JSON: length" ); - } - start(); - }); - }); - - asyncTest( "jQuery.getJSON - Using Native JSON", function() { - expect( 2 ); - - var restore = "JSON" in window, - old = window.JSON; - - jQuery.globalEval("var JSON;"); - window.JSON = { - parse: function( str ) { - ok( true, "Verifying that parse method was run" ); - window.JSON = old; - if ( !restore ) { - jQuery.globalEval("delete JSON;"); - } - return true; - } - }; - - jQuery.getJSON( url("data/json.php"), function( json ) { - strictEqual( json, true, "Verifying return value" ); - start(); - }); - }); - - test( "jQuery.getJSON(String, Function) - JSON object with absolute url to local content", function() { - expect( 2 ); - - var base = window.location.href.replace( /[^\/]*$/, "" ); - - stop(); - jQuery.getJSON( url( base + "data/json.php" ), function( json ) { - equal( json.data.lang, "en", "Check JSON: lang" ); - equal( json.data.length, 25, "Check JSON: length" ); - start(); - }); - }); - - test( "jQuery.post - data", 3, function() { - stop(); - - jQuery.when( - /* jQuery.when arguments start */ - jQuery.post( - /* jQuery.post arguments start */ - url("data/name.php"), - { - xml: "5-2", - length: 3 - }, - function( xml ) { - jQuery( "math", xml ).each(function() { - equal( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); - equal( jQuery( "result", this ).text(), "3", "Check for XML" ); + jsonpCallback: "functionToCleanUp", + success: function( data ) { + ok( data["data"], "JSON results returned (GET, custom callback name to be cleaned up)" ); + strictEqual( window["functionToCleanUp"], undefined, "Callback was removed (GET, custom callback name to be cleaned up)" ); + var xhr; + jQuery.ajax({ + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + jsonpCallback: "functionToCleanUp", + beforeSend: function( jqXHR ) { + xhr = jqXHR; + return false; + } + }); + xhr.fail(function() { + ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" ); + strictEqual( window["functionToCleanUp"], undefined, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" ); }); } - /* jQuery.post arguments end */ - ), - jQuery.ajax({ - url: url("data/echoData.php"), - type: "POST", - data: { - "test": { - "length": 7, - "foo": "bar" - } + }, { + url: "data/jsonp.php?callback=XXX", + dataType: "jsonp", + jsonp: false, + jsonpCallback: "XXX", + crossDomain: crossDomain, + beforeSend: function() { + ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ), "The URL wasn't messed with (GET, custom callback name with no url manipulation)" ); }, success: function( data ) { - strictEqual( data, "test%5Blength%5D=7&test%5Bfoo%5D=bar", "Check if a sub-object with a length param is serialized correctly" ); + ok( data["data"], "JSON results returned (GET, custom callback name with no url manipulation)" ); } - }) - /* jQuery.when arguments end */ - ).always(function() { - start(); + }] }); - }); - - test( "jQuery.post(String, Hash, Function) - simple with xml", function() { - expect( 4 ); - stop(); - var done = 0; - - jQuery.post( - /* jQuery.post arguments start */ - url("data/name.php"), + ajaxTest( "jQuery.ajax() - JSONP - Callback in data" + label, 2, [ { - "xml": "5-2" + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + data: "callback=?", + success: function( data ) { + ok( data.data, "JSON results returned (GET, data callback)" ); + } }, - function( xml ) { - jQuery( "math", xml ).each(function() { - equal( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); - equal( jQuery( "result", this ).text(), "3", "Check for XML" ); - }); - if ( ++done === 2 ) { - start(); + { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + data: "callback=??", + success: function( data ) { + ok( data.data, "JSON results returned (GET, data context-free callback)" ); } } - /* jQuery.post arguments end */ - ); - - jQuery.post( url("data/name.php?xml=5-2"), {}, function( xml ) { - jQuery( "math", xml ).each(function() { - equal( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); - equal( jQuery( "result", this ).text(), "3", "Check for XML" ); - }); - if ( ++done === 2 ) { - start(); - } - }); - }); + ]); - test( "jQuery.ajaxSetup({timeout: Number}) - with global timeout", function() { - var passed = 0; - expect( 2 ); - - stop(); - - jQuery.ajaxSetup({ - timeout: 1000 - }); - - var pass = function() { - ok( passed++ < 2, "Error callback executed" ); - if ( passed == 2 ) { - jQuery("#qunit-fixture").unbind("ajaxError"); - start(); + ajaxTest( "jQuery.ajax() - JSONP - POST" + label, 3, [ + { + type: "POST", + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data["data"], "JSON results returned (POST, no callback)" ); + } + }, + { + type: "POST", + url: "data/jsonp.php", + data: "callback=?", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data["data"], "JSON results returned (POST, data callback)" ); + } + }, + { + type: "POST", + url: "data/jsonp.php", + jsonp: "callback", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data["data"], "JSON results returned (POST, data obj callback)" ); + } } - }; + ]); - var fail = function( a, b, c ) { - ok( false, "Check for timeout failed " + a + " " + b ); - start(); - }; + ajaxTest( "jQuery.ajax() - JSONP" + label, 3, [ + { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + success: function( data ) { + ok( data.data, "JSON results returned (GET, no callback)" ); + } + }, + { + create: function( options ) { + var request = jQuery.ajax( options ), + promise = request.then(function( data ) { + ok( data.data, "first request: JSON results returned (GET, no callback)" ); + request = jQuery.ajax( this ).done(function( data ) { + ok( data.data, "this re-used: JSON results returned (GET, no callback)" ); + }); + promise.abort = request.abort; + return request; + }); + promise.abort = request.abort; + return promise; + }, + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + success: true + } + ]); - jQuery("#qunit-fixture").ajaxError( pass ); + }); - jQuery.ajax({ - type: "GET", - url: url("data/name.php?wait=5"), - error: pass, - success: fail - }); + ajaxTest( "jQuery.ajax() - script, Remote", 2, { + url: window.location.href.replace( /[^\/]*$/, "" ) + "data/test.js", + dataType: "script", + success: function( data ) { + ok( window[ "foobar" ], "Script results returned (GET, no callback)" ); + } + }); - // reset timeout - jQuery.ajaxSetup({ - timeout: 0 - }); + ajaxTest( "jQuery.ajax() - script, Remote with POST", 3, { + url: window.location.href.replace( /[^\/]*$/, "" ) + "data/test.js", + type: "POST", + dataType: "script", + success: function( data, status ) { + ok( window[ "foobar" ], "Script results returned (POST, no callback)" ); + strictEqual( status, "success", "Script results returned (POST, no callback)" ); + } }); - test( "jQuery.ajaxSetup({timeout: Number}) with localtimeout", function() { - expect( 1 ); - stop(); + ajaxTest( "jQuery.ajax() - script, Remote with scheme-less URL", 2, { + url: window.location.href.replace( /[^\/]*$/, "" ).replace( /^.*?\/\//, "//" ) + "data/test.js", + dataType: "script", + success: function( data ) { + ok( window[ "foobar" ], "Script results returned (GET, no callback)" ); + } + }); - jQuery.ajaxSetup({ - timeout: 50 - }); + ajaxTest( "jQuery.ajax() - malformed JSON", 2, { + url: "data/badjson.js", + dataType: "json", + error: function( xhr, msg, detailedMsg ) { + strictEqual( msg, "parsererror", "A parse error occurred." ); + ok( /(invalid|error|exception)/i.test( detailedMsg ), "Detailed parsererror message provided" ); + } + }); - jQuery.ajax({ - type: "GET", - timeout: 15000, - url: url("data/name.php?wait=1"), - error: function() { - ok( false, "Check for local timeout failed" ); - start(); + ajaxTest( "jQuery.ajax() - script by content-type", 2, [ + { + url: "data/script.php", + data: { + "header": "script" }, - success: function() { - ok( true, "Check for local timeout" ); - start(); - } - }); - - // reset timeout - jQuery.ajaxSetup({ - timeout: 0 - }); - }); + success: true + }, + { + url: "data/script.php", + data: { + "header": "ecma" + }, + success: true + } + ]); - test( "jQuery.ajax - simple get", function() { - expect( 1 ); - stop(); - jQuery.ajax({ - type: "GET", - url: url("data/name.php?name=foo"), - success: function( msg ) { - equal( msg, "bar", "Check for GET" ); - start(); - } - }); + ajaxTest( "jQuery.ajax() - JSON by content-type", 5, { + url: "data/json.php", + data: { + "header": "json", + "json": "array" + }, + success: function( json ) { + ok( json.length >= 2, "Check length" ); + strictEqual( json[ 0 ]["name"], "John", "Check JSON: first, name" ); + strictEqual( json[ 0 ]["age"], 21, "Check JSON: first, age" ); + strictEqual( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); + strictEqual( json[ 1 ]["age"], 25, "Check JSON: second, age" ); + } }); - test( "jQuery.ajax - simple post", function() { - expect( 1 ); - stop(); - jQuery.ajax({ - type: "POST", - url: url("data/name.php"), - data: "name=peter", - success: function( msg ) { - equal( msg, "pan", "Check for POST" ); - start(); - } - }); + ajaxTest( "jQuery.ajax() - JSON by content-type disabled with options", 6, { + url: url("data/json.php"), + data: { + "header": "json", + "json": "array" + }, + contents: { + "json": false + }, + success: function( text ) { + strictEqual( typeof text, "string", "json wasn't auto-determined" ); + var json = jQuery.parseJSON( text ); + ok( json.length >= 2, "Check length"); + strictEqual( json[ 0 ]["name"], "John", "Check JSON: first, name" ); + strictEqual( json[ 0 ]["age"], 21, "Check JSON: first, age" ); + strictEqual( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); + strictEqual( json[ 1 ]["age"], 25, "Check JSON: second, age" ); + } }); - test( "ajaxSetup()", function() { - expect( 1 ); - stop(); - jQuery.ajaxSetup({ - url: url("data/name.php?name=foo"), - success: function( msg ) { - equal( msg, "bar", "Check for GET" ); - start(); - } - }); - jQuery.ajax(); + ajaxTest( "jQuery.ajax() - simple get", 1, { + type: "GET", + url: url("data/name.php?name=foo"), + success: function( msg ) { + strictEqual( msg, "bar", "Check for GET" ); + } }); - test( "data option: evaluate function values (#2806)", function() { - expect( 1 ); - stop(); - jQuery.ajax({ - url: "data/echoQuery.php", - data: { - key: function() { - return "value"; - } - }, - success: function( result ) { - equal( result, "key=value" ); - start(); - } - }); + ajaxTest( "jQuery.ajax() - simple post", 1, { + type: "POST", + url: url("data/name.php"), + data: "name=peter", + success: function( msg ) { + strictEqual( msg, "pan", "Check for POST" ); + } }); - test( "data option: empty bodies for non-GET requests", function() { - expect( 1 ); - stop(); - jQuery.ajax({ - url: "data/echoData.php", - data: undefined, - type: "post", - success: function( result ) { - equal( result, "" ); - start(); - } - }); + ajaxTest( "jQuery.ajax() - data option - empty bodies for non-GET requests", 1, { + url: "data/echoData.php", + data: undefined, + type: "post", + success: function( result ) { + strictEqual( result, "" ); + } }); var ifModifiedNow = new Date(); @@ -2363,12 +1041,9 @@ " (no cache)": false }, function( label, cache ) { + var isOpera = !!window.opera; - test( "jQuery.ajax - If-Modified-Since support" + label, function() { - expect( 3 ); - - stop(); - + asyncTest( "jQuery.ajax() - If-Modified-Since support" + label, 3, function() { var url = "data/if_modified_since.php?ts=" + ifModifiedNow++; jQuery.ajax({ @@ -2376,7 +1051,7 @@ ifModified: true, cache: cache, success: function( data, status ) { - equal( status, "success" ); + strictEqual( status, "success" ); jQuery.ajax({ url: url, @@ -2387,7 +1062,7 @@ ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')." ); ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')." ); } else { - equal( status, "notmodified" ); + strictEqual( status, "notmodified" ); ok( data == null, "response body should be empty" ); } start(); @@ -2403,7 +1078,7 @@ }); }, error: function() { - equal( false, "error" ); + strictEqual( false, "error" ); // Do this because opera simply refuses to implement 304 handling :( // A feature-driven way of detecting this would be appreciated // See: http://gist.github.com/599419 @@ -2413,11 +1088,7 @@ }); }); - test( "jQuery.ajax - Etag support" + label, function() { - expect( 3 ); - - stop(); - + asyncTest( "jQuery.ajax() - Etag support" + label, 3, function() { var url = "data/etag.php?ts=" + ifModifiedNow++; jQuery.ajax({ @@ -2425,7 +1096,7 @@ ifModified: true, cache: cache, success: function( data, status ) { - equal( status, "success" ); + strictEqual( status, "success" ); jQuery.ajax({ url: url, @@ -2436,7 +1107,7 @@ ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-None-Match')." ); ok( isOpera, "Opera is incapable of doing .setRequestHeader('If-None-Match')." ); } else { - equal( status, "notmodified" ); + strictEqual( status, "notmodified" ); ok( data == null, "response body should be empty" ); } start(); @@ -2452,116 +1123,41 @@ }); }, error: function() { - // Do this because opera simply refuses to implement 304 handling :( - // A feature-driven way of detecting this would be appreciated - // See: http://gist.github.com/599419 - ok( isOpera, "error" ); - start(); - } - }); - }); - } - /* jQuery.each arguments end */ - ); - - asyncTest( "jQuery ajax - failing cross-domain (non-existing)", function() { - expect( 1 ); - - var i = 1; - - jQuery.ajax({ - // see RFC 2606 - url: "http://example.invalid", - success: function() { - ok( false, "success" ); - }, - error: function( xhr, _, e ) { - ok( true, "file not found: " + xhr.status + " => " + e ); - }, - complete: function() { - if ( !--i ) { - start(); - } - } - }); - }); - - asyncTest( "jQuery ajax - failing cross-domain", function() { - expect( 1 ); - - var i = 1; - - jQuery.ajax({ - url: "http://" + externalHost, - success: function() { - ok( false, "success" ); - }, - error: function( xhr, _, e ) { - ok( true, "access denied: " + xhr.status + " => " + e ); - }, - complete: function() { - if ( !--i ) { - start(); - } - } - }); - }); - - test( "jQuery ajax - atom+xml", function() { - expect( 1 ); - stop(); - - jQuery.ajax({ - url: url("data/atom+xml.php"), - success: function() { - ok( true, "success" ); - }, - error: function() { - ok( false, "error" ); - }, - complete: function() { - start(); - } - }); - - }); - - test( "jQuery.ajax - Location object as url (#7531)", 1, function () { - var success = false; - try { - var xhr = jQuery.ajax({ - url: window.location + // Do this because opera simply refuses to implement 304 handling :( + // A feature-driven way of detecting this would be appreciated + // See: http://gist.github.com/599419 + ok( isOpera, "error" ); + start(); + } + }); }); - success = true; - xhr.abort(); - } catch (e) { + } + /* jQuery.each arguments end */ + ); + ajaxTest( "jQuery.ajax() - failing cross-domain (non-existing)", 1, { + // see RFC 2606 + url: "http://example.invalid", + error: function( xhr, _, e ) { + ok( true, "file not found: " + xhr.status + " => " + e ); } + }); - ok( success, "document.location did not generate exception" ); + ajaxTest( "jQuery.ajax() - failing cross-domain", 1, { + url: "http://" + externalHost, + error: function( xhr, _, e ) { + ok( true, "access denied: " + xhr.status + " => " + e ); + } }); - test( "jQuery.ajax - Context with circular references (#9887)", 2, function () { - var success = false, - context = {}; - context.field = context; - try { - jQuery.ajax( "non-existing", { - context: context, - beforeSend: function() { - ok( this === context, "context was not deep extended" ); - return false; - } - }); - success = true; - } catch ( e ) { - console.log( e ); + ajaxTest( "jQuery.ajax() - atom+xml", 1, { + url: url("data/atom+xml.php"), + success: function() { + ok( true, "success" ); } - ok( success, "context with circular reference did not generate an exception" ); }); - test( "jQuery.ajax - statusText", 3, function() { - stop(); + asyncTest( "jQuery.ajax() - statusText", 3, function() { jQuery.ajax( url("data/statusText.php?status=200&text=Hello") ).done(function( _, statusText, jqXHR ) { strictEqual( statusText, "success", "callback status text ok for success" ); ok( jqXHR.statusText === "Hello" || jqXHR.statusText === "OK", "jqXHR status text ok for success (" + jqXHR.statusText + ")" ); @@ -2573,13 +1169,10 @@ }); }); - test( "jQuery.ajax - statusCode", function() { + asyncTest( "jQuery.ajax() - statusCode", 20, function() { var count = 12; - expect( 20 ); - stop(); - function countComplete() { if ( ! --count ) { start(); @@ -2593,7 +1186,7 @@ ok( isSuccess, name ); }, 404: function() { - ok( ! isSuccess, name ); + ok( !isSuccess, name ); } }; } @@ -2678,194 +1271,709 @@ ); }); - test( "jQuery.ajax - transitive conversions", function() { + ajaxTest( "jQuery.ajax() - transitive conversions", 8, [ + { + url: url("data/json.php"), + converters: { + "json myJson": function( data ) { + ok( true, "converter called" ); + return data; + } + }, + dataType: "myJson", + success: function() { + ok( true, "Transitive conversion worked" ); + strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text" ); + strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType" ); + } + }, + { + url: url("data/json.php"), + converters: { + "json myJson": function( data ) { + ok( true, "converter called (*)" ); + return data; + } + }, + contents: false, /* headers are wrong so we ignore them */ + dataType: "* myJson", + success: function() { + ok( true, "Transitive conversion worked (*)" ); + strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text (*)" ); + strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType (*)" ); + } + } + ]); + + ajaxTest( "jQuery.ajax() - overrideMimeType", 2, [ + { + url: url("data/json.php"), + beforeSend: function( xhr ) { + xhr.overrideMimeType( "application/json" ); + }, + success: function( json ) { + ok( json.data, "Mimetype overriden using beforeSend" ); + } + }, + { + url: url("data/json.php"), + mimeType: "application/json", + success: function( json ) { + ok( json.data, "Mimetype overriden using mimeType option" ); + } + } + ]); + + ajaxTest( "jQuery.ajax() - empty json gets to error callback instead of success callback.", 1, { + url: url("data/echoData.php"), + error: function( _, __, error ) { + equal( typeof error === "object", true, "Didn't get back error object for empty json response" ); + }, + dataType: "json" + }); + + ajaxTest( "#2688 - jQuery.ajax() - beforeSend, cancel request", 2, { + create: function() { + return jQuery.ajax({ + url: url("data/name.html"), + beforeSend: function() { + ok( true, "beforeSend got called, canceling" ); + return false; + }, + success: function() { + ok( false, "request didn't get canceled" ); + }, + complete: function() { + ok( false, "request didn't get canceled" ); + }, + error: function() { + ok( false, "request didn't get canceled" ); + } + }); + }, + fail: function( _, reason ) { + strictEqual( reason, "canceled", "canceled request must fail with 'canceled' status text" ); + } + }); + + ajaxTest( "#2806 - jQuery.ajax() - data option - evaluate function values", 1, { + url: "data/echoQuery.php", + data: { + key: function() { + return "value"; + } + }, + success: function( result ) { + strictEqual( result, "key=value" ); + } + }); + + test( "#7531 - jQuery.ajax() - Location object as url", 1, function () { + var success = false; + try { + var xhr = jQuery.ajax({ + url: window.location + }); + success = true; + xhr.abort(); + } catch (e) { + + } + ok( success, "document.location did not generate exception" ); + }); + + jQuery.each( [ " - Same Domain", " - Cross Domain" ], function( crossDomain, label ) { + ajaxTest( "#7578 - jQuery.ajax() - JSONP - default for cache option" + label, 1, { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + beforeSend: function( jqXHR, s ) { + strictEqual( this.cache, false, "cache must be false on JSON request" ); + return false; + }, + error: true + }); + }); + + ajaxTest( "#8107 - jQuery.ajax() - multiple method signatures introduced in 1.5", 4, [ + { + create: function() { + return jQuery.ajax(); + }, + done: function() { + ok( true, "With no arguments" ); + } + }, + { + create: function() { + return jQuery.ajax("data/name.html"); + }, + done: function() { + ok( true, "With only string URL argument" ); + } + }, + { + create: function() { + return jQuery.ajax( "data/name.html", {}); + }, + done: function() { + ok( true, "With string URL param and map" ); + } + }, + { + create: function( options ) { + return jQuery.ajax( options ); + }, + url: "data/name.html", + success: function() { + ok( true, "With only map" ); + } + } + ]); + + jQuery.each( [ " - Same Domain", " - Cross Domain" ], function( crossDomain, label ) { + ajaxTest( "#8205 - jQuery.ajax() - JSONP - re-use callbacks name" + label, 2, { + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + beforeSend: function( jqXHR, s ) { + s.callback = s.jsonpCallback; + }, + success: function() { + var previous = this; + strictEqual( previous.jsonpCallback, undefined, "jsonpCallback option is set back to default in callbacks" ); + jQuery.ajax({ + url: "data/jsonp.php", + dataType: "jsonp", + crossDomain: crossDomain, + beforeSend: function() { + strictEqual( this.jsonpCallback, previous.callback, "JSONP callback name is re-used" ); + return false; + } + }); + } + }); + }); + + test( "#9887 - jQuery.ajax() - Context with circular references (#9887)", 2, function () { + var success = false, + context = {}; + context.field = context; + try { + jQuery.ajax( "non-existing", { + context: context, + beforeSend: function() { + ok( this === context, "context was not deep extended" ); + return false; + } + }); + success = true; + } catch ( e ) { + console.log( e ); + } + ok( success, "context with circular reference did not generate an exception" ); + }); + + jQuery.each( [ "as argument", "in settings object" ], function( inSetting, title ) { + + function request( url, test ) { + return { + create: function() { + return jQuery.ajax( inSetting ? { url: url } : url ); + }, + done: function() { + ok( true, ( test || url ) + " " + title ); + } + }; + } + + ajaxTest( "#10093 - jQuery.ajax() - falsy url " + title, 4, [ + request( "", "empty string" ), + request( false ), + request( null ), + request( undefined ) + ]); + + }); + + ajaxTest( "#11426 - jQuery.ajax() - loading binary data shouldn't throw an exception in IE", 1, { + url: url("data/1x1.jpg"), + success: function( data ) { + ok( data === undefined || /JFIF/.test( data ), "success callback reached" ); + } + }); + + test( "#11743 - jQuery.ajax() - script, throws exception", 1, function() { + raises(function() { + jQuery.ajax({ + url: "data/badjson.js", + dataType: "script", + throws: true, + // TODO find a way to test this asynchronously, too + async: false, + // Global events get confused by the exception + global: false, + success: function() { + ok( false, "Success." ); + }, + error: function() { + ok( false, "Error." ); + } + }); + }, "exception bubbled" ); + }); + +//----------- jQuery.ajaxPrefilter() + + ajaxTest( "jQuery.ajaxPrefilter() - abort", 1, { + setup: function() { + jQuery.ajaxPrefilter(function( options, _, jqXHR ) { + if ( options.abortInPrefilter ) { + jqXHR.abort(); + } + }); + }, + abortInPrefilter: true, + error: function() { + ok( false, "error callback called" ); + }, + fail: function( _, reason ) { + strictEqual( reason, "canceled", "Request aborted by the prefilter must fail with 'canceled' status text" ); + } + }); + +//----------- jQuery.ajaxSetup() + + asyncTest( "jQuery.ajaxSetup()", 1, function() { + jQuery.ajaxSetup({ + url: url("data/name.php?name=foo"), + success: function( msg ) { + strictEqual( msg, "bar", "Check for GET" ); + start(); + } + }); + jQuery.ajax(); + }); + + asyncTest( "jQuery.ajaxSetup({ timeout: Number }) - with global timeout", 2, function() { + var passed = 0, + pass = function() { + ok( passed++ < 2, "Error callback executed" ); + if ( passed == 2 ) { + jQuery("#qunit-fixture").unbind("ajaxError"); + start(); + } + }, + fail = function( a, b, c ) { + ok( false, "Check for timeout failed " + a + " " + b ); + start(); + }; + + jQuery("#qunit-fixture").ajaxError( pass ); + + jQuery.ajaxSetup({ + timeout: 1000 + }); + + jQuery.ajax({ + type: "GET", + url: url("data/name.php?wait=5"), + error: pass, + success: fail + }); + }); + + asyncTest( "jQuery.ajaxSetup({ timeout: Number }) with localtimeout", 1, function() { + jQuery.ajaxSetup({ + timeout: 50 + }); + jQuery.ajax({ + type: "GET", + timeout: 15000, + url: url("data/name.php?wait=1"), + error: function() { + ok( false, "Check for local timeout failed" ); + start(); + }, + success: function() { + ok( true, "Check for local timeout" ); + start(); + } + }); + }); + +//----------- jQuery.domManip() + + test( "#11264 - jQuery.domManip() - no side effect because of ajaxSetup or global events", 1, function() { + jQuery.ajaxSetup({ + type: "POST" + }); + + jQuery( document ).bind( "ajaxStart ajaxStop", function() { + ok( false, "Global event triggered" ); + }); + + jQuery("#qunit-fixture").append(""); - expect( 8 ); + jQuery( document ).unbind("ajaxStart ajaxStop"); + }); - stop(); + asyncTest( "#11402 - jQuery.domManip() - script in comments are properly evaluated", 2, function() { + jQuery("#qunit-fixture").load( "data/cleanScript.html", start ); + }); - jQuery.when( - /* jQuery.when arguments start */ - jQuery.ajax( url("data/json.php"), { - converters: { - "json myJson": function( data ) { - ok( true, "converter called" ); - return data; - } - }, - dataType: "myJson", - success: function() { - ok( true, "Transitive conversion worked" ); - strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text" ); - strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType" ); - } - }), +//----------- jQuery.get() - jQuery.ajax( url("data/json.php"), { - converters: { - "json myJson": function( data ) { - ok( true, "converter called (*)" ); - return data; - } - }, - contents: false, /* headers are wrong so we ignore them */ - dataType: "* myJson", - success: function() { - ok( true, "Transitive conversion worked (*)" ); - strictEqual( this.dataTypes[ 0 ], "text", "response was retrieved as text (*)" ); - strictEqual( this.dataTypes[ 1 ], "myjson", "request expected myjson dataType (*)" ); - } - }) - /* jQuery.when arguments end */ - ).always(function() { + asyncTest( "jQuery.get( String, Hash, Function ) - parse xml and use text() on nodes", 2, function() { + jQuery.get( url("data/dashboard.xml"), function( xml ) { + var content = []; + jQuery( "tab", xml ).each(function() { + content.push( jQuery( this ).text() ); + }); + strictEqual( content[ 0 ], "blabla", "Check first tab" ); + strictEqual( content[ 1 ], "blublu", "Check second tab" ); start(); }); + }); + asyncTest( "#8277 - jQuery.get( String, Function ) - data in ajaxSettings", 1, function() { + jQuery.ajaxSetup({ + data: "helloworld" + }); + jQuery.get( url("data/echoQuery.php"), function( data ) { + ok( /helloworld$/.test( data ), "Data from ajaxSettings was used" ); + start(); + }); }); - test( "jQuery.ajax - overrideMimeType", function() { +//----------- jQuery.getJSON() - expect( 2 ); + asyncTest( "jQuery.getJSON( String, Hash, Function ) - JSON array", 5, function() { + jQuery.getJSON( + url("data/json.php"), + { + "json": "array" + }, + function( json ) { + ok( json.length >= 2, "Check length" ); + strictEqual( json[ 0 ]["name"], "John", "Check JSON: first, name" ); + strictEqual( json[ 0 ]["age"], 21, "Check JSON: first, age" ); + strictEqual( json[ 1 ]["name"], "Peter", "Check JSON: second, name" ); + strictEqual( json[ 1 ]["age"], 25, "Check JSON: second, age" ); + start(); + } + ); + }); - stop(); + asyncTest( "jQuery.getJSON( String, Function ) - JSON object", 2, function() { + jQuery.getJSON( url("data/json.php"), function( json ) { + if ( json && json["data"] ) { + strictEqual( json["data"]["lang"], "en", "Check JSON: lang" ); + strictEqual( json["data"].length, 25, "Check JSON: length" ); + start(); + } + }); + }); - jQuery.when( - /* jQuery.when arguments start */ - jQuery.ajax( url("data/json.php"), { - beforeSend: function( xhr ) { - xhr.overrideMimeType( "application/json" ); - }, - success: function( json ) { - ok( json.data, "Mimetype overriden using beforeSend" ); - } - }), - jQuery.ajax( url("data/json.php"), { - mimeType: "application/json", - success: function( json ) { - ok( json.data, "Mimetype overriden using mimeType option" ); - } - }) - /* jQuery.when arguments end */ - ).always(function() { + asyncTest( "jQuery.getJSON() - Using Native JSON", 2, function() { + var restore = "JSON" in window, + old = window.JSON; + if ( !restore ) { + Globals.register("JSON"); + } + window.JSON = { + parse: function( str ) { + ok( true, "Verifying that parse method was run" ); + window.JSON = old; + return true; + } + }; + jQuery.getJSON( url("data/json.php"), function( json ) { + strictEqual( json, true, "Verifying return value" ); start(); }); + }); + asyncTest( "jQuery.getJSON( String, Function ) - JSON object with absolute url to local content", 2, function() { + jQuery.getJSON( url( window.location.href.replace( /[^\/]*$/, "" ) + "data/json.php" ), function( json ) { + strictEqual( json.data.lang, "en", "Check JSON: lang" ); + strictEqual( json.data.length, 25, "Check JSON: length" ); + start(); + }); }); - test( "jQuery.ajax - abort in prefilter", function() { +//----------- jQuery.getScript() - expect( 1 ); + asyncTest( "jQuery.getScript( String, Function ) - with callback", 2, function() { + jQuery.getScript( url("data/test.js"), function( data, _, jqXHR ) { + strictEqual( foobar, "bar", "Check if script was evaluated" ); + start(); + }); + }); - jQuery.ajaxPrefilter(function( options, _, jqXHR ) { - if ( options.abortInPrefilter ) { - jqXHR.abort(); - } + asyncTest( "jQuery.getScript( String, Function ) - no callback", 1, function() { + jQuery.getScript( url("data/test.js") ).done( start ); + }); + + asyncTest( "#8082 - jQuery.getScript( String, Function ) - source as responseText", 2, function() { + jQuery.getScript( url("data/test.js"), function( data, _, jqXHR ) { + strictEqual( data, jqXHR.responseText, "Same-domain script requests returns the source of the script" ); + start(); }); + }); - jQuery.ajax({ - abortInPrefilter: true, - error: function() { - ok( false, "error callback called" ); +//----------- jQuery.fn.load() + + // check if load can be called with only url + asyncTest( "jQuery.fn.load( String )", 2, function() { + jQuery.ajaxSetup({ + beforeSend: function() { + strictEqual( this.type, "GET", "no data means GET request" ); } - }).fail(function( _, reason ) { - strictEqual( reason, "canceled", "Request aborted by the prefilter must fail with 'canceled' status text" ); }); + jQuery("#first").load( "data/name.html", start ); + }); + asyncTest( "jQuery.fn.load() - 404 error callbacks", 6, function() { + jQuery("#foo").ajaxStart(function() { + ok( true, "ajaxStart" ); + }).ajaxStop(function() { + ok( true, "ajaxStop" ); + start(); + }).ajaxSend(function() { + ok( true, "ajaxSend" ); + }).ajaxComplete(function() { + ok( true, "ajaxComplete" ); + }).ajaxError(function() { + ok( true, "ajaxError" ); + }).ajaxSuccess(function() { + ok( false, "ajaxSuccess" ); + }); + jQuery("
").load( "data/404.html", function() { + ok( true, "complete" ); + }); }); - test( "jQuery.ajax - loading binary data shouldn't throw an exception in IE (#11426)", 1, function() { - stop(); - jQuery.ajax( url("data/1x1.jpg"), { - success: function( data ) { - ok( data === undefined || /JFIF/.test( data ), "success callback reached" ); - start(); - }, - error: function( _, __, error ) { - ok( false, "exception thrown: '" + error + "'" ); - start(); + // check if load can be called with url and null data + asyncTest( "jQuery.fn.load( String, null )", 2, function() { + jQuery.ajaxSetup({ + beforeSend: function() { + strictEqual( this.type, "GET", "no data means GET request" ); } }); + jQuery("#first").load( "data/name.html", null, start ); }); - test( "jQuery.domManip - no side effect because of ajaxSetup or global events (#11264)", function() { - expect( 1 ); - + // check if load can be called with url and undefined data + asyncTest( "jQuery.fn.load( String, undefined )", 2, function() { jQuery.ajaxSetup({ - type: "POST" + beforeSend: function() { + strictEqual( this.type, "GET", "no data means GET request" ); + } }); + jQuery("#first").load( "data/name.html", undefined, start ); + }); - jQuery( document ).bind( "ajaxStart ajaxStop", function() { - ok( false, "Global event triggered" ); + // check if load can be called with only url + asyncTest( "jQuery.fn.load( URL_SELECTOR )", 1, function() { + jQuery("#first").load( "data/test3.html div.user", function() { + strictEqual( jQuery( this ).children("div").length, 2, "Verify that specific elements were injected" ); + start(); }); + }); - jQuery("#qunit-fixture").append(""); + asyncTest( "jQuery.fn.load( String, Function ) - simple: inject text into DOM", 2, function() { + jQuery("#first").load( url("data/name.html"), function() { + ok( /^ERROR/.test(jQuery("#first").text()), "Check if content was injected into the DOM" ); + start(); + }); + }); - jQuery( document ).unbind("ajaxStart ajaxStop"); + asyncTest( "jQuery.fn.load( String, Function ) - check scripts", 7, function() { + var verifyEvaluation = function() { + strictEqual( window["foobar"], "bar", "Check if script src was evaluated after load" ); + strictEqual( jQuery("#ap").html(), "bar", "Check if script evaluation has modified DOM"); + start(); + }; + jQuery("#first").load( url("data/test.html"), function() { + ok( jQuery("#first").html().match( /^html text/ ), "Check content after loading html" ); + strictEqual( jQuery("#foo").html(), "foo", "Check if script evaluation has modified DOM" ); + strictEqual( window["testFoo"], "foo", "Check if script was evaluated after load" ); + setTimeout( verifyEvaluation, 600 ); + }); + }); + + asyncTest( "jQuery.fn.load( String, Function ) - check file with only a script tag", 3, function() { + jQuery("#first").load( url("data/test2.html"), function() { + strictEqual( jQuery("#foo").html(), "foo", "Check if script evaluation has modified DOM"); + strictEqual( window["testFoo"], "foo", "Check if script was evaluated after load" ); + start(); + }); + }); + asyncTest( "jQuery.fn.load( String, Function ) - dataFilter in ajaxSettings", 2, function() { jQuery.ajaxSetup({ - type: "GET" + dataFilter: function() { + return "Hello World"; + } + }); + jQuery("
").load( url("data/name.html"), function( responseText ) { + strictEqual( jQuery( this ).html(), "Hello World", "Test div was filled with filtered data" ); + strictEqual( responseText, "Hello World", "Test callback receives filtered data" ); + start(); }); }); - test( "jQuery.domManip - script in comments are properly evaluated (#11402)", function() { - expect( 2 ); - stop(); - jQuery("#qunit-fixture").load( "data/cleanScript.html", function() { + asyncTest( "jQuery.fn.load( String, Object, Function )", 2, function() { + jQuery("
").load( url("data/params_html.php"), { + "foo": 3, + "bar": "ok" + }, function() { + var $post = jQuery( this ).find("#post"); + strictEqual( $post.find("#foo").text(), "3", "Check if a hash of data is passed correctly" ); + strictEqual( $post.find("#bar").text(), "ok", "Check if a hash of data is passed correctly" ); start(); }); }); - test( "jQuery.ajax - active counter", function() { - expect( 1 ); - ok( jQuery.active === 0, "ajax active counter should be zero: " + jQuery.active ); + asyncTest( "jQuery.fn.load( String, String, Function )", 2, function() { + jQuery("
").load( url("data/params_html.php"), "foo=3&bar=ok", function() { + var $get = jQuery( this ).find("#get"); + strictEqual( $get.find("#foo").text(), "3", "Check if a string of data is passed correctly" ); + strictEqual( $get.find("#bar").text(), "ok", "Check if a of data is passed correctly" ); + start(); + }); }); - test("jQuery.ajax - falsy url as argument (#10093)", function() { - expect( 4 ); + asyncTest( "jQuery.fn.load() - callbacks get the correct parameters", 8, function() { + var slice = [].slice, + completeArgs = {}; - jQuery.ajaxSetup({ timeout: 0 }); + jQuery.ajaxSetup({ + success: function( _, status, jqXHR ) { + completeArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ]; + }, + error: function( jqXHR, status ) { + completeArgs[ this.url ] = [ jqXHR.responseText, status, jqXHR ]; + } + }); - stop(); + jQuery.when.apply( + jQuery, + jQuery.map([ + { + type: "success", + url: "data/echoQuery.php?arg=pop" + }, + { + type: "error", + url: "data/404.php" + } + ], + function( options ) { + return jQuery.Deferred(function( defer ) { + jQuery("#foo").load( options.url, function() { + var args = arguments; + strictEqual( completeArgs[ options.url ].length, args.length, "same number of arguments (" + options.type + ")" ); + jQuery.each( completeArgs[ options.url ], function( i, value ) { + strictEqual( args[ i ], value, "argument #" + i + " is the same (" + options.type + ")" ); + }); + defer.resolve(); + }); + }); + }) + ).always( start ); + }); - jQuery.when( - jQuery.ajax("").success(function(){ ok( true, "settings object - empty string" ); }), - jQuery.ajax( false ).success(function(){ ok( true, "false" ); }), - jQuery.ajax( null ).success(function(){ ok( true, "null" ); }), - jQuery.ajax( undefined ).success(function(){ ok( true, "undefined" ); }) - ).always(function () { + asyncTest( "#2046 - jQuery.fn.load( String, Function ) with ajaxSetup on dataType json", 1, function() { + jQuery.ajaxSetup({ + dataType: "json" + }); + jQuery("#first").ajaxComplete(function( e, xml, s ) { + strictEqual( s.dataType, "html", "Verify the load() dataType was html" ); + jQuery("#first").unbind("ajaxComplete"); start(); }); + jQuery("#first").load("data/test3.html"); }); - test("jQuery.ajax - falsy url in settings object (#10093)", function() { - expect( 4 ); - - jQuery.ajaxSetup({ timeout: 0 }); + asyncTest( "#10524 - jQuery.fn.load() - data specified in ajaxSettings is merged in", 1, function() { + var data = { + "baz": 1 + }; + jQuery.ajaxSetup({ + data: { + "foo": "bar" + } + }); + jQuery("#foo") + .load( "data/echoQuery.php", data ) + .ajaxComplete(function( event, jqXHR, options ) { + ok( ~options.data.indexOf("foo=bar"), "Data from ajaxSettings was used" ); + start(); + }); + }); - stop(); +//----------- jQuery.post() + asyncTest( "jQuery.post() - data", 3, function() { jQuery.when( - jQuery.ajax({ url: "" }).success(function(){ ok( true, "settings object - empty string" ); }), - jQuery.ajax({ url: false }).success(function(){ ok( true, "false" ); }), - jQuery.ajax({ url: null }).success(function(){ ok( true, "null" ); }), - jQuery.ajax({ url: undefined }).success(function(){ ok( true, "undefined" ); }) - ).always(function () { - start(); - }); + jQuery.post( + url("data/name.php"), + { + xml: "5-2", + length: 3 + }, + function( xml ) { + jQuery( "math", xml ).each(function() { + equal( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); + equal( jQuery( "result", this ).text(), "3", "Check for XML" ); + }); + } + ), + jQuery.ajax({ + url: url("data/echoData.php"), + type: "POST", + data: { + "test": { + "length": 7, + "foo": "bar" + } + }, + success: function( data ) { + strictEqual( data, "test%5Blength%5D=7&test%5Bfoo%5D=bar", "Check if a sub-object with a length param is serialized correctly" ); + } + }) + ).always( start ); }); - test( "jQuery.ajax - empty json gets to error callback instead of success callback.", function() { - expect( 1 ); + asyncTest( "jQuery.post( String, Hash, Function ) - simple with xml", 4, function() { + jQuery.when( + jQuery.post( + url("data/name.php"), + { + "xml": "5-2" + }, + function( xml ) { + jQuery( "math", xml ).each(function() { + strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); + strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); + }); + } + ), + jQuery.post( url("data/name.php?xml=5-2"), {}, function( xml ) { + jQuery( "math", xml ).each(function() { + strictEqual( jQuery( "calculation", this ).text(), "5-2", "Check for XML" ); + strictEqual( jQuery( "result", this ).text(), "3", "Check for XML" ); + }); + }) + ).always( start ); + }); - stop(); +//----------- jQuery.active - jQuery.ajax( url("data/echoData.php"), { - error: function( _, __, error ) { - equal( typeof error === "object", true, "Didn't get back error object for empty json response" ); - start(); - }, - dataType: "json" - }); + test( "jQuery.active", 1, function() { + ok( jQuery.active === 0, "ajax active counter should be zero: " + jQuery.active ); }); })(); -- 2.39.5