ember-data-factory-guy 0.3.9 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f9b67c07e091270fd561c057ce6b0e3402b14ad4
4
- data.tar.gz: 7568ead17270e5c135bfdc4d572d1734aa9553b2
3
+ metadata.gz: a79807f71868de1b78d4749f7d4a6ae1da807ede
4
+ data.tar.gz: a45cf559a2cbbd4d2c2169bcab63748148988a92
5
5
  SHA512:
6
- metadata.gz: 819e5a60c11d219b1fe68bcf0ae5d04c2e7e33c38e5b748d5177381b53e2c122dc287265e8136196e00ef406e742927c4455776b69dd34685bb8f61286416310
7
- data.tar.gz: 37e73744a1f68bcf7c0dc197a03f86a2ffa8041b2e19816e826b0c33c411924c15a88fecb9875abc4a69ca6e43025edef962c81c0b53b11f82c32a8e65c2111e
6
+ metadata.gz: a3f8360c4ec985b6077dc1e4cc169a531ec8803313a431eba7e03d87cc6282686ce3205bfef824ab386128ed2952617acf4f29a6f06331c0065d5467ad2e54be
7
+ data.tar.gz: d294092adde0d91d1cb8feffccd5cd15f09854509cafe3966674bd0b9ec8220c94c2fb3c8954f21fd8075ede0ad0db2fab1a2779b08a735470189113017d7a4f
data/.gitignore CHANGED
@@ -4,4 +4,5 @@ factory_guy_presentation/
4
4
  factory_guy_presents/
5
5
  stats/
6
6
  *.gem
7
- *.ruby*
7
+ *.ruby*
8
+ .idea/*
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-data-factory-guy",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "authors": [
5
5
  "Daniel Sudol <dansudol@yahoo.com>",
6
6
  "Opak Alex <opak.alexandr@gmail.com>"
@@ -390,9 +390,10 @@ DS.Store.reopen({
390
390
  @returns {Object|DS.Model} json or record depending on the adapter type
391
391
  */
