curation_concerns 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +1 -1
  4. data/Rakefile +3 -11
  5. data/VERSION +1 -1
  6. data/app/assets/javascripts/curation_concerns/application.js +3 -0
  7. data/app/assets/javascripts/curation_concerns/curation_concerns.js +5 -0
  8. data/app/assets/javascripts/curation_concerns/file_manager/affix.es6 +13 -0
  9. data/app/assets/javascripts/curation_concerns/file_manager/list_toggle.es6 +6 -0
  10. data/app/assets/javascripts/curation_concerns/file_manager/member.es6 +82 -0
  11. data/app/assets/javascripts/curation_concerns/file_manager/save_manager.es6 +70 -0
  12. data/app/assets/javascripts/curation_concerns/file_manager/sorting.es6 +82 -0
  13. data/app/assets/stylesheets/curation_concerns/_modules.scss +1 -1
  14. data/app/assets/stylesheets/curation_concerns/_typography.scss +0 -11
  15. data/app/assets/stylesheets/curation_concerns/modules/file_manager.scss +115 -0
  16. data/app/controllers/concerns/curation_concerns/collections_controller_behavior.rb +1 -1
  17. data/app/controllers/concerns/curation_concerns/curation_concern_controller.rb +5 -1
  18. data/app/forms/curation_concerns/forms/work_form.rb +3 -1
  19. data/app/views/catalog/_document_list.html.erb +1 -1
  20. data/app/views/collections/_search_collection_dashboard_form.html.erb +1 -1
  21. data/app/views/collections/_search_form.html.erb +1 -1
  22. data/app/views/collections/show.html.erb +24 -17
  23. data/app/views/curation_concerns/base/_file_manager_actions.html.erb +3 -0
  24. data/app/views/curation_concerns/base/_file_manager_attributes.html.erb +0 -0
  25. data/app/views/curation_concerns/base/_file_manager_extra_tools.html.erb +0 -0
  26. data/app/views/curation_concerns/base/_file_manager_member.html.erb +31 -0
  27. data/app/views/curation_concerns/base/_file_manager_thumbnail.html.erb +1 -0
  28. data/app/views/curation_concerns/base/_show_actions.html.erb +1 -0
  29. data/app/views/curation_concerns/base/file_manager.html.erb +34 -0
  30. data/app/views/shared/_site_search.html.erb +3 -3
  31. data/config/locales/curation_concerns.en.yml +2 -0
  32. data/curation_concerns.gemspec +2 -0
  33. data/lib/curation_concerns/engine.rb +1 -0
  34. data/lib/curation_concerns/rails/routes.rb +5 -0
  35. data/lib/curation_concerns/version.rb +1 -1
  36. data/spec/actors/curation_concerns/work_actor_spec.rb +21 -5
  37. data/spec/controllers/curation_concerns/collections_controller_spec.rb +9 -0
  38. data/spec/controllers/curation_concerns/generic_works_controller_spec.rb +24 -4
  39. data/spec/javascripts/file_manager_member_spec.coffee +87 -0
  40. data/spec/javascripts/fixtures/.gitkeep +0 -0
  41. data/spec/javascripts/fixtures/file_manager_member.html +40 -0
  42. data/spec/javascripts/fixtures/save_button.html +3 -0
  43. data/spec/javascripts/helpers/jasmine-jquery.js +841 -0
  44. data/spec/javascripts/helpers/mock-ajax.js +736 -0
  45. data/spec/javascripts/helpers/test_responses.js +12 -0
  46. data/spec/javascripts/jasmine_spec.rb +25 -0
  47. data/spec/javascripts/save_manager_spec.coffee +84 -0
  48. data/spec/javascripts/support/jasmine.yml +136 -0
  49. data/spec/javascripts/support/jasmine_helper.rb +15 -0
  50. data/spec/routing/route_spec.rb +4 -0
  51. data/spec/support/rake_support.rb +41 -0
  52. data/spec/views/catalog/index.html.erb_spec.rb +2 -2
  53. data/spec/views/curation_concerns/base/file_manager.html.erb_spec.rb +72 -0
  54. data/tasks/jasmine.rake +18 -0
  55. metadata +71 -4
