ember-data-factory-guy 0.7.3 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9c2abf7589fecda0e42120d5c2e9bf8efc2caef7
4
- data.tar.gz: 93fb335e1e15c4ad91be1b1716b7b30c71483f03
3
+ metadata.gz: 0c363f00f4ebb7fb8180ca566590bc388b72088a
4
+ data.tar.gz: 48aef40535b00c54b9c593c12a3b795452d7e8f2
5
5
  SHA512:
6
- metadata.gz: 0b84a2d29390fd35426e6eb4e5fa5b04338999f5e2c859bebc8a76f53a24ad5b1487a18bacb2d0d110fc482b1211fdf6b4d412d91df557913eea1af496ce438a
7
- data.tar.gz: 4f707a3a8702fb5ab142bf97c1e5a9dbb94ee709989e929d3b4356ba847b6798c86c571dba925c8412678bc926024df409438078f4034a041148e6d2d710fefc
6
+ metadata.gz: c6f5c33236bbeee62b5a61dcf321ad535af9f3e7af1677b7cc4e0ffcecf2ae1996ff4af4e352956d7d644e931e974e4aec4bc8c91d36f29297b6fd04216d7f3e
7
+ data.tar.gz: c3280a7223574403a20cd4cc34b8bb47ca4ffbb4c044a6249a33370e61ee55dac5e441438cc460eeae006a46dce8b32bd321ce4f7c26635556f8f6bc5d466619
data/Gruntfile.js CHANGED
@@ -11,7 +11,8 @@ module.exports = function(grunt) {
11
11
  'src/model_definition.js',
12
12
  'src/factory_guy.js',
13
13
  'src/store.js',
14
- 'src/factory_guy_test_mixin.js'],
14
+ 'src/factory_guy_test_mixin.js',
15
+ 'bower_components/jquery-mockjax/jquery.mockjax.js'],
15
16
  dest: "dist/ember-data-factory-guy.js"
16
17
  },
17
18
  extra: {
@@ -25,7 +26,8 @@ module.exports = function(grunt) {
25
26
  'src/model_definition.js',
26
27
  'src/factory_guy.js',
27
28
  'src/store.js',
28
- 'src/factory_guy_test_mixin.js'],
29
+ 'src/factory_guy_test_mixin.js',
30
+ 'bower_components/jquery-mockjax/jquery.mockjax.js'],
29
31
  "vendor/assets/javascripts/factory_guy_has_many.js": ['src/has_many.js']
30
32
  }
31
33
  },
data/README.md CHANGED
@@ -7,12 +7,12 @@ so, if you are using ember-data-1.0.0-beta.8 and earlier, then be sure to use ve
7
7
  ( or below ) of ember-data-factory-guy.
8
8
 
9
9
  - Versions:
10
- - 0.6.4 -> ember-data-1.0.0-beta.8 and under
11
- - 0.7.1 -> ember-data-1.0.0-beta.10
12
- - 0.7.3 -> ember-data-1.0.0-beta.11
13
- - 0.7.3 -> ember-data-1.0.0-beta.12
10
+ - 0.6.4 -> ember-data-1.0.0-beta.8 and under
11
+ - 0.7.1.1 -> ember-data-1.0.0-beta.10
12
+ - 0.7.5 -> ember-data-1.0.0-beta.11
13
+ - 0.7.5 -> ember-data-1.0.0-beta.12
14
14
 
15
- **For versions ( 0.7.1 -> 0.7.3 ), support for the fixture adapter is currently broken.**
15
+ **For versions ( 0.7.1 -> 0.7.5 ), support for the fixture adapter is currently broken.**
16
16
 
17
17
  ## Using as Gem
18
18
 
@@ -517,7 +517,7 @@ the reverse 'user' belongsTo association is being setup for you on the project
517
517
  ```
518
518
 
519
519
 
520
- ###Testing models, controllers, views
520
+ ### Testing models, controllers, views
521
521
 
522
522
  - Testing the models, controllers and views in isolation
523
523
  - Use FactoryGuyTestMixin to help with testing
@@ -563,17 +563,17 @@ test("make a user using your applications default adapter", function() {
563
563
  ```
564
564
 
565
565
 
566
- ###Integration Tests
566
+ ### Integration Tests
567
567
 
568
568
 
569
- ##### Using FactoryGuyTestMixin
569
+ #### Using FactoryGuyTestMixin
570
570
 
571
571
  - Uses mockjax
572
572
  - Has helper methods
573
- - handleFind
573
+ - handleFindMany
574
574
  - handleCreate
575
- - handleUpdate
576
- - handleDelete
575
+ - handleUpdate ( can mock success or failure )
576
+ - handleDelete ( can mock success or failure )
577
577
 
578
578
  Since it is recommended to use your normal adapter ( which is usually a subclass of RESTAdapter, )
579
579
  FactoryGuyTestMixin assumes you will want to use that adapter to do your integration tests.
