ember-data-factory-guy 0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ bower_components/
2
+ node_modules/
data/Gruntfile.js ADDED
@@ -0,0 +1,45 @@
1
+ module.exports = function(grunt) {
2
+
3
+ grunt.initConfig({
4
+
5
+ pkg: grunt.file.readJSON('package.json'),
6
+
7
+ concat: {
8
+ dist: {
9
+ src: ['src/factory_guy.js', 'src/store.js', 'src/factory_guy_helper_mixin.js'],
10
+ dest: "dist/ember-data-factory-guy.js"
11
+ },
12
+ gem: {
13
+ files: {
14
+ "vendor/assets/javascripts/ember_data_factory_guy.js": ['src/factory_guy.js', 'src/store.js', 'src/factory_guy_helper_mixin.js'],
15
+ "vendor/assets/javascripts/factory_guy_has_many.js": ['src/has_many.js']
16
+ }
17
+ },
18
+ test: {
19
+ src: ['tests/support/factories/*.js', 'tests/support/models/*.js'],
20
+ dest: "tests/test_setup.js"
21
+ }
22
+ },
23
+
24
+ uglify: {
25
+ options: { mangle: false, compress: false },
26
+
27
+ dist: {
28
+ src: ['dist/ember-data-factory-guy.js'],
29
+ dest: 'dist/ember-data-factory-guy.min.js'
30
+ }
31
+ },
32
+
33
+ qunit: {
34
+ all: ['tests/*.html']
35
+ }
36
+ });
37
+
38
+ grunt.loadNpmTasks('grunt-contrib-coffee');
39
+ grunt.loadNpmTasks('grunt-contrib-concat');
40
+ grunt.loadNpmTasks('grunt-contrib-uglify');
41
+ grunt.loadNpmTasks('grunt-contrib-qunit');
42
+
43
+ grunt.registerTask('default', ['concat', 'uglify']);
44
+ grunt.registerTask('test', ['concat:dist', 'qunit']);
45
+ };
data/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # Using as Gem
2
+
3
+ To Use with in Rails project or project with sprockets:
4
+
5
+ In Gemfile:
6
+
7
+ ```ruby
8
+ gem 'ember-data-factory-guy', group: test
9
+ ```
10
+
11
+ then:
12
+
13
+ ```
14
+ $ bundle install
15
+ ```
16
+
17
+ # How this works
18
+
19
+ Add fixtures to the store using the:
20
+
21
+ * DS.FixtureAdapter
22
+ * DS.RestAdapter
23
+ * DS.ActiveModelAdapter
24
+
25
+ ```javascript
26
+
27
+ ////////////////////////////////////////////
28
+ // Model definitions
29
+
30
+ User = DS.Model.extend({
31
+ name: DS.attr 'string',
32
+ projects: DS.hasMany 'project'
33
+ })
34
+
35
+ Project = DS.Model.extend({
36
+ title: DS.attr 'string'
37
+ })
38
+
39
+ ////////////////////////////////////////////
40
+ // Fixture definitions for models
41
+
42
+ FactoryGuy.define('user', {
43
+ // default values for 'user' attributes
44
+ default: {
45
+ name: 'User1'
46
+ },
47
+ // named 'user' type with custom attributes
48
+ admin: {
49
+ name: 'Admin'
50
+ }
51
+ });
52
+
53
+ FactoryGuy.define('project', {
54
+ default: {title: 'Project'}
55
+ });
56
+
57
+ //////////////////////////////////////////////////////////////////
58
+ //
59
+ // building json with FactoryGuy.build
60
+ //
61
+ var userJson = FactoryGuy.build('user') // {id: 1, name: 'User1'}
62
+ var customUserJson = FactoryGuy.build('user', name: 'bob') // {id: 2, name: 'bob'}
63
+ var namedUserJson = FactoryGuy.build('admin') // {id: 3, name: 'Admin'}
64
+
65
+ //////////////////////////////////////////////////////////////////
66
+ // store.makeFixture method creates model in the store
67
+ //
68
+ // with DS.Fixture adapter
69
+ // makeFixture returns json
70
+ //
71
+ store.makeFixture('user'); // user.FIXTURES = {id: 1, name: 'User1'}
72
+ store.makeFixture('user', {name: 'bob'}); // user.FIXTURES = {id: 2, name: 'bob'}
73
+ store.makeFixture('admin'); // user.FIXTURES = {id: 3, name: 'Admin'}
74
+ store.makeFixture('admin', name: 'My name'); // user.FIXTURES = {id: 4, name: 'My name'}
75
+
76
+ // Use store.find to get the model instance
77
+ store.makeFixture('user');
78
+ store.find('user', 1).then(function(user) {
79
+ user.get('name') == 'My name';
80
+ });
81
+
82
+ // and to setup associations ...
83
+ var project = store.makeFixture('project');
84
+ var user = store.makeFixture('user', projects: [project.id]);
85
+
86
+ // with fixture adapter all associations are treated as async, so it's
87
+ // a bit clunky to get this associated data. When using DS.FixtureAdapter
88
+ // in view specs though, this clunk is dealt with for you.
89
+ store.find('user', 1).then(function(user) {
90
+ user.get('name') == 'My name';
91
+ user.get('projects').then(function(projects) {
92
+ projects.length == 1;
93
+ });
94
+ });
95
+
96
+ //////////////////////////////////////////////////////////////////
97
+ // store.makeFixture method creates model and adds it to store
98
+ //
99
+ // with DS.ActiveModelAdapter/DS.RestAdapter
100
+ //
101
+ // returns a model instances so you can synchronously
102
+ // start asking for data, as soon as you get the model
103
+ //
104
+ var user = store.makeFixture('user');
105
+ var user = store.makeFixture('user', {name: 'bob'}); // user.toJSON() = {id: 2, name: 'bob'}
106
+ var user = store.makeFixture('admin'); // user.toJSON() = {id: 3, name: 'Admin'}
107
+ var user = store.makeFixture('admin', name: 'My name'); // user.toJSON() = {id: 4, name: 'My name'}
108
+
109
+ // and to setup associations ...
110
+
111
+ var project = store.makeFixture('project');
112
+ var user = store.makeFixture('user', projects: [project.id]);
113
+
114
+ user.get('projects.length') == 1;
115
+ user.get('projects.firstObject.user') == user;
116
+
117
+
118
+ ```
data/bower.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "ember-data-factory-guy",
3
+ "version": "0.0.1",
4
+ "authors": [
5
+ "Daniel Sudol <dansudol@yahoo.com>",
6
+ "Opak Alex <opak.alexandr@gmail.com>"
7
+ ],
8
+ "description": "Factory for testing Ember application using Ember Data",
9
+ "main": "dist/ember-data-factory-guy.js",
10
+ "keywords": [
11
+ "Factory",
12
+ "Ember",
13
+ "Data",
14
+ "FixtureAdapter"
15
+ ],
16
+ "license": "MIT",
17
+
18
+ "dependencies": {
19
+ "handlebars": "~1.1.2",
20
+ "jquery": "1.10.2",
21
+ "ember": "~1.6.0",
22
+ "ember-data": "~1.0.0-beta.7",
23
+ "emblem.js": "*",
24
+ "chance": "latest",
25
+ "qunit": "latest"
26
+ },
27
+
28
+ "ignore": [
29
+ "**/.*",
30
+ "node_modules",
31
+ "bower_components",
32
+ "test",
33
+ "tests"
34
+ ]
35
+ }
@@ -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
+ })