@@ -0,0 +1,736 @@
1
+ /*
2
+
3
+ Jasmine-Ajax - v3.2.0: a set of helpers for testing AJAX requests under the Jasmine
4
+ BDD framework for JavaScript.
5
+
6
+ http://github.com/jasmine/jasmine-ajax
7
+
8
+ Jasmine Home page: http://jasmine.github.io/
9
+
10
+ Copyright (c) 2008-2015 Pivotal Labs
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining
13
+ a copy of this software and associated documentation files (the
14
+ "Software"), to deal in the Software without restriction, including
15
+ without limitation the rights to use, copy, modify, merge, publish,
16
+ distribute, sublicense, and/or sell copies of the Software, and to
17
+ permit persons to whom the Software is furnished to do so, subject to
18
+ the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be
21
+ included in all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
+
31
+ */
32
+
33
+ getJasmineRequireObj().ajax = function(jRequire) {
34
+ var $ajax = {};
35
+
36
+ $ajax.RequestStub = jRequire.AjaxRequestStub();
37
+ $ajax.RequestTracker = jRequire.AjaxRequestTracker();
38
+ $ajax.StubTracker = jRequire.AjaxStubTracker();
39
+ $ajax.ParamParser = jRequire.AjaxParamParser();
40
+ $ajax.event = jRequire.AjaxEvent();
41
+ $ajax.eventBus = jRequire.AjaxEventBus($ajax.event);
42
+ $ajax.fakeRequest = jRequire.AjaxFakeRequest($ajax.eventBus);
43
+ $ajax.MockAjax = jRequire.MockAjax($ajax);
44
+
45
+ return $ajax.MockAjax;
46
+ };
47
+
48
+ getJasmineRequireObj().AjaxEvent = function() {
49
+ function now() {
50
+ return new Date().getTime();
51
+ }
52
+
53
+ function noop() {
54
+ }
55
+
56
+ // Event object
57
+ // https://dom.spec.whatwg.org/#concept-event
58
+ function XMLHttpRequestEvent(xhr, type) {
59
+ this.type = type;
60
+ this.bubbles = false;
61
+ this.cancelable = false;
62
+ this.timeStamp = now();
63
+
64
+ this.isTrusted = false;
65
+ this.defaultPrevented = false;
66
+
67
+ // Event phase should be "AT_TARGET"
68
+ // https://dom.spec.whatwg.org/#dom-event-at_target
69
+ this.eventPhase = 2;
70
+
71
+ this.target = xhr;
72
+ this.currentTarget = xhr;
73
+ }
74
+
75
+ XMLHttpRequestEvent.prototype.preventDefault = noop;
76
+ XMLHttpRequestEvent.prototype.stopPropagation = noop;
77
+ XMLHttpRequestEvent.prototype.stopImmediatePropagation = noop;
78
+
79
+ function XMLHttpRequestProgressEvent() {
80
+ XMLHttpRequestEvent.apply(this, arguments);
81
+
82
+ this.lengthComputable = false;
83
+ this.loaded = 0;
84
+ this.total = 0;
85
+ }
86
+
87
+ // Extend prototype
88
+ XMLHttpRequestProgressEvent.prototype = XMLHttpRequestEvent.prototype;
89
+
90
+ return {
91
+ event: function(xhr, type) {
92
+ return new XMLHttpRequestEvent(xhr, type);
93
+ },
94
+
95
+ progressEvent: function(xhr, type) {
96
+ return new XMLHttpRequestProgressEvent(xhr, type);
97
+ }
98
+ };
99
+ };
100
+ getJasmineRequireObj().AjaxEventBus = function(eventFactory) {
101
+ function EventBus(source) {
102
+ this.eventList = {};
103
+ this.source = source;
104
+ }
105
+
106
+ function ensureEvent(eventList, name) {
107
+ eventList[name] = eventList[name] || [];
108
+ return eventList[name];
109
+ }
110
+
111
+ function findIndex(list, thing) {
112
+ if (list.indexOf) {
113
+ return list.indexOf(thing);
114
+ }
115
+
116
+ for(var i = 0; i < list.length; i++) {
117
+ if (thing === list[i]) {
118
+ return i;
119
+ }
120
+ }
121
+
122
+ return -1;
123
+ }
124
+
125
+ EventBus.prototype.addEventListener = function(event, callback) {
126
+ ensureEvent(this.eventList, event).push(callback);
127
+ };
128
+
129
+ EventBus.prototype.removeEventListener = function(event, callback) {
130
+ var index = findIndex(this.eventList[event], callback);
131
+
132
+ if (index >= 0) {
133
+ this.eventList[event].splice(index, 1);
134
+ }
135
+ };
136
+
137
+ EventBus.prototype.trigger = function(event) {
138
+ var evt;
139
+
140
+ // Event 'readystatechange' is should be a simple event.
141
+ // Others are progress event.
142
+ // https://xhr.spec.whatwg.org/#events
143
+ if (event === 'readystatechange') {
144
+ evt = eventFactory.event(this.source, event);
145
+ } else {
146
+ evt = eventFactory.progressEvent(this.source, event);
147
+ }
148
+
149
+ var eventListeners = this.eventList[event];
150
+
151
+ if (eventListeners) {
152
+ for (var i = 0; i < eventListeners.length; i++) {
153
+ eventListeners[i].call(this.source, evt);
154
+ }
155
+ }
156
+ };
157
+
158
+ return function(source) {
159
+ return new EventBus(source);
160
+ };
161
+ };
162
+
163
+ getJasmineRequireObj().AjaxFakeRequest = function(eventBusFactory) {
164
+ function extend(destination, source, propertiesToSkip) {
165
+ propertiesToSkip = propertiesToSkip || [];
166
+ for (var property in source) {
167
+ if (!arrayContains(propertiesToSkip, property)) {
168
+ destination[property] = source[property];
169
+ }
170
+ }
171
+ return destination;
172
+ }
173
+
174
+ function arrayContains(arr, item) {
175
+ for (var i = 0; i < arr.length; i++) {
176
+ if (arr[i] === item) {
177
+ return true;
178
+ }
179
+ }
180
+ return false;
181
+ }
182
+
183
+ function wrapProgressEvent(xhr, eventName) {
184
+ return function() {
185
+ if (xhr[eventName]) {
186
+ xhr[eventName].apply(xhr, arguments);
187
+ }
188
+ };
189
+ }
190
+
191
+ function initializeEvents(xhr) {
192
+ xhr.eventBus.addEventListener('readystatechange', wrapProgressEvent(xhr, 'onreadystatechange'));
193
+ xhr.eventBus.addEventListener('loadstart', wrapProgressEvent(xhr, 'onloadstart'));
194
+ xhr.eventBus.addEventListener('load', wrapProgressEvent(xhr, 'onload'));
195
+ xhr.eventBus.addEventListener('loadend', wrapProgressEvent(xhr, 'onloadend'));
196
+ xhr.eventBus.addEventListener('progress', wrapProgressEvent(xhr, 'onprogress'));
197
+ xhr.eventBus.addEventListener('error', wrapProgressEvent(xhr, 'onerror'));
198
+ xhr.eventBus.addEventListener('abort', wrapProgressEvent(xhr, 'onabort'));
199
+ xhr.eventBus.addEventListener('timeout', wrapProgressEvent(xhr, 'ontimeout'));
200
+ }
201
+
202
+ function unconvertibleResponseTypeMessage(type) {
203
+ var msg = [
204
+ "Can't build XHR.response for XHR.responseType of '",
205
+ type,
206
+ "'.",
207
+ "XHR.response must be explicitly stubbed"
208
+ ];
209
+ return msg.join(' ');
210
+ }
211
+
212
+ function fakeRequest(global, requestTracker, stubTracker, paramParser) {
213
+ function FakeXMLHttpRequest() {
214
+ requestTracker.track(this);
215
+ this.eventBus = eventBusFactory(this);
216
+ initializeEvents(this);
217
+ this.requestHeaders = {};
218
+ this.overriddenMimeType = null;
219
+ }
220
+
221
+ function findHeader(name, headers) {
222
+ name = name.toLowerCase();
223
+ for (var header in headers) {
224
+ if (header.toLowerCase() === name) {
225
+ return headers[header];
226
+ }
227
+ }
228
+ }
229
+
230
+ function normalizeHeaders(rawHeaders, contentType) {
231
+ var headers = [];
232
+
233
+ if (rawHeaders) {
234
+ if (rawHeaders instanceof Array) {
235
+ headers = rawHeaders;
236
+ } else {
237
+ for (var headerName in rawHeaders) {
238
+ if (rawHeaders.hasOwnProperty(headerName)) {
239
+ headers.push({ name: headerName, value: rawHeaders[headerName] });
240
+ }
241
+ }
242
+ }
243
+ } else {
244
+ headers.push({ name: "Content-Type", value: contentType || "application/json" });
245
+ }
246
+
247
+ return headers;
248
+ }
249
+
250
+ function parseXml(xmlText, contentType) {
251
+ if (global.DOMParser) {
252
+ return (new global.DOMParser()).parseFromString(xmlText, 'text/xml');
253
+ } else {
254
+ var xml = new global.ActiveXObject("Microsoft.XMLDOM");
255
+ xml.async = "false";
256
+ xml.loadXML(xmlText);
257
+ return xml;
258
+ }
259
+ }
260
+
261
+ var xmlParsables = ['text/xml', 'application/xml'];
262
+
263
+ function getResponseXml(responseText, contentType) {
264
+ if (arrayContains(xmlParsables, contentType.toLowerCase())) {
265
+ return parseXml(responseText, contentType);
266
+ } else if (contentType.match(/\+xml$/)) {
267
+ return parseXml(responseText, 'text/xml');
268
+ }
269
+ return null;
270
+ }
271
+
272
+ var iePropertiesThatCannotBeCopied = ['responseBody', 'responseText', 'responseXML', 'status', 'statusText', 'responseTimeout'];
273
+ extend(FakeXMLHttpRequest.prototype, new global.XMLHttpRequest(), iePropertiesThatCannotBeCopied);
274
+ extend(FakeXMLHttpRequest.prototype, {
275
+ open: function() {
276
+ this.method = arguments[0];
277
+ this.url = arguments[1];
278
+ this.username = arguments[3];
279
+ this.password = arguments[4];
280
+ this.readyState = 1;
281
+ this.eventBus.trigger('readystatechange');
282
+ },
283
+
284
+ setRequestHeader: function(header, value) {
285
+ if(this.requestHeaders.hasOwnProperty(header)) {
286
+ this.requestHeaders[header] = [this.requestHeaders[header], value].join(', ');
287
+ } else {
288
+ this.requestHeaders[header] = value;
289
+ }
290
+ },
291
+
292
+ overrideMimeType: function(mime) {
293
+ this.overriddenMimeType = mime;
294
+ },
295
+
296
+ abort: function() {
297
+ this.readyState = 0;
298
+ this.status = 0;
299
+ this.statusText = "abort";
300
+ this.eventBus.trigger('readystatechange');
301
+ this.eventBus.trigger('progress');
302
+ this.eventBus.trigger('abort');
303
+ this.eventBus.trigger('loadend');
304
+ },
305
+
306
+ readyState: 0,
307
+
308
+ onloadstart: null,
309
+ onprogress: null,
310
+ onabort: null,
311
+ onerror: null,
312
+ onload: null,
313
+ ontimeout: null,
314
+ onloadend: null,
315
+ onreadystatechange: null,
316
+
317
+ addEventListener: function() {
318
+ this.eventBus.addEventListener.apply(this.eventBus, arguments);
319
+ },
320
+
321
+ removeEventListener: function(event, callback) {
322
+ this.eventBus.removeEventListener.apply(this.eventBus, arguments);
323
+ },
324
+
325
+ status: null,
326
+
327
+ send: function(data) {
328
+ this.params = data;
329
+ this.eventBus.trigger('loadstart');
330
+
331
+ var stub = stubTracker.findStub(this.url, data, this.method);
332
+ if (stub) {
333
+ if (stub.isReturn()) {
334
+ this.respondWith(stub);
335
+ } else if (stub.isError()) {
336
+ this.responseError();
337
+ } else if (stub.isTimeout()) {
338
+ this.responseTimeout();
339
+ }
340
+ }
341
+ },
342
+
343
+ contentType: function() {
344
+ return findHeader('content-type', this.requestHeaders);
345
+ },
346
+
347
+ data: function() {
348
+ if (!this.params) {
349
+ return {};
350
+ }
351
+
352
+ return paramParser.findParser(this).parse(this.params);
353
+ },
354
+
355
+ getResponseHeader: function(name) {
356
+ name = name.toLowerCase();
357
+ var resultHeader;
358
+ for(var i = 0; i < this.responseHeaders.length; i++) {
359
+ var header = this.responseHeaders[i];
360
+ if (name === header.name.toLowerCase()) {
361
+ if (resultHeader) {
362
+ resultHeader = [resultHeader, header.value].join(', ');
363
+ } else {
364
+ resultHeader = header.value;
365
+ }
366
+ }
367
+ }
368
+ return resultHeader;
369
+ },
370
+
371
+ getAllResponseHeaders: function() {
372
+ var responseHeaders = [];
373
+ for (var i = 0; i < this.responseHeaders.length; i++) {
374
+ responseHeaders.push(this.responseHeaders[i].name + ': ' +
375
+ this.responseHeaders[i].value);
376
+ }
377
+ return responseHeaders.join('\r\n') + '\r\n';
378
+ },
379
+
380
+ responseText: null,
381
+ response: null,
382
+ responseType: null,
383
+
384
+ responseValue: function() {
385
+ switch(this.responseType) {
386
+ case null:
387
+ case "":
388
+ case "text":
389
+ return this.readyState >= 3 ? this.responseText : "";
390
+ case "json":
391
+ return JSON.parse(this.responseText);
392
+ case "arraybuffer":
393
+ throw unconvertibleResponseTypeMessage('arraybuffer');
394
+ case "blob":
395
+ throw unconvertibleResponseTypeMessage('blob');
396
+ case "document":
397
+ return this.responseXML;
398
+ }
399
+ },
400
+
401
+
402
+ respondWith: function(response) {
403
+ if (this.readyState === 4) {
404
+ throw new Error("FakeXMLHttpRequest already completed");
405
+ }
406
+
407
+ this.status = response.status;
408
+ this.statusText = response.statusText || "";
409
+ this.responseHeaders = normalizeHeaders(response.responseHeaders, response.contentType);
410
+ this.readyState = 2;
411
+ this.eventBus.trigger('readystatechange');
412
+
413
+ this.responseText = response.responseText || "";
414
+ this.responseType = response.responseType || "";
415
+ this.readyState = 4;
416
+ this.responseXML = getResponseXml(response.responseText, this.getResponseHeader('content-type') || '');
417
+ if (this.responseXML) {
418
+ this.responseType = 'document';
419
+ }
420
+
421
+ if ('response' in response) {
422
+ this.response = response.response;
423
+ } else {
424
+ this.response = this.responseValue();
425
+ }
426
+
427
+ this.eventBus.trigger('readystatechange');
428
+ this.eventBus.trigger('progress');
429
+ this.eventBus.trigger('load');
430
+ this.eventBus.trigger('loadend');
431
+ },
432
+
433
+ responseTimeout: function() {
434
+ if (this.readyState === 4) {
435
+ throw new Error("FakeXMLHttpRequest already completed");
436
+ }
437
+ this.readyState = 4;
438
+ jasmine.clock().tick(30000);
439
+ this.eventBus.trigger('readystatechange');
440
+ this.eventBus.trigger('progress');
441
+ this.eventBus.trigger('timeout');
442
+ this.eventBus.trigger('loadend');
443
+ },
444
+
445
+ responseError: function() {
446
+ if (this.readyState === 4) {
447
+ throw new Error("FakeXMLHttpRequest already completed");
448
+ }
449
+ this.readyState = 4;
450
+ this.eventBus.trigger('readystatechange');
451
+ this.eventBus.trigger('progress');
452
+ this.eventBus.trigger('error');
453
+ this.eventBus.trigger('loadend');
454
+ }
455
+ });
456
+
457
+ return FakeXMLHttpRequest;
458
+ }
459
+
460
+ return fakeRequest;
461
+ };
462
+
463
+ getJasmineRequireObj().MockAjax = function($ajax) {
464
+ function MockAjax(global) {
465
+ var requestTracker = new $ajax.RequestTracker(),
466
+ stubTracker = new $ajax.StubTracker(),
467
+ paramParser = new $ajax.ParamParser(),
468
+ realAjaxFunction = global.XMLHttpRequest,
469
+ mockAjaxFunction = $ajax.fakeRequest(global, requestTracker, stubTracker, paramParser);
470
+
471
+ this.install = function() {
472
+ if (global.XMLHttpRequest === mockAjaxFunction) {
473
+ throw "MockAjax is already installed.";
474
+ }
475
+
476
+ global.XMLHttpRequest = mockAjaxFunction;
477
+ };
478
+
479
+ this.uninstall = function() {
480
+ if (global.XMLHttpRequest !== mockAjaxFunction) {
481
+ throw "MockAjax not installed.";
482
+ }
483
+ global.XMLHttpRequest = realAjaxFunction;
484
+
485
+ this.stubs.reset();
486
+ this.requests.reset();
487
+ paramParser.reset();
488
+ };
489
+
490
+ this.stubRequest = function(url, data, method) {
491
+ var stub = new $ajax.RequestStub(url, data, method);
492
+ stubTracker.addStub(stub);
493
+ return stub;
494
+ };
495
+
496
+ this.withMock = function(closure) {
497
+ this.install();
498
+ try {
499
+ closure();
500
+ } finally {
501
+ this.uninstall();
502
+ }
503
+ };
504
+
505
+ this.addCustomParamParser = function(parser) {
506
+ paramParser.add(parser);
507
+ };
508
+
509
+ this.requests = requestTracker;
510
+ this.stubs = stubTracker;
511
+ }
512
+
513
+ return MockAjax;
514
+ };
515
+
516
+ getJasmineRequireObj().AjaxParamParser = function() {
517
+ function ParamParser() {
518
+ var defaults = [
519
+ {
520
+ test: function(xhr) {
521
+ return (/^application\/json/).test(xhr.contentType());
522
+ },
523
+ parse: function jsonParser(paramString) {
524
+ return JSON.parse(paramString);
525
+ }
526
+ },
527
+ {
528
+ test: function(xhr) {
529
+ return true;
530
+ },
531
+ parse: function naiveParser(paramString) {
532
+ var data = {};
533
+ var params = paramString.split('&');
534
+
535
+ for (var i = 0; i < params.length; ++i) {
536
+ var kv = params[i].replace(/\+/g, ' ').split('=');
537
+ var key = decodeURIComponent(kv[0]);
538
+ data[key] = data[key] || [];
539
+ data[key].push(decodeURIComponent(kv[1]));
540
+ }
541
+ return data;
542
+ }
543
+ }
544
+ ];
545
+ var paramParsers = [];
546
+
547
+ this.add = function(parser) {
548
+ paramParsers.unshift(parser);
549
+ };
550
+
551
+ this.findParser = function(xhr) {
552
+ for(var i in paramParsers) {
553
+ var parser = paramParsers[i];
554
+ if (parser.test(xhr)) {
555
+ return parser;
556
+ }
557
+ }
558
+ };
559
+
560
+ this.reset = function() {
561
+ paramParsers = [];
562
+ for(var i in defaults) {
563
+ paramParsers.push(defaults[i]);
564
+ }
565
+ };
566
+
567
+ this.reset();
568
+ }
569
+
570
+ return ParamParser;
571
+ };
572
+
573
+ getJasmineRequireObj().AjaxRequestStub = function() {
574
+ var RETURN = 0,
575
+ ERROR = 1,
576
+ TIMEOUT = 2;
577
+
578
+ function RequestStub(url, stubData, method) {
579
+ var normalizeQuery = function(query) {
580
+ return query ? query.split('&').sort().join('&') : undefined;
581
+ };
582
+
583
+ if (url instanceof RegExp) {
584
+ this.url = url;
585
+ this.query = undefined;
586
+ } else {
587
+ var split = url.split('?');
588
+ this.url = split[0];
589
+ this.query = split.length > 1 ? normalizeQuery(split[1]) : undefined;
590
+ }
591
+
592
+ this.data = (stubData instanceof RegExp) ? stubData : normalizeQuery(stubData);
593
+ this.method = method;
594
+
595
+ this.andReturn = function(options) {
596
+ this.action = RETURN;
597
+ this.status = options.status || 200;
598
+
599
+ this.contentType = options.contentType;
600
+ this.response = options.response;
601
+ this.responseText = options.responseText;
602
+ this.responseHeaders = options.responseHeaders;
603
+ };
604
+
605
+ this.isReturn = function() {
606
+ return this.action === RETURN;
607
+ };
608
+
609
+ this.andError = function() {
610
+ this.action = ERROR;
611
+ };
612
+
613
+ this.isError = function() {
614
+ return this.action === ERROR;
615
+ };
616
+
617
+ this.andTimeout = function() {
618
+ this.action = TIMEOUT;
619
+ };
620
+
621
+ this.isTimeout = function() {
622
+ return this.action === TIMEOUT;
623
+ };
624
+
625
+ this.matches = function(fullUrl, data, method) {
626
+ var urlMatches = false;
627
+ fullUrl = fullUrl.toString();
628
+ if (this.url instanceof RegExp) {
629
+ urlMatches = this.url.test(fullUrl);
630
+ } else {
631
+ var urlSplit = fullUrl.split('?'),
632
+ url = urlSplit[0],
633
+ query = urlSplit[1];
634
+ urlMatches = this.url === url && this.query === normalizeQuery(query);
635
+ }
636
+ var dataMatches = false;
637
+ if (this.data instanceof RegExp) {
638
+ dataMatches = this.data.test(data);
639
+ } else {
640
+ dataMatches = !this.data || this.data === normalizeQuery(data);
641
+ }
642
+ return urlMatches && dataMatches && (!this.method || this.method === method);
643
+ };
644
+ }
645
+
646
+ return RequestStub;
647
+ };
648
+
649
+ getJasmineRequireObj().AjaxRequestTracker = function() {
650
+ function RequestTracker() {
651
+ var requests = [];
652
+
653
+ this.track = function(request) {
654
+ requests.push(request);
655
+ };
656
+
657
+ this.first = function() {
658
+ return requests[0];
659
+ };
660
+
661
+ this.count = function() {
662
+ return requests.length;
663
+ };
664
+
665
+ this.reset = function() {
666
+ requests = [];
667
+ };
668
+
669
+ this.mostRecent = function() {
670
+ return requests[requests.length - 1];
671
+ };
672
+
673
+ this.at = function(index) {
674
+ return requests[index];
675
+ };
676
+
677
+ this.filter = function(url_to_match) {
678
+ var matching_requests = [];
679
+
680
+ for (var i = 0; i < requests.length; i++) {
681
+ if (url_to_match instanceof RegExp &&
682
+ url_to_match.test(requests[i].url)) {
683
+ matching_requests.push(requests[i]);
684
+ } else if (url_to_match instanceof Function &&
685
+ url_to_match(requests[i])) {
686
+ matching_requests.push(requests[i]);
687
+ } else {
688
+ if (requests[i].url === url_to_match) {
689
+ matching_requests.push(requests[i]);
690
+ }
691
+ }
692
+ }
693
+
694
+ return matching_requests;
695
+ };
696
+ }
697
+
698
+ return RequestTracker;
699
+ };
700
+
701
+ getJasmineRequireObj().AjaxStubTracker = function() {
702
+ function StubTracker() {
703
+ var stubs = [];
704
+
705
+ this.addStub = function(stub) {
706
+ stubs.push(stub);
707
+ };
708
+
709
+ this.reset = function() {
710
+ stubs = [];
711
+ };
712
+
713
+ this.findStub = function(url, data, method) {
714
+ for (var i = stubs.length - 1; i >= 0; i--) {
715
+ var stub = stubs[i];
716
+ if (stub.matches(url, data, method)) {
717
+ return stub;
718
+ }
719
+ }
720
+ };
721
+ }
722
+
723
+ return StubTracker;
724
+ };
725
+
726
+ (function() {
727
+ var jRequire = getJasmineRequireObj(),
728
+ MockAjax = jRequire.ajax(jRequire);
729
+ if (typeof window === "undefined" && typeof exports === "object") {
730
+ exports.MockAjax = MockAjax;
731
+ jasmine.Ajax = new MockAjax(exports);
732
+ } else {
733
+ window.MockAjax = MockAjax;
734
+ jasmine.Ajax = new MockAjax(window);
735
+ }
736
+ }());