@@ -584,8 +584,55 @@ If you put models into the store ( with store#makeFixture ), the http GET call d
584
584
  since that model is already in the store.
585
585
 
586
586
  But what if you want to handle create, update or delete?
587
+
587
588
  FactoryGuy assumes you want to mock ajax calls with the mockjax library,
588
- and you will need to download and include that library to use the following feature.
589
+ and this is already bundled for you when you use the ember-data-factory-guy library.
590
+
591
+
592
+ ##### handleUpdate
593
+
594
+ *success case is the default*
595
+
596
+ ```javascript
597
+ var profile = store.makeFixture('profile');
598
+ testHelper.handleUpdate('profile', profile.id);
599
+
600
+ profile.set('description', 'good value');
601
+ profile.save() //=> will succeed
602
+ ````
603
+
604
+ *mocking failed update*
605
+
606
+ ```javascript
607
+ var profile = store.makeFixture('profile');
608
+ testHelper.handleUpdate('profile', profile.id, false);
609
+
610
+ profile.set('description', 'bad value');
611
+ profile.save() //=> will fail
612
+ ````
613
+
614
+
615
+ ##### handleDelete
616
+
617
+ *success case is the default*
618
+
619
+ ```javascript
620
+ var profile = store.makeFixture('profile');
621
+ testHelper.handleDelete('profile', profile.id);
622
+
623
+ profile.destroyRecord() // => will succeed
624
+ ````
625
+
626
+ *mocking failed delete*
627
+
628
+ ```javascript
629
+ var profile = store.makeFixture('profile');
630
+ // set the succeed flag to 'false'
631
+ testHelper.handleDelete('profile', profile.id, false);
632
+
633
+ profile.destroyRecord() // => will fail
634
+ ````
635
+
589
636
 
590
637
  Here is a sample of what you could do in a view test:
591
638
 
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-data-factory-guy",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
4
4
  "authors": [
5
5
  "Daniel Sudol <dansudol@yahoo.com>",
6
6
  "Opak Alex <opak.alexandr@gmail.com>"
@@ -21,7 +21,8 @@
21
21
  "ember": "1.7.0",
22
22
  "ember-data": "1.0.0-beta.11",
23
23
  "chance": "latest",
24
- "qunit": "latest"
24
+ "qunit": "latest",
25
+ "jquery-mockjax": "latest"
25
26
  },
26
27
 
27
28
  "ignore": [
@@ -328,9 +328,9 @@ FactoryGuy = {
328
328
  Given a fixture name like 'person' or 'dude' determine what model this name
329
329
  refers to. In this case it's 'person' for each one.
330
330
 
331
- @param {String} name a fixture name could be model name like 'person'
331
+ @param {String} name a fixture name could be model name like 'person'
332
332
  or a named person in model definition like 'dude'
333
- @returns {String} model name associated with fixture name or undefined if not found
333
+ @returns {String} model name associated with fixture name or undefined if not found
334
334
  */
335
335
  lookupModelForFixtureName: function (name) {
336
336
  var definition = this.lookupDefinitionForFixtureName(name);
@@ -360,11 +360,11 @@ FactoryGuy = {
360
360
  FactoryGuy.build('bob') for a 'bob' User
361
361
  FactoryGuy.build('bob', 'dude') for a 'bob' User with dude traits
362
362
  FactoryGuy.build('bob', 'dude', 'funny') for a 'bob' User with dude and funny traits
363
- FactoryGuy.build('bob', 'dude', name: 'wombat') for a 'bob' User with dude trait and custom attribute name of 'wombat'
363
+ FactoryGuy.build('bob', 'dude', {name: 'wombat'}) for a 'bob' User with dude trait and custom attribute name of 'wombat'
364
364
 
365
- @param {String} name Fixture name
366
- @param {String} trait trait name ( can be more than one )
367
- @param {Object} opts Options that will override default fixture values
365
+ @param {String} name fixture name
366
+ @param {String} trait optional trait names ( one or more )
367
+ @param {Object} opts optional fixture options that will override default fixture values
368
368
  @returns {Object} json fixture
369
369
  */
370
370
  build: function () {
@@ -378,6 +378,7 @@ FactoryGuy = {
378
378
  opts = args.pop();
379
379
  }
380
380
  var traits = args; // whatever is left are traits
381
+
381
382
  var definition = this.lookupDefinitionForFixtureName(name);
382
383
  if (!definition) {
383
384
  throw new Error("Can't find that factory named [" + name + "]");
@@ -391,10 +392,10 @@ FactoryGuy = {
391
392
  FactoryGuy.buildList('user', 2) for 2 User models
392
393
  FactoryGuy.build('bob', 2) for 2 User model with bob attributes
393
394
 
394
- @param {String} name fixture name
395
- @param {Number} number number of fixtures to create
396
- @param {String} trait (one or more)
397
- @param {Object} opts options that will override default fixture values
395
+ @param {String} name fixture name
396
+ @param {Number} number number of fixtures to create
397
+ @param {String} trait optional traits (one or more)
398
+ @param {Object} opts optional fixture options that will override default fixture values
398
399
  @returns {Array} list of fixtures
399
400
  */
400
401
  buildList: function () {
@@ -478,40 +479,47 @@ DS.Store.reopen({
478
479
 
479
480
  /**
480
481
  Make new fixture and save to store. If the store is using FixtureAdapter,
481
- will push to FIXTURE array, otherwise will use push method on adapter.
482
+ will push to FIXTURE array, otherwise will use push method on adapter to load
483
+ the record into the store
482
484
 
483
- @param {String} name name of fixture
484
- @param {Object} options fixture options
485
+ @param {String} name fixture name
486
+ @param {String} trait optional trait names ( one or more )
487
+ @param {Object} opts optional fixture options that will override default fixture values
485
488
  @returns {Object|DS.Model} json or record depending on the adapter type
486
489
  */
487
- makeFixture: function (name, options) {
490
+ makeFixture: function () {
488
491
  var store = this;
492
+ var fixture = FactoryGuy.build.apply(FactoryGuy,arguments);
493
+ var name = arguments[0];
489
494
  var modelName = FactoryGuy.lookupModelForFixtureName(name);
490
- var fixture = FactoryGuy.build(name, options);
491
495
  var modelType = store.modelFor(modelName);
492
496
 
493
497
  if (this.usingFixtureAdapter()) {
494
498
  this.setAssociationsForFixtureAdapter(modelType, modelName, fixture);
495
499
  return FactoryGuy.pushFixture(modelType, fixture);
496
500
  } else {
497
- var store = this;
498
-
499
- var model;
500
- Em.run(function () {
501
- store.findEmbeddedAssociationsForRESTAdapter(modelType, fixture);
502
- if (fixture.type) {
503
- // assuming its polymorphic if there is a type attribute
504
- // is this too bold an assumption?
505
- modelName = fixture.type.underscore();
506
- modelType = store.modelFor(modelName);
507
- }
508
- model = store.push(modelName, fixture);
509
- store.setAssociationsForRESTAdapter(modelType, modelName, model);
510
- });
511
- return model;
501
+ return store.makeModel(modelType, fixture)
512
502
  }
513
503
  },
514
504
 
505
+ makeModel: function (modelType, fixture) {
506
+ var store = this,
507
+ modelName = store.modelFor(modelType).typeKey,
508
+ model;
509
+ Em.run(function () {
510
+ store.findEmbeddedAssociationsForRESTAdapter(modelType, fixture);
511
+ if (fixture.type) {
512
+ // assuming its polymorphic if there is a type attribute
513
+ // is this too bold an assumption?
514
+ modelName = fixture.type.underscore();
515
+ modelType = store.modelFor(modelName);
516
+ }
517
+ model = store.push(modelName, fixture);
518
+ store.setAssociationsForRESTAdapter(modelType, modelName, model);
519
+ });
520
+ return model;
521
+ },
522
+
515
523
  /**
516
524
  Make a list of Fixtures
517
525
 
@@ -520,10 +528,11 @@ DS.Store.reopen({
520
528
  @param {Object} options fixture options
521
529
  @returns {Array} list of json fixtures or records depending on the adapter type
522
530
  */
523
- makeList: function (name, number, options) {
531
+ makeList: function () {
524
532
  var arr = [];
533
+ var number = arguments[1];
525
534
  for (var i = 0; i < number; i++) {
526
- arr.push(this.makeFixture(name, options))
535
+ arr.push(this.makeFixture.apply(this,arguments));
527
536
  }
528
537
  return arr;
529
538
  },
@@ -597,7 +606,8 @@ DS.Store.reopen({
597
606
  },
598
607
 
599
608
  /**
600
- Before pushing the fixture to the store, do some preprocessing.
609
+ Before pushing the fixture to the store, do some preprocessing. Descend into the tree
610
+ of object data, and convert child objects to record instances recursively.
601
611
 
602
612
  If its a belongs to association, and the fixture has an object there,
603
613
  then push that model to the store and set the id of that new model
@@ -619,12 +629,11 @@ DS.Store.reopen({
619
629
  }
620
630
  if (relationship.kind == 'hasMany') {
621
631
  var hasManyRecords = fixture[relationship.key];
622
- // if the records are objects and not instances they need to be converted to
623
- // instances
624
632
  if (Ember.typeOf(hasManyRecords) == 'array') {
625
633
  if (Ember.typeOf(hasManyRecords[0]) == 'object') {
626
634
  var records = Em.A()
627
635
  hasManyRecords.map(function (object) {
636
+ store.findEmbeddedAssociationsForRESTAdapter(relationship.type, object);
628
637
  var record = store.push(relationship.type, object);
629
638
  records.push(record);
630
639
  return record;
@@ -681,7 +690,6 @@ DS.Store.reopen({
681
690
  }
682
691
  })
683
692
  }
684
-
685
693
  })
686
694
  },
687
695
 
@@ -812,15 +820,15 @@ FactoryGuyTestMixin = Em.Mixin.create({
812
820
  $.mockjax(request);
813
821
  },
814
822
 
823
+
815
824
  /**
816
825
  Build the json used for creating or finding a record.
817
826
 
818
- @param {String} name of the fixture ( or model ) to create/find
819
- @param {Object} opts fixture options
827
+ @param {String} modelName model name like 'user'
828
+ @param {String} fixture the fixture data
829
+ @return {Object} json response used for mocking a request
820
830
  */
821
- buildAjaxHttpResponse: function (name, opts) {
822
- var fixture = FactoryGuy.build(name, opts);
823
- var modelName = FactoryGuy.lookupModelForFixtureName(name);
831
+ buildAjaxHttpResponse: function (modelName, fixture) {
824
832
  if (this.usingActiveModelSerializer(modelName)) {
825
833
  this.toSnakeCase(fixture);
826
834
  }
@@ -829,6 +837,26 @@ FactoryGuyTestMixin = Em.Mixin.create({
829
837
  return hash;
830
838
  },
831
839
 
840
+
841
+ _collectArgs: function (args, fromMethod) {
842
+ var args = Array.prototype.slice.call(arguments);
843
+ var name = args.shift();
844
+ if (!name) {
845
+ throw new Error(fromMethod + " needs a factory name to build");
846
+ }
847
+ var succeed = true;
848
+ if (Ember.typeOf(args[args.length-1]) == 'boolean') {
849
+ succeed = args.pop();
850
+ }
851
+ var opts = {}
852
+ if (Ember.typeOf(args[args.length-1]) == 'object') {
853
+ opts = args.pop();
854
+ }
855
+ var traits = args; // whatever is left are traits
856
+
857
+ return {name: name, traits: traits, opts: opts, succeed: succeed}
858
+ },
859
+
832
860
  /**
833
861
  Convert Object's keys to snake case
834
862
 
@@ -856,95 +884,796 @@ FactoryGuyTestMixin = Em.Mixin.create({
856
884
  },
857
885
 
858
886
 
859
- handleSideloadFind: function (modelName, json, sideload) {
860
- var id = json.id
861
- var url = this.buildURL(modelName, id);
862
- var responseJson = {};
863
- responseJson[modelName] = json;
864
- $.extend(responseJson, sideload)
865
-
866
- this.stubEndpointForHttpRequest(
867
- url,
868
- responseJson,
869
- {type: 'GET', status: (status || 200)}
870
- )
871
- },
872
-
873
-
874
887
  /**
875
- Handling ajax GET ( find record ) for a model. You can mock
876
- failed find by passing in status of 500.
888
+ Handling ajax GET for finding all records for a type of model.
889
+ You can mock failed find by passing in success argument as false.
890
+
891
+ @param {String} name name of the fixture ( or model ) to find
892
+ @param {Number} number number of fixtures to create
893
+ @param {String} trait optional traits (one or more)
894
+ @param {Object} opts optional fixture options
895
+ @return {Object} json response
896
+ */
897
+ handleFindMany: function () {
898
+ var store = this.getStore();
899
+ // make the records and load them in the store
900
+ store.makeList.apply(store,arguments);
877
901
 
878
- @param {String} name of the fixture ( or model ) to find
879
- @param {Object} opts fixture options
880
- @param {Integer} status Optional HTTP status response code
881
- */
882
- handleFind: function (name, opts, status) {
902
+ var name = arguments[0];
883
903
  var modelName = FactoryGuy.lookupModelForFixtureName(name);
884
- var responseJson = this.buildAjaxHttpResponse(name, opts);
885
- var id = responseJson[modelName].id
886
- var url = this.buildURL(modelName, id);
887
- this.stubEndpointForHttpRequest(
888
- url,
889
- responseJson,
890
- {type: 'GET', status: (status || 200)}
891
- )
892
- return responseJson;
904
+ var responseJson = {};
905
+ responseJson[modelName]=[];
906
+ var url = this.buildURL(modelName);
907
+ // mock the ajax call, but return nothing, since the records will be
908
+ // retrieved since they are already in the store
909
+ this.stubEndpointForHttpRequest(url, responseJson, {type: 'GET'})
893
910
  },
894
911
 
895
912
  /**
896
913
  Handling ajax POST ( create record ) for a model. You can mock
897
- failed create by passing in status of 500.
914
+ failed create by passing in success argument as false.
898
915
 
899
- @param {String} name of the fixture ( or model ) to create
900
- @param {Object} opts fixture options
901
- @param {Integer} status Optional HTTP status response code
916
+ @param {String} name name of the fixture ( or model ) to create
917
+ @param {String} trait optional traits ( one or more )
918
+ @param {Object} opts optional fixture options
919
+ @return {Object} json response
902
920
  */
903
- handleCreate: function (name, opts, status) {
921
+ handleCreate: function () {
922
+ var args = Array.prototype.slice.call(arguments);
923
+
924
+ var succeed = true;
925
+ if (Ember.typeOf(args[args.length-1]) == 'boolean') {
926
+ succeed = args.pop();
927
+ }
928
+
929
+ var name = args[0];
904
930
  var modelName = FactoryGuy.lookupModelForFixtureName(name);
905
- var responseJson = this.buildAjaxHttpResponse(name, opts);
906
931
  var url = this.buildURL(modelName);
907
- this.stubEndpointForHttpRequest(
908
- url,
909
- responseJson,
910
- {type: 'POST', status: (status || 200)}
911
- )
912
- return responseJson;
932
+ var responseJson = {};
933
+ var httpOptions = {type: 'POST'}
934
+
935
+ if (succeed) {
936
+ var store = this.getStore();
937
+ // make the records and load them in the store
938
+ var model = store.makeFixture.apply(store,args);
939
+ responseJson[modelName]=model;
940
+ } else {
941
+ httpOptions.status = 500;
942
+ }
943
+ this.stubEndpointForHttpRequest(url, responseJson, httpOptions)
913
944
  },
914
945
 
915
946
  /**
916
947
  Handling ajax PUT ( update record ) for a model type. You can mock
917
- failed update by passing in status of 500.
948
+ failed update by passing in success argument as false.
918
949
 
919
- @param {String} type model type like 'user' for User model
920
- @param {String} id id of record to update
921
- @param {Integer} status Optional HTTP status response code
950
+ @param {String} type model type like 'user' for User model
951
+ @param {String} id id of record to update
952
+ @param {Boolean} succeed optional flag to indicate if the request
953
+ should succeed ( default is true )
922
954
  */
923
- handleUpdate: function (type, id, status) {
955
+ handleUpdate: function (type, id, succeed) {
956
+ succeed = succeed === undefined ? true : succeed;
957
+
924
958
  this.stubEndpointForHttpRequest(
925
959
  this.buildURL(type, id),
926
960
  {},
927
- {type: 'PUT', status: (status || 200)}
961
+ {type: 'PUT', status: (succeed ? 200 : 500)}
928
962
  )
929
963
  },
930
964
 
931
965
  /**
932
966
  Handling ajax DELETE ( delete record ) for a model type. You can mock
933
- failed delete by passing in status of 500.
967
+ failed delete by passing in success argument as false.
934
968
 
935
- @param {String} type model type like 'user' for User model
936
- @param {String} id id of record to update
937
- @param {Integer} status Optional HTTP status response code
969
+ @param {String} type model type like 'user' for User model
970
+ @param {String} id id of record to update
971
+ @param {Boolean} succeed optional flag to indicate if the request
972
+ should succeed ( default is true )
938
973
  */
939
- handleDelete: function (type, id, status) {
974
+ handleDelete: function (type, id, succeed) {
975
+ succeed = succeed === undefined ? true : succeed;
976
+
940
977
  this.stubEndpointForHttpRequest(
941
978
  this.buildURL(type, id),
942
979
  {},
943
- {type: 'DELETE', status: (status || 200)}
980
+ {type: 'DELETE', status: (succeed ? 200 : 500)}
944
981
  )
945
982
  },
946
983
 
947
984
  teardown: function () {
948
985
  FactoryGuy.resetModels(this.getStore());
949
986
  }
950
- })
987
+ });
988
+ /*!
989
+ * MockJax - jQuery Plugin to Mock Ajax requests
990
+ *
991
+ * Version: 1.6.1
992
+ * Released:
993
+ * Home: https://github.com/jakerella/jquery-mockjax
994
+ * Author: Jonathan Sharp (http://jdsharp.com)
995
+ * License: MIT,GPL
996
+ *
997
+ * Copyright (c) 2014 appendTo, Jordan Kasper
998
+ * NOTE: This repository was taken over by Jordan Kasper (@jakerella) October, 2014
999
+ *
1000
+ * Dual licensed under the MIT or GPL licenses.
1001
+ * http://opensource.org/licenses/MIT OR http://www.gnu.org/licenses/gpl-2.0.html
1002
+ */
1003
+ (function($) {
1004
+ var _ajax = $.ajax,
1005
+ mockHandlers = [],
1006
+ mockedAjaxCalls = [],
1007
+ unmockedAjaxCalls = [],
1008
+ CALLBACK_REGEX = /=\?(&|$)/,
1009
+ jsc = (new Date()).getTime();
1010
+
1011
+
1012
+ // Parse the given XML string.
1013
+ function parseXML(xml) {
1014
+ if ( window.DOMParser == undefined && window.ActiveXObject ) {
1015
+ DOMParser = function() { };
1016
+ DOMParser.prototype.parseFromString = function( xmlString ) {
1017
+ var doc = new ActiveXObject('Microsoft.XMLDOM');
1018
+ doc.async = 'false';
1019
+ doc.loadXML( xmlString );
1020
+ return doc;
1021
+ };
1022
+ }
1023
+
1024
+ try {
1025
+ var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
1026
+ if ( $.isXMLDoc( xmlDoc ) ) {
1027
+ var err = $('parsererror', xmlDoc);
1028
+ if ( err.length == 1 ) {
1029
+ throw new Error('Error: ' + $(xmlDoc).text() );
1030
+ }
1031
+ } else {
1032
+ throw new Error('Unable to parse XML');
1033
+ }
1034
+ return xmlDoc;
1035
+ } catch( e ) {
1036
+ var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
1037
+ $(document).trigger('xmlParseError', [ msg ]);
1038
+ return undefined;
1039
+ }
1040
+ }
1041
+
1042
+ // Check if the data field on the mock handler and the request match. This
1043
+ // can be used to restrict a mock handler to being used only when a certain
1044
+ // set of data is passed to it.
1045
+ function isMockDataEqual( mock, live ) {
1046
+ var identical = true;
1047
+ // Test for situations where the data is a querystring (not an object)
1048
+ if (typeof live === 'string') {
1049
+ // Querystring may be a regex
1050
+ return $.isFunction( mock.test ) ? mock.test(live) : mock == live;
1051
+ }
1052
+ $.each(mock, function(k) {
1053
+ if ( live[k] === undefined ) {
1054
+ identical = false;
1055
+ return identical;
1056
+ } else {
1057
+ if ( typeof live[k] === 'object' && live[k] !== null ) {
1058
+ if ( identical && $.isArray( live[k] ) ) {
1059
+ identical = $.isArray( mock[k] ) && live[k].length === mock[k].length;
1060
+ }
1061
+ identical = identical && isMockDataEqual(mock[k], live[k]);
1062
+ } else {
1063
+ if ( mock[k] && $.isFunction( mock[k].test ) ) {
1064
+ identical = identical && mock[k].test(live[k]);
1065
+ } else {
1066
+ identical = identical && ( mock[k] == live[k] );
1067
+ }
1068
+ }
1069
+ }
1070
+ });
1071
+
1072
+ return identical;
1073
+ }
1074
+
1075
+ // See if a mock handler property matches the default settings
1076
+ function isDefaultSetting(handler, property) {
1077
+ return handler[property] === $.mockjaxSettings[property];
1078
+ }
1079
+
1080
+ // Check the given handler should mock the given request
1081
+ function getMockForRequest( handler, requestSettings ) {
1082
+ // If the mock was registered with a function, let the function decide if we
1083
+ // want to mock this request
1084
+ if ( $.isFunction(handler) ) {
1085
+ return handler( requestSettings );
1086
+ }
1087
+
1088
+ // Inspect the URL of the request and check if the mock handler's url
1089
+ // matches the url for this ajax request
1090
+ if ( $.isFunction(handler.url.test) ) {
1091
+ // The user provided a regex for the url, test it
1092
+ if ( !handler.url.test( requestSettings.url ) ) {
1093
+ return null;
1094
+ }
1095
+ } else {
1096
+ // Look for a simple wildcard '*' or a direct URL match
1097
+ var star = handler.url.indexOf('*');
1098
+ if (handler.url !== requestSettings.url && star === -1 ||
1099
+ !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\\$&").replace(/\*/g, '.+')).test(requestSettings.url)) {
1100
+ return null;
1101
+ }
1102
+ }
1103
+
1104
+ // Inspect the data submitted in the request (either POST body or GET query string)
1105
+ if ( handler.data ) {
1106
+ if ( ! requestSettings.data || !isMockDataEqual(handler.data, requestSettings.data) ) {
1107
+ // They're not identical, do not mock this request
1108
+ return null;
1109
+ }
1110
+ }
1111
+ // Inspect the request type
1112
+ if ( handler && handler.type &&
1113
+ handler.type.toLowerCase() != requestSettings.type.toLowerCase() ) {
1114
+ // The request type doesn't match (GET vs. POST)
1115
+ return null;
1116
+ }
1117
+
1118
+ return handler;
1119
+ }
1120
+
1121
+ function parseResponseTimeOpt(responseTime) {
1122
+ if ($.isArray(responseTime)) {
1123
+ var min = responseTime[0];
1124
+ var max = responseTime[1];
1125
+ return (typeof min === 'number' && typeof max === 'number') ? Math.floor(Math.random() * (max - min)) + min : null;
1126
+ } else {
1127
+ return (typeof responseTime === 'number') ? responseTime: null;
1128
+ }
1129
+ }
1130
+
1131
+ // Process the xhr objects send operation
1132
+ function _xhrSend(mockHandler, requestSettings, origSettings) {
1133
+
1134
+ // This is a substitute for < 1.4 which lacks $.proxy
1135
+ var process = (function(that) {
1136
+ return function() {
1137
+ return (function() {
1138
+ // The request has returned
1139
+ this.status = mockHandler.status;
1140
+ this.statusText = mockHandler.statusText;
1141
+ this.readyState = 1;
1142
+
1143
+ var finishRequest = function () {
1144
+ this.readyState = 4;
1145
+
1146
+ var onReady;
1147
+ // Copy over our mock to our xhr object before passing control back to
1148
+ // jQuery's onreadystatechange callback
1149
+ if ( requestSettings.dataType == 'json' && ( typeof mockHandler.responseText == 'object' ) ) {
1150
+ this.responseText = JSON.stringify(mockHandler.responseText);
1151
+ } else if ( requestSettings.dataType == 'xml' ) {
1152
+ if ( typeof mockHandler.responseXML == 'string' ) {
1153
+ this.responseXML = parseXML(mockHandler.responseXML);
1154
+ //in jQuery 1.9.1+, responseXML is processed differently and relies on responseText
1155
+ this.responseText = mockHandler.responseXML;
1156
+ } else {
1157
+ this.responseXML = mockHandler.responseXML;
1158
+ }
1159
+ } else if (typeof mockHandler.responseText === 'object' && mockHandler.responseText !== null) {
1160
+ // since jQuery 1.9 responseText type has to match contentType
1161
+ mockHandler.contentType = 'application/json';
1162
+ this.responseText = JSON.stringify(mockHandler.responseText);
1163
+ } else {
1164
+ this.responseText = mockHandler.responseText;
1165
+ }
1166
+ if( typeof mockHandler.status == 'number' || typeof mockHandler.status == 'string' ) {
1167
+ this.status = mockHandler.status;
1168
+ }
1169
+ if( typeof mockHandler.statusText === "string") {
1170
+ this.statusText = mockHandler.statusText;
1171
+ }
1172
+ // jQuery 2.0 renamed onreadystatechange to onload
1173
+ onReady = this.onreadystatechange || this.onload;
1174
+
1175
+ // jQuery < 1.4 doesn't have onreadystate change for xhr
1176
+ if ( $.isFunction( onReady ) ) {
1177
+ if( mockHandler.isTimeout) {
1178
+ this.status = -1;
1179
+ }
1180
+ onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined );
1181
+ } else if ( mockHandler.isTimeout ) {
1182
+ // Fix for 1.3.2 timeout to keep success from firing.
1183
+ this.status = -1;
1184
+ }
1185
+ };
1186
+
1187
+ // We have an executable function, call it to give
1188
+ // the mock handler a chance to update it's data
1189
+ if ( $.isFunction(mockHandler.response) ) {
1190
+ // Wait for it to finish
1191
+ if ( mockHandler.response.length === 2 ) {
1192
+ mockHandler.response(origSettings, function () {
1193
+ finishRequest.call(that);
1194
+ });
1195
+ return;
1196
+ } else {
1197
+ mockHandler.response(origSettings);
1198
+ }
1199
+ }
1200
+
1201
+ finishRequest.call(that);
1202
+ }).apply(that);
1203
+ };
1204
+ })(this);
1205
+
1206
+ if ( mockHandler.proxy ) {
1207
+ // We're proxying this request and loading in an external file instead
1208
+ _ajax({
1209
+ global: false,
1210
+ url: mockHandler.proxy,
1211
+ type: mockHandler.proxyType,
1212
+ data: mockHandler.data,
1213
+ dataType: requestSettings.dataType === "script" ? "text/plain" : requestSettings.dataType,
1214
+ complete: function(xhr) {
1215
+ mockHandler.responseXML = xhr.responseXML;
1216
+ mockHandler.responseText = xhr.responseText;
1217
+ // Don't override the handler status/statusText if it's specified by the config
1218
+ if (isDefaultSetting(mockHandler, 'status')) {
1219
+ mockHandler.status = xhr.status;
1220
+ }
1221
+ if (isDefaultSetting(mockHandler, 'statusText')) {
1222
+ mockHandler.statusText = xhr.statusText;
1223
+ }
1224
+ this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime) || 0);
1225
+ }
1226
+ });
1227
+ } else {
1228
+ // type == 'POST' || 'GET' || 'DELETE'
1229
+ if ( requestSettings.async === false ) {
1230
+ // TODO: Blocking delay
1231
+ process();
1232
+ } else {
1233
+ this.responseTimer = setTimeout(process, parseResponseTimeOpt(mockHandler.responseTime) || 50);
1234
+ }
1235
+ }
1236
+ }
1237
+
1238
+ // Construct a mocked XHR Object
1239
+ function xhr(mockHandler, requestSettings, origSettings, origHandler) {
1240
+ // Extend with our default mockjax settings
1241
+ mockHandler = $.extend(true, {}, $.mockjaxSettings, mockHandler);
1242
+
1243
+ if (typeof mockHandler.headers === 'undefined') {
1244
+ mockHandler.headers = {};
1245
+ }
1246
+ if (typeof requestSettings.headers === 'undefined') {
1247
+ requestSettings.headers = {};
1248
+ }
1249
+ if ( mockHandler.contentType ) {
1250
+ mockHandler.headers['content-type'] = mockHandler.contentType;
1251
+ }
1252
+
1253
+ return {
1254
+ status: mockHandler.status,
1255
+ statusText: mockHandler.statusText,
1256
+ readyState: 1,
1257
+ open: function() { },
1258
+ send: function() {
1259
+ origHandler.fired = true;
1260
+ _xhrSend.call(this, mockHandler, requestSettings, origSettings);
1261
+ },
1262
+ abort: function() {
1263
+ clearTimeout(this.responseTimer);
1264
+ },
1265
+ setRequestHeader: function(header, value) {
1266
+ requestSettings.headers[header] = value;
1267
+ },
1268
+ getResponseHeader: function(header) {
1269
+ // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
1270
+ if ( mockHandler.headers && mockHandler.headers[header] ) {
1271
+ // Return arbitrary headers
1272
+ return mockHandler.headers[header];
1273
+ } else if ( header.toLowerCase() == 'last-modified' ) {
1274
+ return mockHandler.lastModified || (new Date()).toString();
1275
+ } else if ( header.toLowerCase() == 'etag' ) {
1276
+ return mockHandler.etag || '';
1277
+ } else if ( header.toLowerCase() == 'content-type' ) {
1278
+ return mockHandler.contentType || 'text/plain';
1279
+ }
1280
+ },
1281
+ getAllResponseHeaders: function() {
1282
+ var headers = '';
1283
+ // since jQuery 1.9 responseText type has to match contentType
1284
+ if (mockHandler.contentType) {
1285
+ mockHandler.headers['Content-Type'] = mockHandler.contentType;
1286
+ }
1287
+ $.each(mockHandler.headers, function(k, v) {
1288
+ headers += k + ': ' + v + "\n";
1289
+ });
1290
+ return headers;
1291
+ }
1292
+ };
1293
+ }
1294
+
1295
+ // Process a JSONP mock request.
1296
+ function processJsonpMock( requestSettings, mockHandler, origSettings ) {
1297
+ // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
1298
+ // because there isn't an easy hook for the cross domain script tag of jsonp
1299
+
1300
+ processJsonpUrl( requestSettings );
1301
+
1302
+ requestSettings.dataType = "json";
1303
+ if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
1304
+ createJsonpCallback(requestSettings, mockHandler, origSettings);
1305
+
1306
+ // We need to make sure
1307
+ // that a JSONP style response is executed properly
1308
+
1309
+ var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
1310
+ parts = rurl.exec( requestSettings.url ),
1311
+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
1312
+
1313
+ requestSettings.dataType = "script";
1314
+ if(requestSettings.type.toUpperCase() === "GET" && remote ) {
1315
+ var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
1316
+
1317
+ // Check if we are supposed to return a Deferred back to the mock call, or just
1318
+ // signal success
1319
+ if(newMockReturn) {
1320
+ return newMockReturn;
1321
+ } else {
1322
+ return true;
1323
+ }
1324
+ }
1325
+ }
1326
+ return null;
1327
+ }
1328
+
1329
+ // Append the required callback parameter to the end of the request URL, for a JSONP request
1330
+ function processJsonpUrl( requestSettings ) {
1331
+ if ( requestSettings.type.toUpperCase() === "GET" ) {
1332
+ if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
1333
+ requestSettings.url += (/\?/.test( requestSettings.url ) ? "&" : "?") +
1334
+ (requestSettings.jsonp || "callback") + "=?";
1335
+ }
1336
+ } else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
1337
+ requestSettings.data = (requestSettings.data ? requestSettings.data + "&" : "") + (requestSettings.jsonp || "callback") + "=?";
1338
+ }
1339
+ }
1340
+
1341
+ // Process a JSONP request by evaluating the mocked response text
1342
+ function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
1343
+ // Synthesize the mock request for adding a script tag
1344
+ var callbackContext = origSettings && origSettings.context || requestSettings,
1345
+ newMock = null;
1346
+
1347
+
1348
+ // If the response handler on the moock is a function, call it
1349
+ if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
1350
+ mockHandler.response(origSettings);
1351
+ } else {
1352
+
1353
+ // Evaluate the responseText javascript in a global context
1354
+ if( typeof mockHandler.responseText === 'object' ) {
1355
+ $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
1356
+ } else {
1357
+ $.globalEval( '(' + mockHandler.responseText + ')');
1358
+ }
1359
+ }
1360
+
1361
+ // Successful response
1362
+ setTimeout(function() {
1363
+ jsonpSuccess( requestSettings, callbackContext, mockHandler );
1364
+ jsonpComplete( requestSettings, callbackContext, mockHandler );
1365
+ }, parseResponseTimeOpt(mockHandler.responseTime) || 0);
1366
+
1367
+ // If we are running under jQuery 1.5+, return a deferred object
1368
+ if($.Deferred){
1369
+ newMock = new $.Deferred();
1370
+ if(typeof mockHandler.responseText == "object"){
1371
+ newMock.resolveWith( callbackContext, [mockHandler.responseText] );
1372
+ }
1373
+ else{
1374
+ newMock.resolveWith( callbackContext, [$.parseJSON( mockHandler.responseText )] );
1375
+ }
1376
+ }
1377
+ return newMock;
1378
+ }
1379
+
1380
+
1381
+ // Create the required JSONP callback function for the request
1382
+ function createJsonpCallback( requestSettings, mockHandler, origSettings ) {
1383
+ var callbackContext = origSettings && origSettings.context || requestSettings;
1384
+ var jsonp = requestSettings.jsonpCallback || ("jsonp" + jsc++);
1385
+
1386
+ // Replace the =? sequence both in the query string and the data
1387
+ if ( requestSettings.data ) {
1388
+ requestSettings.data = (requestSettings.data + "").replace(CALLBACK_REGEX, "=" + jsonp + "$1");
1389
+ }
1390
+
1391
+ requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, "=" + jsonp + "$1");
1392
+
1393
+
1394
+ // Handle JSONP-style loading
1395
+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
1396
+ data = tmp;
1397
+ jsonpSuccess( requestSettings, callbackContext, mockHandler );
1398
+ jsonpComplete( requestSettings, callbackContext, mockHandler );
1399
+ // Garbage collect
1400
+ window[ jsonp ] = undefined;
1401
+
1402
+ try {
1403
+ delete window[ jsonp ];
1404
+ } catch(e) {}
1405
+
1406
+ if ( head ) {
1407
+ head.removeChild( script );
1408
+ }
1409
+ };
1410
+ }
1411
+
1412
+ // The JSONP request was successful
1413
+ function jsonpSuccess(requestSettings, callbackContext, mockHandler) {
1414
+ // If a local callback was specified, fire it and pass it the data
1415
+ if ( requestSettings.success ) {
1416
+ requestSettings.success.call( callbackContext, mockHandler.responseText || "", status, {} );
1417
+ }
1418
+
1419
+ // Fire the global callback
1420
+ if ( requestSettings.global ) {
1421
+ (requestSettings.context ? $(requestSettings.context) : $.event).trigger("ajaxSuccess", [{}, requestSettings]);
1422
+ }
1423
+ }
1424
+
1425
+ // The JSONP request was completed
1426
+ function jsonpComplete(requestSettings, callbackContext) {
1427
+ // Process result
1428
+ if ( requestSettings.complete ) {
1429
+ requestSettings.complete.call( callbackContext, {} , status );
1430
+ }
1431
+
1432
+ // The request was completed
1433
+ if ( requestSettings.global ) {
1434
+ (requestSettings.context ? $(requestSettings.context) : $.event).trigger("ajaxComplete", [{}, requestSettings]);
1435
+ }
1436
+
1437
+ // Handle the global AJAX counter
1438
+ if ( requestSettings.global && ! --$.active ) {
1439
+ $.event.trigger( "ajaxStop" );
1440
+ }
1441
+ }
1442
+
1443
+
1444
+ // The core $.ajax replacement.
1445
+ function handleAjax( url, origSettings ) {
1446
+ var mockRequest, requestSettings, mockHandler, overrideCallback;
1447
+
1448
+ // If url is an object, simulate pre-1.5 signature
1449
+ if ( typeof url === "object" ) {
1450
+ origSettings = url;
1451
+ url = undefined;
1452
+ } else {
1453
+ // work around to support 1.5 signature
1454
+ origSettings = origSettings || {};
1455
+ origSettings.url = url;
1456
+ }
1457
+
1458
+ // Extend the original settings for the request
1459
+ requestSettings = $.extend(true, {}, $.ajaxSettings, origSettings);
1460
+
1461
+ // Generic function to override callback methods for use with
1462
+ // callback options (onAfterSuccess, onAfterError, onAfterComplete)
1463
+ overrideCallback = function(action, mockHandler) {
1464
+ var origHandler = origSettings[action.toLowerCase()];
1465
+ return function() {
1466
+ if ( $.isFunction(origHandler) ) {
1467
+ origHandler.apply(this, [].slice.call(arguments));
1468
+ }
1469
+ mockHandler['onAfter' + action]();
1470
+ };
1471
+ };
1472
+
1473
+ // Iterate over our mock handlers (in registration order) until we find
1474
+ // one that is willing to intercept the request
1475
+ for(var k = 0; k < mockHandlers.length; k++) {
1476
+ if ( !mockHandlers[k] ) {
1477
+ continue;
1478
+ }
1479
+
1480
+ mockHandler = getMockForRequest( mockHandlers[k], requestSettings );
1481
+ if(!mockHandler) {
1482
+ // No valid mock found for this request
1483
+ continue;
1484
+ }
1485
+
1486
+ mockedAjaxCalls.push(requestSettings);
1487
+
1488
+ // If logging is enabled, log the mock to the console
1489
+ $.mockjaxSettings.log( mockHandler, requestSettings );
1490
+
1491
+
1492
+ if ( requestSettings.dataType && requestSettings.dataType.toUpperCase() === 'JSONP' ) {
1493
+ if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
1494
+ // This mock will handle the JSONP request
1495
+ return mockRequest;
1496
+ }
1497
+ }
1498
+
1499
+
1500
+ // Removed to fix #54 - keep the mocking data object intact
1501
+ //mockHandler.data = requestSettings.data;
1502
+
1503
+ mockHandler.cache = requestSettings.cache;
1504
+ mockHandler.timeout = requestSettings.timeout;
1505
+ mockHandler.global = requestSettings.global;
1506
+
1507
+ // In the case of a timeout, we just need to ensure
1508
+ // an actual jQuery timeout (That is, our reponse won't)
1509
+ // return faster than the timeout setting.
1510
+ if ( mockHandler.isTimeout ) {
1511
+ if ( mockHandler.responseTime > 1 ) {
1512
+ origSettings.timeout = mockHandler.responseTime - 1;
1513
+ } else {
1514
+ mockHandler.responseTime = 2;
1515
+ origSettings.timeout = 1;
1516
+ }
1517
+ mockHandler.isTimeout = false;
1518
+ }
1519
+
1520
+ // Set up onAfter[X] callback functions
1521
+ if ( $.isFunction( mockHandler.onAfterSuccess ) ) {
1522
+ origSettings.success = overrideCallback('Success', mockHandler);
1523
+ }
1524
+ if ( $.isFunction( mockHandler.onAfterError ) ) {
1525
+ origSettings.error = overrideCallback('Error', mockHandler);
1526
+ }
1527
+ if ( $.isFunction( mockHandler.onAfterComplete ) ) {
1528
+ origSettings.complete = overrideCallback('Complete', mockHandler);
1529
+ }
1530
+
1531
+ copyUrlParameters(mockHandler, origSettings);
1532
+
1533
+ (function(mockHandler, requestSettings, origSettings, origHandler) {
1534
+
1535
+ mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
1536
+ // Mock the XHR object
1537
+ xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ); }
1538
+ }));
1539
+ })(mockHandler, requestSettings, origSettings, mockHandlers[k]);
1540
+
1541
+ return mockRequest;
1542
+ }
1543
+
1544
+ // We don't have a mock request
1545
+ unmockedAjaxCalls.push(origSettings);
1546
+ if($.mockjaxSettings.throwUnmocked === true) {
1547
+ throw new Error('AJAX not mocked: ' + origSettings.url);
1548
+ }
1549
+ else { // trigger a normal request
1550
+ return _ajax.apply($, [origSettings]);
1551
+ }
1552
+ }
1553
+
1554
+ /**
1555
+ * Copies URL parameter values if they were captured by a regular expression
1556
+ * @param {Object} mockHandler
1557
+ * @param {Object} origSettings
1558
+ */
1559
+ function copyUrlParameters(mockHandler, origSettings) {
1560
+ //parameters aren't captured if the URL isn't a RegExp
1561
+ if (!(mockHandler.url instanceof RegExp)) {
1562
+ return;
1563
+ }
1564
+ //if no URL params were defined on the handler, don't attempt a capture
1565
+ if (!mockHandler.hasOwnProperty('urlParams')) {
1566
+ return;
1567
+ }
1568
+ var captures = mockHandler.url.exec(origSettings.url);
1569
+ //the whole RegExp match is always the first value in the capture results
1570
+ if (captures.length === 1) {
1571
+ return;
1572
+ }
1573
+ captures.shift();
1574
+ //use handler params as keys and capture resuts as values
1575
+ var i = 0,
1576
+ capturesLength = captures.length,
1577
+ paramsLength = mockHandler.urlParams.length,
1578
+ //in case the number of params specified is less than actual captures
1579
+ maxIterations = Math.min(capturesLength, paramsLength),
1580
+ paramValues = {};
1581
+ for (i; i < maxIterations; i++) {
1582
+ var key = mockHandler.urlParams[i];
1583
+ paramValues[key] = captures[i];
1584
+ }
1585
+ origSettings.urlParams = paramValues;
1586
+ }
1587
+
1588
+
1589
+ // Public
1590
+
1591
+ $.extend({
1592
+ ajax: handleAjax
1593
+ });
1594
+
1595
+ $.mockjaxSettings = {
1596
+ //url: null,
1597
+ //type: 'GET',
1598
+ log: function( mockHandler, requestSettings ) {
1599
+ if ( mockHandler.logging === false ||
1600
+ ( typeof mockHandler.logging === 'undefined' && $.mockjaxSettings.logging === false ) ) {
1601
+ return;
1602
+ }
1603
+ if ( window.console && console.log ) {
1604
+ var message = 'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url;
1605
+ var request = $.extend({}, requestSettings);
1606
+
1607
+ if (typeof console.log === 'function') {
1608
+ console.log(message, request);
1609
+ } else {
1610
+ try {
1611
+ console.log( message + ' ' + JSON.stringify(request) );
1612
+ } catch (e) {
1613
+ console.log(message);
1614
+ }
1615
+ }
1616
+ }
1617
+ },
1618
+ logging: true,
1619
+ status: 200,
1620
+ statusText: "OK",
1621
+ responseTime: 500,
1622
+ isTimeout: false,
1623
+ throwUnmocked: false,
1624
+ contentType: 'text/plain',
1625
+ response: '',
1626
+ responseText: '',
1627
+ responseXML: '',
1628
+ proxy: '',
1629
+ proxyType: 'GET',
1630
+
1631
+ lastModified: null,
1632
+ etag: '',
1633
+ headers: {
1634
+ etag: 'IJF@H#@923uf8023hFO@I#H#',
1635
+ 'content-type' : 'text/plain'
1636
+ }
1637
+ };
1638
+
1639
+ $.mockjax = function(settings) {
1640
+ var i = mockHandlers.length;
1641
+ mockHandlers[i] = settings;
1642
+ return i;
1643
+ };
1644
+ $.mockjax.clear = function(i) {
1645
+ if ( arguments.length == 1 ) {
1646
+ mockHandlers[i] = null;
1647
+ } else {
1648
+ mockHandlers = [];
1649
+ }
1650
+ mockedAjaxCalls = [];
1651
+ unmockedAjaxCalls = [];
1652
+ };
1653
+ // support older, deprecated version
1654
+ $.mockjaxClear = function(i) {
1655
+ 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!' );
1656
+ $.mockjax.clear();
1657
+ };
1658
+ $.mockjax.handler = function(i) {
1659
+ if ( arguments.length == 1 ) {
1660
+ return mockHandlers[i];
1661
+ }
1662
+ };
1663
+ $.mockjax.mockedAjaxCalls = function() {
1664
+ return mockedAjaxCalls;
1665
+ };
1666
+ $.mockjax.unfiredHandlers = function() {
1667
+ var results = [];
1668
+ for (var i=0, len=mockHandlers.length; i<len; i++) {
1669
+ var handler = mockHandlers[i];
1670
+ if (handler !== null && !handler.fired) {
1671
+ results.push(handler);
1672
+ }
1673
+ }
1674
+ return results;
1675
+ };
1676
+ $.mockjax.unmockedAjaxCalls = function() {
1677
+ return unmockedAjaxCalls;
1678
+ };
1679
+ })(jQuery);