ajax.html 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  6. <link rel="stylesheet" href="test.css">
  7. <title>Zepto Ajax unit tests</title>
  8. <script src="../vendor/evidence.js"></script>
  9. <script src="evidence_runner.js"></script>
  10. <script>
  11. // avoid caching
  12. (function(){
  13. function load(scripts){
  14. scripts.split(' ').forEach(function(script){
  15. document.write('<script src="../src/'+script+'.js?'+(+new Date)+'"></scr'+'ipt>')
  16. })
  17. }
  18. load('zepto event ajax ie')
  19. })()
  20. </script>
  21. </head>
  22. <body>
  23. <h1>Zepto Ajax unit tests</h1>
  24. <p id="results">
  25. Running… see browser console for results
  26. </p>
  27. <div id="fixtures">
  28. <div id="ajax_load"></div>
  29. </div>
  30. <script>
  31. (function(){
  32. function deferredResume(t, fn) {
  33. setTimeout(function() { t.resume(fn || function(){}) }, 5)
  34. }
  35. function resumeOnAjaxError(t) {
  36. $(document).on('ajaxError', function(e, xhr){
  37. deferredResume(t, function(){
  38. t.assert(false, "request errored out: " + xhr.responseText)
  39. })
  40. })
  41. }
  42. function toArray(list) {
  43. if ($.type(list) == "string") return list.split(/(?:\s*,\s*|\s+)/)
  44. else return list
  45. }
  46. Evidence.Assertions.assertEqualList = function(expected, actual, message) {
  47. var expectedList = toArray(expected),
  48. actualList = toArray(actual)
  49. this._assertExpression(
  50. expectedList.join(' ') == actualList.join(' '),
  51. message || "Lists don't match.",
  52. 'Expected %o, got %o.', expectedList, actualList
  53. )
  54. }
  55. Evidence.Assertions.assertLine = function(line, string, message) {
  56. var lines = string.split("\n")
  57. this._assertExpression(
  58. $.inArray(line, lines) >= 0,
  59. message || "Line not found.",
  60. 'Expected line %s in %s.', line, string
  61. )
  62. }
  63. Evidence.Assertions.assertLinePattern = function(pattern, string, message) {
  64. var lines = string.split("\n")
  65. var i, match = false
  66. if (lines.length) {
  67. for (i = 0; i < lines.length; i++) {
  68. if (lines[i].search(pattern) !== -1) {
  69. match = true
  70. break
  71. }
  72. }
  73. }
  74. this._assertExpression(
  75. match === true,
  76. message || "Pattern not found.",
  77. 'Expected pattern %s in %s.', pattern, string
  78. )
  79. }
  80. var slice = [].slice
  81. function CallbackRegistry(t) {
  82. this.testCase = t
  83. this.called = []
  84. }
  85. $.extend(CallbackRegistry.prototype, {
  86. register: function(name, context, args){
  87. this.called.push([name, context, args])
  88. },
  89. handler: function(name, fn){
  90. var that = this
  91. return function(){
  92. that.register(name, this, slice.call(arguments))
  93. if (fn) return fn.apply(this, arguments)
  94. }
  95. },
  96. resumeHandler: function(name, fn){
  97. var that = this
  98. return this.handler(name, function(){
  99. var context = this, args = arguments
  100. setTimeout(function(){
  101. that.testCase.resume(function(){
  102. if (fn) fn.apply(context, args)
  103. })
  104. }, 5)
  105. })
  106. },
  107. handlers: function(){
  108. var that = this, hash = {}
  109. $.each(arguments, function(i, name){
  110. hash[name] = that.handler(name)
  111. })
  112. return hash
  113. },
  114. events: function(){
  115. return $.map(this.called, function(item){ return item[0] })
  116. },
  117. context: function(name){
  118. return this.find(name, function(item){ return item[1] })
  119. },
  120. args: function(name){
  121. return this.find(name, function(item){ return item[2] })
  122. },
  123. target: function(name){
  124. var args = this.args(name)
  125. return args && args[0].target
  126. },
  127. find: function(name, fn){
  128. var obj
  129. $.each(this.called, function(i, item){
  130. if (item[0] == name) {
  131. obj = fn(item)
  132. return false
  133. }
  134. })
  135. return obj
  136. }
  137. })
  138. Evidence('ZeptoAjaxTest', {
  139. setUp: function() {
  140. var reg = new CallbackRegistry(this),
  141. globals = toArray('ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete')
  142. $(document).on(reg.handlers.apply(reg, globals))
  143. this.reg = reg
  144. window.jsonpDummy = $.noop
  145. },
  146. tearDown: function() {
  147. $(document).off()
  148. for (var key in window)
  149. if (/^(Zepto\d+|blah)$/.test(key) && window[key] === undefined)
  150. delete window[key]
  151. },
  152. testAjaxBase: function(t){
  153. t.pause()
  154. var xhr = $.ajax({
  155. url: 'fixtures/ajax_load_simple.html',
  156. success: t.reg.handler('success'),
  157. error: t.reg.handler('error'),
  158. complete: t.reg.resumeHandler('complete', function(){
  159. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess complete ajaxComplete', t.reg.events())
  160. })
  161. })
  162. t.assert($.isFunction(xhr.getResponseHeader))
  163. },
  164. testAjaxGet: function(t){
  165. t.pause()
  166. var xhr = $.get('echo', t.reg.resumeHandler('success', function(response){
  167. t.assertIdentical(window, this)
  168. t.assertLine("GET ?{}", response)
  169. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
  170. }))
  171. t.assertIn('abort', xhr)
  172. },
  173. testAjaxGetWithParams: function(t){
  174. t.pause()
  175. $.get('echo', { sample: 'data' }, t.reg.resumeHandler('success', function(response){
  176. t.assertLine('GET ?{"sample":"data"}', response)
  177. t.assertLine("accept: */*", response)
  178. }))
  179. },
  180. testAjaxGetWithParamsAndType: function(t){
  181. t.pause()
  182. $.get('echo', { sample: 'plain' }, t.reg.resumeHandler('success', function(response){
  183. t.assertLine('GET ?{"sample":"plain"}', response)
  184. t.assertLine("accept: text/plain", response)
  185. }), 'text')
  186. },
  187. testAjaxGetWithParamsAndTypeNoCallback: function(t){
  188. t.pause()
  189. $(document).on('ajaxSuccess', function(e, xhr, settings, response){
  190. deferredResume(t, function(){
  191. t.assertLine('GET ?{"sample":"plain"}', response)
  192. t.assertLine("accept: text/plain", response)
  193. t.assertEqualList('ajaxBeforeSend ajaxSend ajaxSuccess ajaxComplete', t.reg.events())
  194. })
  195. })
  196. $.get('echo', { sample: 'plain' }, 'text')
  197. },
  198. testAjaxGetWithParamsAutoParsesJSON: function(t) {
  199. t.pause()
  200. $.get('json', { sample: 'data' }, t.reg.resumeHandler('success', function(data){
  201. t.assertEqual('data', data.query.sample)
  202. t.assertEqual('world', data.hello)
  203. }))
  204. },
  205. testAjaxGetNoParamsAutoParsesJSON: function(t) {
  206. t.pause()
  207. $.get('json', t.reg.resumeHandler('success', function(data){
  208. t.assertIdentical(0, $.map(data.query).length)
  209. t.assertEqual('world', data.hello)
  210. }))
  211. },
  212. testAjaxGetNullParamsAutoParsesJSON: function(t) {
  213. t.pause()
  214. $.get('json', null, t.reg.resumeHandler('success', function(data){
  215. t.assertIdentical(0, $.map(data.query).length)
  216. t.assertEqual('world', data.hello)
  217. }))
  218. },
  219. testAjaxBeforeSendSetRequestHeader: function(t){
  220. t.pause()
  221. $.ajax({
  222. url: 'echo',
  223. beforeSend: function(xhr, settings){
  224. xhr.setRequestHeader('Accept', 'text/plain')
  225. t.assertUndefined(settings.headers)
  226. },
  227. success: t.reg.resumeHandler('success', function(response){
  228. t.assertLine("accept: text/plain", response)
  229. })
  230. })
  231. },
  232. testAjaxPost: function(t){
  233. t.pause()
  234. var xhr = $.post('echo', t.reg.resumeHandler('success', function(response){
  235. t.assertIdentical(window, this)
  236. t.assertLine("POST ?{}", response)
  237. t.assertLine("accept: */*", response)
  238. t.assertLine('{}', response)
  239. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
  240. }))
  241. t.assertIn('abort', xhr)
  242. },
  243. testAjaxPostWithPayloadAndType: function(t) {
  244. t.pause()
  245. var payload = { sample: 'data' }
  246. $.post('echo', payload, t.reg.resumeHandler('success', function(response){
  247. t.assertLine("content-type: application/x-www-form-urlencoded", response)
  248. t.assertLine("accept: text/plain", response)
  249. t.assertLine('{"sample":"data"}', response)
  250. }), 'text')
  251. },
  252. testAjaxPostAutoParsesJSON: function(t) {
  253. t.pause()
  254. var payload = { sample: 'data' }
  255. $.post('create', payload, t.reg.resumeHandler('success', function(data){
  256. t.assertEqual('data', data.payload.sample)
  257. }))
  258. },
  259. testNumberOfActiveRequests: function(t) {
  260. var maxActive = 0, ajaxStarted = 0, ajaxEnded = 0, requestsCompleted = 0
  261. t.assertIdentical(0, $.active, 'initial count mismatch')
  262. $(document)
  263. .on('ajaxStart', function() { ajaxStarted++ })
  264. .on('ajaxEnd', function() { ajaxEnded++ })
  265. .on('ajaxSend', function() {
  266. if ($.active > maxActive) maxActive = $.active
  267. })
  268. .on('ajaxComplete', function() {
  269. if (++requestsCompleted == 3)
  270. deferredResume(t, function() {
  271. this.assertEqual(3, maxActive)
  272. this.assertIdentical(0, $.active)
  273. })
  274. })
  275. t.pause()
  276. $.ajax({ url: 'echo' })
  277. $.ajax({ url: 'echo' })
  278. $.ajax({ url: 'echo' })
  279. },
  280. testAjaxJSON: function(t){
  281. t.pause()
  282. resumeOnAjaxError(t)
  283. $.ajax({
  284. url: 'json',
  285. headers: { accept: 'application/json' },
  286. success: t.reg.resumeHandler('success', function(data){
  287. t.assertEqual('world', data.hello)
  288. })
  289. })
  290. },
  291. testAjaxDataFilterJSON: function(t){
  292. t.pause()
  293. resumeOnAjaxError(t)
  294. $.ajax({
  295. url: 'taintedJSON',
  296. dataFilter: function(data, type) {
  297. if (!data) return
  298. return data.replace(/^\s*while\(1\);\s*/, '')
  299. },
  300. headers: { accept: 'application/json' },
  301. success: t.reg.resumeHandler('success', function(data){
  302. t.assertEqual('world', data.hello)
  303. })
  304. })
  305. },
  306. testAjaxGetJSON: function(t){
  307. t.pause()
  308. resumeOnAjaxError(t)
  309. var xhr = $.getJSON(
  310. 'json',
  311. t.reg.resumeHandler('success', function(data){
  312. t.assertEqual('world', data.hello)
  313. t.assert($.isEmptyObject(data.query))
  314. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
  315. })
  316. )
  317. t.assertIn('abort', xhr)
  318. },
  319. testAjaxGetJSONWithParams: function(t){
  320. t.pause()
  321. resumeOnAjaxError(t)
  322. $.getJSON(
  323. 'json', { sample: 'data' },
  324. t.reg.resumeHandler('success', function(data){
  325. t.assertEqual('data', data.query.sample)
  326. }),
  327. 'text' // ignored
  328. )
  329. },
  330. testAjaxJSONParserError: function(t){
  331. t.pause()
  332. $.ajax({
  333. url: 'json',
  334. dataType: 'json',
  335. data: { invalid: true },
  336. success: t.reg.handler('success'),
  337. error: t.reg.handler('error'),
  338. complete: t.reg.resumeHandler('complete', function(){
  339. t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
  340. var errorArgs = t.reg.args('error')
  341. t.assertEqual('parsererror', errorArgs[1])
  342. t.assert(errorArgs[2] instanceof SyntaxError)
  343. var globalErrorArgs = t.reg.args('ajaxError')
  344. t.assert(globalErrorArgs[3] instanceof SyntaxError)
  345. t.assertEqual(0, $('script[src^=slow]').size())
  346. })
  347. })
  348. },
  349. testAjaxEqualQuestionmarkIsNotAlwaysJSONP: function(t){
  350. t.pause()
  351. resumeOnAjaxError(t)
  352. $.ajax({
  353. url: 'echo=?',
  354. dataType: 'text',
  355. success: t.reg.resumeHandler('success', function(data){
  356. t.assertLine('GET ?{}', data)
  357. t.assertLine("accept: text/plain", data)
  358. })
  359. })
  360. },
  361. testAjaxGetJSONP: function(t){
  362. t.pause()
  363. $.getJSON(
  364. 'jsonp?callback=?&timestamp='+(+new Date),
  365. t.reg.resumeHandler('success', function(data){
  366. t.assertEqual('world', data.hello)
  367. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
  368. t.assertEqual(0, $('script[src^=jsonp]').size())
  369. })
  370. )
  371. t.assertEqual(1, $('script[src^=jsonp]').size())
  372. },
  373. testAjaxGetJSONPWithParams: function(t){
  374. t.pause()
  375. $.getJSON(
  376. 'jsonp?callback=?&timestamp='+(+new Date),
  377. { sample: 'data' },
  378. t.reg.resumeHandler('success', function(data){
  379. t.assertEqual('data', data.query.sample)
  380. })
  381. )
  382. },
  383. testAjaxJSONP: function(t){
  384. t.pause()
  385. var xhr = $.ajaxJSONP({
  386. url: 'jsonp?callback=?&timestamp='+(+new Date),
  387. success: t.reg.handler('success'),
  388. complete: t.reg.resumeHandler('complete', function(data){
  389. var successArgs = t.reg.args('success')
  390. t.assertEqual('world', successArgs[0].hello)
  391. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess complete ajaxComplete', t.reg.events())
  392. t.assertEqual(0, $('script[src^=jsonp]').size())
  393. })
  394. })
  395. t.assertIn('abort', xhr)
  396. },
  397. testAjaxJSONPBeforeSend: function(t){
  398. t.pause()
  399. $(document).on('ajaxBeforeSend', function(){ return false })
  400. $.ajax({
  401. url: 'jsonp?callback=?&timestamp='+(+new Date),
  402. beforeSend: t.reg.resumeHandler('beforeSend', function(){
  403. t.assertEqualList('beforeSend ajaxBeforeSend ajaxError complete ajaxComplete', t.reg.events())
  404. }),
  405. success: t.reg.handler('success'),
  406. complete: t.reg.handler('complete')
  407. })
  408. },
  409. testAjaxGetJSONPErrorCallback: function(t){
  410. t.pause()
  411. $.ajax({
  412. type: 'GET',
  413. url: 'fixtures/404.js?timestamp='+(+new Date),
  414. dataType: 'jsonp',
  415. success: t.reg.handler('success'),
  416. error: t.reg.handler('error'),
  417. complete: t.reg.resumeHandler('complete', function(){
  418. t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
  419. t.assertEqual(0, $('script[src^=fixtures]').size())
  420. })
  421. })
  422. },
  423. testAjaxGetJSONPErrorWithoutCallback: function(t){
  424. t.pause()
  425. $.ajax({
  426. type: 'GET',
  427. url: 'fixtures/404.js?timestamp='+(+new Date),
  428. dataType: 'jsonp',
  429. success: t.reg.handler('success'),
  430. complete: t.reg.resumeHandler('complete', function(){
  431. t.assertEqualList('ajaxBeforeSend ajaxSend ajaxError complete ajaxComplete', t.reg.events())
  432. t.assertEqual(0, $('script[src^=fixtures]').size())
  433. })
  434. })
  435. },
  436. testAjaxJSONPTimeout: function(t){
  437. t.pause()
  438. $.ajax({
  439. url: 'slow?timestamp='+(+new Date),
  440. dataType: 'jsonp',
  441. jsonpCallback: 'jsonpDummy',
  442. timeout: 20,
  443. success: t.reg.handler('success'),
  444. error: t.reg.handler('error'),
  445. complete: t.reg.resumeHandler('complete', function(){
  446. t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
  447. var errorArgs = t.reg.args('error')
  448. t.assertEqual('timeout', errorArgs[1])
  449. var globalErrorArgs = t.reg.args('ajaxError')
  450. t.assertEqual('timeout', globalErrorArgs[3])
  451. t.assertEqual(0, $('script[src^=slow]').size())
  452. })
  453. })
  454. },
  455. testAjaxJSONPAbort: function(t){
  456. t.pause()
  457. var xhr = $.ajax({
  458. url: 'slow?timestamp='+(+new Date),
  459. dataType: 'jsonp',
  460. jsonpCallback: 'jsonpDummy',
  461. timeout: 30,
  462. success: t.reg.handler('success'),
  463. error: t.reg.handler('error'),
  464. complete: t.reg.handler('complete')
  465. })
  466. setTimeout(function(){ xhr.abort() }, 10)
  467. setTimeout(function(){
  468. t.resume(function(){
  469. t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
  470. var errorArgs = t.reg.args('error')
  471. t.assertEqual('abort', errorArgs[1])
  472. var globalErrorArgs = t.reg.args('ajaxError')
  473. t.assertEqual('abort', globalErrorArgs[3])
  474. t.assertEqual(0, $('script[src^=slow]').size())
  475. })
  476. }, 50)
  477. },
  478. testAjaxJSONPError: function(t){
  479. t.pause()
  480. var xhr = $.ajax({
  481. url: 'error?timestamp='+(+new Date),
  482. dataType: 'jsonp',
  483. success: t.reg.handler('success'),
  484. error: t.reg.handler('error'),
  485. complete: t.reg.resumeHandler('complete', function(){
  486. t.assertEqualList('ajaxBeforeSend ajaxSend error ajaxError complete ajaxComplete', t.reg.events())
  487. var errorArgs = t.reg.args('error')
  488. t.assertEqual('error', errorArgs[1])
  489. t.assertEqual(0, $('script[src^=error]').size())
  490. })
  491. })
  492. },
  493. testAjaxJSONPWithDataSupport: function(t) {
  494. t.pause()
  495. var xhr = $.ajax({
  496. url: 'jsonp?callback=?&timestamp='+(+new Date),
  497. data: {
  498. param1: 'val1',
  499. param2: 'val2'
  500. },
  501. success: t.reg.resumeHandler('success', function(data){
  502. t.assertEqual('val1', data.query.param1)
  503. t.assertEqual('val2', data.query.param2)
  504. })
  505. })
  506. },
  507. testAjaxJSONPWithCallbackName: function(t) {
  508. var xhr = $.ajax({
  509. url: 'jsonp',
  510. dataType: 'jsonp',
  511. jsonpCallback: 'blah',
  512. success: t.reg.resumeHandler('success', function(data){
  513. t.assertUndefined(window.blah)
  514. })
  515. })
  516. t.assert($.isFunction(window.blah))
  517. t.pause()
  518. },
  519. testAjaxJSONPWithCallbackNameAsFunction: function(t) {
  520. var xhr = $.ajax({
  521. url: 'jsonp',
  522. dataType: 'jsonp',
  523. jsonpCallback: function(){ return 'blah' },
  524. success: t.reg.resumeHandler('success', function(data){
  525. t.assertUndefined(window.blah)
  526. })
  527. })
  528. t.assert($.isFunction(window.blah))
  529. t.pause()
  530. },
  531. testAjaxJSONPWithCallbackNameAndJSONPsetToFalse: function(t) {
  532. var xhr = $.ajax({
  533. url: 'jsonpBlah',
  534. dataType: 'jsonp',
  535. jsonp: false,
  536. jsonpCallback: 'blah',
  537. success: t.reg.resumeHandler('success', function(data){
  538. t.assertUndefined(window.blah)
  539. })
  540. })
  541. var scriptSrc = $('head script:last-child').attr('src')
  542. t.assert(/^jsonpBlah\?_=[\d]{13}$/.test(scriptSrc), scriptSrc)
  543. t.assert($.isFunction(window.blah))
  544. t.pause()
  545. },
  546. testAjaxJSONPWithCallbackNameAsFunctionAndJSONPsetToFalse: function(t) {
  547. var xhr = $.ajax({
  548. url: 'jsonpBlah',
  549. dataType: 'jsonp',
  550. jsonp: false,
  551. jsonpCallback: function(){ return 'blah' },
  552. success: t.reg.resumeHandler('success', function(data){
  553. t.assertUndefined(window.blah)
  554. })
  555. })
  556. var scriptSrc = $('head script:last-child').attr('src')
  557. t.assert(/^jsonpBlah\?_=[\d]{13}$/.test(scriptSrc), scriptSrc)
  558. t.assert($.isFunction(window.blah))
  559. t.pause()
  560. },
  561. testAjaxJSONPWithData: function(t) {
  562. t.pause()
  563. $.ajax({
  564. url: 'jsonp',
  565. type: 'post',
  566. data: { foo: 'bar' },
  567. dataType: 'jsonp',
  568. success: t.reg.resumeHandler('success', function(data){
  569. t.assertEqual('bar', data.query.foo)
  570. })
  571. })
  572. },
  573. testNoCacheParam: function(t) {
  574. t.pause()
  575. var xhr = $.ajax({
  576. url:'echo',
  577. cache: false,
  578. success: t.reg.resumeHandler('success', function(response){
  579. // check that the no-cache param (or an element of it) looks like a timestamp
  580. t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
  581. })
  582. })
  583. },
  584. testNoCacheParameterWithParam: function(t) {
  585. t.pause()
  586. var xhr = $.ajax({
  587. url:'echo',
  588. data:{ data: 'sample' },
  589. cache: false,
  590. success: t.reg.resumeHandler('success', function(response){
  591. // check that the no-cache param (or an element of it) looks like a timestamp
  592. t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
  593. })
  594. })
  595. },
  596. testNoCacheParameterAlreadyPresent: function(t) {
  597. t.pause()
  598. var xhr = $.ajax({
  599. url:'echo',
  600. data:{ _: 'test' },
  601. cache: false,
  602. success: t.reg.resumeHandler('success', function(response){
  603. // check that the no-cache param (or an element of it) looks like a timestamp
  604. t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
  605. })
  606. })
  607. },
  608. testNoCacheParameterAlreadyPresentWithParam: function(t) {
  609. t.pause()
  610. var xhr = $.ajax({
  611. url:'echo',
  612. data:{ _: 'test', data: 'sample' },
  613. cache: false,
  614. success: t.reg.resumeHandler('success', function(response){
  615. // check that the no-cache param (or an element of it) looks like a timestamp
  616. t.assertLinePattern(/"_":(\[".*",)?"[\d]{13}"/g, response)
  617. })
  618. })
  619. },
  620. testJSONPCacheBustingByDefault: function(t) {
  621. $.ajax({
  622. url: 'jsonp?callback=?',
  623. success: t.reg.resumeHandler('success')
  624. })
  625. var scriptSrc = $('head script:last-child').attr('src')
  626. t.assert(/^jsonp\?callback=Zepto\d+&_=[\d]{13}$/.test(scriptSrc), scriptSrc)
  627. t.pause()
  628. },
  629. testJSONPCacheBustingDisabled: function(t) {
  630. $.ajax({
  631. url: 'jsonp?callback=?',
  632. cache: true,
  633. success: t.reg.resumeHandler('success')
  634. })
  635. var scriptSrc = $('head script:last-child').attr('src')
  636. t.assert(/^jsonp\?callback=Zepto\d+$/.test(scriptSrc), scriptSrc)
  637. t.pause()
  638. },
  639. testBrowserCaching: function(t) {
  640. t.pause()
  641. resumeOnAjaxError(t)
  642. $.ajax({
  643. url: 'cached',
  644. cache: true,
  645. success: function(firstResponse){
  646. $.ajax({
  647. url: 'cached',
  648. cache: true,
  649. success: t.reg.resumeHandler('success', function(secondResponse){
  650. t.assertEqual(secondResponse, firstResponse)
  651. })
  652. })
  653. }
  654. })
  655. },
  656. testAjaxLoad: function(t) {
  657. t.pause()
  658. var testEl = $('#ajax_load')
  659. var el = testEl.load(
  660. 'fixtures/ajax_load_simple.html',
  661. t.reg.resumeHandler('success', function(response, status, xhr){
  662. t.assertIdentical(testEl, this)
  663. t.assertEqual("simple ajax load\n", response.replace(/\r\n|\r/,"\n"))
  664. t.assertEqual('simple ajax load', testEl.html().trim())
  665. t.assertEqual('success', status)
  666. t.assertIn('abort', xhr)
  667. t.assertEqualList('ajaxBeforeSend ajaxSend success ajaxSuccess ajaxComplete', t.reg.events())
  668. })
  669. )
  670. t.assertIdentical(testEl, el)
  671. },
  672. testAjaxLoadWithSelector: function(t) {
  673. t.pause()
  674. var testEl = $('#ajax_load')
  675. testEl.load(
  676. 'fixtures/ajax_load_selector.html #ajax_load_test_div',
  677. t.reg.resumeHandler('success', function(){
  678. t.assertEqual(
  679. '<div id="ajax_load_test_div">ajax load with selector</div>',
  680. testEl.html().trim()
  681. )
  682. })
  683. )
  684. },
  685. testAjaxLoadWithJavaScript: function (t) {
  686. var testEl = $('#ajax_load')
  687. t.pause()
  688. window.testValue = 0
  689. testEl.load('fixtures/ajax_load_selector_javascript.html', function(){
  690. deferredResume(t, function(){
  691. this.assertEqual(window.testValue, 1)
  692. delete window.testValue
  693. })
  694. })
  695. },
  696. testAjaxLoadWithSelectorAndJavaScript: function (t) {
  697. var testEl = $('#ajax_load')
  698. t.pause()
  699. window.testValue = 0
  700. testEl.load('fixtures/ajax_load_selector_javascript.html #ajax_load_test_div', function() {
  701. deferredResume(t, function(){
  702. this.assertEqual(window.testValue, 0)
  703. delete window.testValue
  704. })
  705. })
  706. },
  707. testAjaxWithContext: function(t) {
  708. t.pause()
  709. var body = $('body')
  710. $.ajax({
  711. url: 'fixtures/ajax_load_simple.html',
  712. context: body,
  713. beforeSend: t.reg.handler('beforeSend'),
  714. success: t.reg.handler('success'),
  715. complete: t.reg.resumeHandler('complete', function(){
  716. t.assertIdentical(body, this)
  717. t.assertIdentical(body, t.reg.context('beforeSend'))
  718. t.assertIdentical(body, t.reg.context('success'))
  719. t.assertIdentical(document.body, t.reg.target('ajaxBeforeSend'))
  720. t.assertIdentical(document.body, t.reg.target('ajaxSuccess'))
  721. })
  722. })
  723. },
  724. testAjaxWithContextPlainObject: function(t) {
  725. t.pause()
  726. var obj = {}
  727. $.ajax({
  728. url: 'fixtures/ajax_load_simple.html',
  729. context: obj,
  730. beforeSend: t.reg.handler('beforeSend'),
  731. success: t.reg.handler('success'),
  732. complete: t.reg.resumeHandler('complete', function(){
  733. t.assertIdentical(obj, this)
  734. t.assertIdentical(obj, t.reg.context('beforeSend'))
  735. t.assertIdentical(obj, t.reg.context('success'))
  736. t.assertUndefined(t.reg.target('ajaxBeforeSend'))
  737. t.assertUndefined(t.reg.target('ajaxSuccess'))
  738. })
  739. })
  740. },
  741. testAjaxLoadJavaScript: function (t) {
  742. t.pause()
  743. window.testValue = 0
  744. var xhr = $.ajax({
  745. url:'fixtures/ajax_load_javascript.js',
  746. success: t.reg.resumeHandler('success', function(response){
  747. // check that the javascript has loaded and executed.
  748. t.assertEqual(window.testValue, 1)
  749. delete window.testValue
  750. })
  751. })
  752. },
  753. testAjaxBasicAuth: function(t) {
  754. t.pause()
  755. resumeOnAjaxError(t)
  756. $.ajax({
  757. url: 'auth?realm=zepto',
  758. username: 'zepto',
  759. password: 'doge',
  760. success: t.reg.resumeHandler('success')
  761. })
  762. }
  763. })
  764. var OriginalXHR = $.ajaxSettings.xhr
  765. function MockXHR() {
  766. this.headers = []
  767. this.responseHeaders = {}
  768. MockXHR.last = this
  769. }
  770. MockXHR.prototype = {
  771. open: function(method, url, async) {
  772. this.method = method
  773. this.url = url
  774. this.async = async
  775. },
  776. setRequestHeader: function(name, value) {
  777. if (!this.method) throw "setRequestHeader() called before open()"
  778. this.headers.push({ name: name, value: value })
  779. },
  780. getResponseHeader: function(name) {
  781. return this.responseHeaders[name]
  782. },
  783. overrideMimeType: function(type) {
  784. this.responseHeaders['content-type'] = type
  785. },
  786. withCredentials: false,
  787. send: function(data) {
  788. this.data = data
  789. },
  790. abort: function() {
  791. this.aborted = true
  792. },
  793. ready: function(readyState, status, responseText, headers) {
  794. this.readyState = readyState
  795. this.status = status
  796. this.responseText = responseText
  797. $.extend(this.responseHeaders, headers)
  798. this.onreadystatechange()
  799. },
  800. onreadystatechange: function() {}
  801. }
  802. function matchHeader(name, value) {
  803. return function(header) {
  804. return header.name == name && (!value || header.value == value)
  805. }
  806. }
  807. Evidence('ZeptoAjaxTest2', {
  808. setUp: function() {
  809. $.ajaxSettings.xhr = function(){ return new MockXHR }
  810. },
  811. tearDown: function() {
  812. $.ajaxSettings.xhr = OriginalXHR
  813. $(document).off()
  814. $.active = 0
  815. },
  816. testTypeDefaultsToGET: function(t) {
  817. $.ajax({
  818. url: '/foo',
  819. beforeSend: function(xhr, settings) {
  820. t.assertFalse(settings.crossDomain)
  821. }
  822. })
  823. t.assertEqual('GET', MockXHR.last.method)
  824. },
  825. testURLDefaultsToWindowLocation: function(t) {
  826. $.ajax()
  827. t.assertEqual(window.location, MockXHR.last.url)
  828. },
  829. testCrossDomainCrossOrigin: function(t) {
  830. $.ajax({
  831. url: 'http://example.com/foo',
  832. beforeSend: function(xhr, settings) {
  833. t.assertTrue(settings.crossDomain)
  834. }
  835. })
  836. },
  837. testCrossDomainSameOrigin: function(t) {
  838. $.ajax({
  839. url: window.location.href,
  840. beforeSend: function(xhr, settings) {
  841. t.assertFalse(settings.crossDomain)
  842. }
  843. })
  844. },
  845. testCrossDomainLeadingSpace: function(t) {
  846. $.ajax({
  847. url: ' http://example.com/foo',
  848. beforeSend: function(xhr, settings) {
  849. t.assertTrue(settings.crossDomain)
  850. }
  851. })
  852. },
  853. testCrossDomainTrippleSlash: function(t) {
  854. $.ajax({
  855. url: 'http:///example.com/foo',
  856. beforeSend: function(xhr, settings) {
  857. t.assertTrue(settings.crossDomain)
  858. }
  859. })
  860. },
  861. testCrossDomainWithQuery: function(t) {
  862. $.ajax({
  863. url: window.location.href + "?foo=bar",
  864. beforeSend: function(xhr, settings) {
  865. t.assertFalse(settings.crossDomain)
  866. }
  867. })
  868. },
  869. testCrossDomainDifferentScheme: function(t) {
  870. $.ajax({
  871. url: "foo://" + window.location.host,
  872. beforeSend: function(xhr, settings) {
  873. t.assertTrue(settings.crossDomain)
  874. }
  875. })
  876. },
  877. testCrossDomainPeriodInScheme: function(t) {
  878. $.ajax({
  879. url: "foo.bar://example.com/foo",
  880. beforeSend: function(xhr, settings) {
  881. t.assertTrue(settings.crossDomain)
  882. }
  883. })
  884. },
  885. testDefaultAcceptHeader: function(t) {
  886. $.ajax()
  887. t.assert(MockXHR.last.headers.some(matchHeader('Accept', '*/*')))
  888. },
  889. testDataTypeOptionSetsAcceptHeader: function(t) {
  890. $.ajax({ dataType: 'json' })
  891. t.assert(MockXHR.last.headers.some(matchHeader('Accept', 'application/json')))
  892. // verifies overrideMimeType:
  893. t.assertEqual('application/json', MockXHR.last.getResponseHeader('content-type'))
  894. $.ajax({ dataType: 'script' })
  895. //check that the head matches all of those required for loading scripts.
  896. t.assert(MockXHR.last.headers.some(matchHeader('Accept', 'text/javascript, application/javascript, application/x-javascript')))
  897. },
  898. testMimeTypeOptionOverride: function(t) {
  899. $.ajax({ mimeType: 'text/plain' })
  900. t.assertEqual('text/plain', MockXHR.last.getResponseHeader('content-type'))
  901. },
  902. testContentTypeOptionSetsContentTypeHeader: function(t) {
  903. $.ajax()
  904. t.assert(!MockXHR.last.headers.some(matchHeader('Content-Type')))
  905. $.ajax({ contentType: 'text/html' })
  906. t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'text/html')))
  907. $.ajax({ type: 'POST', data: [], contentType: 'application/x-foo' })
  908. t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-foo')))
  909. },
  910. testHeadersOptionCanSetContentType: function(t) {
  911. $.ajax({ type: 'POST', data: [], headers: { 'Content-Type': 'application/hal+json' }})
  912. t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/hal+json')))
  913. },
  914. testContentTypeDefaultsToUrlEncoded: function(t) {
  915. $.ajax({ type: 'GET', data: 'x' })
  916. t.refute(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-www-form-urlencoded')))
  917. $.ajax({ type: 'POST', data: 'x' })
  918. t.assert(MockXHR.last.headers.some(matchHeader('Content-Type', 'application/x-www-form-urlencoded')))
  919. },
  920. testDefaultContentTypeDisabled: function(t) {
  921. $.ajax({ type: 'POST', data: {a:1}, contentType: false })
  922. t.refute(MockXHR.last.headers.some(matchHeader('Content-Type')))
  923. },
  924. testCustomHeader: function(t) {
  925. $.ajax({ headers: {'X-Awesome': 'true'} })
  926. t.assert(MockXHR.last.headers.some(matchHeader('X-Requested-With', 'XMLHttpRequest')))
  927. t.assert(MockXHR.last.headers.some(matchHeader('X-Awesome', 'true')))
  928. },
  929. testXhrFieldsOptionSetsWithCredentialsProperty: function(t) {
  930. var xhr = $.ajax({
  931. url: 'http://example.com/foo',
  932. xhrFields: { withCredentials: true }
  933. })
  934. t.assert(xhr.withCredentials)
  935. },
  936. testScriptDataTypeCacheBustByDefault: function(t) {
  937. $.ajax({ url: '/', dataType: 'script' })
  938. var xhr = MockXHR.last
  939. t.assert(/^\/\?_=[\d]{13}$/.test(xhr.url), xhr.url)
  940. },
  941. testScriptDataTypeCacheBustDisable: function(t) {
  942. $.ajax({ url: '/', dataType: 'script', cache: true })
  943. var xhr = MockXHR.last
  944. t.assertEqual('/', xhr.url)
  945. },
  946. testJSONdataType: function(t) {
  947. var result = {}
  948. $.ajax({ dataType: 'json', success: function(json) {result = json } })
  949. MockXHR.last.ready(4, 200, '{"hello":"world"}')
  950. t.assertEqual("world", result.hello)
  951. },
  952. testJSONcontentType: function(t) {
  953. var result = {}
  954. $.ajax({ success: function(json) {result = json } })
  955. MockXHR.last.ready(4, 200, '{"hello":"world"}', {'content-type': 'application/json'})
  956. t.assertEqual("world", result.hello)
  957. },
  958. testJSONResponseBodiesAreNotParsedWhenDataTypeOptionIsJSONButResponseIsEmptyString: function(t) {
  959. var result, success = false
  960. $.ajax({ dataType: 'json', success: function(json) {result = json; success = true } })
  961. MockXHR.last.ready(4, 200, '')
  962. t.assert(success)
  963. t.assertNull(result)
  964. },
  965. testJSONResponseBodiesAreNotParsedWhenDataTypeOptionIsJSONButResponseIsSingleSpace: function(t) {
  966. var result, success = false
  967. $.ajax({ dataType: 'json', success: function(json) {result = json; success = true } })
  968. MockXHR.last.ready(4, 200, ' ')
  969. t.assert(success)
  970. t.assertNull(result)
  971. },
  972. testDataIsNotSentAsBodyForGetRequests: function(t) {
  973. $.ajax({ type: 'GET', data: {a:'b'} })
  974. t.assertNull(MockXHR.last.data)
  975. },
  976. testDataOptionIsConvertedToSerializedForm: function(t) {
  977. $.ajax({
  978. type: 'POST',
  979. data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } }
  980. })
  981. var data = decodeURIComponent(MockXHR.last.data)
  982. t.assertEqual('hello=world&array[]=1&array[]=2&array[]=3&object[prop1]=val&object[prop2]=2', data)
  983. },
  984. testDataOptionIsConvertedToSerializedTraditionalForm: function(t) {
  985. $.ajax({
  986. type: 'POST',
  987. data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } },
  988. traditional: true
  989. })
  990. var data = decodeURIComponent(MockXHR.last.data)
  991. t.assertEqual('hello=world&array=1&array=2&array=3&object=[object+Object]', data)
  992. },
  993. testQueryParamsTraditional: function(t) {
  994. $.ajax({
  995. url: '/',
  996. data: {hello: 'world', array: [1,2,3], object: { prop1: 'val', prop2: 2 } },
  997. traditional: true
  998. })
  999. var url = decodeURIComponent(MockXHR.last.url)
  1000. t.assertEqual('/?hello=world&array=1&array=2&array=3&object=[object+Object]', url)
  1001. },
  1002. testProcessDataDisabled: function(t) {
  1003. var data = { country: 'Ecuador' }
  1004. $.ajax({
  1005. data: data,
  1006. processData: false,
  1007. type: "POST"
  1008. })
  1009. t.assertIdentical(data, MockXHR.last.data)
  1010. },
  1011. testDataIsAppendedToGETURL: function(t) {
  1012. $.ajax({ url:'test.html', data:'foo=bar' })
  1013. t.assertEqual('test.html?foo=bar', MockXHR.last.url)
  1014. $.ajax({ url:'test.html', data:'?foo=bar' })
  1015. t.assertEqual('test.html?foo=bar', MockXHR.last.url)
  1016. $.ajax({ url:'test.html?', data:'foo=bar' })
  1017. t.assertEqual('test.html?foo=bar', MockXHR.last.url)
  1018. $.ajax({ url:'test.html?baz', data:'foo=bar' })
  1019. t.assertEqual('test.html?baz&foo=bar', MockXHR.last.url)
  1020. $.ajax({ url:'test.html?bar=baz', data:'foo=bar' })
  1021. t.assertEqual('test.html?bar=baz&foo=bar', MockXHR.last.url)
  1022. $.ajax({ url:'test.html', data:{foo:'bar'} })
  1023. t.assertEqual('test.html?foo=bar', MockXHR.last.url)
  1024. },
  1025. testDataIsAppendedToGETURLWithHashStripped: function(t) {
  1026. $.ajax({ url:'test.html#?ignore=me', data:'foo=bar' })
  1027. t.assertEqual('test.html?foo=bar', MockXHR.last.url)
  1028. $.ajax({ url:'test.html?a=b#?ignore=me', data:'foo=bar' })
  1029. t.assertEqual('test.html?a=b&foo=bar', MockXHR.last.url)
  1030. },
  1031. testScriptResponseIsEvald: function(t) {
  1032. var result
  1033. $.ajax({ success: function(text){ result = text } })
  1034. MockXHR.last.ready(4, 200, 'this.testValue = 42', {'content-type': 'application/javascript'})
  1035. t.assertEqual('this.testValue = 42', result)
  1036. t.assertIdentical(42, window.testValue)
  1037. delete window.testValue
  1038. },
  1039. testErrorCallback: function(t) {
  1040. var successFired = false, xhr, status
  1041. $.ajax({
  1042. success: function() { successFired = true },
  1043. error: function(x, s) { xhr = x, status = s }
  1044. })
  1045. MockXHR.last.ready(4, 500, '500 Internal Server Error')
  1046. t.assert(!successFired)
  1047. t.assertEqual(MockXHR.last, xhr)
  1048. t.assertEqual('error', status)
  1049. },
  1050. testErrorCallbackWithInvalidJSON: function(t) {
  1051. var successFired = false, xhr, status, exception
  1052. $.ajax({
  1053. dataType: 'json',
  1054. succes: function() { successFired = true },
  1055. error: function(x, s, e) { xhr = x, status = s, exception = e }
  1056. })
  1057. MockXHR.last.ready(4, 200, '{invalid')
  1058. t.assert(!successFired)
  1059. t.assertEqual(MockXHR.last, xhr)
  1060. t.assertEqual('parsererror', status)
  1061. t.assert(exception.toString().match(/SyntaxError/))
  1062. },
  1063. test201ResponseIsSuccess: function(t) {
  1064. var successFired, errorFired
  1065. $.ajax({
  1066. success: function() { successFired = true },
  1067. error: function() { errorFired = true }
  1068. })
  1069. MockXHR.last.ready(4, 201, 'Created')
  1070. t.assert(successFired)
  1071. t.refute(errorFired)
  1072. },
  1073. test304ResponseIsSuccess: function(t) {
  1074. var successFired, errorFired
  1075. $.ajax({
  1076. success: function() { successFired = true },
  1077. error: function() { errorFired = true }
  1078. })
  1079. MockXHR.last.ready(4, 304, 'Not Modified')
  1080. t.assert(successFired)
  1081. t.refute(errorFired)
  1082. },
  1083. testXHRParameterInSuccessCallback: function(t) {
  1084. var body, status, xhr
  1085. $.ajax({
  1086. success: function(b, s, x) { body = b, status = s, xhr = x }
  1087. })
  1088. MockXHR.last.ready(4, 200, 'Hello')
  1089. t.assertEqual('Hello', body)
  1090. t.assertEqual('success', status)
  1091. t.assertEqual(MockXHR.last, xhr)
  1092. body = status = xhr = null
  1093. $.ajax({
  1094. dataType: 'json',
  1095. success: function(b, s, x) { body = b, status = s, xhr = x }
  1096. })
  1097. MockXHR.last.ready(4, 200, '{"message":"Hello"}')
  1098. t.assertEqual('Hello', body.message)
  1099. t.assertEqual('success', status)
  1100. t.assertEqual(MockXHR.last, xhr)
  1101. },
  1102. testBeforeSendCanChangeUrl: function(t) {
  1103. var xhr = $.ajax({
  1104. url: 'one',
  1105. beforeSend: function(x, s) {
  1106. s.url = 'two'
  1107. }
  1108. })
  1109. t.assertEqual('two', xhr.url)
  1110. },
  1111. testBeforeSendCanChangeMethod: function(t) {
  1112. var xhr = $.ajax({
  1113. type: 'POST',
  1114. beforeSend: function(x, s) {
  1115. s.type = 'PUT'
  1116. }
  1117. })
  1118. t.assertEqual('PUT', xhr.method)
  1119. },
  1120. testBeforeSendCanAccessSerializedPostData: function(t) {
  1121. var xhr = $.ajax({
  1122. type: 'POST',
  1123. data: { a:'b' },
  1124. beforeSend: function(x, s) {
  1125. s.data = s.data.toUpperCase()
  1126. }
  1127. })
  1128. t.assertEqual('A=B', xhr.data)
  1129. },
  1130. testBeforeSendCannotAccessRawQueryParams: function(t) {
  1131. var url, data
  1132. $.ajax({
  1133. url: '/',
  1134. type: 'GET',
  1135. data: { a:'b' },
  1136. beforeSend: function(x, s) {
  1137. url = s.url
  1138. data = s.data
  1139. }
  1140. })
  1141. t.assertEqual('/?a=b', url)
  1142. t.assertUndefined(data)
  1143. },
  1144. testBeforeSendCannotChangeOrAddHeadersViaObject: function(t) {
  1145. var xhr = $.ajax({
  1146. headers: { a:'b', c:'d' },
  1147. beforeSend: function(x, s) {
  1148. s.headers['a'] = 'B'
  1149. s.headers['e'] = 'f'
  1150. }
  1151. })
  1152. t.assert(xhr.headers.some(matchHeader('a', 'b')))
  1153. t.assert(xhr.headers.some(matchHeader('c', 'd')))
  1154. t.refute(xhr.headers.some(matchHeader('e', 'f')))
  1155. },
  1156. testBeforeSendCanChangeAndAddHeadersViaXhr: function(t) {
  1157. var xhr = $.ajax({
  1158. headers: { a:'b', c:'d' },
  1159. beforeSend: function(x, s) {
  1160. x.setRequestHeader('a', 'B')
  1161. x.setRequestHeader('e', 'f')
  1162. }
  1163. })
  1164. t.assert(xhr.headers.some(matchHeader('a', 'B')))
  1165. t.assert(xhr.headers.some(matchHeader('c', 'd')))
  1166. t.assert(xhr.headers.some(matchHeader('e', 'f')))
  1167. },
  1168. testBeforeSendAbortCallback: function(t) {
  1169. var xhr, settings
  1170. $.ajax({
  1171. beforeSend: function(x, s) {
  1172. settings = s, xhr = x
  1173. }
  1174. })
  1175. t.assertEqual(MockXHR.last, xhr)
  1176. t.assertEqual('GET', settings.type)
  1177. },
  1178. testBeforeSendAbort: function(t) {
  1179. var xhr
  1180. $.ajax({ beforeSend: function(x) { xhr = x; return false } })
  1181. t.assert(xhr.aborted)
  1182. },
  1183. testGlobalBeforeSendAbort: function(t) {
  1184. $(document).on('ajaxBeforeSend', false)
  1185. var xhr = $.ajax()
  1186. t.assert(xhr.aborted)
  1187. },
  1188. testGlobalAjaxSendCantAbort: function(t) {
  1189. var xhr
  1190. $(document).on('ajaxSend', function(e, x) { xhr = x; return false })
  1191. t.assert($.ajax())
  1192. t.assert(!xhr.aborted)
  1193. },
  1194. testCompleteCallback: function(t) {
  1195. var status, xhr
  1196. $.ajax({ complete: function(x, s) { status = s, xhr = x } })
  1197. MockXHR.last.ready(4, 200, 'OK')
  1198. t.assertEqual(MockXHR.last, xhr)
  1199. t.assertEqual('success', status)
  1200. },
  1201. testCallbackOrder: function(t) {
  1202. var order = []
  1203. $.ajax({
  1204. beforeSend: function() { order.push('beforeSend') },
  1205. success: function() { order.push('success') },
  1206. complete: function() { order.push('complete') }
  1207. })
  1208. MockXHR.last.ready(4, 200, 'OK')
  1209. t.assertEqual('beforeSend,success,complete', order.join(','))
  1210. },
  1211. testGlobalCallbacks: function(t) {
  1212. var fired = []
  1213. $(document).on('ajaxStart ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete ajaxStop', function(e) {
  1214. fired.push(e.type)
  1215. })
  1216. $.ajax({
  1217. beforeSend: function() { fired.push('beforeSend') },
  1218. success: function() { fired.push('success') },
  1219. error: function() { fired.push('error') },
  1220. complete: function() { fired.push('complete') }
  1221. })
  1222. t.assertEqual('ajaxStart beforeSend ajaxBeforeSend ajaxSend', fired.join(' '))
  1223. fired = []
  1224. MockXHR.last.ready(4, 200, 'OK')
  1225. t.assertEqual('success ajaxSuccess complete ajaxComplete ajaxStop', fired.join(' '))
  1226. },
  1227. testGlobalCallbacksOff: function(t) {
  1228. var fired = []
  1229. $(document).on('ajaxStart ajaxBeforeSend ajaxSend ajaxSuccess ajaxError ajaxComplete ajaxStop', function(e) {
  1230. fired.push(e.type)
  1231. })
  1232. $.ajax({
  1233. global: false,
  1234. beforeSend: function() { fired.push('beforeSend') },
  1235. success: function() { fired.push('success') },
  1236. error: function() { fired.push('error') },
  1237. complete: function() { fired.push('complete') }
  1238. })
  1239. t.assertEqual('beforeSend', fired.join(' '))
  1240. fired = []
  1241. MockXHR.last.ready(4, 200, 'OK')
  1242. t.assertEqual('success complete', fired.join(' '))
  1243. },
  1244. testTimeout: function(t) {
  1245. var successFired = false, xhr, status, globalStatus
  1246. t.pause()
  1247. $(document).on('ajaxError', function (e, x, o, s) {
  1248. globalStatus = s
  1249. })
  1250. $.ajax({
  1251. timeout: 30,
  1252. success: function() { successFired = true },
  1253. error: function(x, s) { xhr = x, status = s }
  1254. })
  1255. setTimeout(function(){
  1256. t.assertFalse(successFired)
  1257. t.assertUndefined(status)
  1258. }, 20)
  1259. setTimeout(function(){
  1260. t.resume(function(){
  1261. t.assertFalse(successFired)
  1262. t.assertTrue(xhr.aborted)
  1263. t.assertEqual('timeout', status)
  1264. t.assertEqual('timeout', globalStatus)
  1265. })
  1266. }, 40)
  1267. },
  1268. testAbort: function(t) {
  1269. var successFired = false, xhr, status, globalStatus
  1270. t.pause()
  1271. $(document).on('ajaxError', function (e, x, o, s) {
  1272. globalStatus = s
  1273. })
  1274. $.ajax({
  1275. success: function() { successFired = true },
  1276. error: function(x, s) { xhr = x, status = s }
  1277. })
  1278. MockXHR.last.abort()
  1279. MockXHR.last.ready(4, 0, 'Aborted')
  1280. setTimeout(function(){
  1281. t.resume(function(){
  1282. t.assertFalse(successFired)
  1283. t.assertTrue(xhr.aborted)
  1284. t.assertEqual('abort', status)
  1285. t.assertEqual('abort', globalStatus)
  1286. })
  1287. }, 20)
  1288. },
  1289. testAsyncDefaultsToTrue: function(t) {
  1290. $.ajax({ url: '/foo' })
  1291. t.assertTrue(MockXHR.last.async)
  1292. },
  1293. testAsyncFalse: function(t) {
  1294. $.ajax({ url: '/foo', async: false })
  1295. t.assertFalse(MockXHR.last.async)
  1296. }
  1297. })
  1298. Evidence('ZeptoAjaxHelperMethodsTest', {
  1299. testParamMethod: function(t) {
  1300. var result = $.param({ libs: ['jQuery', 'script.aculo.us', 'Prototype', 'Dojo'] })
  1301. result = decodeURIComponent(result)
  1302. t.assertEqual(result, "libs[]=jQuery&libs[]=script.aculo.us&libs[]=Prototype&libs[]=Dojo")
  1303. result = $.param({ jquery: 'Javascript', rails: 'Ruby', django: 'Python' })
  1304. result = decodeURIComponent(result)
  1305. t.assertEqual(result, "jquery=Javascript&rails=Ruby&django=Python")
  1306. result = $.param({
  1307. title: "Some Countries",
  1308. list: ['Ecuador', 'Austria', 'England'],
  1309. capitals: { ecuador: 'Quito', austria: 'Vienna', GB: { england: 'London', scotland: 'Edinburgh'} }
  1310. })
  1311. result = decodeURIComponent(result)
  1312. t.assertEqual(result, "title=Some+Countries&list[]=Ecuador&list[]=Austria&list[]=England&capitals[ecuador]=Quito&capitals[austria]=Vienna&capitals[GB][england]=London&capitals[GB][scotland]=Edinburgh")
  1313. },
  1314. testParamNullValues: function(t) {
  1315. t.assertEqual("x=&a[b]=&a[c]=",
  1316. decodeURIComponent($.param({ x: null, a: { b: null, c: undefined }})))
  1317. t.assertEqual("x=",
  1318. decodeURIComponent($.param([{ name: "x", value: null }])))
  1319. },
  1320. testParamFunctionValues: function(t) {
  1321. t.assertEqual("x=&a[b]=B",
  1322. decodeURIComponent($.param({ x: function(){}, a: { b: function(){ return "B" }}})))
  1323. t.assertEqual("x=&a[b]=B",
  1324. decodeURIComponent($.param([{ name: "x", value: null }, { name: "a[b]", value: function(){ return "B" }}])))
  1325. },
  1326. testParamEscaping: function(t) {
  1327. var result = $.param({ 'equation[1]': 'bananas+peaches=smoothie' })
  1328. t.assertEqual("equation%5B1%5D=bananas%2Bpeaches%3Dsmoothie", result)
  1329. },
  1330. testParamSpaces: function(t) {
  1331. var result = $.param({ "foo bar": "baz kuux" })
  1332. t.assertEqual("foo+bar=baz+kuux", result)
  1333. },
  1334. testParamComplex: function(t) {
  1335. var data = {
  1336. a: ['b', 'c', { d:'e', f:['g','h'] }]
  1337. }
  1338. var result = $.param(data)
  1339. result = decodeURIComponent(result)
  1340. t.assertEqual("a[]=b&a[]=c&a[2][d]=e&a[2][f][]=g&a[2][f][]=h", result)
  1341. },
  1342. testParamComplexIssue850: function(t) {
  1343. var data = {
  1344. $push: { _:[ { name: 'bob', members:['aaa'] } ] }
  1345. }
  1346. var result = $.param(data)
  1347. result = decodeURIComponent(result)
  1348. t.assertEqual("$push[_][0][name]=bob&$push[_][0][members][]=aaa", result)
  1349. },
  1350. testParamComplexNested: function(t) {
  1351. var data = {
  1352. x: [
  1353. [1, { attr1: 2 } ],
  1354. 3,
  1355. { attr1: 4 },
  1356. { attr1: 5, attr2: [ 6 ] },
  1357. [ 7, [8, 9] ],
  1358. { attr1: { attr2: [ [ 10 ] ] } }
  1359. ]
  1360. }
  1361. var result = $.param(data)
  1362. result = decodeURIComponent(result)
  1363. t.assertEqual(
  1364. [ "x[0][]=1"
  1365. , "x[0][1][attr1]=2"
  1366. , "x[]=3"
  1367. , "x[2][attr1]=4"
  1368. , "x[3][attr1]=5"
  1369. , "x[3][attr2][]=6"
  1370. , "x[4][]=7"
  1371. , "x[4][1][]=8"
  1372. , "x[4][1][]=9"
  1373. , "x[5][attr1][attr2][0][]=10"
  1374. ].join('&'), result)
  1375. },
  1376. testParamShallow: function(t) {
  1377. var data = {
  1378. libs: ['jQuery', 'Prototype', 'Dojo'],
  1379. nested: { will: 'be ignored' }
  1380. }
  1381. var result = $.param(data, true)
  1382. result = decodeURIComponent(result)
  1383. t.assertEqual("libs=jQuery&libs=Prototype&libs=Dojo&nested=[object+Object]", result)
  1384. },
  1385. testParamArray: function(t) {
  1386. var data = [
  1387. {name:'country', value:'Ecuador'},
  1388. {name:'capital', value:'Quito'}
  1389. ]
  1390. var result = $.param(data)
  1391. t.assertEqual(result, "country=Ecuador&capital=Quito")
  1392. }
  1393. })
  1394. })()
  1395. </script>
  1396. </body>
  1397. </html>