ember-data-factory-guy 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bower.json +1 -1
- data/dist/ember-data-factory-guy.js +138 -42
- data/dist/ember-data-factory-guy.min.js +1 -1
- data/ember-data-factory-guy.gemspec +1 -1
- data/package.json +7 -8
- data/src/factory_guy_test_mixin.js +102 -38
- data/src/model_definition.js +3 -3
- data/src/store.js +33 -1
- data/tests/active_model_adapter_factory_test.js +33 -8
- data/tests/support/factories/profile_factory.js +1 -3
- data/tests/support/models/user.js +2 -1
- data/tests/support/test_helper.js +7 -2
- data/tests/test_setup.js +3 -3
- data/vendor/assets/javascripts/ember_data_factory_guy.js +138 -42
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5bdae9f46c1972abb834e6dbc097e0c078d8e97
|
4
|
+
data.tar.gz: 6587a2575c0b315ebf1e03a1157e219f051e4e72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 287ae58b03af66d6fde0256d692ce1b8ed7609487c5fa619f4fed997b980fe41eae3205aa1e97144bc643dc15f2e74b6a250721e1c097107d97af7b13fd67930
|
7
|
+
data.tar.gz: 29510c92fc6965cf66059895635de26153e14b818c9fd52f0974d06802091367ddb5cd625808632b70faac1578408a51901dd5ead3cedda9e846ec018eef9971
|
data/bower.json
CHANGED
@@ -96,9 +96,9 @@ ModelDefinition = function (model, config) {
|
|
96
96
|
/**
|
97
97
|
Build a list of fixtures
|
98
98
|
|
99
|
-
@param name model name or named model type
|
100
|
-
@param number of fixtures to build
|
101
|
-
@param opts attribute options
|
99
|
+
@param {String} name model name or named model type
|
100
|
+
@param {Integer} number of fixtures to build
|
101
|
+
@param {Object} opts attribute options
|
102
102
|
@returns array of fixtures
|
103
103
|
*/
|
104
104
|
this.buildList = function (name, number, opts) {
|
@@ -381,6 +381,12 @@ DS.Store.reopen({
|
|
381
381
|
return adapter instanceof DS.FixtureAdapter;
|
382
382
|
},
|
383
383
|
|
384
|
+
usingActiveModelSerializer: function () {
|
385
|
+
var adapter = this.adapterFor('application');
|
386
|
+
console.log('adapter.defaultSerializer', adapter.defaultSerializer)
|
387
|
+
return adapter.defaultSerializer == 'active-model';
|
388
|
+
},
|
389
|
+
|
384
390
|
/**
|
385
391
|
Make new fixture and save to store. If the store is using FixtureAdapter,
|
386
392
|
will push to FIXTURE array, otherwise will use push method on adapter.
|
@@ -400,6 +406,7 @@ DS.Store.reopen({
|
|
400
406
|
return FactoryGuy.pushFixture(modelType, fixture);
|
401
407
|
} else {
|
402
408
|
var store = this;
|
409
|
+
|
403
410
|
var model;
|
404
411
|
Em.run(function () {
|
405
412
|
store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType, fixture);
|
@@ -543,6 +550,7 @@ DS.Store.reopen({
|
|
543
550
|
*/
|
544
551
|
setAssociationsForRESTAdapter: function (modelType, modelName, model) {
|
545
552
|
var self = this;
|
553
|
+
|
546
554
|
Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
|
547
555
|
if (relationship.kind == 'hasMany') {
|
548
556
|
var children = model.get(name) || [];
|
@@ -555,7 +563,9 @@ DS.Store.reopen({
|
|
555
563
|
if (relationship.options && relationship.options.inverse) {
|
556
564
|
belongsToName = relationship.options.inverse;
|
557
565
|
}
|
558
|
-
|
566
|
+
if (belongsToName) {
|
567
|
+
child.set(belongsToName, model);
|
568
|
+
}
|
559
569
|
})
|
560
570
|
}
|
561
571
|
|
@@ -570,6 +580,7 @@ DS.Store.reopen({
|
|
570
580
|
)
|
571
581
|
if (hasManyName) {
|
572
582
|
belongsToRecord.get(hasManyName).addObject(model);
|
583
|
+
return;
|
573
584
|
}
|
574
585
|
var oneToOneName = self.findRelationshipName(
|
575
586
|
'belongsTo',
|
@@ -621,6 +632,27 @@ DS.Store.reopen({
|
|
621
632
|
return relationshipName;
|
622
633
|
},
|
623
634
|
|
635
|
+
// /**
|
636
|
+
// Adding the ability to check the serializer and convert the json before
|
637
|
+
// it's pushed. For the ActiveModelSerializer, the attributes should be snake case,
|
638
|
+
// for example.
|
639
|
+
//
|
640
|
+
// @method push
|
641
|
+
// @param {String or subclass of DS.Model} type
|
642
|
+
// @param {Object} data
|
643
|
+
// @return {DS.Model} the record that was created or updated.
|
644
|
+
// */
|
645
|
+
// push: function(type, data, _partial) {
|
646
|
+
// var type = this.modelFor(type);
|
647
|
+
// var serializer = this.serializerFor(type.typeKey);
|
648
|
+
// console.log('serializer',serializer, serializer+'')
|
649
|
+
//// if (this.usingActiveModelSerializer()) {
|
650
|
+
//// var model = this.modelFor(modelName);
|
651
|
+
//// FactoryGuy.pushFixture(model, payload);
|
652
|
+
//// }
|
653
|
+
// this._super(type, data, _partial);
|
654
|
+
// },
|
655
|
+
|
624
656
|
/**
|
625
657
|
Adding a pushPayload for FixtureAdapter, but using the original with
|
626
658
|
other adapters that support pushPayload.
|
@@ -706,16 +738,27 @@ DS.FixtureAdapter.reopen({
|
|
706
738
|
FactoryGuyTestMixin = Em.Mixin.create({
|
707
739
|
|
708
740
|
// Pass in the app root, which typically is App.
|
709
|
-
setup: function(app) {
|
741
|
+
setup: function (app) {
|
710
742
|
this.set('container', app.__container__);
|
711
743
|
return this;
|
712
744
|
},
|
713
745
|
|
714
|
-
useFixtureAdapter: function(app) {
|
746
|
+
useFixtureAdapter: function (app) {
|
715
747
|
app.ApplicationAdapter = DS.FixtureAdapter;
|
716
748
|
this.getStore().adapterFor('application').simulateRemoteResponse = false;
|
717
749
|
},
|
718
750
|
|
751
|
+
/**
|
752
|
+
@param {String} model type like user for model User
|
753
|
+
@return {boolean} true if model's serializer is ActiveModelSerializer based
|
754
|
+
*/
|
755
|
+
usingActiveModelSerializer: function (type) {
|
756
|
+
var store = this.getStore()
|
757
|
+
var type = store.modelFor(type);
|
758
|
+
var serializer = store.serializerFor(type.typeKey);
|
759
|
+
return serializer instanceof DS.ActiveModelSerializer;
|
760
|
+
},
|
761
|
+
|
719
762
|
/**
|
720
763
|
Proxy to store's find method
|
721
764
|
|
@@ -723,11 +766,11 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
723
766
|
@param {Object|String|Integer|null} id
|
724
767
|
@return {Promise} promise
|
725
768
|
*/
|
726
|
-
find: function(type, id) {
|
769
|
+
find: function (type, id) {
|
727
770
|
return this.getStore().find(type, id);
|
728
771
|
},
|
729
772
|
|
730
|
-
make: function(name, opts) {
|
773
|
+
make: function (name, opts) {
|
731
774
|
return this.getStore().makeFixture(name, opts);
|
732
775
|
},
|
733
776
|
|
@@ -735,20 +778,20 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
735
778
|
return this.get('container').lookup('store:main');
|
736
779
|
},
|
737
780
|
|
738
|
-
pushPayload: function(type, hash) {
|
781
|
+
pushPayload: function (type, hash) {
|
739
782
|
return this.getStore().pushPayload(type, hash);
|
740
783
|
},
|
741
784
|
|
742
|
-
pushRecord: function(type, hash) {
|
785
|
+
pushRecord: function (type, hash) {
|
743
786
|
return this.getStore().push(type, hash);
|
744
787
|
},
|
745
788
|
|
746
789
|
/**
|
747
|
-
|
790
|
+
Using mockjax to stub an http request.
|
748
791
|
|
749
|
-
|
750
|
-
|
751
|
-
|
792
|
+
@param {String} url request url
|
793
|
+
@param {Object} json response
|
794
|
+
@param {Object} options ajax request options
|
752
795
|
*/
|
753
796
|
stubEndpointForHttpRequest: function (url, json, options) {
|
754
797
|
options = options || {};
|
@@ -768,54 +811,107 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
768
811
|
},
|
769
812
|
|
770
813
|
/**
|
771
|
-
|
814
|
+
Build the json used for creating record
|
772
815
|
|
773
|
-
|
774
|
-
|
816
|
+
@param {String} name of the fixture ( or model ) to create
|
817
|
+
@param {Object} opts fixture options
|
775
818
|
*/
|
776
|
-
|
777
|
-
var
|
778
|
-
var
|
779
|
-
|
780
|
-
|
819
|
+
buildAjaxHttpResponse: function (name, opts) {
|
820
|
+
var fixture = FactoryGuy.build(name, opts);
|
821
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
822
|
+
if (this.usingActiveModelSerializer(modelName)) {
|
823
|
+
this.toSnakeCase(fixture);
|
824
|
+
}
|
825
|
+
var hash = {};
|
826
|
+
hash[modelName] = fixture;
|
827
|
+
return hash;
|
828
|
+
},
|
829
|
+
|
830
|
+
/**
|
831
|
+
Convert Object's keys to snake case
|
832
|
+
|
833
|
+
@param {Object} fixture to convert
|
834
|
+
*/
|
835
|
+
toSnakeCase: function (fixture) {
|
836
|
+
for (key in fixture) {
|
837
|
+
if (key != Em.String.decamelize(key)) {
|
838
|
+
var value = fixture[key];
|
839
|
+
delete fixture[key];
|
840
|
+
fixture[Em.String.decamelize(key)] = value
|
841
|
+
}
|
842
|
+
}
|
843
|
+
},
|
844
|
+
|
845
|
+
/**
|
846
|
+
Handling ajax GET ( find record ) for a model. You can mock
|
847
|
+
failed find by passing in status of 500.
|
848
|
+
|
849
|
+
@param {String} name of the fixture ( or model ) to find
|
850
|
+
@param {Object} opts fixture options
|
851
|
+
@param {Integer} status Optional HTTP status response code
|
852
|
+
*/
|
853
|
+
handleFind: function (name, opts, status) {
|
854
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
855
|
+
var responseJson = this.buildAjaxHttpResponse(name, opts);
|
856
|
+
var id = responseJson[modelName].id
|
857
|
+
var url = "/" + Em.String.pluralize(modelName) + "/" + id;
|
858
|
+
this.stubEndpointForHttpRequest(
|
859
|
+
url,
|
860
|
+
responseJson,
|
861
|
+
{type: 'GET', status: (status || 200)}
|
862
|
+
)
|
781
863
|
return responseJson;
|
782
864
|
},
|
783
865
|
|
784
866
|
/**
|
785
|
-
|
867
|
+
Handling ajax POST ( create record ) for a model. You can mock
|
868
|
+
failed create by passing in status of 500.
|
786
869
|
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
var
|
793
|
-
var
|
794
|
-
|
795
|
-
|
870
|
+
@param {String} name of the fixture ( or model ) to create
|
871
|
+
@param {Object} opts fixture options
|
872
|
+
@param {Integer} status Optional HTTP status response code
|
873
|
+
*/
|
874
|
+
handleCreate: function (name, opts, status) {
|
875
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
876
|
+
var responseJson = this.buildAjaxHttpResponse(name, opts);
|
877
|
+
var url = "/" + Em.String.pluralize(modelName);
|
878
|
+
this.stubEndpointForHttpRequest(
|
879
|
+
url,
|
880
|
+
responseJson,
|
881
|
+
{type: 'POST', status: (status || 200)}
|
882
|
+
)
|
883
|
+
return responseJson;
|
796
884
|
},
|
797
885
|
|
798
886
|
/**
|
799
|
-
|
887
|
+
Handling ajax PUT ( update record ) for a model type. You can mock
|
888
|
+
failed update by passing in status of 500.
|
800
889
|
|
801
|
-
|
802
|
-
|
890
|
+
@param {String} root modelType like 'user' for User
|
891
|
+
@param {String} id id of record to update
|
892
|
+
@param {Integer} status Optional HTTP status response code
|
803
893
|
*/
|
804
|
-
handleUpdate: function (root, id) {
|
894
|
+
handleUpdate: function (root, id, status) {
|
805
895
|
this.stubEndpointForHttpRequest(
|
806
|
-
|
896
|
+
"/" + Em.String.pluralize(root) + "/" + id,
|
897
|
+
{},
|
898
|
+
{type: 'PUT', status: (status || 200)}
|
807
899
|
)
|
808
900
|
},
|
809
901
|
|
810
902
|
/**
|
811
|
-
|
903
|
+
Handling ajax DELETE ( delete record ) for a model type. You can mock
|
904
|
+
failed delete by passing in status of 500.
|
812
905
|
|
813
|
-
|
814
|
-
|
906
|
+
@param {String} root modelType like 'user' for User
|
907
|
+
@param {String} id id of record to update
|
908
|
+
@param {Integer} status Optional HTTP status response code
|
815
909
|
*/
|
816
|
-
handleDelete: function (root, id) {
|
910
|
+
handleDelete: function (root, id, status) {
|
817
911
|
this.stubEndpointForHttpRequest(
|
818
|
-
|
912
|
+
"/" + Em.String.pluralize(root) + "/" + id,
|
913
|
+
{},
|
914
|
+
{type: 'DELETE', status: (status || 200)}
|
819
915
|
)
|
820
916
|
},
|
821
917
|
|
@@ -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 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
|
+
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},usingActiveModelSerializer:function(){var adapter=this.adapterFor("application");console.log("adapter.defaultSerializer",adapter.defaultSerializer);return adapter.defaultSerializer=="active-model"},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}if(belongsToName){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);return}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},usingActiveModelSerializer:function(type){var store=this.getStore();var type=store.modelFor(type);var serializer=store.serializerFor(type.typeKey);return serializer instanceof DS.ActiveModelSerializer},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)},buildAjaxHttpResponse:function(name,opts){var fixture=FactoryGuy.build(name,opts);var modelName=FactoryGuy.lookupModelForFixtureName(name);if(this.usingActiveModelSerializer(modelName)){this.toSnakeCase(fixture)}var hash={};hash[modelName]=fixture;return hash},toSnakeCase:function(fixture){for(key in fixture){if(key!=Em.String.decamelize(key)){var value=fixture[key];delete fixture[key];fixture[Em.String.decamelize(key)]=value}}},handleFind:function(name,opts,status){var modelName=FactoryGuy.lookupModelForFixtureName(name);var responseJson=this.buildAjaxHttpResponse(name,opts);var id=responseJson[modelName].id;var url="/"+Em.String.pluralize(modelName)+"/"+id;this.stubEndpointForHttpRequest(url,responseJson,{type:"GET",status:status||200});return responseJson},handleCreate:function(name,opts,status){var modelName=FactoryGuy.lookupModelForFixtureName(name);var responseJson=this.buildAjaxHttpResponse(name,opts);var url="/"+Em.String.pluralize(modelName);this.stubEndpointForHttpRequest(url,responseJson,{type:"POST",status:status||200});return responseJson},handleUpdate:function(root,id,status){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"PUT",status:status||200})},handleDelete:function(root,id,status){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"DELETE",status:status||200})},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.4.
|
4
|
+
s.version = "0.4.1"
|
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.4.
|
3
|
+
"version": "0.4.1",
|
4
4
|
"authors": [
|
5
5
|
"Daniel Sudol <dansudol@yahoo.com>",
|
6
6
|
"Opak Alex <opak.alexandr@gmail.com>"
|
@@ -24,13 +24,12 @@
|
|
24
24
|
"type": "git",
|
25
25
|
"url": ""
|
26
26
|
},
|
27
|
-
"devDependencies":
|
28
|
-
"
|
29
|
-
"
|
30
|
-
"
|
31
|
-
"
|
32
|
-
|
33
|
-
},
|
27
|
+
"devDependencies": [
|
28
|
+
"grunt-contrib-coffee",
|
29
|
+
"grunt-contrib-concat",
|
30
|
+
"grunt-contrib-uglify",
|
31
|
+
"grunt-contrib-qunit"
|
32
|
+
],
|
34
33
|
"engines": {
|
35
34
|
"node": ">=v0.10.1"
|
36
35
|
}
|
@@ -1,16 +1,27 @@
|
|
1
1
|
FactoryGuyTestMixin = Em.Mixin.create({
|
2
2
|
|
3
3
|
// Pass in the app root, which typically is App.
|
4
|
-
setup: function(app) {
|
4
|
+
setup: function (app) {
|
5
5
|
this.set('container', app.__container__);
|
6
6
|
return this;
|
7
7
|
},
|
8
8
|
|
9
|
-
useFixtureAdapter: function(app) {
|
9
|
+
useFixtureAdapter: function (app) {
|
10
10
|
app.ApplicationAdapter = DS.FixtureAdapter;
|
11
11
|
this.getStore().adapterFor('application').simulateRemoteResponse = false;
|
12
12
|
},
|
13
13
|
|
14
|
+
/**
|
15
|
+
@param {String} model type like user for model User
|
16
|
+
@return {boolean} true if model's serializer is ActiveModelSerializer based
|
17
|
+
*/
|
18
|
+
usingActiveModelSerializer: function (type) {
|
19
|
+
var store = this.getStore()
|
20
|
+
var type = store.modelFor(type);
|
21
|
+
var serializer = store.serializerFor(type.typeKey);
|
22
|
+
return serializer instanceof DS.ActiveModelSerializer;
|
23
|
+
},
|
24
|
+
|
14
25
|
/**
|
15
26
|
Proxy to store's find method
|
16
27
|
|
@@ -18,11 +29,11 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
18
29
|
@param {Object|String|Integer|null} id
|
19
30
|
@return {Promise} promise
|
20
31
|
*/
|
21
|
-
find: function(type, id) {
|
32
|
+
find: function (type, id) {
|
22
33
|
return this.getStore().find(type, id);
|
23
34
|
},
|
24
35
|
|
25
|
-
make: function(name, opts) {
|
36
|
+
make: function (name, opts) {
|
26
37
|
return this.getStore().makeFixture(name, opts);
|
27
38
|
},
|
28
39
|
|
@@ -30,20 +41,20 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
30
41
|
return this.get('container').lookup('store:main');
|
31
42
|
},
|
32
43
|
|
33
|
-
pushPayload: function(type, hash) {
|
44
|
+
pushPayload: function (type, hash) {
|
34
45
|
return this.getStore().pushPayload(type, hash);
|
35
46
|
},
|
36
47
|
|
37
|
-
pushRecord: function(type, hash) {
|
48
|
+
pushRecord: function (type, hash) {
|
38
49
|
return this.getStore().push(type, hash);
|
39
50
|
},
|
40
51
|
|
41
52
|
/**
|
42
|
-
|
53
|
+
Using mockjax to stub an http request.
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
|
55
|
+
@param {String} url request url
|
56
|
+
@param {Object} json response
|
57
|
+
@param {Object} options ajax request options
|
47
58
|
*/
|
48
59
|
stubEndpointForHttpRequest: function (url, json, options) {
|
49
60
|
options = options || {};
|
@@ -63,54 +74,107 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
63
74
|
},
|
64
75
|
|
65
76
|
/**
|
66
|
-
|
77
|
+
Build the json used for creating record
|
78
|
+
|
79
|
+
@param {String} name of the fixture ( or model ) to create
|
80
|
+
@param {Object} opts fixture options
|
81
|
+
*/
|
82
|
+
buildAjaxHttpResponse: function (name, opts) {
|
83
|
+
var fixture = FactoryGuy.build(name, opts);
|
84
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
85
|
+
if (this.usingActiveModelSerializer(modelName)) {
|
86
|
+
this.toSnakeCase(fixture);
|
87
|
+
}
|
88
|
+
var hash = {};
|
89
|
+
hash[modelName] = fixture;
|
90
|
+
return hash;
|
91
|
+
},
|
92
|
+
|
93
|
+
/**
|
94
|
+
Convert Object's keys to snake case
|
95
|
+
|
96
|
+
@param {Object} fixture to convert
|
97
|
+
*/
|
98
|
+
toSnakeCase: function (fixture) {
|
99
|
+
for (key in fixture) {
|
100
|
+
if (key != Em.String.decamelize(key)) {
|
101
|
+
var value = fixture[key];
|
102
|
+
delete fixture[key];
|
103
|
+
fixture[Em.String.decamelize(key)] = value
|
104
|
+
}
|
105
|
+
}
|
106
|
+
},
|
107
|
+
|
108
|
+
/**
|
109
|
+
Handling ajax GET ( find record ) for a model. You can mock
|
110
|
+
failed find by passing in status of 500.
|
67
111
|
|
68
|
-
|
69
|
-
|
112
|
+
@param {String} name of the fixture ( or model ) to find
|
113
|
+
@param {Object} opts fixture options
|
114
|
+
@param {Integer} status Optional HTTP status response code
|
70
115
|
*/
|
71
|
-
|
72
|
-
var
|
73
|
-
var responseJson = this.
|
74
|
-
var
|
75
|
-
|
116
|
+
handleFind: function (name, opts, status) {
|
117
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
118
|
+
var responseJson = this.buildAjaxHttpResponse(name, opts);
|
119
|
+
var id = responseJson[modelName].id
|
120
|
+
var url = "/" + Em.String.pluralize(modelName) + "/" + id;
|
121
|
+
this.stubEndpointForHttpRequest(
|
122
|
+
url,
|
123
|
+
responseJson,
|
124
|
+
{type: 'GET', status: (status || 200)}
|
125
|
+
)
|
76
126
|
return responseJson;
|
77
127
|
},
|
78
128
|
|
79
129
|
/**
|
80
|
-
|
130
|
+
Handling ajax POST ( create record ) for a model. You can mock
|
131
|
+
failed create by passing in status of 500.
|
81
132
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
var
|
88
|
-
var
|
89
|
-
|
90
|
-
|
133
|
+
@param {String} name of the fixture ( or model ) to create
|
134
|
+
@param {Object} opts fixture options
|
135
|
+
@param {Integer} status Optional HTTP status response code
|
136
|
+
*/
|
137
|
+
handleCreate: function (name, opts, status) {
|
138
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
139
|
+
var responseJson = this.buildAjaxHttpResponse(name, opts);
|
140
|
+
var url = "/" + Em.String.pluralize(modelName);
|
141
|
+
this.stubEndpointForHttpRequest(
|
142
|
+
url,
|
143
|
+
responseJson,
|
144
|
+
{type: 'POST', status: (status || 200)}
|
145
|
+
)
|
146
|
+
return responseJson;
|
91
147
|
},
|
92
148
|
|
93
149
|
/**
|
94
|
-
|
150
|
+
Handling ajax PUT ( update record ) for a model type. You can mock
|
151
|
+
failed update by passing in status of 500.
|
95
152
|
|
96
|
-
|
97
|
-
|
153
|
+
@param {String} root modelType like 'user' for User
|
154
|
+
@param {String} id id of record to update
|
155
|
+
@param {Integer} status Optional HTTP status response code
|
98
156
|
*/
|
99
|
-
handleUpdate: function (root, id) {
|
157
|
+
handleUpdate: function (root, id, status) {
|
100
158
|
this.stubEndpointForHttpRequest(
|
101
|
-
|
159
|
+
"/" + Em.String.pluralize(root) + "/" + id,
|
160
|
+
{},
|
161
|
+
{type: 'PUT', status: (status || 200)}
|
102
162
|
)
|
103
163
|
},
|
104
164
|
|
105
165
|
/**
|
106
|
-
|
166
|
+
Handling ajax DELETE ( delete record ) for a model type. You can mock
|
167
|
+
failed delete by passing in status of 500.
|
107
168
|
|
108
|
-
|
109
|
-
|
169
|
+
@param {String} root modelType like 'user' for User
|
170
|
+
@param {String} id id of record to update
|
171
|
+
@param {Integer} status Optional HTTP status response code
|
110
172
|
*/
|
111
|
-
handleDelete: function (root, id) {
|
173
|
+
handleDelete: function (root, id, status) {
|
112
174
|
this.stubEndpointForHttpRequest(
|
113
|
-
|
175
|
+
"/" + Em.String.pluralize(root) + "/" + id,
|
176
|
+
{},
|
177
|
+
{type: 'DELETE', status: (status || 200)}
|
114
178
|
)
|
115
179
|
},
|
116
180
|
|
data/src/model_definition.js
CHANGED
@@ -80,9 +80,9 @@ ModelDefinition = function (model, config) {
|
|
80
80
|
/**
|
81
81
|
Build a list of fixtures
|
82
82
|
|
83
|
-
@param name model name or named model type
|
84
|
-
@param number of fixtures to build
|
85
|
-
@param opts attribute options
|
83
|
+
@param {String} name model name or named model type
|
84
|
+
@param {Integer} number of fixtures to build
|
85
|
+
@param {Object} opts attribute options
|
86
86
|
@returns array of fixtures
|
87
87
|
*/
|
88
88
|
this.buildList = function (name, number, opts) {
|
data/src/store.js
CHANGED
@@ -7,6 +7,12 @@ DS.Store.reopen({
|
|
7
7
|
return adapter instanceof DS.FixtureAdapter;
|
8
8
|
},
|
9
9
|
|
10
|
+
usingActiveModelSerializer: function () {
|
11
|
+
var adapter = this.adapterFor('application');
|
12
|
+
console.log('adapter.defaultSerializer', adapter.defaultSerializer)
|
13
|
+
return adapter.defaultSerializer == 'active-model';
|
14
|
+
},
|
15
|
+
|
10
16
|
/**
|
11
17
|
Make new fixture and save to store. If the store is using FixtureAdapter,
|
12
18
|
will push to FIXTURE array, otherwise will use push method on adapter.
|
@@ -26,6 +32,7 @@ DS.Store.reopen({
|
|
26
32
|
return FactoryGuy.pushFixture(modelType, fixture);
|
27
33
|
} else {
|
28
34
|
var store = this;
|
35
|
+
|
29
36
|
var model;
|
30
37
|
Em.run(function () {
|
31
38
|
store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType, fixture);
|
@@ -169,6 +176,7 @@ DS.Store.reopen({
|
|
169
176
|
*/
|
170
177
|
setAssociationsForRESTAdapter: function (modelType, modelName, model) {
|
171
178
|
var self = this;
|
179
|
+
|
172
180
|
Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
|
173
181
|
if (relationship.kind == 'hasMany') {
|
174
182
|
var children = model.get(name) || [];
|
@@ -181,7 +189,9 @@ DS.Store.reopen({
|
|
181
189
|
if (relationship.options && relationship.options.inverse) {
|
182
190
|
belongsToName = relationship.options.inverse;
|
183
191
|
}
|
184
|
-
|
192
|
+
if (belongsToName) {
|
193
|
+
child.set(belongsToName, model);
|
194
|
+
}
|
185
195
|
})
|
186
196
|
}
|
187
197
|
|
@@ -196,6 +206,7 @@ DS.Store.reopen({
|
|
196
206
|
)
|
197
207
|
if (hasManyName) {
|
198
208
|
belongsToRecord.get(hasManyName).addObject(model);
|
209
|
+
return;
|
199
210
|
}
|
200
211
|
var oneToOneName = self.findRelationshipName(
|
201
212
|
'belongsTo',
|
@@ -247,6 +258,27 @@ DS.Store.reopen({
|
|
247
258
|
return relationshipName;
|
248
259
|
},
|
249
260
|
|
261
|
+
// /**
|
262
|
+
// Adding the ability to check the serializer and convert the json before
|
263
|
+
// it's pushed. For the ActiveModelSerializer, the attributes should be snake case,
|
264
|
+
// for example.
|
265
|
+
//
|
266
|
+
// @method push
|
267
|
+
// @param {String or subclass of DS.Model} type
|
268
|
+
// @param {Object} data
|
269
|
+
// @return {DS.Model} the record that was created or updated.
|
270
|
+
// */
|
271
|
+
// push: function(type, data, _partial) {
|
272
|
+
// var type = this.modelFor(type);
|
273
|
+
// var serializer = this.serializerFor(type.typeKey);
|
274
|
+
// console.log('serializer',serializer, serializer+'')
|
275
|
+
//// if (this.usingActiveModelSerializer()) {
|
276
|
+
//// var model = this.modelFor(modelName);
|
277
|
+
//// FactoryGuy.pushFixture(model, payload);
|
278
|
+
//// }
|
279
|
+
// this._super(type, data, _partial);
|
280
|
+
// },
|
281
|
+
|
250
282
|
/**
|
251
283
|
Adding a pushPayload for FixtureAdapter, but using the original with
|
252
284
|
other adapters that support pushPayload.
|
@@ -60,10 +60,15 @@ asyncTest("creates records in the store", function() {
|
|
60
60
|
});
|
61
61
|
|
62
62
|
|
63
|
+
test("handles camelCase attributes", function() {
|
64
|
+
var profile = store.makeFixture('profile', {camelCaseDescription: 'description'});
|
65
|
+
ok(!!profile.get('camelCaseDescription'))
|
66
|
+
});
|
67
|
+
|
68
|
+
|
63
69
|
test("when hasMany associations assigned, belongTo parent is assigned", function() {
|
64
70
|
var project = store.makeFixture('project');
|
65
71
|
var user = store.makeFixture('user', {projects: [project]})
|
66
|
-
|
67
72
|
deepEqual(project.get('user').toJSON(), user.toJSON());
|
68
73
|
});
|
69
74
|
|
@@ -210,14 +215,34 @@ test("creates records in the store", function() {
|
|
210
215
|
});
|
211
216
|
|
212
217
|
|
213
|
-
|
214
|
-
|
215
|
-
|
218
|
+
|
219
|
+
module('DS.Store with ActiveModelAdapter', {
|
220
|
+
setup: function() {
|
221
|
+
testHelper = TestHelper.setup(DS.ActiveModelAdapter);
|
222
|
+
store = testHelper.getStore();
|
223
|
+
},
|
224
|
+
teardown: function() {
|
225
|
+
Em.run(function() { testHelper.teardown(); });
|
226
|
+
}
|
227
|
+
});
|
228
|
+
|
229
|
+
|
230
|
+
asyncTest("#createRecord with mockjax handles model's camelCase attributes", function() {
|
231
|
+
testHelper.handleCreate('profile', {camelCaseDescription: 'description'})
|
232
|
+
|
216
233
|
store.createRecord('profile').save().then(function(profile) {
|
217
|
-
// both types of attributes work just fine
|
218
|
-
ok(!!profile.get('snake_case_description'))
|
219
234
|
ok(!!profile.get('camelCaseDescription'))
|
220
235
|
start();
|
221
|
-
})
|
222
|
-
})
|
236
|
+
});
|
237
|
+
});
|
223
238
|
|
239
|
+
|
240
|
+
asyncTest("#find with mockjax handles camelCase attributes", function() {
|
241
|
+
var responseJson = testHelper.handleFind('profile', {camelCaseDescription: 'description'})
|
242
|
+
var id = responseJson.profile.id
|
243
|
+
|
244
|
+
store.find('profile', id).then(function(profile) {
|
245
|
+
ok(!!profile.get('camelCaseDescription'))
|
246
|
+
start();
|
247
|
+
});
|
248
|
+
});
|
@@ -8,7 +8,6 @@ TestHelper = Ember.Object.createWithMixins(FactoryGuyTestMixin,{
|
|
8
8
|
setup: function(adapter) {
|
9
9
|
$.mockjaxSettings.logging = false;
|
10
10
|
$.mockjaxSettings.responseTime = 0;
|
11
|
-
|
12
11
|
var container = new Ember.Container();
|
13
12
|
this.set('container', container);
|
14
13
|
|
@@ -21,7 +20,13 @@ TestHelper = Ember.Object.createWithMixins(FactoryGuyTestMixin,{
|
|
21
20
|
container.register("model:company", Company);
|
22
21
|
container.register("model:project", Project);
|
23
22
|
container.register("store:main", DS.Store.extend({adapter: adapter}));
|
24
|
-
|
23
|
+
if (adapter == DS.ActiveModelAdapter) {
|
24
|
+
container.register("serializer:-default", DS.ActiveModelSerializer);
|
25
|
+
} else if (adapter == DS.RESTAdapter) {
|
26
|
+
container.register("serializer:-default", DS.RESTSerializer);
|
27
|
+
} else {
|
28
|
+
container.register("serializer:-default", DS.JSONSerializer);
|
29
|
+
}
|
25
30
|
container.register('transform:string', DS.StringTransform);
|
26
31
|
|
27
32
|
if (adapter instanceof DS.FixtureAdapter) {
|
data/tests/test_setup.js
CHANGED
@@ -22,9 +22,7 @@ FactoryGuy.define('soft_material', {
|
|
22
22
|
})
|
23
23
|
FactoryGuy.define('profile', {
|
24
24
|
default: {
|
25
|
-
description: 'Text goes here'
|
26
|
-
camelCaseDescription: 'boyThisIsSilly',
|
27
|
-
snake_case_description: 'how_do_birds_find_worms'
|
25
|
+
description: 'Text goes here'
|
28
26
|
}
|
29
27
|
})
|
30
28
|
FactoryGuy.define('project', {
|
@@ -102,6 +100,8 @@ User = DS.Model.extend({
|
|
102
100
|
projects: DS.hasMany('project'),
|
103
101
|
hats: DS.hasMany('hat', {polymorphic: true})
|
104
102
|
});
|
103
|
+
|
104
|
+
|
105
105
|
/*!
|
106
106
|
* MockJax - jQuery Plugin to Mock Ajax requests
|
107
107
|
*
|
@@ -96,9 +96,9 @@ ModelDefinition = function (model, config) {
|
|
96
96
|
/**
|
97
97
|
Build a list of fixtures
|
98
98
|
|
99
|
-
@param name model name or named model type
|
100
|
-
@param number of fixtures to build
|
101
|
-
@param opts attribute options
|
99
|
+
@param {String} name model name or named model type
|
100
|
+
@param {Integer} number of fixtures to build
|
101
|
+
@param {Object} opts attribute options
|
102
102
|
@returns array of fixtures
|
103
103
|
*/
|
104
104
|
this.buildList = function (name, number, opts) {
|
@@ -381,6 +381,12 @@ DS.Store.reopen({
|
|
381
381
|
return adapter instanceof DS.FixtureAdapter;
|
382
382
|
},
|
383
383
|
|
384
|
+
usingActiveModelSerializer: function () {
|
385
|
+
var adapter = this.adapterFor('application');
|
386
|
+
console.log('adapter.defaultSerializer', adapter.defaultSerializer)
|
387
|
+
return adapter.defaultSerializer == 'active-model';
|
388
|
+
},
|
389
|
+
|
384
390
|
/**
|
385
391
|
Make new fixture and save to store. If the store is using FixtureAdapter,
|
386
392
|
will push to FIXTURE array, otherwise will use push method on adapter.
|
@@ -400,6 +406,7 @@ DS.Store.reopen({
|
|
400
406
|
return FactoryGuy.pushFixture(modelType, fixture);
|
401
407
|
} else {
|
402
408
|
var store = this;
|
409
|
+
|
403
410
|
var model;
|
404
411
|
Em.run(function () {
|
405
412
|
store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType, fixture);
|
@@ -543,6 +550,7 @@ DS.Store.reopen({
|
|
543
550
|
*/
|
544
551
|
setAssociationsForRESTAdapter: function (modelType, modelName, model) {
|
545
552
|
var self = this;
|
553
|
+
|
546
554
|
Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
|
547
555
|
if (relationship.kind == 'hasMany') {
|
548
556
|
var children = model.get(name) || [];
|
@@ -555,7 +563,9 @@ DS.Store.reopen({
|
|
555
563
|
if (relationship.options && relationship.options.inverse) {
|
556
564
|
belongsToName = relationship.options.inverse;
|
557
565
|
}
|
558
|
-
|
566
|
+
if (belongsToName) {
|
567
|
+
child.set(belongsToName, model);
|
568
|
+
}
|
559
569
|
})
|
560
570
|
}
|
561
571
|
|
@@ -570,6 +580,7 @@ DS.Store.reopen({
|
|
570
580
|
)
|
571
581
|
if (hasManyName) {
|
572
582
|
belongsToRecord.get(hasManyName).addObject(model);
|
583
|
+
return;
|
573
584
|
}
|
574
585
|
var oneToOneName = self.findRelationshipName(
|
575
586
|
'belongsTo',
|
@@ -621,6 +632,27 @@ DS.Store.reopen({
|
|
621
632
|
return relationshipName;
|
622
633
|
},
|
623
634
|
|
635
|
+
// /**
|
636
|
+
// Adding the ability to check the serializer and convert the json before
|
637
|
+
// it's pushed. For the ActiveModelSerializer, the attributes should be snake case,
|
638
|
+
// for example.
|
639
|
+
//
|
640
|
+
// @method push
|
641
|
+
// @param {String or subclass of DS.Model} type
|
642
|
+
// @param {Object} data
|
643
|
+
// @return {DS.Model} the record that was created or updated.
|
644
|
+
// */
|
645
|
+
// push: function(type, data, _partial) {
|
646
|
+
// var type = this.modelFor(type);
|
647
|
+
// var serializer = this.serializerFor(type.typeKey);
|
648
|
+
// console.log('serializer',serializer, serializer+'')
|
649
|
+
//// if (this.usingActiveModelSerializer()) {
|
650
|
+
//// var model = this.modelFor(modelName);
|
651
|
+
//// FactoryGuy.pushFixture(model, payload);
|
652
|
+
//// }
|
653
|
+
// this._super(type, data, _partial);
|
654
|
+
// },
|
655
|
+
|
624
656
|
/**
|
625
657
|
Adding a pushPayload for FixtureAdapter, but using the original with
|
626
658
|
other adapters that support pushPayload.
|
@@ -706,16 +738,27 @@ DS.FixtureAdapter.reopen({
|
|
706
738
|
FactoryGuyTestMixin = Em.Mixin.create({
|
707
739
|
|
708
740
|
// Pass in the app root, which typically is App.
|
709
|
-
setup: function(app) {
|
741
|
+
setup: function (app) {
|
710
742
|
this.set('container', app.__container__);
|
711
743
|
return this;
|
712
744
|
},
|
713
745
|
|
714
|
-
useFixtureAdapter: function(app) {
|
746
|
+
useFixtureAdapter: function (app) {
|
715
747
|
app.ApplicationAdapter = DS.FixtureAdapter;
|
716
748
|
this.getStore().adapterFor('application').simulateRemoteResponse = false;
|
717
749
|
},
|
718
750
|
|
751
|
+
/**
|
752
|
+
@param {String} model type like user for model User
|
753
|
+
@return {boolean} true if model's serializer is ActiveModelSerializer based
|
754
|
+
*/
|
755
|
+
usingActiveModelSerializer: function (type) {
|
756
|
+
var store = this.getStore()
|
757
|
+
var type = store.modelFor(type);
|
758
|
+
var serializer = store.serializerFor(type.typeKey);
|
759
|
+
return serializer instanceof DS.ActiveModelSerializer;
|
760
|
+
},
|
761
|
+
|
719
762
|
/**
|
720
763
|
Proxy to store's find method
|
721
764
|
|
@@ -723,11 +766,11 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
723
766
|
@param {Object|String|Integer|null} id
|
724
767
|
@return {Promise} promise
|
725
768
|
*/
|
726
|
-
find: function(type, id) {
|
769
|
+
find: function (type, id) {
|
727
770
|
return this.getStore().find(type, id);
|
728
771
|
},
|
729
772
|
|
730
|
-
make: function(name, opts) {
|
773
|
+
make: function (name, opts) {
|
731
774
|
return this.getStore().makeFixture(name, opts);
|
732
775
|
},
|
733
776
|
|
@@ -735,20 +778,20 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
735
778
|
return this.get('container').lookup('store:main');
|
736
779
|
},
|
737
780
|
|
738
|
-
pushPayload: function(type, hash) {
|
781
|
+
pushPayload: function (type, hash) {
|
739
782
|
return this.getStore().pushPayload(type, hash);
|
740
783
|
},
|
741
784
|
|
742
|
-
pushRecord: function(type, hash) {
|
785
|
+
pushRecord: function (type, hash) {
|
743
786
|
return this.getStore().push(type, hash);
|
744
787
|
},
|
745
788
|
|
746
789
|
/**
|
747
|
-
|
790
|
+
Using mockjax to stub an http request.
|
748
791
|
|
749
|
-
|
750
|
-
|
751
|
-
|
792
|
+
@param {String} url request url
|
793
|
+
@param {Object} json response
|
794
|
+
@param {Object} options ajax request options
|
752
795
|
*/
|
753
796
|
stubEndpointForHttpRequest: function (url, json, options) {
|
754
797
|
options = options || {};
|
@@ -768,54 +811,107 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
768
811
|
},
|
769
812
|
|
770
813
|
/**
|
771
|
-
|
814
|
+
Build the json used for creating record
|
772
815
|
|
773
|
-
|
774
|
-
|
816
|
+
@param {String} name of the fixture ( or model ) to create
|
817
|
+
@param {Object} opts fixture options
|
775
818
|
*/
|
776
|
-
|
777
|
-
var
|
778
|
-
var
|
779
|
-
|
780
|
-
|
819
|
+
buildAjaxHttpResponse: function (name, opts) {
|
820
|
+
var fixture = FactoryGuy.build(name, opts);
|
821
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
822
|
+
if (this.usingActiveModelSerializer(modelName)) {
|
823
|
+
this.toSnakeCase(fixture);
|
824
|
+
}
|
825
|
+
var hash = {};
|
826
|
+
hash[modelName] = fixture;
|
827
|
+
return hash;
|
828
|
+
},
|
829
|
+
|
830
|
+
/**
|
831
|
+
Convert Object's keys to snake case
|
832
|
+
|
833
|
+
@param {Object} fixture to convert
|
834
|
+
*/
|
835
|
+
toSnakeCase: function (fixture) {
|
836
|
+
for (key in fixture) {
|
837
|
+
if (key != Em.String.decamelize(key)) {
|
838
|
+
var value = fixture[key];
|
839
|
+
delete fixture[key];
|
840
|
+
fixture[Em.String.decamelize(key)] = value
|
841
|
+
}
|
842
|
+
}
|
843
|
+
},
|
844
|
+
|
845
|
+
/**
|
846
|
+
Handling ajax GET ( find record ) for a model. You can mock
|
847
|
+
failed find by passing in status of 500.
|
848
|
+
|
849
|
+
@param {String} name of the fixture ( or model ) to find
|
850
|
+
@param {Object} opts fixture options
|
851
|
+
@param {Integer} status Optional HTTP status response code
|
852
|
+
*/
|
853
|
+
handleFind: function (name, opts, status) {
|
854
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
855
|
+
var responseJson = this.buildAjaxHttpResponse(name, opts);
|
856
|
+
var id = responseJson[modelName].id
|
857
|
+
var url = "/" + Em.String.pluralize(modelName) + "/" + id;
|
858
|
+
this.stubEndpointForHttpRequest(
|
859
|
+
url,
|
860
|
+
responseJson,
|
861
|
+
{type: 'GET', status: (status || 200)}
|
862
|
+
)
|
781
863
|
return responseJson;
|
782
864
|
},
|
783
865
|
|
784
866
|
/**
|
785
|
-
|
867
|
+
Handling ajax POST ( create record ) for a model. You can mock
|
868
|
+
failed create by passing in status of 500.
|
786
869
|
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
var
|
793
|
-
var
|
794
|
-
|
795
|
-
|
870
|
+
@param {String} name of the fixture ( or model ) to create
|
871
|
+
@param {Object} opts fixture options
|
872
|
+
@param {Integer} status Optional HTTP status response code
|
873
|
+
*/
|
874
|
+
handleCreate: function (name, opts, status) {
|
875
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
876
|
+
var responseJson = this.buildAjaxHttpResponse(name, opts);
|
877
|
+
var url = "/" + Em.String.pluralize(modelName);
|
878
|
+
this.stubEndpointForHttpRequest(
|
879
|
+
url,
|
880
|
+
responseJson,
|
881
|
+
{type: 'POST', status: (status || 200)}
|
882
|
+
)
|
883
|
+
return responseJson;
|
796
884
|
},
|
797
885
|
|
798
886
|
/**
|
799
|
-
|
887
|
+
Handling ajax PUT ( update record ) for a model type. You can mock
|
888
|
+
failed update by passing in status of 500.
|
800
889
|
|
801
|
-
|
802
|
-
|
890
|
+
@param {String} root modelType like 'user' for User
|
891
|
+
@param {String} id id of record to update
|
892
|
+
@param {Integer} status Optional HTTP status response code
|
803
893
|
*/
|
804
|
-
handleUpdate: function (root, id) {
|
894
|
+
handleUpdate: function (root, id, status) {
|
805
895
|
this.stubEndpointForHttpRequest(
|
806
|
-
|
896
|
+
"/" + Em.String.pluralize(root) + "/" + id,
|
897
|
+
{},
|
898
|
+
{type: 'PUT', status: (status || 200)}
|
807
899
|
)
|
808
900
|
},
|
809
901
|
|
810
902
|
/**
|
811
|
-
|
903
|
+
Handling ajax DELETE ( delete record ) for a model type. You can mock
|
904
|
+
failed delete by passing in status of 500.
|
812
905
|
|
813
|
-
|
814
|
-
|
906
|
+
@param {String} root modelType like 'user' for User
|
907
|
+
@param {String} id id of record to update
|
908
|
+
@param {Integer} status Optional HTTP status response code
|
815
909
|
*/
|
816
|
-
handleDelete: function (root, id) {
|
910
|
+
handleDelete: function (root, id, status) {
|
817
911
|
this.stubEndpointForHttpRequest(
|
818
|
-
|
912
|
+
"/" + Em.String.pluralize(root) + "/" + id,
|
913
|
+
{},
|
914
|
+
{type: 'DELETE', status: (status || 200)}
|
819
915
|
)
|
820
916
|
},
|
821
917
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ember-data-factory-guy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Sudol
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-07-11 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Easily create Fixtures for Ember Data
|
15
15
|
email:
|
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
80
|
version: 1.3.6
|
81
81
|
requirements: []
|
82
82
|
rubyforge_project: ember-data-factory-guy
|
83
|
-
rubygems_version: 2.
|
83
|
+
rubygems_version: 2.2.2
|
84
84
|
signing_key:
|
85
85
|
specification_version: 4
|
86
86
|
summary: Easily create Fixtures for Ember Data
|