corrade-nucleus-nucleons – Blame information for rev 20
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
20 | office | 1 | /*! |
2 | * MockJax - jQuery Plugin to Mock Ajax requests |
||
3 | * |
||
4 | * Version: 1.6.1 |
||
5 | * Released: |
||
6 | * Home: https://github.com/jakerella/jquery-mockjax |
||
7 | * Author: Jonathan Sharp (http://jdsharp.com) |
||
8 | * License: MIT,GPL |
||
9 | * |
||
10 | * Copyright (c) 2014 appendTo, Jordan Kasper |
||
11 | * NOTE: This repository was taken over by Jordan Kasper (@jakerella) October, 2014 |
||
12 | * |
||
13 | * Dual licensed under the MIT or GPL licenses. |
||
14 | * http://opensource.org/licenses/MIT OR http://www.gnu.org/licenses/gpl-2.0.html |
||
15 | */ |
||
16 | (function($) { |
||
17 | var _ajax = $.ajax, |
||
18 | mockHandlers = [], |
||
19 | mockedAjaxCalls = [], |
||
20 | unmockedAjaxCalls = [], |
||
21 | CALLBACK_REGEX = /=\?(&|$)/, |
||
22 | jsc = (new Date()).getTime(); |
||
23 | |||
24 | |||
25 | // Parse the given XML string. |
||
26 | function parseXML(xml) { |
||
27 | if ( window.DOMParser == undefined && window.ActiveXObject ) { |
||
28 | DOMParser = function() { }; |
||
29 | DOMParser.prototype.parseFromString = function( xmlString ) { |
||
30 | var doc = new ActiveXObject('Microsoft.XMLDOM'); |
||
31 | doc.async = 'false'; |
||
32 | doc.loadXML( xmlString ); |
||
33 | return doc; |
||
34 | }; |
||
35 | } |
||
36 | |||
37 | try { |
||
38 | var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' ); |
||
39 | if ( $.isXMLDoc( xmlDoc ) ) { |
||
40 | var err = $('parsererror', xmlDoc); |
||
41 | if ( err.length == 1 ) { |
||
42 | throw new Error('Error: ' + $(xmlDoc).text() ); |
||
43 | } |
||
44 | } else { |
||
45 | throw new Error('Unable to parse XML'); |
||
46 | } |
||
47 | return xmlDoc; |
||
48 | } catch( e ) { |
||
49 | var msg = ( e.name == undefined ? e : e.name + ': ' + e.message ); |
||
50 | $(document).trigger('xmlParseError', [ msg ]); |
||
51 | return undefined; |
||
52 | } |
||
53 | } |
||
54 | |||
55 | // Check if the data field on the mock handler and the request match. This |
||
56 | // can be used to restrict a mock handler to being used only when a certain |
||
57 | // set of data is passed to it. |
||
58 | function isMockDataEqual( mock, live ) { |
||
59 | var identical = true; |
||
60 | // Test for situations where the data is a querystring (not an object) |
||
61 | if (typeof live === 'string') { |
||
62 | // Querystring may be a regex |
||
63 | return $.isFunction( mock.test ) ? mock.test(live) : mock == live; |
||
64 | } |
||
65 | $.each(mock, function(k) { |
||
66 | if ( live[k] === undefined ) { |
||
67 | identical = false; |
||
68 | return identical; |
||
69 | } else { |
||
70 | if ( typeof live[k] === 'object' && live[k] !== null ) { |
||
71 | if ( identical && $.isArray( live[k] ) ) { |
||
72 | identical = $.isArray( mock[k] ) && live[k].length === mock[k].length; |
||
73 | } |
||
74 | identical = identical && isMockDataEqual(mock[k], live[k]); |
||
75 | } else { |
||
76 | if ( mock[k] && $.isFunction( mock[k].test ) ) { |
||
77 | identical = identical && mock[k].test(live[k]); |
||
78 | } else { |
||
79 | identical = identical && ( mock[k] == live[k] ); |
||
80 | } |
||
81 | } |
||
82 | } |
||
83 | }); |
||
84 | |||
85 | return identical; |
||
86 | } |
||
87 | |||
88 | // See if a mock handler property matches the default settings |
||
89 | function isDefaultSetting(handler, property) { |
||
90 | return handler[property] === $.mockjaxSettings[property]; |
||
91 | } |
||
92 | |||
93 | // Check the given handler should mock the given request |
||
94 | function getMockForRequest( handler, requestSettings ) { |
||
95 | // If the mock was registered with a function, let the function decide if we |
||
96 | // want to mock this request |
||
97 | if ( $.isFunction(handler) ) { |
||
98 | return handler( requestSettings ); |
||
99 | } |
||
100 | |||
101 | // Inspect the URL of the request and check if the mock handler's url |
||
102 | // matches the url for this ajax request |
||
103 | if ( $.isFunction(handler.url.test) ) { |
||
104 | // The user provided a regex for the url, test it |
||
105 | if ( !handler.url.test( requestSettings.url ) ) { |
||
106 | return null; |
||
107 | } |
||
108 | } else { |
||
109 | // Look for a simple wildcard '*' or a direct URL match |
||
110 | var star = handler.url.indexOf('*'); |
||
111 | if (handler.url !== requestSettings.url && star === -1 || |
||
112 | !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\\$&").replace(/\*/g, '.+')).test(requestSettings.url)) { |
||
113 | return null; |
||
114 | } |
||
115 | } |
||
116 | |||
117 | // Inspect the data submitted in the request (either POST body or GET query string) |
||
118 | if ( handler.data ) { |
||
119 | if ( ! requestSettings.data || !isMockDataEqual(handler.data, requestSettings.data) ) { |
||
120 | // They're not identical, do not mock this request |
||
121 | return null; |
||
122 | } |
||
123 | } |
||
124 | // Inspect the request type |
||
125 | if ( handler && handler.type && |
||
126 | handler.type.toLowerCase() != requestSettings.type.toLowerCase() ) { |
||
127 | // The request type doesn't match (GET vs. POST) |
||
128 | return null; |
||
129 | } |
||
130 | |||
131 | return handler; |
||
132 | } |
||
133 | |||
134 | function parseResponseTimeOpt(responseTime) { |
||
135 | if ($.isArray(responseTime)) { |
||
136 | var min = responseTime[0]; |
||
137 | var max = responseTime[1]; |
||
138 | return (typeof min === 'number' && typeof max === 'number') ? Math.floor(Math.random() * (max - min)) + min : null; |
||
139 | } else { |
||
140 | return (typeof responseTime === 'number') ? responseTime: null; |
||
141 | } |
||
142 | } |
||
143 | |||
144 | // Process the xhr objects send operation |
||
145 | function _xhrSend(mockHandler, requestSettings, origSettings) { |
||
146 | |||
147 | // This is a substitute for < 1.4 which lacks $.proxy |
||
148 | var process = (function(that) { |
||
149 | return function() { |
||
150 | return (function() { |
||
151 | // The request has returned |
||
152 | this.status = mockHandler.status; |
||
153 | this.statusText = mockHandler.statusText; |
||
154 | this.readyState = 1; |
||
155 | |||
156 | var finishRequest = function () { |
||
157 | this.readyState = 4; |
||
158 | |||
159 | var onReady; |
||
160 | // Copy over our mock to our xhr object before passing control back to |
||
161 | // jQuery's onreadystatechange callback |
||
162 | if ( requestSettings.dataType == 'json' && ( typeof mockHandler.responseText == 'object' ) ) { |
||
163 | this.responseText = JSON.stringify(mockHandler.responseText); |
||
164 | } else if ( requestSettings.dataType == 'xml' ) { |
||
165 | if ( typeof mockHandler.responseXML == 'string' ) { |
||
166 | this.responseXML = parseXML(mockHandler.responseXML); |
||
167 | //in jQuery 1.9.1+, responseXML is processed differently and relies on responseText |
||
168 | this.responseText = mockHandler.responseXML; |
||
169 | } else { |
||
170 | this.responseXML = mockHandler.responseXML; |
||
171 | } |
||
172 | } else if (typeof mockHandler.responseText === 'object' && mockHandler.responseText !== null) { |
||
173 | // since jQuery 1.9 responseText type has to match contentType |
||
174 | mockHandler.contentType = 'application/json'; |
||
175 | this.responseText = JSON.stringify(mockHandler.responseText); |
||
176 | } else { |
||
177 | this.responseText = mockHandler.responseText; |
||
178 | } |
||
179 | if( typeof mockHandler.status == 'number' || typeof mockHandler.status == 'string' ) { |
||
180 | this.status = mockHandler.status; |
||
181 | } |
||
182 | if( typeof mockHandler.statusText === "string") { |
||
183 | this.statusText = mockHandler.statusText; |
||
184 | } |
||
185 | // jQuery 2.0 renamed onreadystatechange to onload |
||
186 | onReady = this.onreadystatechange || this.onload; |
||
187 | |||
188 | // jQuery < 1.4 doesn't have onreadystate change for xhr |
||
189 | if ( $.isFunction( onReady ) ) { |
||
190 | if( mockHandler.isTimeout) { |
||
191 | this.status = -1; |
||
192 | } |
||
193 | onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined ); |
||
194 | } else if ( mockHandler.isTimeout ) { |
||
195 | // Fix for 1.3.2 timeout to keep success from firing. |
||
196 | this.status = -1; |
||
197 | } |
||
198 | }; |
||
199 | |||
200 | // We have an executable function, call it to give |
||
201 | // the mock handler a chance to update it's data |
||
202 | if ( $.isFunction(mockHandler.response) ) { |
||
203 | // Wait for it to finish |
||
204 | if ( mockHandler.response.length === 2 ) { |
||
205 | mockHandler.response(origSettings, function () { |
||
206 | finishRequest.call(that); |
||
207 | }); |
||
208 | return; |
||
209 | } else { |
||
210 | mockHandler.response(origSettings); |
||
211 | } |
||
212 | } |
||
213 | |||
214 | finishRequest.call(that); |
||
215 | }).apply(that); |
||
216 | }; |
||
217 | })(this); |
||
218 | |||
219 | if ( mockHandler.proxy ) { |
||
220 | // We're proxying this request and loading in an external file instead |
||
221 | _ajax({ |
||
222 | global: false, |
||
223 | url: mockHandler.proxy, |
||
224 | type: mockHandler.proxyType, |
||
225 | data: mockHandler.data, |
||
226 | dataType: requestSettings.dataType === "script" ? "text/plain" : requestSettings.dataType, |
||
227 | complete: function(xhr) { |
||
228 | mockHandler.responseXML = xhr.responseXML; |
||
229 | mockHandler.responseText = xhr.responseText; |
||
230 | // Don't override the handler status/statusText if it's specified by the config |
||
231 | if (isDefaultSetting(mockHandler, 'status')) { |
||
232 | mockHandler.status = xhr.status; |
||
233 | } |
||
234 | if (isDefaultSetting(mockHandler, 'statusText')) { |
||
235 | mockHandler.statusText = xhr.statusText; |
||
236 | } |
||
237 | this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime) || 0); |
||
238 | } |
||
239 | }); |
||
240 | } else { |
||
241 | // type == 'POST' || 'GET' || 'DELETE' |
||
242 | if ( requestSettings.async === false ) { |
||
243 | // TODO: Blocking delay |
||
244 | process(); |
||
245 | } else { |
||
246 | this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime) || 50); |
||
247 | } |
||
248 | } |
||
249 | } |
||
250 | |||
251 | // Construct a mocked XHR Object |
||
252 | function xhr(mockHandler, requestSettings, origSettings, origHandler) { |
||
253 | // Extend with our default mockjax settings |
||
254 | mockHandler = $.extend(true, {}, $.mockjaxSettings, mockHandler); |
||
255 | |||
256 | if (typeof mockHandler.headers === 'undefined') { |
||
257 | mockHandler.headers = {}; |
||
258 | } |
||
259 | if (typeof requestSettings.headers === 'undefined') { |
||
260 | requestSettings.headers = {}; |
||
261 | } |
||
262 | if ( mockHandler.contentType ) { |
||
263 | mockHandler.headers['content-type'] = mockHandler.contentType; |
||
264 | } |
||
265 | |||
266 | return { |
||
267 | status: mockHandler.status, |
||
268 | statusText: mockHandler.statusText, |
||
269 | readyState: 1, |
||
270 | open: function() { }, |
||
271 | send: function() { |
||
272 | origHandler.fired = true; |
||
273 | _xhrSend.call(this, mockHandler, requestSettings, origSettings); |
||
274 | }, |
||
275 | abort: function() { |
||
276 | clearTimeout(this.responseTimer); |
||
277 | }, |
||
278 | setRequestHeader: function(header, value) { |
||
279 | requestSettings.headers[header] = value; |
||
280 | }, |
||
281 | getResponseHeader: function(header) { |
||
282 | // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery |
||
283 | if ( mockHandler.headers && mockHandler.headers[header] ) { |
||
284 | // Return arbitrary headers |
||
285 | return mockHandler.headers[header]; |
||
286 | } else if ( header.toLowerCase() == 'last-modified' ) { |
||
287 | return mockHandler.lastModified || (new Date()).toString(); |
||
288 | } else if ( header.toLowerCase() == 'etag' ) { |
||
289 | return mockHandler.etag || ''; |
||
290 | } else if ( header.toLowerCase() == 'content-type' ) { |
||
291 | return mockHandler.contentType || 'text/plain'; |
||
292 | } |
||
293 | }, |
||
294 | getAllResponseHeaders: function() { |
||
295 | var headers = ''; |
||
296 | // since jQuery 1.9 responseText type has to match contentType |
||
297 | if (mockHandler.contentType) { |
||
298 | mockHandler.headers['Content-Type'] = mockHandler.contentType; |
||
299 | } |
||
300 | $.each(mockHandler.headers, function(k, v) { |
||
301 | headers += k + ': ' + v + "\n"; |
||
302 | }); |
||
303 | return headers; |
||
304 | } |
||
305 | }; |
||
306 | } |
||
307 | |||
308 | // Process a JSONP mock request. |
||
309 | function processJsonpMock( requestSettings, mockHandler, origSettings ) { |
||
310 | // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here |
||
311 | // because there isn't an easy hook for the cross domain script tag of jsonp |
||
312 | |||
313 | processJsonpUrl( requestSettings ); |
||
314 | |||
315 | requestSettings.dataType = "json"; |
||
316 | if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) { |
||
317 | createJsonpCallback(requestSettings, mockHandler, origSettings); |
||
318 | |||
319 | // We need to make sure |
||
320 | // that a JSONP style response is executed properly |
||
321 | |||
322 | var rurl = /^(\w+:)?\/\/([^\/?#]+)/, |
||
323 | parts = rurl.exec( requestSettings.url ), |
||
324 | remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host); |
||
325 | |||
326 | requestSettings.dataType = "script"; |
||
327 | if(requestSettings.type.toUpperCase() === "GET" && remote ) { |
||
328 | var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings ); |
||
329 | |||
330 | // Check if we are supposed to return a Deferred back to the mock call, or just |
||
331 | // signal success |
||
332 | if(newMockReturn) { |
||
333 | return newMockReturn; |
||
334 | } else { |
||
335 | return true; |
||
336 | } |
||
337 | } |
||
338 | } |
||
339 | return null; |
||
340 | } |
||
341 | |||
342 | // Append the required callback parameter to the end of the request URL, for a JSONP request |
||
343 | function processJsonpUrl( requestSettings ) { |
||
344 | if ( requestSettings.type.toUpperCase() === "GET" ) { |
||
345 | if ( !CALLBACK_REGEX.test( requestSettings.url ) ) { |
||
346 | requestSettings.url += (/\?/.test( requestSettings.url ) ? "&" : "?") + |
||
347 | (requestSettings.jsonp || "callback") + "=?"; |
||
348 | } |
||
349 | } else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) { |
||
350 | requestSettings.data = (requestSettings.data ? requestSettings.data + "&" : "") + (requestSettings.jsonp || "callback") + "=?"; |
||
351 | } |
||
352 | } |
||
353 | |||
354 | // Process a JSONP request by evaluating the mocked response text |
||
355 | function processJsonpRequest( requestSettings, mockHandler, origSettings ) { |
||
356 | // Synthesize the mock request for adding a script tag |
||
357 | var callbackContext = origSettings && origSettings.context || requestSettings, |
||
358 | newMock = null; |
||
359 | |||
360 | |||
361 | // If the response handler on the moock is a function, call it |
||
362 | if ( mockHandler.response && $.isFunction(mockHandler.response) ) { |
||
363 | mockHandler.response(origSettings); |
||
364 | } else { |
||
365 | |||
366 | // Evaluate the responseText javascript in a global context |
||
367 | if( typeof mockHandler.responseText === 'object' ) { |
||
368 | $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')'); |
||
369 | } else { |
||
370 | $.globalEval( '(' + mockHandler.responseText + ')'); |
||
371 | } |
||
372 | } |
||
373 | |||
374 | // Successful response |
||
375 | setTimeout(function() { |
||
376 | jsonpSuccess( requestSettings, callbackContext, mockHandler ); |
||
377 | jsonpComplete( requestSettings, callbackContext, mockHandler ); |
||
378 | }, parseResponseTimeOpt(mockHandler.responseTime) || 0); |
||
379 | |||
380 | // If we are running under jQuery 1.5+, return a deferred object |
||
381 | if($.Deferred){ |
||
382 | newMock = new $.Deferred(); |
||
383 | if(typeof mockHandler.responseText == "object"){ |
||
384 | newMock.resolveWith( callbackContext, [mockHandler.responseText] ); |
||
385 | } |
||
386 | else{ |
||
387 | newMock.resolveWith( callbackContext, [$.parseJSON( mockHandler.responseText )] ); |
||
388 | } |
||
389 | } |
||
390 | return newMock; |
||
391 | } |
||
392 | |||
393 | |||
394 | // Create the required JSONP callback function for the request |
||
395 | function createJsonpCallback( requestSettings, mockHandler, origSettings ) { |
||
396 | var callbackContext = origSettings && origSettings.context || requestSettings; |
||
397 | var jsonp = requestSettings.jsonpCallback || ("jsonp" + jsc++); |
||
398 | |||
399 | // Replace the =? sequence both in the query string and the data |
||
400 | if ( requestSettings.data ) { |
||
401 | requestSettings.data = (requestSettings.data + "").replace(CALLBACK_REGEX, "=" + jsonp + "$1"); |
||
402 | } |
||
403 | |||
404 | requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, "=" + jsonp + "$1"); |
||
405 | |||
406 | |||
407 | // Handle JSONP-style loading |
||
408 | window[ jsonp ] = window[ jsonp ] || function( tmp ) { |
||
409 | data = tmp; |
||
410 | jsonpSuccess( requestSettings, callbackContext, mockHandler ); |
||
411 | jsonpComplete( requestSettings, callbackContext, mockHandler ); |
||
412 | // Garbage collect |
||
413 | window[ jsonp ] = undefined; |
||
414 | |||
415 | try { |
||
416 | delete window[ jsonp ]; |
||
417 | } catch(e) {} |
||
418 | |||
419 | if ( head ) { |
||
420 | head.removeChild( script ); |
||
421 | } |
||
422 | }; |
||
423 | } |
||
424 | |||
425 | // The JSONP request was successful |
||
426 | function jsonpSuccess(requestSettings, callbackContext, mockHandler) { |
||
427 | // If a local callback was specified, fire it and pass it the data |
||
428 | if ( requestSettings.success ) { |
||
429 | requestSettings.success.call( callbackContext, mockHandler.responseText || "", status, {} ); |
||
430 | } |
||
431 | |||
432 | // Fire the global callback |
||
433 | if ( requestSettings.global ) { |
||
434 | (requestSettings.context ? $(requestSettings.context) : $.event).trigger("ajaxSuccess", [{}, requestSettings]); |
||
435 | } |
||
436 | } |
||
437 | |||
438 | // The JSONP request was completed |
||
439 | function jsonpComplete(requestSettings, callbackContext) { |
||
440 | // Process result |
||
441 | if ( requestSettings.complete ) { |
||
442 | requestSettings.complete.call( callbackContext, {} , status ); |
||
443 | } |
||
444 | |||
445 | // The request was completed |
||
446 | if ( requestSettings.global ) { |
||
447 | (requestSettings.context ? $(requestSettings.context) : $.event).trigger("ajaxComplete", [{}, requestSettings]); |
||
448 | } |
||
449 | |||
450 | // Handle the global AJAX counter |
||
451 | if ( requestSettings.global && ! --$.active ) { |
||
452 | $.event.trigger( "ajaxStop" ); |
||
453 | } |
||
454 | } |
||
455 | |||
456 | |||
457 | // The core $.ajax replacement. |
||
458 | function handleAjax( url, origSettings ) { |
||
459 | var mockRequest, requestSettings, mockHandler, overrideCallback; |
||
460 | |||
461 | // If url is an object, simulate pre-1.5 signature |
||
462 | if ( typeof url === "object" ) { |
||
463 | origSettings = url; |
||
464 | url = undefined; |
||
465 | } else { |
||
466 | // work around to support 1.5 signature |
||
467 | origSettings = origSettings || {}; |
||
468 | origSettings.url = url; |
||
469 | } |
||
470 | |||
471 | // Extend the original settings for the request |
||
472 | requestSettings = $.extend(true, {}, $.ajaxSettings, origSettings); |
||
473 | |||
474 | // Generic function to override callback methods for use with |
||
475 | // callback options (onAfterSuccess, onAfterError, onAfterComplete) |
||
476 | overrideCallback = function(action, mockHandler) { |
||
477 | var origHandler = origSettings[action.toLowerCase()]; |
||
478 | return function() { |
||
479 | if ( $.isFunction(origHandler) ) { |
||
480 | origHandler.apply(this, [].slice.call(arguments)); |
||
481 | } |
||
482 | mockHandler['onAfter' + action](); |
||
483 | }; |
||
484 | }; |
||
485 | |||
486 | // Iterate over our mock handlers (in registration order) until we find |
||
487 | // one that is willing to intercept the request |
||
488 | for(var k = 0; k < mockHandlers.length; k++) { |
||
489 | if ( !mockHandlers[k] ) { |
||
490 | continue; |
||
491 | } |
||
492 | |||
493 | mockHandler = getMockForRequest( mockHandlers[k], requestSettings ); |
||
494 | if(!mockHandler) { |
||
495 | // No valid mock found for this request |
||
496 | continue; |
||
497 | } |
||
498 | |||
499 | mockedAjaxCalls.push(requestSettings); |
||
500 | |||
501 | // If logging is enabled, log the mock to the console |
||
502 | $.mockjaxSettings.log( mockHandler, requestSettings ); |
||
503 | |||
504 | |||
505 | if ( requestSettings.dataType && requestSettings.dataType.toUpperCase() === 'JSONP' ) { |
||
506 | if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) { |
||
507 | // This mock will handle the JSONP request |
||
508 | return mockRequest; |
||
509 | } |
||
510 | } |
||
511 | |||
512 | |||
513 | // Removed to fix #54 - keep the mocking data object intact |
||
514 | //mockHandler.data = requestSettings.data; |
||
515 | |||
516 | mockHandler.cache = requestSettings.cache; |
||
517 | mockHandler.timeout = requestSettings.timeout; |
||
518 | mockHandler.global = requestSettings.global; |
||
519 | |||
520 | // In the case of a timeout, we just need to ensure |
||
521 | // an actual jQuery timeout (That is, our reponse won't) |
||
522 | // return faster than the timeout setting. |
||
523 | if ( mockHandler.isTimeout ) { |
||
524 | if ( mockHandler.responseTime > 1 ) { |
||
525 | origSettings.timeout = mockHandler.responseTime - 1; |
||
526 | } else { |
||
527 | mockHandler.responseTime = 2; |
||
528 | origSettings.timeout = 1; |
||
529 | } |
||
530 | mockHandler.isTimeout = false; |
||
531 | } |
||
532 | |||
533 | // Set up onAfter[X] callback functions |
||
534 | if ( $.isFunction( mockHandler.onAfterSuccess ) ) { |
||
535 | origSettings.success = overrideCallback('Success', mockHandler); |
||
536 | } |
||
537 | if ( $.isFunction( mockHandler.onAfterError ) ) { |
||
538 | origSettings.error = overrideCallback('Error', mockHandler); |
||
539 | } |
||
540 | if ( $.isFunction( mockHandler.onAfterComplete ) ) { |
||
541 | origSettings.complete = overrideCallback('Complete', mockHandler); |
||
542 | } |
||
543 | |||
544 | copyUrlParameters(mockHandler, origSettings); |
||
545 | |||
546 | (function(mockHandler, requestSettings, origSettings, origHandler) { |
||
547 | |||
548 | mockRequest = _ajax.call($, $.extend(true, {}, origSettings, { |
||
549 | // Mock the XHR object |
||
550 | xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ); } |
||
551 | })); |
||
552 | })(mockHandler, requestSettings, origSettings, mockHandlers[k]); |
||
553 | |||
554 | return mockRequest; |
||
555 | } |
||
556 | |||
557 | // We don't have a mock request |
||
558 | unmockedAjaxCalls.push(origSettings); |
||
559 | if($.mockjaxSettings.throwUnmocked === true) { |
||
560 | throw new Error('AJAX not mocked: ' + origSettings.url); |
||
561 | } |
||
562 | else { // trigger a normal request |
||
563 | return _ajax.apply($, [origSettings]); |
||
564 | } |
||
565 | } |
||
566 | |||
567 | /** |
||
568 | * Copies URL parameter values if they were captured by a regular expression |
||
569 | * @param {Object} mockHandler |
||
570 | * @param {Object} origSettings |
||
571 | */ |
||
572 | function copyUrlParameters(mockHandler, origSettings) { |
||
573 | //parameters aren't captured if the URL isn't a RegExp |
||
574 | if (!(mockHandler.url instanceof RegExp)) { |
||
575 | return; |
||
576 | } |
||
577 | //if no URL params were defined on the handler, don't attempt a capture |
||
578 | if (!mockHandler.hasOwnProperty('urlParams')) { |
||
579 | return; |
||
580 | } |
||
581 | var captures = mockHandler.url.exec(origSettings.url); |
||
582 | //the whole RegExp match is always the first value in the capture results |
||
583 | if (captures.length === 1) { |
||
584 | return; |
||
585 | } |
||
586 | captures.shift(); |
||
587 | //use handler params as keys and capture resuts as values |
||
588 | var i = 0, |
||
589 | capturesLength = captures.length, |
||
590 | paramsLength = mockHandler.urlParams.length, |
||
591 | //in case the number of params specified is less than actual captures |
||
592 | maxIterations = Math.min(capturesLength, paramsLength), |
||
593 | paramValues = {}; |
||
594 | for (i; i < maxIterations; i++) { |
||
595 | var key = mockHandler.urlParams[i]; |
||
596 | paramValues[key] = captures[i]; |
||
597 | } |
||
598 | origSettings.urlParams = paramValues; |
||
599 | } |
||
600 | |||
601 | |||
602 | // Public |
||
603 | |||
604 | $.extend({ |
||
605 | ajax: handleAjax |
||
606 | }); |
||
607 | |||
608 | $.mockjaxSettings = { |
||
609 | //url: null, |
||
610 | //type: 'GET', |
||
611 | log: function( mockHandler, requestSettings ) { |
||
612 | if ( mockHandler.logging === false || |
||
613 | ( typeof mockHandler.logging === 'undefined' && $.mockjaxSettings.logging === false ) ) { |
||
614 | return; |
||
615 | } |
||
616 | if ( window.console && console.log ) { |
||
617 | var message = 'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url; |
||
618 | var request = $.extend({}, requestSettings); |
||
619 | |||
620 | if (typeof console.log === 'function') { |
||
621 | console.log(message, request); |
||
622 | } else { |
||
623 | try { |
||
624 | console.log( message + ' ' + JSON.stringify(request) ); |
||
625 | } catch (e) { |
||
626 | console.log(message); |
||
627 | } |
||
628 | } |
||
629 | } |
||
630 | }, |
||
631 | logging: true, |
||
632 | status: 200, |
||
633 | statusText: "OK", |
||
634 | responseTime: 500, |
||
635 | isTimeout: false, |
||
636 | throwUnmocked: false, |
||
637 | contentType: 'text/plain', |
||
638 | response: '', |
||
639 | responseText: '', |
||
640 | responseXML: '', |
||
641 | proxy: '', |
||
642 | proxyType: 'GET', |
||
643 | |||
644 | lastModified: null, |
||
645 | etag: '', |
||
646 | headers: { |
||
647 | etag: 'IJF@H#@923uf8023hFO@I#H#', |
||
648 | 'content-type' : 'text/plain' |
||
649 | } |
||
650 | }; |
||
651 | |||
652 | $.mockjax = function(settings) { |
||
653 | var i = mockHandlers.length; |
||
654 | mockHandlers[i] = settings; |
||
655 | return i; |
||
656 | }; |
||
657 | $.mockjax.clear = function(i) { |
||
658 | if ( arguments.length == 1 ) { |
||
659 | mockHandlers[i] = null; |
||
660 | } else { |
||
661 | mockHandlers = []; |
||
662 | } |
||
663 | mockedAjaxCalls = []; |
||
664 | unmockedAjaxCalls = []; |
||
665 | }; |
||
666 | // support older, deprecated version |
||
667 | $.mockjaxClear = function(i) { |
||
668 | window.console && window.console.warn && window.console.warn( 'DEPRECATED: The $.mockjaxClear() method has been deprecated in 1.6.0. Please use $.mockjax.clear() as the older function will be removed soon!' ); |
||
669 | $.mockjax.clear(); |
||
670 | }; |
||
671 | $.mockjax.handler = function(i) { |
||
672 | if ( arguments.length == 1 ) { |
||
673 | return mockHandlers[i]; |
||
674 | } |
||
675 | }; |
||
676 | $.mockjax.mockedAjaxCalls = function() { |
||
677 | return mockedAjaxCalls; |
||
678 | }; |
||
679 | $.mockjax.unfiredHandlers = function() { |
||
680 | var results = []; |
||
681 | for (var i=0, len=mockHandlers.length; i<len; i++) { |
||
682 | var handler = mockHandlers[i]; |
||
683 | if (handler !== null && !handler.fired) { |
||
684 | results.push(handler); |
||
685 | } |
||
686 | } |
||
687 | return results; |
||
688 | }; |
||
689 | $.mockjax.unmockedAjaxCalls = function() { |
||
690 | return unmockedAjaxCalls; |
||
691 | }; |
||
692 | })(jQuery); |