jqtree 1.8.2 → 1.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bower.json +1 -1
- package/package.json +31 -29
- package/src/dragAndDropHandler/generateHitAreas.ts +47 -43
- package/src/nodeElement/ghostDropHint.ts +3 -37
- package/src/nodeElement/index.ts +1 -1
- package/src/saveStateHandler.ts +43 -59
- package/src/version.ts +1 -1
- package/tree.jquery.debug.js +69 -106
- package/tree.jquery.debug.js.map +1 -1
- package/tree.jquery.js +2 -2
- package/tree.jquery.js.map +1 -1
- package/.editorconfig +0 -12
- package/.eslintrc +0 -48
- package/.github/workflows/ci.yml +0 -68
- package/.github/workflows/codeql-analysis.yml +0 -32
- package/.github/workflows/size.yml +0 -24
- package/.github/workflows/static.yml +0 -57
- package/.prettier +0 -3
- package/config/.postcssrc +0 -6
- package/config/babel.config.json +0 -11
- package/config/babel.coverage.config.json +0 -4
- package/config/jest.config.js +0 -24
- package/config/jest.polyfills.js +0 -14
- package/config/playwright.config.js +0 -18
- package/config/production +0 -6
- package/config/rollup.config.mjs +0 -71
- package/css/jqtree.postcss +0 -193
- package/devserver/devserver.js +0 -7
- package/devserver/devserver_scroll.js +0 -8
- package/devserver/index.html +0 -22
- package/devserver/test_index.html +0 -22
- package/devserver/test_scroll.html +0 -28
- package/devserver/test_scroll_container.html +0 -39
- package/docs/.ruby-version +0 -1
- package/docs/Gemfile +0 -5
- package/docs/Gemfile.lock +0 -82
- package/docs/_config.yml +0 -126
- package/docs/_entries/events/index.md +0 -6
- package/docs/_entries/events/tree-click.md +0 -37
- package/docs/_entries/events/tree-close.md +0 -15
- package/docs/_entries/events/tree-contextmenu.md +0 -21
- package/docs/_entries/events/tree-dblclick.md +0 -19
- package/docs/_entries/events/tree-init.md +0 -15
- package/docs/_entries/events/tree-load-data.md +0 -15
- package/docs/_entries/events/tree-loading-data.md +0 -27
- package/docs/_entries/events/tree-move.md +0 -73
- package/docs/_entries/events/tree-open.md +0 -15
- package/docs/_entries/events/tree-refresh.md +0 -12
- package/docs/_entries/events/tree-select.md +0 -28
- package/docs/_entries/functions/addnodeafter.md +0 -20
- package/docs/_entries/functions/addnodebefore.md +0 -8
- package/docs/_entries/functions/addparentnode.md +0 -20
- package/docs/_entries/functions/appendnode.md +0 -50
- package/docs/_entries/functions/closenode.md +0 -23
- package/docs/_entries/functions/destroy.md +0 -12
- package/docs/_entries/functions/getnodebycallback.md +0 -24
- package/docs/_entries/functions/getnodebyhtmlelement.md +0 -29
- package/docs/_entries/functions/getnodebyid.md +0 -21
- package/docs/_entries/functions/getselectednode.md +0 -10
- package/docs/_entries/functions/getstate.md +0 -19
- package/docs/_entries/functions/gettree.md +0 -12
- package/docs/_entries/functions/index.md +0 -6
- package/docs/_entries/functions/is-node-selected.md +0 -11
- package/docs/_entries/functions/isdragging.md +0 -12
- package/docs/_entries/functions/loaddata.md +0 -46
- package/docs/_entries/functions/loaddatafromurl.md +0 -55
- package/docs/_entries/functions/movedown.md +0 -8
- package/docs/_entries/functions/movenode.md +0 -15
- package/docs/_entries/functions/moveup.md +0 -8
- package/docs/_entries/functions/opennode.md +0 -44
- package/docs/_entries/functions/prependnode.md +0 -21
- package/docs/_entries/functions/refresh.md +0 -12
- package/docs/_entries/functions/reload.md +0 -22
- package/docs/_entries/functions/removenode.md +0 -12
- package/docs/_entries/functions/scrolltonode.md +0 -13
- package/docs/_entries/functions/selectnode.md +0 -45
- package/docs/_entries/functions/setoption.md +0 -12
- package/docs/_entries/functions/setstate.md +0 -8
- package/docs/_entries/functions/toggle.md +0 -25
- package/docs/_entries/functions/tojson.md +0 -13
- package/docs/_entries/functions/updatenode.md +0 -50
- package/docs/_entries/general/changelog.md +0 -434
- package/docs/_entries/general/demo.html +0 -28
- package/docs/_entries/general/downloads.md +0 -9
- package/docs/_entries/general/examples.md +0 -8
- package/docs/_entries/general/features.md +0 -15
- package/docs/_entries/general/index.md +0 -7
- package/docs/_entries/general/introduction.md +0 -9
- package/docs/_entries/general/requirements.md +0 -6
- package/docs/_entries/general/tutorial.md +0 -71
- package/docs/_entries/general/usecases.md +0 -15
- package/docs/_entries/multiple_selection/add-to-selection.md +0 -21
- package/docs/_entries/multiple_selection/get-selected-nodes.md +0 -10
- package/docs/_entries/multiple_selection/index.md +0 -9
- package/docs/_entries/multiple_selection/remove-from-selection.md +0 -11
- package/docs/_entries/node/children.md +0 -12
- package/docs/_entries/node/getdata.md +0 -17
- package/docs/_entries/node/getlevel.md +0 -13
- package/docs/_entries/node/getnextnode.md +0 -12
- package/docs/_entries/node/getnextsibling.md +0 -10
- package/docs/_entries/node/getnextvisiblenode.md +0 -15
- package/docs/_entries/node/getpreviousnode.md +0 -12
- package/docs/_entries/node/getprevioussibling.md +0 -10
- package/docs/_entries/node/getpreviousvisiblenode.md +0 -15
- package/docs/_entries/node/index.md +0 -13
- package/docs/_entries/node/parent.md +0 -10
- package/docs/_entries/options/animationspeed.md +0 -7
- package/docs/_entries/options/autoescape.md +0 -6
- package/docs/_entries/options/autoopen.md +0 -28
- package/docs/_entries/options/buttonleft.md +0 -12
- package/docs/_entries/options/closedicon.md +0 -26
- package/docs/_entries/options/data-url.md +0 -45
- package/docs/_entries/options/data.md +0 -46
- package/docs/_entries/options/datafilter.md +0 -17
- package/docs/_entries/options/draganddrop.md +0 -18
- package/docs/_entries/options/index.md +0 -6
- package/docs/_entries/options/keyboardsupport.md +0 -14
- package/docs/_entries/options/oncanmove.md +0 -22
- package/docs/_entries/options/oncanmoveto.md +0 -22
- package/docs/_entries/options/oncanselectnode.md +0 -26
- package/docs/_entries/options/oncreateli.md +0 -22
- package/docs/_entries/options/ondragmove.md +0 -20
- package/docs/_entries/options/ondragstop.md +0 -20
- package/docs/_entries/options/onismovehandle.md +0 -17
- package/docs/_entries/options/onloadfailed.md +0 -15
- package/docs/_entries/options/onloading.md +0 -22
- package/docs/_entries/options/openedicon.md +0 -26
- package/docs/_entries/options/openfolderdelay.md +0 -15
- package/docs/_entries/options/rtl.md +0 -18
- package/docs/_entries/options/savestate.md +0 -39
- package/docs/_entries/options/selectable.md +0 -18
- package/docs/_entries/options/showemptyfolder.md +0 -26
- package/docs/_entries/options/slide.md +0 -12
- package/docs/_entries/options/start_dnd_delay.md +0 -13
- package/docs/_entries/options/tabindex.md +0 -14
- package/docs/_entries/options/usecontextmenu.md +0 -14
- package/docs/_examples/01_load_json_data.html +0 -45
- package/docs/_examples/02_load_json_data_from_server.html +0 -29
- package/docs/_examples/03_drag_and_drop.html +0 -42
- package/docs/_examples/04_save_state.html +0 -46
- package/docs/_examples/05_load_on_demand.html +0 -68
- package/docs/_examples/06_autoescape.html +0 -45
- package/docs/_examples/07_autoscroll.html +0 -42
- package/docs/_examples/08_multiple_select.html +0 -60
- package/docs/_examples/09_custom_html.html +0 -61
- package/docs/_examples/10_icon_buttons.html +0 -26
- package/docs/_examples/11_right-to-left.html +0 -25
- package/docs/_examples/12_button_on_right.html +0 -26
- package/docs/_examples/13_drag_outside.html +0 -48
- package/docs/_examples/14_filter.html +0 -111
- package/docs/_layouts/example.html +0 -7
- package/docs/_layouts/page.html +0 -26
- package/docs/documentation.css +0 -3
- package/docs/index.html +0 -65
- package/docs/package.json +0 -22
- package/docs/pnpm-lock.yaml +0 -892
- package/docs/postcss.config.js +0 -7
- package/docs/static/bower.json +0 -8
- package/docs/static/bower_components/fontawesome/css/all.min.css +0 -9
- package/docs/static/bower_components/fontawesome/webfonts/fa-brands-400.ttf +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-regular-400.ttf +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-v4compatibility.ttf +0 -0
- package/docs/static/bower_components/fontawesome/webfonts/fa-v4compatibility.woff2 +0 -0
- package/docs/static/bower_components/jquery/dist/jquery.js +0 -10704
- package/docs/static/bower_components/jquery/dist/jquery.min.js +0 -2
- package/docs/static/bower_components/jquery-mockjax/dist/jquery.mockjax.js +0 -1061
- package/docs/static/documentation.js +0 -26
- package/docs/static/example.postcss +0 -68
- package/docs/static/example_data.js +0 -122
- package/docs/static/examples/autoescape.js +0 -17
- package/docs/static/examples/autoscroll.js +0 -6
- package/docs/static/examples/button-on-right.js +0 -13
- package/docs/static/examples/custom_html.js +0 -27
- package/docs/static/examples/drag-outside.js +0 -37
- package/docs/static/examples/drag_and_drop.js +0 -13
- package/docs/static/examples/filter.js +0 -63
- package/docs/static/examples/icon_buttons.js +0 -12
- package/docs/static/examples/load_json_data.js +0 -16
- package/docs/static/examples/load_json_data_from_server.js +0 -9
- package/docs/static/examples/load_on_demand.js +0 -19
- package/docs/static/examples/multiple_select.js +0 -23
- package/docs/static/examples/right-to-left.js +0 -11
- package/docs/static/examples/save_state.js +0 -11
- package/docs/static/monokai.css +0 -70
- package/docs/static/spinner.gif +0 -0
- package/docs/tailwind.config.js +0 -16
- package/sitemap.txt +0 -14
- package/src/playwright/.eslintrc +0 -5
- package/src/playwright/coverage.ts +0 -38
- package/src/playwright/playwright.test.ts +0 -401
- package/src/playwright/playwright.test.ts-snapshots/with-dragAndDrop-moves-a-node-1-Chromium-darwin.png +0 -0
- package/src/playwright/playwright.test.ts-snapshots/with-dragAndDrop-moves-a-node-1-Chromium-linux.png +0 -0
- package/src/playwright/playwright.test.ts-snapshots/without-dragAndDrop-displays-a-tree-1-Chromium-darwin.png +0 -0
- package/src/playwright/playwright.test.ts-snapshots/without-dragAndDrop-displays-a-tree-1-Chromium-linux.png +0 -0
- package/src/playwright/playwright.test.ts-snapshots/without-dragAndDrop-selects-a-node-1-Chromium-darwin.png +0 -0
- package/src/playwright/playwright.test.ts-snapshots/without-dragAndDrop-selects-a-node-1-Chromium-linux.png +0 -0
- package/src/playwright/testUtils.ts +0 -153
- package/src/test/.eslintrc +0 -17
- package/src/test/global.d.ts +0 -1
- package/src/test/jqTree/accessibility.test.ts +0 -25
- package/src/test/jqTree/create.test.ts +0 -54
- package/src/test/jqTree/events.test.ts +0 -290
- package/src/test/jqTree/keyboard.test.ts +0 -247
- package/src/test/jqTree/loadOnDemand.test.ts +0 -198
- package/src/test/jqTree/methods.test.ts +0 -1491
- package/src/test/jqTree/mouse.test.ts +0 -82
- package/src/test/jqTree/options.test.ts +0 -595
- package/src/test/node.test.ts +0 -1396
- package/src/test/nodeUtils.test.ts +0 -21
- package/src/test/position.test.ts +0 -30
- package/src/test/support/exampleData.ts +0 -23
- package/src/test/support/jqTreeMatchers.ts +0 -68
- package/src/test/support/matchers.d.ts +0 -31
- package/src/test/support/setupTests.ts +0 -5
- package/src/test/support/testUtil.ts +0 -30
- package/src/test/support/treeStructure.ts +0 -39
- package/src/test/util.test.ts +0 -27
- package/tsconfig.json +0 -24
|
@@ -1,1061 +0,0 @@
|
|
|
1
|
-
/*! jQuery Mockjax
|
|
2
|
-
* A Plugin providing simple and flexible mocking of ajax requests and responses
|
|
3
|
-
*
|
|
4
|
-
* Version: 2.6.0
|
|
5
|
-
* Home: https://github.com/jakerella/jquery-mockjax
|
|
6
|
-
* Copyright (c) 2020 Jordan Kasper, formerly appendTo;
|
|
7
|
-
* NOTE: This repository was taken over by Jordan Kasper (@jakerella) October, 2014
|
|
8
|
-
*
|
|
9
|
-
* Dual licensed under the MIT or GPL licenses.
|
|
10
|
-
* http://opensource.org/licenses/MIT OR http://www.gnu.org/licenses/gpl-2.0.html
|
|
11
|
-
*/
|
|
12
|
-
(function(root, factory) {
|
|
13
|
-
'use strict';
|
|
14
|
-
|
|
15
|
-
// AMDJS module definition
|
|
16
|
-
if ( typeof define === 'function' && define.amd && define.amd.jQuery ) {
|
|
17
|
-
define(['jquery'], function($) {
|
|
18
|
-
return factory($, root);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// CommonJS module definition
|
|
22
|
-
} else if ( typeof exports === 'object') {
|
|
23
|
-
|
|
24
|
-
// NOTE: To use Mockjax as a Node module you MUST provide the factory with
|
|
25
|
-
// a valid version of jQuery and a window object (the global scope):
|
|
26
|
-
// var mockjax = require('jquery.mockjax')(jQuery, window);
|
|
27
|
-
|
|
28
|
-
module.exports = factory;
|
|
29
|
-
|
|
30
|
-
// Global jQuery in web browsers
|
|
31
|
-
} else {
|
|
32
|
-
return factory(root.jQuery || root.$, root);
|
|
33
|
-
}
|
|
34
|
-
}(this, function($, window) {
|
|
35
|
-
'use strict';
|
|
36
|
-
|
|
37
|
-
var _ajax = $.ajax,
|
|
38
|
-
mockHandlers = [],
|
|
39
|
-
mockedAjaxCalls = [],
|
|
40
|
-
unmockedAjaxCalls = [],
|
|
41
|
-
CALLBACK_REGEX = /=\?(&|$)/,
|
|
42
|
-
jsc = (new Date()).getTime(),
|
|
43
|
-
DEFAULT_RESPONSE_TIME = 500;
|
|
44
|
-
|
|
45
|
-
// Parse the given XML string.
|
|
46
|
-
function parseXML(xml) {
|
|
47
|
-
if ( window.DOMParser === undefined && window.ActiveXObject ) {
|
|
48
|
-
window.DOMParser = function() { };
|
|
49
|
-
DOMParser.prototype.parseFromString = function( xmlString ) {
|
|
50
|
-
var doc = new ActiveXObject('Microsoft.XMLDOM');
|
|
51
|
-
doc.async = 'false';
|
|
52
|
-
doc.loadXML( xmlString );
|
|
53
|
-
return doc;
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
|
|
59
|
-
if ( $.isXMLDoc( xmlDoc ) ) {
|
|
60
|
-
var err = $('parsererror', xmlDoc);
|
|
61
|
-
if ( err.length === 1 ) {
|
|
62
|
-
throw new Error('Error: ' + $(xmlDoc).text() );
|
|
63
|
-
}
|
|
64
|
-
} else {
|
|
65
|
-
throw new Error('Unable to parse XML');
|
|
66
|
-
}
|
|
67
|
-
return xmlDoc;
|
|
68
|
-
} catch( e ) {
|
|
69
|
-
var msg = ( e.name === undefined ? e : e.name + ': ' + e.message );
|
|
70
|
-
$(document).trigger('xmlParseError', [ msg ]);
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Check if the data field on the mock handler and the request match. This
|
|
76
|
-
// can be used to restrict a mock handler to being used only when a certain
|
|
77
|
-
// set of data is passed to it.
|
|
78
|
-
function isMockDataEqual( mock, live ) {
|
|
79
|
-
logger.debug( mock, ['Checking mock data against request data', mock, live] );
|
|
80
|
-
var identical = true;
|
|
81
|
-
|
|
82
|
-
if ( $.isFunction(mock) ) {
|
|
83
|
-
return !!mock(live);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Test for situations where the data is a querystring (not an object)
|
|
87
|
-
if (typeof live === 'string') {
|
|
88
|
-
// Querystring may be a regex
|
|
89
|
-
if ($.isFunction( mock.test )) {
|
|
90
|
-
return mock.test(live);
|
|
91
|
-
} else if (typeof mock === 'object') {
|
|
92
|
-
live = getQueryParams(live);
|
|
93
|
-
} else {
|
|
94
|
-
return mock === live;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
$.each(mock, function(k) {
|
|
99
|
-
if ( live[k] === undefined ) {
|
|
100
|
-
identical = false;
|
|
101
|
-
return identical;
|
|
102
|
-
} else {
|
|
103
|
-
if ( typeof live[k] === 'object' && live[k] !== null ) {
|
|
104
|
-
if ( identical && $.isArray( live[k] ) ) {
|
|
105
|
-
identical = $.isArray( mock[k] ) && live[k].length === mock[k].length;
|
|
106
|
-
}
|
|
107
|
-
identical = identical && isMockDataEqual(mock[k], live[k]);
|
|
108
|
-
} else {
|
|
109
|
-
if ( mock[k] && $.isFunction( mock[k].test ) ) {
|
|
110
|
-
identical = identical && mock[k].test(live[k]);
|
|
111
|
-
} else {
|
|
112
|
-
identical = identical && ( mock[k] === live[k] );
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
return identical;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function getQueryParams(queryString) {
|
|
122
|
-
var i, l, param, tmp,
|
|
123
|
-
paramsObj = {},
|
|
124
|
-
params = String(queryString).split(/&/);
|
|
125
|
-
|
|
126
|
-
for (i=0, l=params.length; i<l; ++i) {
|
|
127
|
-
param = params[i];
|
|
128
|
-
try {
|
|
129
|
-
param = decodeURIComponent(param.replace(/\+/g, ' '));
|
|
130
|
-
param = param.split(/=/);
|
|
131
|
-
} catch(e) {
|
|
132
|
-
// Can't parse this one, so let it go?
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (paramsObj[param[0]]) {
|
|
137
|
-
// this is an array query param (more than one entry in query)
|
|
138
|
-
if (!paramsObj[param[0]].splice) {
|
|
139
|
-
// if not already an array, make it one
|
|
140
|
-
tmp = paramsObj[param[0]];
|
|
141
|
-
paramsObj[param[0]] = [];
|
|
142
|
-
paramsObj[param[0]].push(tmp);
|
|
143
|
-
}
|
|
144
|
-
paramsObj[param[0]].push(param[1]);
|
|
145
|
-
} else {
|
|
146
|
-
paramsObj[param[0]] = param[1];
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
logger.debug( null, ['Getting query params from string', queryString, paramsObj] );
|
|
151
|
-
|
|
152
|
-
return paramsObj;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// See if a mock handler property matches the default settings
|
|
156
|
-
function isDefaultSetting(handler, property) {
|
|
157
|
-
return handler[property] === $.mockjaxSettings[property];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Check the given handler should mock the given request
|
|
161
|
-
function getMockForRequest( handler, requestSettings ) {
|
|
162
|
-
// If the mock was registered with a function, let the function decide if we
|
|
163
|
-
// want to mock this request
|
|
164
|
-
if ( $.isFunction(handler) ) {
|
|
165
|
-
return handler( requestSettings );
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Apply namespace prefix to the mock handler's url.
|
|
169
|
-
var namespace = handler.namespace || (typeof(handler.namespace) === 'undefined' && $.mockjaxSettings.namespace);
|
|
170
|
-
|
|
171
|
-
// Inspect the URL of the request and check if the mock handler's url
|
|
172
|
-
// matches the url for this ajax request
|
|
173
|
-
if ( $.isFunction(handler.url.test) ) {
|
|
174
|
-
// namespace exists prepend handler.url with namespace
|
|
175
|
-
if (!!namespace) {
|
|
176
|
-
namespace = namespace.replace(/(\/+)$/, '');
|
|
177
|
-
var pattern = handler.url.source.replace(/^(\^+)/, '').replace(/^/, '^(' + namespace + ')?\/?');
|
|
178
|
-
handler.url = new RegExp(pattern);
|
|
179
|
-
}
|
|
180
|
-
// The user provided a regex for the url, test it
|
|
181
|
-
if ( !handler.url.test( requestSettings.url ) ) {
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
} else {
|
|
185
|
-
|
|
186
|
-
var effectiveUrl = handler.url;
|
|
187
|
-
|
|
188
|
-
if (!!namespace) {
|
|
189
|
-
var namespacedUrl = [
|
|
190
|
-
namespace.replace(/(\/+)$/, ''),
|
|
191
|
-
handler.url.replace(/^(\/+)/, '')
|
|
192
|
-
].join('/');
|
|
193
|
-
effectiveUrl = namespacedUrl;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Look for a simple wildcard '*' or a direct URL match
|
|
197
|
-
var star = effectiveUrl.indexOf('*');
|
|
198
|
-
if (effectiveUrl !== requestSettings.url && star === -1 ||
|
|
199
|
-
!new RegExp(effectiveUrl.replace(/[-[\]{}()+?.,\\^$|#\s]/g, '\\$&').replace(/\*/g, '.+')).test(requestSettings.url)) {
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Inspect the request headers submitted
|
|
205
|
-
if ( handler.requestHeaders ) {
|
|
206
|
-
//No expectation for headers, do not mock this request
|
|
207
|
-
if (requestSettings.headers === undefined) {
|
|
208
|
-
return null;
|
|
209
|
-
} else {
|
|
210
|
-
var headersMismatch = false;
|
|
211
|
-
$.each(handler.requestHeaders, function(key, value) {
|
|
212
|
-
var v = requestSettings.headers[key];
|
|
213
|
-
if(v !== value) {
|
|
214
|
-
headersMismatch = true;
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
//Headers do not match, do not mock this request
|
|
219
|
-
if (headersMismatch) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Inspect the data submitted in the request (either POST body or GET query string)
|
|
226
|
-
if ( handler.data ) {
|
|
227
|
-
if ( !requestSettings.data || !isMockDataEqual(handler.data, requestSettings.data) ) {
|
|
228
|
-
// They're not identical, do not mock this request
|
|
229
|
-
return null;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
// Inspect the request type
|
|
233
|
-
if ( handler && handler.type &&
|
|
234
|
-
handler.type.toLowerCase() !== requestSettings.type.toLowerCase() ) {
|
|
235
|
-
// The request type doesn't match (GET vs. POST)
|
|
236
|
-
return null;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return handler;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function isPosNum(value) {
|
|
243
|
-
return typeof value === 'number' && value >= 0;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function parseResponseTimeOpt(responseTime) {
|
|
247
|
-
if ($.isArray(responseTime) && responseTime.length === 2) {
|
|
248
|
-
var min = responseTime[0];
|
|
249
|
-
var max = responseTime[1];
|
|
250
|
-
if(isPosNum(min) && isPosNum(max)) {
|
|
251
|
-
return Math.floor(Math.random() * (max - min)) + min;
|
|
252
|
-
}
|
|
253
|
-
} else if(isPosNum(responseTime)) {
|
|
254
|
-
return responseTime;
|
|
255
|
-
}
|
|
256
|
-
return DEFAULT_RESPONSE_TIME;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Process the xhr objects send operation
|
|
260
|
-
function _xhrSend(mockHandler, requestSettings, origSettings) {
|
|
261
|
-
logger.debug( mockHandler, ['Sending fake XHR request', mockHandler, requestSettings, origSettings] );
|
|
262
|
-
|
|
263
|
-
// This is a substitute for < 1.4 which lacks $.proxy
|
|
264
|
-
var process = (function(that) {
|
|
265
|
-
return function() {
|
|
266
|
-
return (function() {
|
|
267
|
-
// The request has returned
|
|
268
|
-
this.status = mockHandler.status;
|
|
269
|
-
this.statusText = mockHandler.statusText;
|
|
270
|
-
this.readyState = 1;
|
|
271
|
-
|
|
272
|
-
var finishRequest = function () {
|
|
273
|
-
this.readyState = 4;
|
|
274
|
-
|
|
275
|
-
var onReady;
|
|
276
|
-
// Copy over our mock to our xhr object before passing control back to
|
|
277
|
-
// jQuery's onreadystatechange callback
|
|
278
|
-
if ( requestSettings.dataType === 'json' && ( typeof mockHandler.responseText === 'object' ) ) {
|
|
279
|
-
this.responseText = JSON.stringify(mockHandler.responseText);
|
|
280
|
-
} else if ( requestSettings.dataType === 'xml' ) {
|
|
281
|
-
if ( typeof mockHandler.responseXML === 'string' ) {
|
|
282
|
-
this.responseXML = parseXML(mockHandler.responseXML);
|
|
283
|
-
//in jQuery 1.9.1+, responseXML is processed differently and relies on responseText
|
|
284
|
-
this.responseText = mockHandler.responseXML;
|
|
285
|
-
} else {
|
|
286
|
-
this.responseXML = mockHandler.responseXML;
|
|
287
|
-
}
|
|
288
|
-
} else if (typeof mockHandler.responseText === 'object' && mockHandler.responseText !== null) {
|
|
289
|
-
// since jQuery 1.9 responseText type has to match contentType
|
|
290
|
-
mockHandler.contentType = 'application/json';
|
|
291
|
-
this.responseText = JSON.stringify(mockHandler.responseText);
|
|
292
|
-
} else {
|
|
293
|
-
this.responseText = mockHandler.responseText;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if ($.isArray(mockHandler.status)) {
|
|
297
|
-
var idxStatus = Math.floor(Math.random() * mockHandler.status.length);
|
|
298
|
-
this.status = mockHandler.status[idxStatus];
|
|
299
|
-
} else if (typeof mockHandler.status === 'number' || typeof mockHandler.status === 'string') {
|
|
300
|
-
this.status = mockHandler.status;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if( typeof mockHandler.statusText === 'string') {
|
|
304
|
-
this.statusText = mockHandler.statusText;
|
|
305
|
-
}
|
|
306
|
-
// jQuery 2.0 renamed onreadystatechange to onload
|
|
307
|
-
onReady = this.onload || this.onreadystatechange;
|
|
308
|
-
|
|
309
|
-
// jQuery < 1.4 doesn't have onreadystate change for xhr
|
|
310
|
-
if ( $.isFunction( onReady ) ) {
|
|
311
|
-
if( mockHandler.isTimeout) {
|
|
312
|
-
this.status = -1;
|
|
313
|
-
}
|
|
314
|
-
onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined );
|
|
315
|
-
} else if ( mockHandler.isTimeout ) {
|
|
316
|
-
// Fix for 1.3.2 timeout to keep success from firing.
|
|
317
|
-
this.status = -1;
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
// We have an executable function, call it to give
|
|
322
|
-
// the mock handler a chance to update it's data
|
|
323
|
-
if ( $.isFunction(mockHandler.response) ) {
|
|
324
|
-
// Wait for it to finish
|
|
325
|
-
if ( mockHandler.response.length === 2 ) {
|
|
326
|
-
mockHandler.response(origSettings, function () {
|
|
327
|
-
finishRequest.call(that);
|
|
328
|
-
});
|
|
329
|
-
return;
|
|
330
|
-
} else {
|
|
331
|
-
mockHandler.response(origSettings);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
finishRequest.call(that);
|
|
336
|
-
}).apply(that);
|
|
337
|
-
};
|
|
338
|
-
})(this);
|
|
339
|
-
|
|
340
|
-
if ( mockHandler.proxy ) {
|
|
341
|
-
logger.info( mockHandler, ['Retrieving proxy file: ' + mockHandler.proxy, mockHandler] );
|
|
342
|
-
// We're proxying this request and loading in an external file instead
|
|
343
|
-
_ajax({
|
|
344
|
-
global: false,
|
|
345
|
-
url: mockHandler.proxy,
|
|
346
|
-
type: mockHandler.proxyType,
|
|
347
|
-
data: mockHandler.data,
|
|
348
|
-
async: requestSettings.async,
|
|
349
|
-
dataType: requestSettings.dataType === 'script' ? 'text/plain' : requestSettings.dataType,
|
|
350
|
-
complete: function(xhr) {
|
|
351
|
-
// Fix for bug #105
|
|
352
|
-
// jQuery will convert the text to XML for us, and if we use the actual responseXML here
|
|
353
|
-
// then some other things don't happen, resulting in no data given to the 'success' cb
|
|
354
|
-
mockHandler.responseXML = mockHandler.responseText = xhr.responseText;
|
|
355
|
-
|
|
356
|
-
// Don't override the handler status/statusText if it's specified by the config
|
|
357
|
-
if (isDefaultSetting(mockHandler, 'status')) {
|
|
358
|
-
mockHandler.status = xhr.status;
|
|
359
|
-
}
|
|
360
|
-
if (isDefaultSetting(mockHandler, 'statusText')) {
|
|
361
|
-
mockHandler.statusText = xhr.statusText;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
if ( requestSettings.async === false ) {
|
|
365
|
-
// TODO: Blocking delay
|
|
366
|
-
process();
|
|
367
|
-
} else {
|
|
368
|
-
this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime));
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
} else {
|
|
373
|
-
// type === 'POST' || 'GET' || 'DELETE'
|
|
374
|
-
if ( requestSettings.async === false ) {
|
|
375
|
-
// TODO: Blocking delay
|
|
376
|
-
process();
|
|
377
|
-
} else {
|
|
378
|
-
this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime));
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Construct a mocked XHR Object
|
|
385
|
-
function xhr(mockHandler, requestSettings, origSettings, origHandler) {
|
|
386
|
-
logger.debug( mockHandler, ['Creating new mock XHR object', mockHandler, requestSettings, origSettings, origHandler] );
|
|
387
|
-
|
|
388
|
-
// Extend with our default mockjax settings
|
|
389
|
-
mockHandler = $.extend(true, {}, $.mockjaxSettings, mockHandler);
|
|
390
|
-
|
|
391
|
-
if (typeof mockHandler.headers === 'undefined') {
|
|
392
|
-
mockHandler.headers = {};
|
|
393
|
-
}
|
|
394
|
-
if (typeof requestSettings.headers === 'undefined') {
|
|
395
|
-
requestSettings.headers = {};
|
|
396
|
-
}
|
|
397
|
-
if ( mockHandler.contentType ) {
|
|
398
|
-
mockHandler.headers['content-type'] = mockHandler.contentType;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
return {
|
|
402
|
-
status: mockHandler.status,
|
|
403
|
-
statusText: mockHandler.statusText,
|
|
404
|
-
readyState: 1,
|
|
405
|
-
open: function() { },
|
|
406
|
-
send: function() {
|
|
407
|
-
origHandler.fired = true;
|
|
408
|
-
_xhrSend.call(this, mockHandler, requestSettings, origSettings);
|
|
409
|
-
},
|
|
410
|
-
abort: function() {
|
|
411
|
-
clearTimeout(this.responseTimer);
|
|
412
|
-
},
|
|
413
|
-
setRequestHeader: function(header, value) {
|
|
414
|
-
requestSettings.headers[header] = value;
|
|
415
|
-
},
|
|
416
|
-
getResponseHeader: function(header) {
|
|
417
|
-
// 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
|
|
418
|
-
if ( mockHandler.headers && mockHandler.headers[header] ) {
|
|
419
|
-
// Return arbitrary headers
|
|
420
|
-
return mockHandler.headers[header];
|
|
421
|
-
} else if ( header.toLowerCase() === 'last-modified' ) {
|
|
422
|
-
return mockHandler.lastModified || (new Date()).toString();
|
|
423
|
-
} else if ( header.toLowerCase() === 'etag' ) {
|
|
424
|
-
return mockHandler.etag || '';
|
|
425
|
-
} else if ( header.toLowerCase() === 'content-type' ) {
|
|
426
|
-
return mockHandler.contentType || 'text/plain';
|
|
427
|
-
}
|
|
428
|
-
},
|
|
429
|
-
getAllResponseHeaders: function() {
|
|
430
|
-
var headers = '';
|
|
431
|
-
// since jQuery 1.9 responseText type has to match contentType
|
|
432
|
-
if (mockHandler.contentType) {
|
|
433
|
-
mockHandler.headers['content-type'] = mockHandler.contentType;
|
|
434
|
-
}
|
|
435
|
-
$.each(mockHandler.headers, function(k, v) {
|
|
436
|
-
headers += k + ': ' + v + '\n';
|
|
437
|
-
});
|
|
438
|
-
return headers;
|
|
439
|
-
}
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// Process a JSONP mock request.
|
|
444
|
-
function processJsonpMock( requestSettings, mockHandler, origSettings ) {
|
|
445
|
-
// Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
|
|
446
|
-
// because there isn't an easy hook for the cross domain script tag of jsonp
|
|
447
|
-
|
|
448
|
-
processJsonpUrl( requestSettings );
|
|
449
|
-
|
|
450
|
-
requestSettings.dataType = 'json';
|
|
451
|
-
if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
|
|
452
|
-
createJsonpCallback(requestSettings, mockHandler, origSettings);
|
|
453
|
-
|
|
454
|
-
// We need to make sure
|
|
455
|
-
// that a JSONP style response is executed properly
|
|
456
|
-
|
|
457
|
-
var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
|
|
458
|
-
parts = rurl.exec( requestSettings.url ),
|
|
459
|
-
remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
|
|
460
|
-
|
|
461
|
-
requestSettings.dataType = 'script';
|
|
462
|
-
if(requestSettings.type.toUpperCase() === 'GET' && remote ) {
|
|
463
|
-
var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
|
|
464
|
-
|
|
465
|
-
// Check if we are supposed to return a Deferred back to the mock call, or just
|
|
466
|
-
// signal success
|
|
467
|
-
if(newMockReturn) {
|
|
468
|
-
return newMockReturn;
|
|
469
|
-
} else {
|
|
470
|
-
return true;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
return null;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// Append the required callback parameter to the end of the request URL, for a JSONP request
|
|
478
|
-
function processJsonpUrl( requestSettings ) {
|
|
479
|
-
if ( requestSettings.type.toUpperCase() === 'GET' ) {
|
|
480
|
-
if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
|
|
481
|
-
requestSettings.url += (/\?/.test( requestSettings.url ) ? '&' : '?') +
|
|
482
|
-
(requestSettings.jsonp || 'callback') + '=?';
|
|
483
|
-
}
|
|
484
|
-
} else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
|
|
485
|
-
requestSettings.data = (requestSettings.data ? requestSettings.data + '&' : '') + (requestSettings.jsonp || 'callback') + '=?';
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// Process a JSONP request by evaluating the mocked response text
|
|
490
|
-
function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
|
|
491
|
-
logger.debug( mockHandler, ['Performing JSONP request', mockHandler, requestSettings, origSettings] );
|
|
492
|
-
|
|
493
|
-
// Synthesize the mock request for adding a script tag
|
|
494
|
-
var callbackContext = origSettings && origSettings.context || requestSettings,
|
|
495
|
-
// If we are running under jQuery 1.5+, return a deferred object
|
|
496
|
-
newMock = ($.Deferred) ? (new $.Deferred()) : null;
|
|
497
|
-
|
|
498
|
-
// If the response handler on the moock is a function, call it
|
|
499
|
-
if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
|
|
500
|
-
|
|
501
|
-
mockHandler.response(origSettings);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
} else if ( typeof mockHandler.responseText === 'object' ) {
|
|
505
|
-
// Evaluate the responseText javascript in a global context
|
|
506
|
-
$.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
|
|
507
|
-
|
|
508
|
-
} else if (mockHandler.proxy) {
|
|
509
|
-
logger.info( mockHandler, ['Performing JSONP proxy request: ' + mockHandler.proxy, mockHandler] );
|
|
510
|
-
|
|
511
|
-
// This handles the unique case where we have a remote URL, but want to proxy the JSONP
|
|
512
|
-
// response to another file (not the same URL as the mock matching)
|
|
513
|
-
_ajax({
|
|
514
|
-
global: false,
|
|
515
|
-
url: mockHandler.proxy,
|
|
516
|
-
type: mockHandler.proxyType,
|
|
517
|
-
data: mockHandler.data,
|
|
518
|
-
dataType: requestSettings.dataType === 'script' ? 'text/plain' : requestSettings.dataType,
|
|
519
|
-
complete: function(xhr) {
|
|
520
|
-
$.globalEval( '(' + xhr.responseText + ')');
|
|
521
|
-
completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock );
|
|
522
|
-
}
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
return newMock;
|
|
526
|
-
|
|
527
|
-
} else {
|
|
528
|
-
$.globalEval( '(' +
|
|
529
|
-
((typeof mockHandler.responseText === 'string') ?
|
|
530
|
-
('"' + mockHandler.responseText + '"') : mockHandler.responseText) +
|
|
531
|
-
')');
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock );
|
|
535
|
-
|
|
536
|
-
return newMock;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
function completeJsonpCall( requestSettings, mockHandler, callbackContext, newMock ) {
|
|
540
|
-
var json;
|
|
541
|
-
|
|
542
|
-
// Successful response
|
|
543
|
-
setTimeout(function() {
|
|
544
|
-
jsonpSuccess( requestSettings, callbackContext, mockHandler );
|
|
545
|
-
jsonpComplete( requestSettings, callbackContext );
|
|
546
|
-
|
|
547
|
-
if ( newMock ) {
|
|
548
|
-
try {
|
|
549
|
-
json = $.parseJSON( mockHandler.responseText );
|
|
550
|
-
} catch (err) { /* just checking... */ }
|
|
551
|
-
|
|
552
|
-
newMock.resolveWith( callbackContext, [json || mockHandler.responseText] );
|
|
553
|
-
logger.log( mockHandler, ['JSONP mock call complete', mockHandler, newMock] );
|
|
554
|
-
}
|
|
555
|
-
}, parseResponseTimeOpt( mockHandler.responseTime ));
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
// Create the required JSONP callback function for the request
|
|
560
|
-
function createJsonpCallback( requestSettings, mockHandler, origSettings ) {
|
|
561
|
-
var callbackContext = origSettings && origSettings.context || requestSettings;
|
|
562
|
-
var jsonp = (typeof requestSettings.jsonpCallback === 'string' && requestSettings.jsonpCallback) || ('jsonp' + jsc++);
|
|
563
|
-
|
|
564
|
-
// Replace the =? sequence both in the query string and the data
|
|
565
|
-
if ( requestSettings.data ) {
|
|
566
|
-
requestSettings.data = (requestSettings.data + '').replace(CALLBACK_REGEX, '=' + jsonp + '$1');
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, '=' + jsonp + '$1');
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
// Handle JSONP-style loading
|
|
573
|
-
window[ jsonp ] = window[ jsonp ] || function() {
|
|
574
|
-
jsonpSuccess( requestSettings, callbackContext, mockHandler );
|
|
575
|
-
jsonpComplete( requestSettings, callbackContext );
|
|
576
|
-
// Garbage collect
|
|
577
|
-
window[ jsonp ] = undefined;
|
|
578
|
-
|
|
579
|
-
try {
|
|
580
|
-
delete window[ jsonp ];
|
|
581
|
-
} catch(e) {}
|
|
582
|
-
};
|
|
583
|
-
requestSettings.jsonpCallback = jsonp;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// The JSONP request was successful
|
|
587
|
-
function jsonpSuccess(requestSettings, callbackContext, mockHandler) {
|
|
588
|
-
// If a local callback was specified, fire it and pass it the data
|
|
589
|
-
if ( requestSettings.success ) {
|
|
590
|
-
requestSettings.success.call( callbackContext, mockHandler.responseText || '', 'success', {} );
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// Fire the global callback
|
|
594
|
-
if ( requestSettings.global ) {
|
|
595
|
-
(requestSettings.context ? $(requestSettings.context) : $.event).trigger('ajaxSuccess', [{}, requestSettings]);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// The JSONP request was completed
|
|
600
|
-
function jsonpComplete(requestSettings, callbackContext) {
|
|
601
|
-
if ( requestSettings.complete ) {
|
|
602
|
-
requestSettings.complete.call( callbackContext, {
|
|
603
|
-
statusText: 'success',
|
|
604
|
-
status: 200
|
|
605
|
-
} , 'success' );
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// The request was completed
|
|
609
|
-
if ( requestSettings.global ) {
|
|
610
|
-
(requestSettings.context ? $(requestSettings.context) : $.event).trigger('ajaxComplete', [{}, requestSettings]);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// Handle the global AJAX counter
|
|
614
|
-
if ( requestSettings.global && ! --$.active ) {
|
|
615
|
-
$.event.trigger( 'ajaxStop' );
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
// The core $.ajax replacement.
|
|
621
|
-
function handleAjax( url, origSettings ) {
|
|
622
|
-
var mockRequest, requestSettings, mockHandler, overrideCallback;
|
|
623
|
-
|
|
624
|
-
logger.debug( null, ['Ajax call intercepted', url, origSettings] );
|
|
625
|
-
|
|
626
|
-
// If url is an object, simulate pre-1.5 signature
|
|
627
|
-
if ( typeof url === 'object' ) {
|
|
628
|
-
origSettings = url;
|
|
629
|
-
url = undefined;
|
|
630
|
-
} else {
|
|
631
|
-
// work around to support 1.5 signature
|
|
632
|
-
origSettings = origSettings || {};
|
|
633
|
-
origSettings.url = url || origSettings.url;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// Extend the original settings for the request
|
|
637
|
-
requestSettings = $.ajaxSetup({}, origSettings);
|
|
638
|
-
requestSettings.type = requestSettings.method = requestSettings.method || requestSettings.type;
|
|
639
|
-
|
|
640
|
-
// Generic function to override callback methods for use with
|
|
641
|
-
// callback options (onAfterSuccess, onAfterError, onAfterComplete)
|
|
642
|
-
overrideCallback = function(action, mockHandler) {
|
|
643
|
-
var origHandler = origSettings[action.toLowerCase()];
|
|
644
|
-
return function() {
|
|
645
|
-
if ( $.isFunction(origHandler) ) {
|
|
646
|
-
origHandler.apply(this, [].slice.call(arguments));
|
|
647
|
-
}
|
|
648
|
-
mockHandler['onAfter' + action]();
|
|
649
|
-
};
|
|
650
|
-
};
|
|
651
|
-
|
|
652
|
-
// Iterate over our mock handlers (in order depending on the matchInRegistrationOrder setting)
|
|
653
|
-
// until we find one that is willing to intercept the request
|
|
654
|
-
for(var k = 0; k < mockHandlers.length; k++) {
|
|
655
|
-
var handlerIndex = $.mockjaxSettings.matchInRegistrationOrder ? k : mockHandlers.length - 1 - k;
|
|
656
|
-
var origHandler = mockHandlers[handlerIndex];
|
|
657
|
-
if ( !origHandler ) {
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
mockHandler = getMockForRequest( origHandler, requestSettings );
|
|
662
|
-
if(!mockHandler) {
|
|
663
|
-
logger.debug( origHandler, ['Mock does not match request', url, requestSettings] );
|
|
664
|
-
// No valid mock found for this request
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
if ($.mockjaxSettings.retainAjaxCalls) {
|
|
669
|
-
mockedAjaxCalls.push(requestSettings);
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
// If logging is enabled, log the mock to the console
|
|
673
|
-
logger.info( mockHandler, [
|
|
674
|
-
'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url,
|
|
675
|
-
$.ajaxSetup({}, requestSettings)
|
|
676
|
-
] );
|
|
677
|
-
|
|
678
|
-
if ((mockHandler.status === 301 || mockHandler.status === 302) &&
|
|
679
|
-
(requestSettings.type.toUpperCase() === 'GET' || requestSettings.type.toUpperCase() === 'HEAD') &&
|
|
680
|
-
mockHandler.headers.Location) {
|
|
681
|
-
logger.debug('Doing mock redirect to', mockHandler.headers.Location, requestSettings.type);
|
|
682
|
-
|
|
683
|
-
var redirectSettings = {};
|
|
684
|
-
var origKeys = Object.keys(origSettings);
|
|
685
|
-
// We can't alter origSettings, so we need a shallow copy of it...
|
|
686
|
-
for (var oi=0; oi<origKeys.length; oi++) {
|
|
687
|
-
redirectSettings[origKeys[oi]] = origSettings[origKeys[oi]];
|
|
688
|
-
}
|
|
689
|
-
redirectSettings.url = mockHandler.headers.Location;
|
|
690
|
-
redirectSettings.headers = {
|
|
691
|
-
Referer: origSettings.url
|
|
692
|
-
};
|
|
693
|
-
|
|
694
|
-
return handleAjax(redirectSettings);
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
if ( requestSettings.dataType && requestSettings.dataType.toUpperCase() === 'JSONP' ) {
|
|
698
|
-
if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
|
|
699
|
-
// This mock will handle the JSONP request
|
|
700
|
-
return mockRequest;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// We are mocking, so there will be no cross domain request, however, jQuery
|
|
705
|
-
// aggressively pursues this if the domains don't match, so we need to
|
|
706
|
-
// explicitly disallow it. (See #136)
|
|
707
|
-
origSettings.crossDomain = false;
|
|
708
|
-
|
|
709
|
-
// Removed to fix #54 - keep the mocking data object intact
|
|
710
|
-
//mockHandler.data = requestSettings.data;
|
|
711
|
-
|
|
712
|
-
mockHandler.cache = requestSettings.cache;
|
|
713
|
-
mockHandler.timeout = requestSettings.timeout;
|
|
714
|
-
mockHandler.global = requestSettings.global;
|
|
715
|
-
|
|
716
|
-
// In the case of a timeout, we just need to ensure
|
|
717
|
-
// an actual jQuery timeout (That is, our reponse won't)
|
|
718
|
-
// return faster than the timeout setting.
|
|
719
|
-
if ( mockHandler.isTimeout ) {
|
|
720
|
-
if ( mockHandler.responseTime > 1 ) {
|
|
721
|
-
origSettings.timeout = mockHandler.responseTime - 1;
|
|
722
|
-
} else {
|
|
723
|
-
mockHandler.responseTime = 2;
|
|
724
|
-
origSettings.timeout = 1;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// Set up onAfter[X] callback functions
|
|
729
|
-
if ( $.isFunction( mockHandler.onAfterSuccess ) ) {
|
|
730
|
-
origSettings.success = overrideCallback('Success', mockHandler);
|
|
731
|
-
}
|
|
732
|
-
if ( $.isFunction( mockHandler.onAfterError ) ) {
|
|
733
|
-
origSettings.error = overrideCallback('Error', mockHandler);
|
|
734
|
-
}
|
|
735
|
-
if ( $.isFunction( mockHandler.onAfterComplete ) ) {
|
|
736
|
-
origSettings.complete = overrideCallback('Complete', mockHandler);
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
copyUrlParameters(mockHandler, origSettings);
|
|
740
|
-
|
|
741
|
-
/* jshint loopfunc:true */
|
|
742
|
-
(function(mockHandler, requestSettings, origSettings, origHandler) {
|
|
743
|
-
|
|
744
|
-
mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
|
|
745
|
-
// Mock the XHR object
|
|
746
|
-
xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ); }
|
|
747
|
-
}));
|
|
748
|
-
})(mockHandler, requestSettings, origSettings, origHandler);
|
|
749
|
-
/* jshint loopfunc:false */
|
|
750
|
-
|
|
751
|
-
return mockRequest;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// We don't have a mock request
|
|
755
|
-
logger.log( null, ['No mock matched to request', url, origSettings] );
|
|
756
|
-
if ($.mockjaxSettings.retainAjaxCalls) {
|
|
757
|
-
unmockedAjaxCalls.push(origSettings);
|
|
758
|
-
}
|
|
759
|
-
if($.mockjaxSettings.throwUnmocked === true) {
|
|
760
|
-
throw new Error('AJAX not mocked: ' + origSettings.url);
|
|
761
|
-
}
|
|
762
|
-
else { // trigger a normal request
|
|
763
|
-
logger.log('Real ajax call to', origSettings.url);
|
|
764
|
-
return _ajax.apply($, [origSettings]);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
/**
|
|
769
|
-
* Copies URL parameter values if they were captured by a regular expression
|
|
770
|
-
* @param {Object} mockHandler
|
|
771
|
-
* @param {Object} origSettings
|
|
772
|
-
*/
|
|
773
|
-
function copyUrlParameters(mockHandler, origSettings) {
|
|
774
|
-
//parameters aren't captured if the URL isn't a RegExp
|
|
775
|
-
if (!(mockHandler.url instanceof RegExp)) {
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
//if no URL params were defined on the handler, don't attempt a capture
|
|
779
|
-
if (!mockHandler.hasOwnProperty('urlParams')) {
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
var captures = mockHandler.url.exec(origSettings.url);
|
|
783
|
-
//the whole RegExp match is always the first value in the capture results
|
|
784
|
-
if (captures.length === 1) {
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
captures.shift();
|
|
788
|
-
//use handler params as keys and capture resuts as values
|
|
789
|
-
var i = 0,
|
|
790
|
-
capturesLength = captures.length,
|
|
791
|
-
paramsLength = mockHandler.urlParams.length,
|
|
792
|
-
//in case the number of params specified is less than actual captures
|
|
793
|
-
maxIterations = Math.min(capturesLength, paramsLength),
|
|
794
|
-
paramValues = {};
|
|
795
|
-
for (i; i < maxIterations; i++) {
|
|
796
|
-
var key = mockHandler.urlParams[i];
|
|
797
|
-
paramValues[key] = captures[i];
|
|
798
|
-
}
|
|
799
|
-
origSettings.urlParams = paramValues;
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/**
|
|
803
|
-
* Clears handlers that mock given url
|
|
804
|
-
* @param url
|
|
805
|
-
* @returns {Array}
|
|
806
|
-
*/
|
|
807
|
-
function clearByUrl(url) {
|
|
808
|
-
var i, len,
|
|
809
|
-
handler,
|
|
810
|
-
results = [],
|
|
811
|
-
match=url instanceof RegExp ?
|
|
812
|
-
function(testUrl) { return url.test(testUrl); } :
|
|
813
|
-
function(testUrl) { return url === testUrl; };
|
|
814
|
-
for (i=0, len=mockHandlers.length; i<len; i++) {
|
|
815
|
-
handler = mockHandlers[i];
|
|
816
|
-
if (!match(handler.url)) {
|
|
817
|
-
results.push(handler);
|
|
818
|
-
} else {
|
|
819
|
-
logger.log( handler, [
|
|
820
|
-
'Clearing mock: ' + (handler && handler.url),
|
|
821
|
-
handler
|
|
822
|
-
] );
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
return results;
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
// Public
|
|
830
|
-
|
|
831
|
-
$.extend({
|
|
832
|
-
ajax: handleAjax
|
|
833
|
-
});
|
|
834
|
-
|
|
835
|
-
var logger = {
|
|
836
|
-
_log: function logger( mockHandler, args, level ) {
|
|
837
|
-
var loggerLevel = $.mockjaxSettings.logging;
|
|
838
|
-
if (mockHandler && typeof mockHandler.logging !== 'undefined') {
|
|
839
|
-
loggerLevel = mockHandler.logging;
|
|
840
|
-
}
|
|
841
|
-
level = ( level === 0 ) ? level : ( level || logLevels.LOG );
|
|
842
|
-
args = (args.splice) ? args : [ args ];
|
|
843
|
-
|
|
844
|
-
// Is logging turned off for this mock or mockjax as a whole?
|
|
845
|
-
// Or is this log message above the desired log level?
|
|
846
|
-
if ( loggerLevel === false || loggerLevel < level ) {
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
if ( $.mockjaxSettings.log ) {
|
|
851
|
-
return $.mockjaxSettings.log( mockHandler, args[1] || args[0] );
|
|
852
|
-
} else if ( $.mockjaxSettings.logger && $.mockjaxSettings.logger[$.mockjaxSettings.logLevelMethods[level]] ) {
|
|
853
|
-
return $.mockjaxSettings.logger[$.mockjaxSettings.logLevelMethods[level]].apply( $.mockjaxSettings.logger, args );
|
|
854
|
-
}
|
|
855
|
-
},
|
|
856
|
-
/**
|
|
857
|
-
* Convenience method for logging a DEBUG level message
|
|
858
|
-
* @param {Object} m The mock handler in question
|
|
859
|
-
* @param {Array|String|Object} a The items to log
|
|
860
|
-
* @return {?} Will return whatever the $.mockjaxSettings.logger method for this level would return (generally 'undefined')
|
|
861
|
-
*/
|
|
862
|
-
debug: function(m,a) { return logger._log(m,a,logLevels.DEBUG); },
|
|
863
|
-
/**
|
|
864
|
-
* @see logger.debug
|
|
865
|
-
*/
|
|
866
|
-
log: function(m,a) { return logger._log(m,a,logLevels.LOG); },
|
|
867
|
-
/**
|
|
868
|
-
* @see logger.debug
|
|
869
|
-
*/
|
|
870
|
-
info: function(m,a) { return logger._log(m,a,logLevels.INFO); },
|
|
871
|
-
/**
|
|
872
|
-
* @see logger.debug
|
|
873
|
-
*/
|
|
874
|
-
warn: function(m,a) { return logger._log(m,a,logLevels.WARN); },
|
|
875
|
-
/**
|
|
876
|
-
* @see logger.debug
|
|
877
|
-
*/
|
|
878
|
-
error: function(m,a) { return logger._log(m,a,logLevels.ERROR); }
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
var logLevels = {
|
|
882
|
-
DEBUG: 4,
|
|
883
|
-
LOG: 3,
|
|
884
|
-
INFO: 2,
|
|
885
|
-
WARN: 1,
|
|
886
|
-
ERROR: 0
|
|
887
|
-
};
|
|
888
|
-
|
|
889
|
-
/**
|
|
890
|
-
* Default settings for mockjax. Some of these are used for defaults of
|
|
891
|
-
* individual mock handlers, and some are for the library as a whole.
|
|
892
|
-
* For individual mock handler settings, please see the README on the repo:
|
|
893
|
-
* https://github.com/jakerella/jquery-mockjax#api-methods.
|
|
894
|
-
* For Global settings see:
|
|
895
|
-
* https://github.com/jakerella/jquery-mockjax#globally-defining-mockjax-settings
|
|
896
|
-
*
|
|
897
|
-
* @type {Object}
|
|
898
|
-
*/
|
|
899
|
-
$.mockjaxSettings = {
|
|
900
|
-
log: null, // this is only here for historical purposes... use $.mockjaxSettings.logger
|
|
901
|
-
logger: window.console,
|
|
902
|
-
logging: 2,
|
|
903
|
-
logLevelMethods: ['error', 'warn', 'info', 'log', 'debug'],
|
|
904
|
-
matchInRegistrationOrder: true,
|
|
905
|
-
namespace: null,
|
|
906
|
-
status: 200,
|
|
907
|
-
statusText: 'OK',
|
|
908
|
-
responseTime: DEFAULT_RESPONSE_TIME,
|
|
909
|
-
isTimeout: false,
|
|
910
|
-
throwUnmocked: false,
|
|
911
|
-
retainAjaxCalls: true,
|
|
912
|
-
contentType: 'text/plain',
|
|
913
|
-
response: '',
|
|
914
|
-
responseText: '',
|
|
915
|
-
responseXML: '',
|
|
916
|
-
proxy: '',
|
|
917
|
-
proxyType: 'GET',
|
|
918
|
-
|
|
919
|
-
lastModified: null,
|
|
920
|
-
etag: '',
|
|
921
|
-
headers: {
|
|
922
|
-
etag: 'IJF@H#@923uf8023hFO@I#H#',
|
|
923
|
-
'content-type' : 'text/plain'
|
|
924
|
-
}
|
|
925
|
-
};
|
|
926
|
-
|
|
927
|
-
/**
|
|
928
|
-
* Create a new mock Ajax handler. When a mock handler is matched during a
|
|
929
|
-
* $.ajax() call this library will intercept that request and fake a response
|
|
930
|
-
* using the data and methods in the mock. You can see all settings in the
|
|
931
|
-
* README of the main repository:
|
|
932
|
-
* https://github.com/jakerella/jquery-mockjax#api-methods
|
|
933
|
-
*
|
|
934
|
-
* @param {Object} settings The mock handelr settings: https://github.com/jakerella/jquery-mockjax#api-methods
|
|
935
|
-
* @return {Number} The id (index) of the mock handler suitable for clearing (see $.mockjax.clear())
|
|
936
|
-
*/
|
|
937
|
-
$.mockjax = function(settings) {
|
|
938
|
-
// Multiple mocks.
|
|
939
|
-
if ( $.isArray(settings) ) {
|
|
940
|
-
return $.map(settings, function(s) {
|
|
941
|
-
return $.mockjax(s);
|
|
942
|
-
});
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
var i = mockHandlers.length;
|
|
946
|
-
mockHandlers[i] = settings;
|
|
947
|
-
logger.log( settings, ['Created new mock handler', settings] );
|
|
948
|
-
return i;
|
|
949
|
-
};
|
|
950
|
-
|
|
951
|
-
$.mockjax._logger = logger;
|
|
952
|
-
|
|
953
|
-
/**
|
|
954
|
-
* Remove an Ajax mock from those held in memory. This will prevent any
|
|
955
|
-
* future Ajax request mocking for matched requests.
|
|
956
|
-
* NOTE: Clearing a mock will not prevent the resolution of in progress requests
|
|
957
|
-
*
|
|
958
|
-
* @param {Number|String|RegExp} i OPTIONAL The mock to clear. If not provided, all mocks are cleared,
|
|
959
|
-
* if a number it is the index in the in-memory cache. If a string or
|
|
960
|
-
* RegExp, find a mock that matches that URL and clear it.
|
|
961
|
-
* @return {void}
|
|
962
|
-
*/
|
|
963
|
-
$.mockjax.clear = function(i) {
|
|
964
|
-
if ( typeof i === 'string' || i instanceof RegExp) {
|
|
965
|
-
mockHandlers = clearByUrl(i);
|
|
966
|
-
} else if ( i || i === 0 ) {
|
|
967
|
-
logger.log( mockHandlers[i], [
|
|
968
|
-
'Clearing mock: ' + (mockHandlers[i] && mockHandlers[i].url),
|
|
969
|
-
mockHandlers[i]
|
|
970
|
-
] );
|
|
971
|
-
mockHandlers[i] = null;
|
|
972
|
-
} else {
|
|
973
|
-
logger.log( null, 'Clearing all mocks' );
|
|
974
|
-
mockHandlers = [];
|
|
975
|
-
}
|
|
976
|
-
mockedAjaxCalls = [];
|
|
977
|
-
unmockedAjaxCalls = [];
|
|
978
|
-
};
|
|
979
|
-
|
|
980
|
-
/**
|
|
981
|
-
* By default all Ajax requests performed after loading Mockjax are recorded
|
|
982
|
-
* so that we can see which requests were mocked and which were not. This
|
|
983
|
-
* method allows the developer to clear those retained requests.
|
|
984
|
-
*
|
|
985
|
-
* @return {void}
|
|
986
|
-
*/
|
|
987
|
-
$.mockjax.clearRetainedAjaxCalls = function() {
|
|
988
|
-
mockedAjaxCalls = [];
|
|
989
|
-
unmockedAjaxCalls = [];
|
|
990
|
-
logger.debug( null, 'Cleared retained ajax calls' );
|
|
991
|
-
};
|
|
992
|
-
|
|
993
|
-
/**
|
|
994
|
-
* Retrive the mock handler with the given id (index).
|
|
995
|
-
*
|
|
996
|
-
* @param {Number} i The id (index) to retrieve
|
|
997
|
-
* @return {Object} The mock handler settings
|
|
998
|
-
*/
|
|
999
|
-
$.mockjax.handler = function(i) {
|
|
1000
|
-
if ( arguments.length === 1 ) {
|
|
1001
|
-
return mockHandlers[i];
|
|
1002
|
-
}
|
|
1003
|
-
};
|
|
1004
|
-
|
|
1005
|
-
/**
|
|
1006
|
-
* Retrieve the current array of mock handlers.
|
|
1007
|
-
* NOTE: Altering these handlers, or the array itself is probably not a good
|
|
1008
|
-
* idea! This could easily lead to malfunction of the library. If you need
|
|
1009
|
-
* to alter a handler, clear(index) it (using the array index) and then
|
|
1010
|
-
* create a new handler with $.mockjax({ ... })
|
|
1011
|
-
*
|
|
1012
|
-
* **WARNING**: Additionally, note that the handlers array WILL NOT CHANGE
|
|
1013
|
-
* when a mock is cleared. This is because we have to maintain the handler
|
|
1014
|
-
* indeces for clearing of other mock handlers. (This is not ideal, and
|
|
1015
|
-
* will probably change in the future.) Cleared mocks are set to null!
|
|
1016
|
-
*
|
|
1017
|
-
* @return {Array} The current collection of handlers
|
|
1018
|
-
*/
|
|
1019
|
-
$.mockjax.handlers = function() {
|
|
1020
|
-
return mockHandlers;
|
|
1021
|
-
};
|
|
1022
|
-
|
|
1023
|
-
/**
|
|
1024
|
-
* Retrieve all Ajax calls that have been mocked by this library during the
|
|
1025
|
-
* current session (in other words, only since you last loaded this file).
|
|
1026
|
-
*
|
|
1027
|
-
* @return {Array} The mocked Ajax calls (request settings)
|
|
1028
|
-
*/
|
|
1029
|
-
$.mockjax.mockedAjaxCalls = function() {
|
|
1030
|
-
return mockedAjaxCalls;
|
|
1031
|
-
};
|
|
1032
|
-
|
|
1033
|
-
/**
|
|
1034
|
-
* Return all mock handlers that have NOT been matched against Ajax requests
|
|
1035
|
-
*
|
|
1036
|
-
* @return {Array} The mock handlers
|
|
1037
|
-
*/
|
|
1038
|
-
$.mockjax.unfiredHandlers = function() {
|
|
1039
|
-
var results = [];
|
|
1040
|
-
for (var i=0, len=mockHandlers.length; i<len; i++) {
|
|
1041
|
-
var handler = mockHandlers[i];
|
|
1042
|
-
if (handler !== null && !handler.fired) {
|
|
1043
|
-
results.push(handler);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
return results;
|
|
1047
|
-
};
|
|
1048
|
-
|
|
1049
|
-
/**
|
|
1050
|
-
* Retrieve all Ajax calls that have NOT been mocked by this library during
|
|
1051
|
-
* the current session (in other words, only since you last loaded this file).
|
|
1052
|
-
*
|
|
1053
|
-
* @return {Array} The mocked Ajax calls (request settings)
|
|
1054
|
-
*/
|
|
1055
|
-
$.mockjax.unmockedAjaxCalls = function() {
|
|
1056
|
-
return unmockedAjaxCalls;
|
|
1057
|
-
};
|
|
1058
|
-
|
|
1059
|
-
return $.mockjax;
|
|
1060
|
-
|
|
1061
|
-
}));
|