392
392
  makeFixture: function (name, options) {
393
+ var store = this;
393
394
  var modelName = FactoryGuy.lookupModelForFixtureName(name);
394
395
  var fixture = FactoryGuy.build(name, options);
395
- var modelType = this.modelFor(modelName);
396
+ var modelType = store.modelFor(modelName);
396
397
 
397
398
  if (this.usingFixtureAdapter()) {
398
399
  this.setAssociationsForFixtureAdapter(modelType, modelName, fixture);
@@ -406,6 +407,7 @@ DS.Store.reopen({
406
407
  // assuming its polymorphic if there is a type attribute
407
408
  // is this too bold an assumption?
408
409
  modelName = fixture.type.underscore();
410
+ modelType = store.modelFor(modelName);
409
411
  }
410
412
  model = store.push(modelName, fixture);
411
413
  store.setAssociationsForRESTAdapter(modelType, modelName, model);
@@ -543,12 +545,16 @@ DS.Store.reopen({
543
545
  var self = this;
544
546
  Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
545
547
  if (relationship.kind == 'hasMany') {
546
- var belongsToName = modelName;
547
- if (relationship.options && relationship.options.inverse) {
548
- belongsToName = relationship.options.inverse;
549
- }
550
548
  var children = model.get(name) || [];
551
549
  children.forEach(function (child) {
550
+ var belongsToName = self.findRelationshipName(
551
+ 'belongsTo',
552
+ child.constructor,
553
+ model
554
+ );
555
+ if (relationship.options && relationship.options.inverse) {
556
+ belongsToName = relationship.options.inverse;
557
+ }
552
558
  child.set(belongsToName, model);
553
559
  })
554
560
  }
@@ -769,11 +775,10 @@ FactoryGuyTestMixin = Em.Mixin.create({
769
775
  */
770
776
  handleCreate: function (name, opts) {
771
777
  var model = FactoryGuy.lookupModelForFixtureName(name);
772
- this.stubEndpointForHttpRequest(
773
- "/" + Em.String.pluralize(model),
774
- this.buildAjaxCreateResponse(name, opts),
775
- {type: 'POST'}
776
- )
778
+ var responseJson = this.buildAjaxCreateResponse(name, opts);
779
+ var url = "/" + Em.String.pluralize(model);
780
+ this.stubEndpointForHttpRequest(url, responseJson, {type: 'POST'})
781
+ return responseJson;
777
782
  },
778
783
 
779
784
  /**
@@ -1 +1 @@
1
- Sequence=function(fn){var index=1;this.next=function(){return fn.call(this,index++)};this.reset=function(){index=1}};function MissingSequenceError(message){this.toString=function(){return message}}ModelDefinition=function(model,config){var sequences={};var defaultAttributes={};var namedModels={};var modelId=1;this.model=model;this.matchesName=function(name){return model==name||namedModels[name]};this.merge=function(config){};this.generate=function(name,sequenceFn){if(sequenceFn){if(!sequences[name]){sequences[name]=new Sequence(sequenceFn)}}var sequence=sequences[name];if(!sequence){throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+model+"' definition")}return sequence.next()};this.build=function(name,opts){var modelAttributes=namedModels[name]||{};var fixture=$.extend({},defaultAttributes,modelAttributes,opts);for(attribute in fixture){if(Ember.typeOf(fixture[attribute])=="function"){fixture[attribute]=fixture[attribute].call(this,fixture)}else if(Ember.typeOf(fixture[attribute])=="object"){fixture[attribute]=FactoryGuy.build(attribute,fixture[attribute])}}if(!fixture.id){fixture.id=modelId++}return fixture};this.buildList=function(name,number,opts){var arr=[];for(var i=0;i<number;i++){arr.push(this.build(name,opts))}return arr};this.reset=function(){modelId=1;for(name in sequences){sequences[name].reset()}};var parseDefault=function(object){if(!object){return}defaultAttributes=object};var parseSequences=function(object){if(!object){return}for(sequenceName in object){var sequenceFn=object[sequenceName];if(typeof sequenceFn!="function"){throw new Error("Problem with ["+sequenceName+"] sequence definition. Sequences must be functions")}object[sequenceName]=new Sequence(sequenceFn)}sequences=object};var parseConfig=function(config){parseSequences(config.sequences);delete config.sequences;parseDefault(config.default);delete config.default;namedModels=config};parseConfig(config)};FactoryGuy={modelDefinitions:{},define:function(model,config){if(this.modelDefinitions[model]){this.modelDefinitions[model].merge(config)}else{this.modelDefinitions[model]=new ModelDefinition(model,config)}},generate:function(nameOrFunction){var sortaRandomName=Math.floor((1+Math.random())*65536).toString(16)+Date.now();return function(){if(Em.typeOf(nameOrFunction)=="function"){return this.generate(sortaRandomName,nameOrFunction)}else{return this.generate(nameOrFunction)}}},association:function(fixtureName,opts){return function(){return FactoryGuy.build(fixtureName,opts)}},lookupModelForFixtureName:function(name){var definition=this.lookupDefinitionForFixtureName(name);if(definition){return definition.model}},lookupDefinitionForFixtureName:function(name){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];if(definition.matchesName(name)){return definition}}},build:function(name,opts){var definition=this.lookupDefinitionForFixtureName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.build(name,opts)},buildList:function(name,number,opts){var definition=this.lookupDefinitionForFixtureName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.buildList(name,number,opts)},resetModels:function(store){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];definition.reset();try{var modelType=store.modelFor(definition.model);if(store.usingFixtureAdapter()){modelType.FIXTURES=[]}store.unloadAll(modelType)}catch(e){}}},pushFixture:function(modelClass,fixture){if(!modelClass["FIXTURES"]){modelClass["FIXTURES"]=[]}modelClass["FIXTURES"].push(fixture);return fixture},clear:function(opts){if(!opts){this.modelDefinitions={}}}};DS.Store.reopen({usingFixtureAdapter:function(){var adapter=this.adapterFor("application");return adapter instanceof DS.FixtureAdapter},makeFixture:function(name,options){var modelName=FactoryGuy.lookupModelForFixtureName(name);var fixture=FactoryGuy.build(name,options);var modelType=this.modelFor(modelName);if(this.usingFixtureAdapter()){this.setAssociationsForFixtureAdapter(modelType,modelName,fixture);return FactoryGuy.pushFixture(modelType,fixture)}else{var store=this;var model;Em.run(function(){store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType,fixture);if(fixture.type){modelName=fixture.type.underscore()}model=store.push(modelName,fixture);store.setAssociationsForRESTAdapter(modelType,modelName,model)});return model}},makeList:function(name,number,options){var arr=[];for(var i=0;i<number;i++){arr.push(this.makeFixture(name,options))}return arr},setAssociationsForFixtureAdapter:function(modelType,modelName,fixture){var self=this;var adapter=this.adapterFor("application");Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){if(fixture[relationship.key]){fixture[relationship.key].forEach(function(id){var hasManyfixtures=adapter.fixturesForType(relationship.type);var fixture=adapter.findFixtureById(hasManyfixtures,id);fixture[modelName]=fixture.id})}}if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(belongsToRecord){if(typeof belongsToRecord=="object"){FactoryGuy.pushFixture(relationship.type,belongsToRecord);fixture[relationship.key]=belongsToRecord.id}var hasManyName=self.findHasManyRelationshipNameForFixtureAdapter(relationship.type,relationship.parentType);var belongsToFixtures=adapter.fixturesForType(relationship.type);var belongsTofixture=adapter.findFixtureById(belongsToFixtures,fixture[relationship.key]);if(!belongsTofixture[hasManyName]){belongsTofixture[hasManyName]=[]}belongsTofixture[hasManyName].push(fixture.id)}}})},findEmbeddedBelongsToAssociationsForRESTAdapter:function(modelType,fixture){var store=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(Ember.typeOf(belongsToRecord)=="object"){belongsToRecord=store.push(relationship.type,belongsToRecord);fixture[relationship.key]=belongsToRecord}}})},setAssociationsForRESTAdapter:function(modelType,modelName,model){var self=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){var belongsToName=modelName;if(relationship.options&&relationship.options.inverse){belongsToName=relationship.options.inverse}var children=model.get(name)||[];children.forEach(function(child){child.set(belongsToName,model)})}if(relationship.kind=="belongsTo"){var belongsToRecord=model.get(name);if(belongsToRecord){var setAssociations=function(){var hasManyName=self.findRelationshipName("hasMany",belongsToRecord.constructor,model);if(hasManyName){belongsToRecord.get(hasManyName).addObject(model)}var oneToOneName=self.findRelationshipName("belongsTo",belongsToRecord.constructor,model);if(oneToOneName&&!(belongsToRecord.constructor==model.constructor)){belongsToRecord.set(oneToOneName,model)}};if(belongsToRecord.then){belongsToRecord.then(function(record){belongsToRecord=record;setAssociations()})}else{setAssociations()}}}})},findRelationshipName:function(kind,belongToModelType,childModel){var relationshipName;Ember.get(belongToModelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind==kind&&childModel instanceof relationship.type){relationshipName=relationship.key}});return relationshipName},findHasManyRelationshipNameForFixtureAdapter:function(belongToModelType,childModelType){var relationshipName;Ember.get(belongToModelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"&&childModelType==relationship.type){relationshipName=relationship.key}});return relationshipName},pushPayload:function(type,payload){if(this.usingFixtureAdapter()){var model=this.modelFor(modelName);FactoryGuy.pushFixture(model,payload)}else{this._super(type,payload)}}});DS.FixtureAdapter.reopen({createRecord:function(store,type,record){var promise=this._super(store,type,record);promise.then(function(){var relationShips=Ember.get(type,"relationshipNames");if(relationShips.belongsTo){relationShips.belongsTo.forEach(function(relationship){var belongsToRecord=record.get(relationship);if(belongsToRecord){var hasManyName=store.findRelationshipName("hasMany",belongsToRecord.constructor,record);belongsToRecord.get(hasManyName).addObject(record)}})}});return promise}});FactoryGuyTestMixin=Em.Mixin.create({setup:function(app){this.set("container",app.__container__);return this},useFixtureAdapter:function(app){app.ApplicationAdapter=DS.FixtureAdapter;this.getStore().adapterFor("application").simulateRemoteResponse=false},find:function(type,id){return this.getStore().find(type,id)},make:function(name,opts){return this.getStore().makeFixture(name,opts)},getStore:function(){return this.get("container").lookup("store:main")},pushPayload:function(type,hash){return this.getStore().pushPayload(type,hash)},pushRecord:function(type,hash){return this.getStore().push(type,hash)},stubEndpointForHttpRequest:function(url,json,options){options=options||{};var request={url:url,dataType:"json",responseText:json,type:options.type||"GET",status:options.status||200};if(options.data){request.data=options.data}$.mockjax(request)},handleCreate:function(name,opts){var model=FactoryGuy.lookupModelForFixtureName(name);this.stubEndpointForHttpRequest("/"+Em.String.pluralize(model),this.buildAjaxCreateResponse(name,opts),{type:"POST"})},buildAjaxCreateResponse:function(name,opts){var fixture=FactoryGuy.build(name,opts);var model=FactoryGuy.lookupModelForFixtureName(name);var hash={};hash[model]=fixture;return hash},handleUpdate:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"PUT"})},handleDelete:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"DELETE"})},teardown:function(){FactoryGuy.resetModels(this.getStore())}});
1
+ Sequence=function(fn){var index=1;this.next=function(){return fn.call(this,index++)};this.reset=function(){index=1}};function MissingSequenceError(message){this.toString=function(){return message}}ModelDefinition=function(model,config){var sequences={};var defaultAttributes={};var namedModels={};var modelId=1;this.model=model;this.matchesName=function(name){return model==name||namedModels[name]};this.merge=function(config){};this.generate=function(name,sequenceFn){if(sequenceFn){if(!sequences[name]){sequences[name]=new Sequence(sequenceFn)}}var sequence=sequences[name];if(!sequence){throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+model+"' definition")}return sequence.next()};this.build=function(name,opts){var modelAttributes=namedModels[name]||{};var fixture=$.extend({},defaultAttributes,modelAttributes,opts);for(attribute in fixture){if(Ember.typeOf(fixture[attribute])=="function"){fixture[attribute]=fixture[attribute].call(this,fixture)}else if(Ember.typeOf(fixture[attribute])=="object"){fixture[attribute]=FactoryGuy.build(attribute,fixture[attribute])}}if(!fixture.id){fixture.id=modelId++}return fixture};this.buildList=function(name,number,opts){var arr=[];for(var i=0;i<number;i++){arr.push(this.build(name,opts))}return arr};this.reset=function(){modelId=1;for(name in sequences){sequences[name].reset()}};var parseDefault=function(object){if(!object){return}defaultAttributes=object};var parseSequences=function(object){if(!object){return}for(sequenceName in object){var sequenceFn=object[sequenceName];if(typeof sequenceFn!="function"){throw new Error("Problem with ["+sequenceName+"] sequence definition. Sequences must be functions")}object[sequenceName]=new Sequence(sequenceFn)}sequences=object};var parseConfig=function(config){parseSequences(config.sequences);delete config.sequences;parseDefault(config.default);delete config.default;namedModels=config};parseConfig(config)};FactoryGuy={modelDefinitions:{},define:function(model,config){if(this.modelDefinitions[model]){this.modelDefinitions[model].merge(config)}else{this.modelDefinitions[model]=new ModelDefinition(model,config)}},generate:function(nameOrFunction){var sortaRandomName=Math.floor((1+Math.random())*65536).toString(16)+Date.now();return function(){if(Em.typeOf(nameOrFunction)=="function"){return this.generate(sortaRandomName,nameOrFunction)}else{return this.generate(nameOrFunction)}}},association:function(fixtureName,opts){return function(){return FactoryGuy.build(fixtureName,opts)}},lookupModelForFixtureName:function(name){var definition=this.lookupDefinitionForFixtureName(name);if(definition){return definition.model}},lookupDefinitionForFixtureName:function(name){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];if(definition.matchesName(name)){return definition}}},build:function(name,opts){var definition=this.lookupDefinitionForFixtureName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.build(name,opts)},buildList:function(name,number,opts){var definition=this.lookupDefinitionForFixtureName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.buildList(name,number,opts)},resetModels:function(store){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];definition.reset();try{var modelType=store.modelFor(definition.model);if(store.usingFixtureAdapter()){modelType.FIXTURES=[]}store.unloadAll(modelType)}catch(e){}}},pushFixture:function(modelClass,fixture){if(!modelClass["FIXTURES"]){modelClass["FIXTURES"]=[]}modelClass["FIXTURES"].push(fixture);return fixture},clear:function(opts){if(!opts){this.modelDefinitions={}}}};DS.Store.reopen({usingFixtureAdapter:function(){var adapter=this.adapterFor("application");return adapter instanceof DS.FixtureAdapter},makeFixture:function(name,options){var store=this;var modelName=FactoryGuy.lookupModelForFixtureName(name);var fixture=FactoryGuy.build(name,options);var modelType=store.modelFor(modelName);if(this.usingFixtureAdapter()){this.setAssociationsForFixtureAdapter(modelType,modelName,fixture);return FactoryGuy.pushFixture(modelType,fixture)}else{var store=this;var model;Em.run(function(){store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType,fixture);if(fixture.type){modelName=fixture.type.underscore();modelType=store.modelFor(modelName)}model=store.push(modelName,fixture);store.setAssociationsForRESTAdapter(modelType,modelName,model)});return model}},makeList:function(name,number,options){var arr=[];for(var i=0;i<number;i++){arr.push(this.makeFixture(name,options))}return arr},setAssociationsForFixtureAdapter:function(modelType,modelName,fixture){var self=this;var adapter=this.adapterFor("application");Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){if(fixture[relationship.key]){fixture[relationship.key].forEach(function(id){var hasManyfixtures=adapter.fixturesForType(relationship.type);var fixture=adapter.findFixtureById(hasManyfixtures,id);fixture[modelName]=fixture.id})}}if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(belongsToRecord){if(typeof belongsToRecord=="object"){FactoryGuy.pushFixture(relationship.type,belongsToRecord);fixture[relationship.key]=belongsToRecord.id}var hasManyName=self.findHasManyRelationshipNameForFixtureAdapter(relationship.type,relationship.parentType);var belongsToFixtures=adapter.fixturesForType(relationship.type);var belongsTofixture=adapter.findFixtureById(belongsToFixtures,fixture[relationship.key]);if(!belongsTofixture[hasManyName]){belongsTofixture[hasManyName]=[]}belongsTofixture[hasManyName].push(fixture.id)}}})},findEmbeddedBelongsToAssociationsForRESTAdapter:function(modelType,fixture){var store=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(Ember.typeOf(belongsToRecord)=="object"){belongsToRecord=store.push(relationship.type,belongsToRecord);fixture[relationship.key]=belongsToRecord}}})},setAssociationsForRESTAdapter:function(modelType,modelName,model){var self=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){var children=model.get(name)||[];children.forEach(function(child){var belongsToName=self.findRelationshipName("belongsTo",child.constructor,model);if(relationship.options&&relationship.options.inverse){belongsToName=relationship.options.inverse}child.set(belongsToName,model)})}if(relationship.kind=="belongsTo"){var belongsToRecord=model.get(name);if(belongsToRecord){var setAssociations=function(){var hasManyName=self.findRelationshipName("hasMany",belongsToRecord.constructor,model);if(hasManyName){belongsToRecord.get(hasManyName).addObject(model)}var oneToOneName=self.findRelationshipName("belongsTo",belongsToRecord.constructor,model);if(oneToOneName&&!(belongsToRecord.constructor==model.constructor)){belongsToRecord.set(oneToOneName,model)}};if(belongsToRecord.then){belongsToRecord.then(function(record){belongsToRecord=record;setAssociations()})}else{setAssociations()}}}})},findRelationshipName:function(kind,belongToModelType,childModel){var relationshipName;Ember.get(belongToModelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind==kind&&childModel instanceof relationship.type){relationshipName=relationship.key}});return relationshipName},findHasManyRelationshipNameForFixtureAdapter:function(belongToModelType,childModelType){var relationshipName;Ember.get(belongToModelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"&&childModelType==relationship.type){relationshipName=relationship.key}});return relationshipName},pushPayload:function(type,payload){if(this.usingFixtureAdapter()){var model=this.modelFor(modelName);FactoryGuy.pushFixture(model,payload)}else{this._super(type,payload)}}});DS.FixtureAdapter.reopen({createRecord:function(store,type,record){var promise=this._super(store,type,record);promise.then(function(){var relationShips=Ember.get(type,"relationshipNames");if(relationShips.belongsTo){relationShips.belongsTo.forEach(function(relationship){var belongsToRecord=record.get(relationship);if(belongsToRecord){var hasManyName=store.findRelationshipName("hasMany",belongsToRecord.constructor,record);belongsToRecord.get(hasManyName).addObject(record)}})}});return promise}});FactoryGuyTestMixin=Em.Mixin.create({setup:function(app){this.set("container",app.__container__);return this},useFixtureAdapter:function(app){app.ApplicationAdapter=DS.FixtureAdapter;this.getStore().adapterFor("application").simulateRemoteResponse=false},find:function(type,id){return this.getStore().find(type,id)},make:function(name,opts){return this.getStore().makeFixture(name,opts)},getStore:function(){return this.get("container").lookup("store:main")},pushPayload:function(type,hash){return this.getStore().pushPayload(type,hash)},pushRecord:function(type,hash){return this.getStore().push(type,hash)},stubEndpointForHttpRequest:function(url,json,options){options=options||{};var request={url:url,dataType:"json",responseText:json,type:options.type||"GET",status:options.status||200};if(options.data){request.data=options.data}$.mockjax(request)},handleCreate:function(name,opts){var model=FactoryGuy.lookupModelForFixtureName(name);var responseJson=this.buildAjaxCreateResponse(name,opts);var url="/"+Em.String.pluralize(model);this.stubEndpointForHttpRequest(url,responseJson,{type:"POST"});return responseJson},buildAjaxCreateResponse:function(name,opts){var fixture=FactoryGuy.build(name,opts);var model=FactoryGuy.lookupModelForFixtureName(name);var hash={};hash[model]=fixture;return hash},handleUpdate:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"PUT"})},handleDelete:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"DELETE"})},teardown:function(){FactoryGuy.resetModels(this.getStore())}});
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = "ember-data-factory-guy"
4
- s.version = "0.3.9"
4
+ s.version = "0.4.0"
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ["Daniel Sudol", "Alex Opak"]
7
7
  s.email = ["dansudol@yahoo.com", "opak.alexandr@gmail.com"]
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-data-factory-guy",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "authors": [
5
5
  "Daniel Sudol <dansudol@yahoo.com>",
6
6
  "Opak Alex <opak.alexandr@gmail.com>"
@@ -24,12 +24,13 @@
24
24
  "type": "git",
25
25
  "url": ""
26
26
  },
27
- "devDependencies": [
28
- "grunt-contrib-coffee",
29
- "grunt-contrib-concat",
30
- "grunt-contrib-uglify",
31
- "grunt-contrib-qunit"
32
- ],
27
+ "devDependencies": {
28
+ "0": "grunt-contrib-coffee",
29
+ "1": "grunt-contrib-concat",
30
+ "2": "grunt-contrib-uglify",
31
+ "3": "grunt-contrib-qunit",
32
+ "grunt-bump": "0.0.14"
33
+ },
33
34
  "engines": {
34
35
  "node": ">=v0.10.1"
35
36
  }
@@ -70,11 +70,10 @@ FactoryGuyTestMixin = Em.Mixin.create({
70
70
  */
71
71
  handleCreate: function (name, opts) {
72
72
  var model = FactoryGuy.lookupModelForFixtureName(name);
73
- this.stubEndpointForHttpRequest(
74
- "/" + Em.String.pluralize(model),
75
- this.buildAjaxCreateResponse(name, opts),
76
- {type: 'POST'}
77
- )
73
+ var responseJson = this.buildAjaxCreateResponse(name, opts);
74
+ var url = "/" + Em.String.pluralize(model);
75
+ this.stubEndpointForHttpRequest(url, responseJson, {type: 'POST'})
76
+ return responseJson;
78
77
  },
79
78
 
80
79
  /**
data/src/store.js CHANGED
@@ -16,9 +16,10 @@ DS.Store.reopen({
16
16
  @returns {Object|DS.Model} json or record depending on the adapter type
17
17
  */
18
18
  makeFixture: function (name, options) {
19
+ var store = this;
19
20
  var modelName = FactoryGuy.lookupModelForFixtureName(name);
20
21
  var fixture = FactoryGuy.build(name, options);
21
- var modelType = this.modelFor(modelName);
22
+ var modelType = store.modelFor(modelName);
22
23
 
23
24
  if (this.usingFixtureAdapter()) {
24
25
  this.setAssociationsForFixtureAdapter(modelType, modelName, fixture);
@@ -32,6 +33,7 @@ DS.Store.reopen({
32
33
  // assuming its polymorphic if there is a type attribute
33
34
  // is this too bold an assumption?
34
35
  modelName = fixture.type.underscore();
36
+ modelType = store.modelFor(modelName);
35
37
  }
36
38
  model = store.push(modelName, fixture);
37
39
  store.setAssociationsForRESTAdapter(modelType, modelName, model);
@@ -169,12 +171,16 @@ DS.Store.reopen({
169
171
  var self = this;
170
172
  Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
171
173
  if (relationship.kind == 'hasMany') {
172
- var belongsToName = modelName;
173
- if (relationship.options && relationship.options.inverse) {
174
- belongsToName = relationship.options.inverse;
175
- }
176
174
  var children = model.get(name) || [];
177
175
  children.forEach(function (child) {
176
+ var belongsToName = self.findRelationshipName(
177
+ 'belongsTo',
178
+ child.constructor,
179
+ model
180
+ );
181
+ if (relationship.options && relationship.options.inverse) {
182
+ belongsToName = relationship.options.inverse;
183
+ }
178
184
  child.set(belongsToName, model);
179
185
  })
180
186
  }
@@ -100,6 +100,13 @@ test("when hasMany associations are assigned, belongsTo parent is assigned using
100
100
  });
101
101
 
102
102
 
103
+ test("when hasMany associations are assigned, belongsTo parent is assigned using actual belongsTo name", function() {
104
+ var silk = store.makeFixture('silk');
105
+ var bh = store.makeFixture('big_hat', {materials: [silk]});
106
+ ok(silk.get('hat') == bh)
107
+ });
108
+
109
+
103
110
  test("when belongTo parent is assigned, parent adds to hasMany records", function() {
104
111
  var user = store.makeFixture('user');
105
112
  var project1 = store.makeFixture('project', {user: user});
@@ -142,6 +149,13 @@ test("when belongTo parent is assigned, parent adds to hasMany record using inve
142
149
  });
143
150
 
144
151
 
152
+ test("when belongTo parent is assigned, parent adds to hasMany record using actual hasMany name", function() {
153
+ var bh = store.makeFixture('big_hat');
154
+ var silk = store.makeFixture('silk', {hat: bh});
155
+ ok(bh.get('materials.firstObject') == silk)
156
+ });
157
+
158
+
145
159
  test("when belongTo parent is assigned, parent adds to belongsTo record", function() {
146
160
  var company = store.makeFixture('company');
147
161
  var profile = store.makeFixture('profile', {company: company});
@@ -194,3 +208,16 @@ test("creates records in the store", function() {
194
208
  deepEqual(storeUsers[0].toJSON(), users[0].toJSON());
195
209
  deepEqual(storeUsers[1].toJSON(), users[1].toJSON());
196
210
  });
211
+
212
+
213
+ asyncTest("#store.createRecord with FactoryGuy fixtures handles snake_case or camelCase attributes", function() {
214
+ var json = testHelper.handleCreate('profile', {})
215
+ // if you examine the json .. you'll see both attributes in there
216
+ store.createRecord('profile').save().then(function(profile) {
217
+ // both types of attributes work just fine
218
+ ok(!!profile.get('snake_case_description'))
219
+ ok(!!profile.get('camelCaseDescription'))
220
+ start();
221
+ })
222
+ })
223
+
@@ -147,9 +147,9 @@ test("#lookupDefinitionForFixtureName", function() {
147
147
  equal(!!FactoryGuy.lookupDefinitionForFixtureName('fake'), false, "return nothing if can't find definition");
148
148
  });
149
149
 
150
-
151
150
  test("#lookupModelForFixtureName", function() {
152
151
  equal(FactoryGuy.lookupModelForFixtureName('person'), 'person', "finds model if its the same as model name");
153
152
  equal(FactoryGuy.lookupModelForFixtureName('funny_person'), 'person', "finds model if it's definition has this named fixture");
154
153
  equal(FactoryGuy.lookupModelForFixtureName('fake'), undefined, "return nothing if can't find definition");
155
- });
154
+ });
155
+
@@ -100,6 +100,13 @@ test("when hasMany associations are assigned, belongsTo parent is assigned using
100
100
  });
101
101
 
102
102
 
103
+ test("when hasMany associations are assigned, belongsTo parent is assigned using actual belongsTo name", function() {
104
+ var silk = store.makeFixture('silk');
105
+ var bh = store.makeFixture('big_hat', {materials: [silk]});
106
+ ok(silk.get('hat') == bh)
107
+ });
108
+
109
+
103
110
  test("when belongTo parent is assigned, parent adds to hasMany records", function() {
104
111
  var user = store.makeFixture('user');
105
112
  var project1 = store.makeFixture('project', {user: user});
@@ -142,6 +149,13 @@ test("when belongTo parent is assigned, parent adds to hasMany record using inve
142
149
  });
143
150
 
144
151
 
152
+ test("when belongTo parent is assigned, parent adds to hasMany record using actual hasMany name", function() {
153
+ var bh = store.makeFixture('big_hat');
154
+ var silk = store.makeFixture('silk', {hat: bh});
155
+ ok(bh.get('materials.firstObject') == silk)
156
+ });
157
+
158
+
145
159
  test("when belongTo parent is assigned, parent adds to belongsTo record", function() {
146
160
  var company = store.makeFixture('company');
147
161
  var profile = store.makeFixture('profile', {company: company});
@@ -0,0 +1,8 @@
1
+ FactoryGuy.define('soft_material', {
2
+ default: {
3
+ name: 'Soft material'
4
+ },
5
+ silk: {
6
+ name: 'silk'
7
+ }
8
+ })
@@ -1,5 +1,7 @@
1
1
  FactoryGuy.define('profile', {
2
2
  default: {
3
- description: 'Text goes here'
3
+ description: 'Text goes here',
4
+ camelCaseDescription: 'boyThisIsSilly',
5
+ snake_case_description: 'how_do_birds_find_worms'
4
6
  }
5
7
  })
@@ -0,0 +1,600 @@
1
+ /*!
2
+ * MockJax - jQuery Plugin to Mock Ajax requests
3
+ *
4
+ * Version: 1.5.3
5
+ * Released:
6
+ * Home: http://github.com/appendto/jquery-mockjax
7
+ * Author: Jonathan Sharp (http://jdsharp.com)
8
+ * License: MIT,GPL
9
+ *
10
+ * Copyright (c) 2011 appendTo LLC.
11
+ * Dual licensed under the MIT or GPL licenses.
12
+ * http://appendto.com/open-source-licenses
13
+ */
14
+ (function($) {
15
+ var _ajax = $.ajax,
16
+ mockHandlers = [],
17
+ mockedAjaxCalls = [],
18
+ CALLBACK_REGEX = /=\?(&|$)/,
19
+ jsc = (new Date()).getTime();
20
+
21
+
22
+ // Parse the given XML string.
23
+ function parseXML(xml) {
24
+ if ( window.DOMParser == undefined && window.ActiveXObject ) {
25
+ DOMParser = function() { };
26
+
27
+ DOMParser.prototype.parseFromString = function( xmlString ) {
28
+ var doc = new ActiveXObject('Microsoft.XMLDOM');
29
+ doc.async = 'false';
30
+ doc.loadXML( xmlString );
31
+ return doc;
32
+ };
33
+ }
34
+
35
+ try {
36
+ var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
37
+ if ( $.isXMLDoc( xmlDoc ) ) {
38
+ var err = $('parsererror', xmlDoc);
39
+ if ( err.length == 1 ) {
40
+ throw('Error: ' + $(xmlDoc).text() );
41
+ }
42
+ } else {
43
+ throw('Unable to parse XML');
44
+ }
45
+ return xmlDoc;
46
+ } catch( e ) {
47
+ var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
48
+ $(document).trigger('xmlParseError', [ msg ]);
49
+ return undefined;
50
+ }
51
+ }
52
+
53
+ // Trigger a jQuery event
54
+ function trigger(s, type, args) {
55
+ (s.context ? $(s.context) : $.event).trigger(type, args);
56
+ }
57
+
58
+ // Check if the data field on the mock handler and the request match. This
59
+ // can be used to restrict a mock handler to being used only when a certain
60
+ // set of data is passed to it.
61
+ function isMockDataEqual( mock, live ) {
62
+ var identical = true;
63
+ // Test for situations where the data is a querystring (not an object)
64
+ if (typeof live === 'string') {
65
+ // Querystring may be a regex
66
+ return $.isFunction( mock.test ) ? mock.test(live) : mock == live;
67
+ }
68
+ $.each(mock, function(k) {
69
+ if ( live[k] === undefined ) {
70
+ identical = false;
71
+ return identical;
72
+ } else {
73
+ // This will allow to compare Arrays
74
+ if ( typeof live[k] === 'object' && live[k] !== null ) {
75
+ identical = identical && isMockDataEqual(mock[k], live[k]);
76
+ } else {
77
+ if ( mock[k] && $.isFunction( mock[k].test ) ) {
78
+ identical = identical && mock[k].test(live[k]);
79
+ } else {
80
+ identical = identical && ( mock[k] == live[k] );
81
+ }
82
+ }
83
+ }
84
+ });
85
+
86
+ return identical;
87
+ }
88
+
89
+ // See if a mock handler property matches the default settings
90
+ function isDefaultSetting(handler, property) {
91
+ return handler[property] === $.mockjaxSettings[property];
92
+ }
93
+
94
+ // Check the given handler should mock the given request
95
+ function getMockForRequest( handler, requestSettings ) {
96
+
97
+ // If the mock was registered with a function, let the function decide if we
98
+ // want to mock this request
99
+ if ( $.isFunction(handler) ) {
100
+ return handler( requestSettings );
101
+ }
102
+
103
+ // Inspect the URL of the request and check if the mock handler's url
104
+ // matches the url for this ajax request
105
+ if ( $.isFunction(handler.url.test) ) {
106
+ // The user provided a regex for the url, test it
107
+ if ( !handler.url.test( requestSettings.url ) ) {
108
+ return null;
109
+ }
110
+ } else {
111
+ // Look for a simple wildcard '*' or a direct URL match
112
+ var star = handler.url.indexOf('*');
113
+ if (handler.url !== requestSettings.url && star === -1 ||
114
+ !new RegExp(handler.url.replace(/[-[\]{}()+?.,\\^$|#\s]/g, "\\$&").replace(/\*/g, '.+')).test(requestSettings.url)) {
115
+ return null;
116
+ }
117
+ }
118
+ // console.log(handler.url, handler.data, requestSettings.data)
119
+ // Inspect the data submitted in the request (either POST body or GET query string)
120
+ if ( handler.data && requestSettings.data ) {
121
+ if ( !isMockDataEqual(handler.data, requestSettings.data) ) {
122
+ // They're not identical, do not mock this request
123
+ return null;
124
+ }
125
+ }
126
+ // Inspect the request type
127
+ if ( handler && handler.type &&
128
+ handler.type.toLowerCase() != requestSettings.type.toLowerCase() ) {
129
+ // The request type doesn't match (GET vs. POST)
130
+ return null;
131
+ }
132
+
133
+ return handler;
134
+ }
135
+
136
+ // Process the xhr objects send operation
137
+ function _xhrSend(mockHandler, requestSettings, origSettings) {
138
+
139
+ // This is a substitute for < 1.4 which lacks $.proxy
140
+ var process = (function(that) {
141
+ return function() {
142
+ return (function() {
143
+ var onReady;
144
+
145
+ // The request has returned
146
+ this.status = mockHandler.status;
147
+ this.statusText = mockHandler.statusText;
148
+ this.readyState = 4;
149
+
150
+ // We have an executable function, call it to give
151
+ // the mock handler a chance to update it's data
152
+ if ( $.isFunction(mockHandler.response) ) {
153
+ mockHandler.response(origSettings);
154
+ }
155
+ // Copy over our mock to our xhr object before passing control back to
156
+ // jQuery's onreadystatechange callback
157
+ if ( requestSettings.dataType == 'json' && ( typeof mockHandler.responseText == 'object' ) ) {
158
+ this.responseText = JSON.stringify(mockHandler.responseText);
159
+ } else if ( requestSettings.dataType == 'xml' ) {
160
+ if ( typeof mockHandler.responseXML == 'string' ) {
161
+ this.responseXML = parseXML(mockHandler.responseXML);
162
+ //in jQuery 1.9.1+, responseXML is processed differently and relies on responseText
163
+ this.responseText = mockHandler.responseXML;
164
+ } else {
165
+ this.responseXML = mockHandler.responseXML;
166
+ }
167
+ } else {
168
+ this.responseText = mockHandler.responseText;
169
+ }
170
+ if( typeof mockHandler.status == 'number' || typeof mockHandler.status == 'string' ) {
171
+ this.status = mockHandler.status;
172
+ }
173
+ if( typeof mockHandler.statusText === "string") {
174
+ this.statusText = mockHandler.statusText;
175
+ }
176
+ // jQuery 2.0 renamed onreadystatechange to onload
177
+ onReady = this.onreadystatechange || this.onload;
178
+
179
+ // jQuery < 1.4 doesn't have onreadystate change for xhr
180
+ if ( $.isFunction( onReady ) ) {
181
+ if( mockHandler.isTimeout) {
182
+ this.status = -1;
183
+ }
184
+ onReady.call( this, mockHandler.isTimeout ? 'timeout' : undefined );
185
+ } else if ( mockHandler.isTimeout ) {
186
+ // Fix for 1.3.2 timeout to keep success from firing.
187
+ this.status = -1;
188
+ }
189
+ }).apply(that);
190
+ };
191
+ })(this);
192
+
193
+ if ( mockHandler.proxy ) {
194
+ // We're proxying this request and loading in an external file instead
195
+ _ajax({
196
+ global: false,
197
+ url: mockHandler.proxy,
198
+ type: mockHandler.proxyType,
199
+ data: mockHandler.data,
200
+ dataType: requestSettings.dataType === "script" ? "text/plain" : requestSettings.dataType,
201
+ complete: function(xhr) {
202
+ mockHandler.responseXML = xhr.responseXML;
203
+ mockHandler.responseText = xhr.responseText;
204
+ // Don't override the handler status/statusText if it's specified by the config
205
+ if (isDefaultSetting(mockHandler, 'status')) {
206
+ mockHandler.status = xhr.status;
207
+ }
208
+ if (isDefaultSetting(mockHandler, 'statusText')) {
209
+ mockHandler.statusText = xhr.statusText;
210
+ }
211
+
212
+ this.responseTimer = setTimeout(process, mockHandler.responseTime || 0);
213
+ }
214
+ });
215
+ } else {
216
+ // type == 'POST' || 'GET' || 'DELETE'
217
+ if ( requestSettings.async === false ) {
218
+ // TODO: Blocking delay
219
+ process();
220
+ } else {
221
+ this.responseTimer = setTimeout(process, mockHandler.responseTime || 50);
222
+ }
223
+ }
224
+ }
225
+
226
+ // Construct a mocked XHR Object
227
+ function xhr(mockHandler, requestSettings, origSettings, origHandler) {
228
+ // Extend with our default mockjax settings
229
+ mockHandler = $.extend(true, {}, $.mockjaxSettings, mockHandler);
230
+
231
+ if (typeof mockHandler.headers === 'undefined') {
232
+ mockHandler.headers = {};
233
+ }
234
+ if ( mockHandler.contentType ) {
235
+ mockHandler.headers['content-type'] = mockHandler.contentType;
236
+ }
237
+
238
+ return {
239
+ status: mockHandler.status,
240
+ statusText: mockHandler.statusText,
241
+ readyState: 1,
242
+ open: function() { },
243
+ send: function() {
244
+ origHandler.fired = true;
245
+ _xhrSend.call(this, mockHandler, requestSettings, origSettings);
246
+ },
247
+ abort: function() {
248
+ clearTimeout(this.responseTimer);
249
+ },
250
+ setRequestHeader: function(header, value) {
251
+ mockHandler.headers[header] = value;
252
+ },
253
+ getResponseHeader: function(header) {
254
+ // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
255
+ if ( mockHandler.headers && mockHandler.headers[header] ) {
256
+ // Return arbitrary headers
257
+ return mockHandler.headers[header];
258
+ } else if ( header.toLowerCase() == 'last-modified' ) {
259
+ return mockHandler.lastModified || (new Date()).toString();
260
+ } else if ( header.toLowerCase() == 'etag' ) {
261
+ return mockHandler.etag || '';
262
+ } else if ( header.toLowerCase() == 'content-type' ) {
263
+ return mockHandler.contentType || 'text/plain';
264
+ }
265
+ },
266
+ getAllResponseHeaders: function() {
267
+ var headers = '';
268
+ $.each(mockHandler.headers, function(k, v) {
269
+ headers += k + ': ' + v + "\n";
270
+ });
271
+ return headers;
272
+ }
273
+ };
274
+ }
275
+
276
+ // Process a JSONP mock request.
277
+ function processJsonpMock( requestSettings, mockHandler, origSettings ) {
278
+ // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
279
+ // because there isn't an easy hook for the cross domain script tag of jsonp
280
+
281
+ processJsonpUrl( requestSettings );
282
+
283
+ requestSettings.dataType = "json";
284
+ if(requestSettings.data && CALLBACK_REGEX.test(requestSettings.data) || CALLBACK_REGEX.test(requestSettings.url)) {
285
+ createJsonpCallback(requestSettings, mockHandler, origSettings);
286
+
287
+ // We need to make sure
288
+ // that a JSONP style response is executed properly
289
+
290
+ var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
291
+ parts = rurl.exec( requestSettings.url ),
292
+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
293
+
294
+ requestSettings.dataType = "script";
295
+ if(requestSettings.type.toUpperCase() === "GET" && remote ) {
296
+ var newMockReturn = processJsonpRequest( requestSettings, mockHandler, origSettings );
297
+
298
+ // Check if we are supposed to return a Deferred back to the mock call, or just
299
+ // signal success
300
+ if(newMockReturn) {
301
+ return newMockReturn;
302
+ } else {
303
+ return true;
304
+ }
305
+ }
306
+ }
307
+ return null;
308
+ }
309
+
310
+ // Append the required callback parameter to the end of the request URL, for a JSONP request
311
+ function processJsonpUrl( requestSettings ) {
312
+ if ( requestSettings.type.toUpperCase() === "GET" ) {
313
+ if ( !CALLBACK_REGEX.test( requestSettings.url ) ) {
314
+ requestSettings.url += (/\?/.test( requestSettings.url ) ? "&" : "?") +
315
+ (requestSettings.jsonp || "callback") + "=?";
316
+ }
317
+ } else if ( !requestSettings.data || !CALLBACK_REGEX.test(requestSettings.data) ) {
318
+ requestSettings.data = (requestSettings.data ? requestSettings.data + "&" : "") + (requestSettings.jsonp || "callback") + "=?";
319
+ }
320
+ }
321
+
322
+ // Process a JSONP request by evaluating the mocked response text
323
+ function processJsonpRequest( requestSettings, mockHandler, origSettings ) {
324
+ // Synthesize the mock request for adding a script tag
325
+ var callbackContext = origSettings && origSettings.context || requestSettings,
326
+ newMock = null;
327
+
328
+
329
+ // If the response handler on the moock is a function, call it
330
+ if ( mockHandler.response && $.isFunction(mockHandler.response) ) {
331
+ mockHandler.response(origSettings);
332
+ } else {
333
+
334
+ // Evaluate the responseText javascript in a global context
335
+ if( typeof mockHandler.responseText === 'object' ) {
336
+ $.globalEval( '(' + JSON.stringify( mockHandler.responseText ) + ')');
337
+ } else {
338
+ $.globalEval( '(' + mockHandler.responseText + ')');
339
+ }
340
+ }
341
+
342
+ // Successful response
343
+ jsonpSuccess( requestSettings, callbackContext, mockHandler );
344
+ jsonpComplete( requestSettings, callbackContext, mockHandler );
345
+
346
+ // If we are running under jQuery 1.5+, return a deferred object
347
+ if($.Deferred){
348
+ newMock = new $.Deferred();
349
+ if(typeof mockHandler.responseText == "object"){
350
+ newMock.resolveWith( callbackContext, [mockHandler.responseText] );
351
+ }
352
+ else{
353
+ newMock.resolveWith( callbackContext, [$.parseJSON( mockHandler.responseText )] );
354
+ }
355
+ }
356
+ return newMock;
357
+ }
358
+
359
+
360
+ // Create the required JSONP callback function for the request
361
+ function createJsonpCallback( requestSettings, mockHandler, origSettings ) {
362
+ var callbackContext = origSettings && origSettings.context || requestSettings;
363
+ var jsonp = requestSettings.jsonpCallback || ("jsonp" + jsc++);
364
+
365
+ // Replace the =? sequence both in the query string and the data
366
+ if ( requestSettings.data ) {
367
+ requestSettings.data = (requestSettings.data + "").replace(CALLBACK_REGEX, "=" + jsonp + "$1");
368
+ }
369
+
370
+ requestSettings.url = requestSettings.url.replace(CALLBACK_REGEX, "=" + jsonp + "$1");
371
+
372
+
373
+ // Handle JSONP-style loading
374
+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
375
+ data = tmp;
376
+ jsonpSuccess( requestSettings, callbackContext, mockHandler );
377
+ jsonpComplete( requestSettings, callbackContext, mockHandler );
378
+ // Garbage collect
379
+ window[ jsonp ] = undefined;
380
+
381
+ try {
382
+ delete window[ jsonp ];
383
+ } catch(e) {}
384
+
385
+ if ( head ) {
386
+ head.removeChild( script );
387
+ }
388
+ };
389
+ }
390
+
391
+ // The JSONP request was successful
392
+ function jsonpSuccess(requestSettings, callbackContext, mockHandler) {
393
+ // If a local callback was specified, fire it and pass it the data
394
+ if ( requestSettings.success ) {
395
+ requestSettings.success.call( callbackContext, mockHandler.responseText || "", status, {} );
396
+ }
397
+
398
+ // Fire the global callback
399
+ if ( requestSettings.global ) {
400
+ trigger(requestSettings, "ajaxSuccess", [{}, requestSettings] );
401
+ }
402
+ }
403
+
404
+ // The JSONP request was completed
405
+ function jsonpComplete(requestSettings, callbackContext) {
406
+ // Process result
407
+ if ( requestSettings.complete ) {
408
+ requestSettings.complete.call( callbackContext, {} , status );
409
+ }
410
+
411
+ // The request was completed
412
+ if ( requestSettings.global ) {
413
+ trigger( "ajaxComplete", [{}, requestSettings] );
414
+ }
415
+
416
+ // Handle the global AJAX counter
417
+ if ( requestSettings.global && ! --$.active ) {
418
+ $.event.trigger( "ajaxStop" );
419
+ }
420
+ }
421
+
422
+
423
+ // The core $.ajax replacement.
424
+ function handleAjax( url, origSettings ) {
425
+ var mockRequest, requestSettings, mockHandler;
426
+ // console.log('handleAjax', url)
427
+ // If url is an object, simulate pre-1.5 signature
428
+ if ( typeof url === "object" ) {
429
+ origSettings = url;
430
+ url = undefined;
431
+ } else {
432
+ // work around to support 1.5 signature
433
+ origSettings.url = url;
434
+ }
435
+
436
+ // Extend the original settings for the request
437
+ requestSettings = $.extend(true, {}, $.ajaxSettings, origSettings);
438
+
439
+ // Iterate over our mock handlers (in registration order) until we find
440
+ // one that is willing to intercept the request
441
+ for(var k = 0; k < mockHandlers.length; k++) {
442
+ if ( !mockHandlers[k] ) {
443
+ continue;
444
+ }
445
+
446
+ mockHandler = getMockForRequest( mockHandlers[k], requestSettings );
447
+ if(!mockHandler) {
448
+ // No valid mock found for this request
449
+ continue;
450
+ }
451
+
452
+ mockedAjaxCalls.push(requestSettings);
453
+
454
+ // If logging is enabled, log the mock to the console
455
+ $.mockjaxSettings.log( mockHandler, requestSettings );
456
+
457
+
458
+ if ( requestSettings.dataType === "jsonp" ) {
459
+ if ((mockRequest = processJsonpMock( requestSettings, mockHandler, origSettings ))) {
460
+ // This mock will handle the JSONP request
461
+ return mockRequest;
462
+ }
463
+ }
464
+
465
+
466
+ // Removed to fix #54 - keep the mocking data object intact
467
+ //mockHandler.data = requestSettings.data;
468
+
469
+ mockHandler.cache = requestSettings.cache;
470
+ mockHandler.timeout = requestSettings.timeout;
471
+ mockHandler.global = requestSettings.global;
472
+
473
+ copyUrlParameters(mockHandler, origSettings);
474
+
475
+ (function(mockHandler, requestSettings, origSettings, origHandler) {
476
+ mockRequest = _ajax.call($, $.extend(true, {}, origSettings, {
477
+ // Mock the XHR object
478
+ xhr: function() { return xhr( mockHandler, requestSettings, origSettings, origHandler ); }
479
+ }));
480
+ })(mockHandler, requestSettings, origSettings, mockHandlers[k]);
481
+
482
+ return mockRequest;
483
+ }
484
+
485
+ // We don't have a mock request
486
+ if($.mockjaxSettings.throwUnmocked === true) {
487
+ throw('AJAX not mocked: ' + origSettings.url);
488
+ }
489
+ else { // trigger a normal request
490
+ return _ajax.apply($, [origSettings]);
491
+ }
492
+ }
493
+
494
+ /**
495
+ * Copies URL parameter values if they were captured by a regular expression
496
+ * @param {Object} mockHandler
497
+ * @param {Object} origSettings
498
+ */
499
+ function copyUrlParameters(mockHandler, origSettings) {
500
+ //parameters aren't captured if the URL isn't a RegExp
501
+ if (!(mockHandler.url instanceof RegExp)) {
502
+ return;
503
+ }
504
+ //if no URL params were defined on the handler, don't attempt a capture
505
+ if (!mockHandler.hasOwnProperty('urlParams')) {
506
+ return;
507
+ }
508
+ var captures = mockHandler.url.exec(origSettings.url);
509
+ //the whole RegExp match is always the first value in the capture results
510
+ if (captures.length === 1) {
511
+ return;
512
+ }
513
+ captures.shift();
514
+ //use handler params as keys and capture resuts as values
515
+ var i = 0,
516
+ capturesLength = captures.length,
517
+ paramsLength = mockHandler.urlParams.length,
518
+ //in case the number of params specified is less than actual captures
519
+ maxIterations = Math.min(capturesLength, paramsLength),
520
+ paramValues = {};
521
+ for (i; i < maxIterations; i++) {
522
+ var key = mockHandler.urlParams[i];
523
+ paramValues[key] = captures[i];
524
+ }
525
+ origSettings.urlParams = paramValues;
526
+ }
527
+
528
+
529
+ // Public
530
+
531
+ $.extend({
532
+ ajax: handleAjax
533
+ });
534
+
535
+ $.mockjaxSettings = {
536
+ //url: null,
537
+ //type: 'GET',
538
+ log: function( mockHandler, requestSettings ) {
539
+ if ( mockHandler.logging === false ||
540
+ ( typeof mockHandler.logging === 'undefined' && $.mockjaxSettings.logging === false ) ) {
541
+ return;
542
+ }
543
+ if ( window.console && console.log ) {
544
+ var message = 'MOCK ' + requestSettings.type.toUpperCase() + ': ' + requestSettings.url;
545
+ var request = $.extend({}, requestSettings);
546
+
547
+ if (typeof console.log === 'function') {
548
+ console.log(message, request);
549
+ } else {
550
+ try {
551
+ console.log( message + ' ' + JSON.stringify(request) );
552
+ } catch (e) {
553
+ console.log(message);
554
+ }
555
+ }
556
+ }
557
+ },
558
+ logging: true,
559
+ status: 200,
560
+ statusText: "OK",
561
+ responseTime: 500,
562
+ isTimeout: false,
563
+ throwUnmocked: false,
564
+ contentType: 'text/plain',
565
+ response: '',
566
+ responseText: '',
567
+ responseXML: '',
568
+ proxy: '',
569
+ proxyType: 'GET',
570
+
571
+ lastModified: null,
572
+ etag: '',
573
+ headers: {
574
+ etag: 'IJF@H#@923uf8023hFO@I#H#',
575
+ 'content-type' : 'text/plain'
576
+ }
577
+ };
578
+
579
+ $.mockjax = function(settings) {
580
+ var i = mockHandlers.length;
581
+ mockHandlers[i] = settings;
582
+ return i;
583
+ };
584
+ $.mockjaxClear = function(i) {
585
+ if ( arguments.length == 1 ) {
586
+ mockHandlers[i] = null;
587
+ } else {
588
+ mockHandlers = [];
589
+ }
590
+ mockedAjaxCalls = [];
591
+ };
592
+ $.mockjax.handler = function(i) {
593
+ if ( arguments.length == 1 ) {
594
+ return mockHandlers[i];
595
+ }
596
+ };
597
+ $.mockjax.mockedAjaxCalls = function() {
598
+ return mockedAjaxCalls;
599
+ };
600
+ })(jQuery);