ember-data-factory-guy 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ FactoryGuy.define('project', {
2
+ default: {title: 'Project'}
3
+ });
@@ -0,0 +1,10 @@
1
+ FactoryGuy.define('user', {
2
+ // default values for 'user' attributes
3
+ default: {
4
+ name: 'User1'
5
+ },
6
+ // named 'user' type with custom attributes
7
+ admin: {
8
+ name: 'Admin'
9
+ }
10
+ });
@@ -0,0 +1,4 @@
1
+ Project = DS.Model.extend({
2
+ title: DS.attr('string'),
3
+ user: DS.belongsTo('user')
4
+ })
@@ -0,0 +1,4 @@
1
+ User = DS.Model.extend({
2
+ name: DS.attr('string'),
3
+ projects: DS.hasMany('project')
4
+ })
@@ -0,0 +1,23 @@
1
+ TestHelper = Ember.Object.createWithMixins(FactoryGuyHelperMixin,{
2
+
3
+ /**
4
+ * Setup with type of adapter
5
+ *
6
+ * @param adapter DS.FixtureAdapter or DS.ActiveModelSerializer or whatever
7
+ */
8
+ setup: function(adapter) {
9
+ var container = new Ember.Container();
10
+ this.set('container', container);
11
+
12
+ container.register("model:user", User);
13
+ container.register("model:project", Project);
14
+ container.register("store:main", DS.Store.extend({adapter: adapter}));
15
+ container.register("serializer:-default", DS.RESTSerializer);
16
+ container.register('transform:string', DS.StringTransform);
17
+
18
+ if (adapter instanceof DS.FixtureAdapter) {
19
+ adapter.simulateRemoteResponse = false;
20
+ }
21
+ return this;
22
+ }
23
+ });
@@ -0,0 +1,22 @@
1
+ FactoryGuy.define('project', {
2
+ default: {title: 'Project'}
3
+ });
4
+ FactoryGuy.define('user', {
5
+ // default values for 'user' attributes
6
+ default: {
7
+ name: 'User1'
8
+ },
9
+ // named 'user' type with custom attributes
10
+ admin: {
11
+ name: 'Admin'
12
+ }
13
+ });
14
+ Project = DS.Model.extend({
15
+ title: DS.attr('string'),
16
+ user: DS.belongsTo('user')
17
+ })
18
+
19
+ User = DS.Model.extend({
20
+ name: DS.attr('string'),
21
+ projects: DS.hasMany('project')
22
+ })
@@ -0,0 +1,376 @@
1
+ FactoryGuy = Ember.Object.reopenClass({
2
+ fixtureStore: {},
3
+ fixtureLookup: {},
4
+ modelIds: {},
5
+
6
+ /**
7
+ ```javascript
8
+
9
+ User = DS.Model.extend({
10
+ name: DS.attr('string'),
11
+ })
12
+
13
+ FactoryGuy.define('user', {
14
+ default: {
15
+ name: "Fred"
16
+ },
17
+
18
+ bob: {
19
+ name: "Bob"
20
+ }
21
+ });
22
+
23
+ ```
24
+
25
+ For the User model, you can define fixtures like 'bob' or just use 'user'
26
+ and get default values.
27
+
28
+ And to get those fixtures you would call them this way:
29
+
30
+ FactoryGuy.build('user') or FactoryGuy.build('bob')
31
+
32
+ @param model the model to define
33
+ @param config your default and specific fixtures
34
+ */
35
+ define: function (model, config) {
36
+ var info = this.getModelInfo(model);
37
+ for (key in config) {
38
+ var value = config[key];
39
+ info[key] = value;
40
+ if (key != 'default') {
41
+ this.fixtureLookup[key] = model;
42
+ }
43
+ }
44
+ // setup id
45
+ this.modelIds[model] = 0;
46
+ },
47
+
48
+ /**
49
+
50
+ @param model
51
+ */
52
+ getModelInfo: function (model) {
53
+ if (!this.fixtureStore[model]) {
54
+ this.fixtureStore[model] = {};
55
+ }
56
+ return this.fixtureStore[model];
57
+ },
58
+
59
+ /**
60
+
61
+ @param name fixture name
62
+ @returns model associated with fixture name
63
+ */
64
+ lookupModelForName: function (name) {
65
+ var model = this.fixtureLookup[name];
66
+ if (!model) {
67
+ if (this.fixtureStore[name]) {
68
+ model = name;
69
+ }
70
+ }
71
+ return model;
72
+ },
73
+
74
+ /**
75
+ Generate next id for model
76
+ */
77
+ generateId: function (model) {
78
+ var lastId = this.modelIds[model] || 0;
79
+ this.modelIds[model] = lastId + 1;
80
+ return this.modelIds[model];
81
+ },
82
+
83
+ /**
84
+ Build fixtures for model or specific fixture name. For example:
85
+
86
+ FactoryGuy.build('user') for User model
87
+ FactoryGuy.build('bob') for User model with bob attributes
88
+
89
+ @param name fixture name
90
+ @param opts options that will override default fixture values
91
+ @returns {*}
92
+ */
93
+ build: function (name, opts) {
94
+ var model = this.lookupModelForName(name);
95
+ if (!model) {
96
+ throw new Error("can't find that factory named [" + name + "]");
97
+ }
98
+
99
+ var modelInfo = this.fixtureStore[model];
100
+ var modelAttributes = modelInfo[name] || {};
101
+ var defaultModelAttributes = modelInfo.default;
102
+ var fixture = $.extend({}, defaultModelAttributes, modelAttributes, opts);
103
+ fixture.id = this.generateId(model);
104
+ return fixture;
105
+ },
106
+
107
+ /**
108
+ Clear model instances from FIXTURES array, and from store cache.
109
+ Reset the id sequence for the models back to zero.
110
+ */
111
+ resetModels: function (store) {
112
+ var typeMaps = store.typeMaps;
113
+ if (store.usingFixtureAdapter()) {
114
+ for (typeKey in this.fixtureStore) {
115
+ var modelType = store.modelFor(typeKey);
116
+ modelType.FIXTURES = [];
117
+ store.unloadAll(modelType);
118
+ }
119
+ } else {
120
+ for (model in typeMaps) {
121
+ if (typeMaps[model].type.typeKey != 'user') {
122
+ // console.log(typeMaps[model].type.typeKey)
123
+ store.unloadAll(typeMaps[model].type);
124
+ }
125
+ }
126
+ }
127
+ this.modelIds = {}
128
+ },
129
+
130
+ /**
131
+ Push fixture to model's FIXTURES array.
132
+ Used when store's adapter is a DS.FixtureAdapter.
133
+
134
+ @param modelClass DS.Model type
135
+ @param fixture the fixture to add
136
+ */
137
+ pushFixture: function (modelClass, fixture) {
138
+ if (!modelClass['FIXTURES']) {
139
+ modelClass['FIXTURES'] = [];
140
+ }
141
+ modelClass['FIXTURES'].push(fixture);
142
+ return fixture;
143
+ }
144
+ })
145
+ DS.Store.reopen({
146
+
147
+ usingFixtureAdapter: function() {
148
+ var adapter = this.adapterFor('application');
149
+ return adapter instanceof DS.FixtureAdapter
150
+ },
151
+
152
+ /**
153
+ Make new fixture and save to store. If the store is using FixtureAdapter,
154
+ will push to FIXTURE array, otherwise will use push method on adapter.
155
+
156
+ @param name
157
+ @param options
158
+ @returns {*}
159
+ */
160
+ makeFixture: function (name, options) {
161
+ var modelName = FactoryGuy.lookupModelForName(name);
162
+ var fixture = FactoryGuy.build(name, options);
163
+ var modelType = this.modelFor(modelName);
164
+
165
+ if (this.usingFixtureAdapter()) {
166
+ this.setBelongsToFixturesAssociation(modelType, modelName, fixture);
167
+ return FactoryGuy.pushFixture(modelType, fixture);
168
+ } else {
169
+ var self = this;
170
+ var model;
171
+ Em.run( function() {
172
+ model = self.push(modelName, fixture);
173
+ self.setBelongsToRestAssociation(modelType, modelName, model);
174
+ });
175
+ return model;
176
+ }
177
+ },
178
+
179
+ /**
180
+ Trying to set the belongsTo association for FixtureAdapter,
181
+ with models that have a hasMany association.
182
+
183
+ For example if a client hasMany projects, then set the client.id
184
+ on each project that the client hasMany of, so that the project
185
+ now has the belongsTo client association setup.
186
+
187
+ @param name
188
+ @param model
189
+ */
190
+ setBelongsToFixturesAssociation: function (modelType, modelName, parentFixture) {
191
+ var store = this;
192
+ var adapter = this.adapterFor('application');
193
+ var relationShips = Ember.get(modelType, 'relationshipNames');
194
+ if (relationShips.hasMany) {
195
+ relationShips.hasMany.forEach(function (relationship) {
196
+ var hasManyModel = store.modelFor(Em.String.singularize(relationship));
197
+ if (parentFixture[relationship]) {
198
+ parentFixture[relationship].forEach(function(id) {
199
+ var hasManyfixtures = adapter.fixturesForType(hasManyModel);
200
+ var fixture = adapter.findFixtureById(hasManyfixtures, id);
201
+ fixture[modelName] = parentFixture.id;
202
+ })
203
+ }
204
+ })
205
+ }
206
+ },
207
+
208
+ /**
209
+ * Trying to set the belongsTo association for the rest type models
210
+ * with a hasMany association
211
+ *
212
+ * For example if a client hasMany projects, then set the client
213
+ * on each project that the client hasMany of, so that the project
214
+ * now has the belongsTo client association setup
215
+ *
216
+ * @param modelType
217
+ * @param modelName
218
+ * @param parent model to check for hasMany
219
+ */
220
+ setBelongsToRestAssociation: function (modelType, modelName, parent) {
221
+ var relationShips = Ember.get(modelType, 'relationshipNames');
222
+
223
+ if (relationShips.hasMany) {
224
+ relationShips.hasMany.forEach(function (name) {
225
+ var children = parent.get(name);
226
+ if (children.get('length') > 0) {
227
+ children.forEach(function(child) {
228
+ child.set(modelName, parent)
229
+ })
230
+ }
231
+ })
232
+ }
233
+ },
234
+
235
+ /**
236
+ Adding a pushPayload for FixtureAdapter, but using the original with
237
+ other adapters that support pushPayload.
238
+
239
+ @param type
240
+ @param payload
241
+ */
242
+ pushPayload: function (type, payload) {
243
+ if (this.usingFixtureAdapter()) {
244
+ var model = this.modelFor(modelName);
245
+ FactoryGuy.pushFixture(model, payload);
246
+ } else {
247
+ this._super(type, payload);
248
+ }
249
+ }
250
+ });
251
+
252
+
253
+ DS.FixtureAdapter.reopen({
254
+
255
+ /**
256
+ Overriding createRecord in FixtureAdapter to add the record
257
+ created to the hashMany records for all of the records that
258
+ this one belongsTo.
259
+
260
+ @method createRecord
261
+ @param {DS.Store} store
262
+ @param {subclass of DS.Model} type
263
+ @param {DS.Model} record
264
+ @return {Promise} promise
265
+ */
266
+ createRecord: function(store, type, record) {
267
+ var promise = this._super(store, type, record);
268
+
269
+ promise.then( function() {
270
+ var hasManyName = Ember.String.pluralize(type.typeKey);
271
+ var relationShips = Ember.get(type, 'relationshipNames');
272
+ if (relationShips.belongsTo) {
273
+ // console.log('record',record+'', type.typeKey, hasManyName);
274
+ // relationShips.belongsTo.forEach(function (relationship) {
275
+ // console.log(relationship, record.get(relationship)+'')
276
+ // var belongsToRecord = record.get(relationship);
277
+ // console.log(relationshipForType)
278
+ // belongsToRecord.get(hasManyName).addObject(record);
279
+ // })
280
+ }
281
+ })
282
+ return promise;
283
+ }
284
+
285
+ })
286
+
287
+
288
+ FactoryGuyHelperMixin = Em.Mixin.create({
289
+
290
+ setup: function(app) {
291
+ this.set('container', app.__container__);
292
+ return this;
293
+ },
294
+
295
+ useFixtureAdapter: function(app) {
296
+ app.ApplicationAdapter = DS.FixtureAdapter;
297
+ this.getStore().adapterFor('application').simulateRemoteResponse = false;
298
+ },
299
+
300
+ find: function(type, id) {
301
+ return this.getStore().find(type, id);
302
+ },
303
+
304
+ make: function(name, opts) {
305
+ return this.getStore().makeFixture(name, opts);
306
+ },
307
+
308
+ getStore: function () {
309
+ return this.get('container').lookup('store:main');
310
+ },
311
+
312
+ pushPayload: function(type, hash) {
313
+ return this.getStore().pushPayload(type, hash);
314
+ },
315
+
316
+ pushRecord: function(type, hash) {
317
+ return this.getStore().push(type, hash);
318
+ },
319
+
320
+ stubEndpointForHttpRequest: function (url, json, options) {
321
+ options = options || {};
322
+ var request = {
323
+ url: url,
324
+ dataType: 'json',
325
+ responseText: json,
326
+ type: options.type || 'GET',
327
+ status: options.status || 200
328
+ }
329
+
330
+ if (options.data) {
331
+ request.data = options.data
332
+ }
333
+
334
+ $.mockjax(request);
335
+ },
336
+
337
+ /**
338
+ * Handling ajax POST for a model
339
+ *
340
+ * @param name of the fixture ( or model ) to create
341
+ * @param opts fixture options
342
+ */
343
+ handleCreate: function (name, opts) {
344
+ var model = FactoryGuy.lookupModelForName(name);
345
+ this.stubEndpointForHttpRequest(
346
+ "/" + Em.String.pluralize(model),
347
+ this.buildAjaxResponse(name, opts),
348
+ {type: 'POST'}
349
+ )
350
+ },
351
+
352
+ buildAjaxResponse: function (name, opts) {
353
+ var fixture = FactoryGuy.build(name, opts);
354
+ var model = FactoryGuy.lookupModelForName(name);
355
+ var hash = {};
356
+ hash[model] = fixture;
357
+ return hash;
358
+ },
359
+
360
+ handleUpdate: function (root, id) {
361
+ this.stubEndpointForHttpRequest(
362
+ "/" + Em.String.pluralize(root) + "/" + id, '{}', {type: 'PUT'}
363
+ )
364
+ },
365
+
366
+ handleDelete: function (root, id) {
367
+ this.stubEndpointForHttpRequest(
368
+ "/" + Em.String.pluralize(root) + "/" + id, {}, {type: 'DELETE'}
369
+ )
370
+ },
371
+
372
+ teardown: function () {
373
+ FactoryGuy.resetModels(this.getStore());
374
+ }
375
+
376
+ })