ember-data-factory-guy 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,6 @@
1
1
  bower_components/
2
2
  node_modules/
3
- *.gem
3
+ factory_guy_presentation/
4
+ factory_guy_presents/
5
+ stats/
6
+ *.gem
data/Gruntfile.js CHANGED
@@ -49,6 +49,14 @@ module.exports = function(grunt) {
49
49
 
50
50
  qunit: {
51
51
  all: ['tests/*.html']
52
+ },
53
+
54
+ bump: {
55
+ options: {
56
+ files: ['package.json', 'bower.json', 'ember-data-factory-guy.gemspec'],
57
+ commitFiles: ["-a"],
58
+ push: false
59
+ }
52
60
  }
53
61
  });
54
62
 
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
- Ember Data Factory Guy [![Build Status](https://secure.travis-ci.org/danielspaniel/ember-data-factory-guy.png?branch=master)](http://travis-ci.org/danielspaniel/ember-data-factory-guy)
2
- =================
1
+ # Ember Data Factory Guy [![Build Status](https://secure.travis-ci.org/danielspaniel/ember-data-factory-guy.png?branch=master)](http://travis-ci.org/danielspaniel/ember-data-factory-guy)
3
2
 
4
- # Using as Gem
3
+ ## Using as Gem
5
4
 
6
5
  To Use with in Rails project or project with sprockets:
7
6
 
@@ -24,7 +23,7 @@ then:
24
23
  //= require ember_data_factory_guy
25
24
  ```
26
25
 
27
- # Using as bower component
26
+ ## Using as bower component
28
27
 
29
28
  Add as one of your dependencies in bower.json file:
30
29
  ```json
@@ -40,13 +39,13 @@ then:
40
39
  $ bower install
41
40
  ```
42
41
 
43
- # How this works
42
+ ## How this works
44
43
 
45
44
  Add fixtures to the store using the:
46
45
 
47
- * DS.FixtureAdapter
48
46
  * DS.RestAdapter
49
47
  * DS.ActiveModelAdapter
48
+ * DS.FixtureAdapter
50
49
 
51
50
  NOTE: The benefit of using FactoryGuy is that you can run your tests with the
52
51
  default adapter that your application's store normally uses. In other words:
@@ -60,25 +59,39 @@ If you do get these types of errors try requiring the factory_guy_has_many.js fi
60
59
  ( located in dist dir and vendor dir ) AFTER you require ember-data,
61
60
  but BEFORE you require your models.
62
61
 
62
+ Let's say you have a few models like these:
63
63
 
64
64
  ```javascript
65
65
 
66
- ////////////////////////////////////////////
67
- // Model definitions
68
-
69
66
  User = DS.Model.extend({
70
67
  name: DS.attr('string'),
71
68
  type: DS.attr('string'),
72
- projects: DS.hasMany('project')
73
- })
69
+ projects: DS.hasMany('project'),
70
+ hats: DS.hasMany('hat', {polymorphic: true})
71
+ });
74
72
 
75
73
  Project = DS.Model.extend({
76
- title: DS.attr('string')
74
+ title: DS.attr('string'),
77
75
  user: DS.belongsTo('user')
78
- })
76
+ });
77
+
78
+ Hat = DS.Model.extend({
79
+ type: DS.attr('string'),
80
+ user: DS.belongsTo('user')
81
+ });
82
+
83
+ BigHat = Hat.extend();
84
+ SmallHat = Hat.extend();
79
85
 
86
+ ```
87
+
88
+
89
+ ### Defining a Fixture Factory for a Model
90
+
91
+ ```javascript
80
92
  ////////////////////////////////////////////
81
93
  // FactoryGuy definitions for models
94
+
82
95
  FactoryGuy.define('user', {
83
96
  // sequences to be used in attributes definition
84
97
  sequences: {
@@ -99,113 +112,185 @@ but BEFORE you require your models.
99
112
  type: 'superuser',
100
113
  name: 'Admin'
101
114
  }
115
+ // using a function for an attribute that refers to other attributes
116
+ funny_user: {
117
+ type: function(f) { return 'funny ' + f.name }
118
+ }
102
119
  });
103
120
 
104
121
  FactoryGuy.define('project', {
105
122
  default: {
106
123
  title: 'Project'
124
+ },
125
+ //
126
+ // define built in belongTo models
127
+ //
128
+ project_with_user: {
129
+ // user model with default attributes
130
+ user: {}
131
+ },
132
+ project_with_dude: {
133
+ // user model with custom attributes
134
+ user: {name: 'Dude'}
135
+ },
136
+ project_with_admin: {
137
+ // for named association, use this FactoryGuy.association helper method
138
+ user: FactoryGuy.association('admin')
107
139
  }
108
140
  });
109
141
 
142
+ FactoryGuy.define('hat', {
143
+ default: {},
144
+ small_hat: {
145
+ type: 'small_hat'
146
+ },
147
+ big_hat: {
148
+ type: 'big_hat'
149
+ }
150
+ })
151
+ ```
152
+
153
+
154
+ ### Building Json
155
+
156
+ ```javascript
110
157
  //////////////////////////////////////////////////////////////////
111
- // ** Make one fixture at time **
158
+ //
112
159
  // building json with FactoryGuy.build
113
160
  //
114
161
 
115
- var userJson = FactoryGuy.build('user') // {id: 1, name: 'User1', type: 'normal'}
162
+ FactoryGuy.build('user') // {id: 1, name: 'User1', type: 'normal'}
116
163
  // note the sequence used in the name attribute
117
- var user2Json = FactoryGuy.build('user') // {id: 2, name: 'User2', type: 'normal'}
118
- var customUserJson = FactoryGuy.build('user', name: 'bob') // {id: 3, name: 'bob', type: 'normal'}
119
- var namedUserJson = FactoryGuy.build('admin') // {id: 4, name: 'Admin', type: 'superuser'}
164
+ FactoryGuy.build('user') // {id: 2, name: 'User2', type: 'normal'}
165
+ FactoryGuy.build('user', {name: 'bob'}) // {id: 3, name: 'bob', type: 'normal'}
166
+ FactoryGuy.build('admin') // {id: 4, name: 'Admin', type: 'superuser'}
167
+ // note the type attribute was built from a function which depends on the name
168
+ // and the name is still a generated attribute from a sequence function
169
+ FactoryGuy.build('funny_user') // {id: 5, name: 'User3', type: 'funny User3'}
170
+
171
+ // basic project
172
+ FactoryGuy.build('project') // {id: 1, title: 'Project'}
173
+
174
+ // project with a user
175
+ FactoryGuy.build('project_with_user') // {id: 1, title: 'Project', user: {id:6, name: 'User4', type: 'normal'}
176
+ // project with user that has custom attributes
177
+ FactoryGuy.build('project_with_dude') // {id: 2, title: 'Project', user: {id:7, name: 'Dude', type: 'normal'}
178
+ // project with user that has a named user
179
+ FactoryGuy.build('project_with_admin') // {id: 3, title: 'Project', user: {id:8, name: 'Admin', type: 'superuser'}
120
180
 
121
181
  //////////////////////////////////////////////////////////////////
122
- // ** Make a list of fixtures **
182
+ //
123
183
  // building json with FactoryGuy.buildList
124
184
  //
125
185
 
126
- var userJson = FactoryGuy.buildList('user',2) // [ {id: 1, name: 'User1', type: 'normal'}, {id: 2, name: 'User2', type: 'normal'} ]
186
+ FactoryGuy.buildList('user', 2) // [ {id: 1, name: 'User1', type: 'normal'}, {id: 2, name: 'User2', type: 'normal'} ]
187
+ ```
127
188
 
128
- //////////////////////////////////////////////////////////////////
129
- //
130
- // with store using => DS.Fixture adapter
131
- //
132
- // store.makeFixture => creates model in the store and returns json
133
- // store.makeList => creates list of models in the store and returns json
134
- //
135
189
 
136
- store.makeFixture('user'); // user.FIXTURES = [{id: 1, name: 'User1', type: 'normal'}]
137
- store.makeFixture('user', {name: 'bob'}); // user.FIXTURES = [{id: 2, name: 'bob', type: 'normal'}]
138
- store.makeFixture('admin'); // user.FIXTURES = [{id: 3, name: 'Admin', type: 'superuser'}]
139
- store.makeFixture('admin', {name: 'Fred'}); // user.FIXTURES = [{id: 4, name: 'Fred', type: 'superuser'}]
190
+ ###Adding records to store
140
191
 
192
+ #####DS.ActiveModelAdapter/DS.RestAdapter
141
193
 
142
- // Use store.find to get the model instance ( Remember this is the Fixture adapter, if
143
- // you use the ActiveModelAdapter or RESTAdapter the record is returned so you don't
144
- // have to then go and find it
145
- var userJson = store.makeFixture('user');
146
- store.find('user', userJson.id).then(function(user) {
147
- user.toJSON() ( has all the same key/values as ) userJson;
148
- });
194
+ ###### The Basics
149
195
 
150
- // and to setup associations ...
151
- var projectJson = store.makeFixture('project');
152
- var userJson = store.makeFixture('user', projects: [project.id]);
153
- // OR
154
- var userJson = store.makeFixture('user');
155
- var projectJson = store.makeFixture('project', user: userJson.id);
156
-
157
- // will give you the same result, but with fixture adapter all associations
158
- // are treated as async ( by factory_guy_has_many.js fix ), so it's
159
- // a bit clunky to get this associated data. When using DS.FixtureAdapter
160
- // in view specs though, this clunk is dealt with for you. But remember,
161
- // you don't have to use the Fixture adapter.
162
- store.find('user', 1).then(function(user) {
163
- user.get('name') == 'My name';
164
- user.get('projects').then(function(projects) {
165
- projects.length == 1;
166
- });
167
- });
196
+ store.makeFixture => creates model in the store and returns model instance
197
+ *NOTE* since you are getting a model instances, you can synchronously
198
+ start asking for data from the model, and its associations
168
199
 
169
- // and for lists
170
- var users = store.makeList('user', 2, projects: [project.id]);
200
+ ```javascript
201
+ var user = store.makeFixture('user'); // user.toJSON() = {id: 1, name: 'User1', type: 'normal'}
202
+ // note that the user name is a sequence
203
+ var user = store.makeFixture('user'); // user.toJSON() = {id: 2, name: 'User2', type: 'normal'}
204
+ var user = store.makeFixture('funny_user'); // user.toJSON() = {id: 3, name: 'User3', type: 'funny User3'}
205
+ var user = store.makeFixture('user', {name: 'bob'}); // user.toJSON() = {id: 4, name: 'bob', type: 'normal'}
206
+ var user = store.makeFixture('admin'); // user.toJSON() = {id: 5, name: 'Admin', type: 'superuser'}
207
+ var user = store.makeFixture('admin', {name: 'Fred'}); // user.toJSON() = {id: 6, name: 'Fred', type: 'superuser'}
208
+ ```
171
209
 
172
- //////////////////////////////////////////////////////////////////
173
- //
174
- // with store using => DS.ActiveModelAdapter/DS.RestAdapter
175
- //
176
- // store.makeFixture => creates model in the store and returns model instance
177
- // store.makeList => creates list of models in the store and returns model instance
178
- //
179
- // *NOTE* since you are now getting a model instances, you can synchronously
180
- // start asking for data from the model
181
- //
210
+ ###### associations
182
211
 
183
- var user = store.makeFixture('user'); // user.toJSON() = {id: 1, name: 'User1', type: 'normal'}
184
- // note that the user name is a sequence
185
- var user = store.makeFixture('user'); // user.toJSON() = {id: 2, name: 'User2', type: 'normal'}
186
- var user = store.makeFixture('user', {name: 'bob'}); // user.toJSON() = {id: 3, name: 'bob', type: 'normal'}
187
- var user = store.makeFixture('admin'); // user.toJSON() = {id: 4, name: 'Admin', type: 'superuser'}
188
- var user = store.makeFixture('admin', name: 'Fred'); // user.toJSON() = {id: 5, name: 'Fred', type: 'superuser'}
212
+ ``` javascript
213
+ var project = store.makeFixture('project');
214
+ var user = store.makeFixture('user', {projects: [project]});
215
+ // OR
216
+ var user = store.makeFixture('user');
217
+ var project = store.makeFixture('project', {user: user});
189
218
 
190
- // and to setup associations ...
219
+ // will get you the same results, since FactoryGuy makes sure the associations
220
+ // are created in both directions
221
+ // user.get('projects.length') == 1;
222
+ // user.get('projects.firstObject.user') == user;
223
+ ```
224
+
225
+ ###### polymorphic hasMany associations
226
+
227
+ ```javascript
228
+ var sh = store.makeFixture('big_hat');
229
+ var bh = store.makeFixture('small_hat');
230
+ var user = store.makeFixture('user', {hats: [sh, bh]})
231
+ // user.get('hats.length') == 2;
232
+ // (user.get('hats.firstObject') instanceof BigHat) == true
233
+ // (user.get('hats.lastObject') instanceof SmallHat) == true
234
+ ```
235
+
236
+ ###### create lists
237
+
238
+ ```javascript
239
+ var users = store.makeList('user', 3);
240
+ ```
241
+
242
+ #####DS.Fixture adapter
243
+
244
+ store.makeFixture => creates model in the store and returns json
191
245
 
192
- var project = store.makeFixture('project');
193
- var user = store.makeFixture('user', projects: [project]);
194
- // OR
195
- var user = store.makeFixture('user');
196
- var project = store.makeFixture('project', user: user);
246
+ Technically when you call store.makeFixture with a store using the DS.FixtureAdapter,
247
+ the fixture is actually added to the models FIXTURE array. It just seems to be added
248
+ to the store because when you call store.find to get that record, the adapter looks
249
+ in that FIXTURE array to find it and then puts it in the store.
250
+
251
+ ```javascript
252
+
253
+ store.makeFixture('user'); // user.FIXTURES = [{id: 1, name: 'User1', type: 'normal'}]
254
+ store.makeFixture('user', {name: 'bob'}); // user.FIXTURES = [{id: 2, name: 'bob', type: 'normal'}]
255
+ store.makeFixture('admin'); // user.FIXTURES = [{id: 3, name: 'Admin', type: 'superuser'}]
256
+ store.makeFixture('admin', {name: 'Fred'}); // user.FIXTURES = [{id: 4, name: 'Fred', type: 'superuser'}]
197
257
 
198
- // will get you the same results
199
- user.get('projects.length') == 1;
200
- user.get('projects.firstObject.user') == user;
201
258
 
202
- // and to create lists ( of 3 users in this case )
203
- var users = store.makeList('user', 3);
259
+ // Use store.find to get the model instance ( Remember this is the Fixture adapter, if
260
+ // you use the ActiveModelAdapter or RESTAdapter the record is returned so you don't
261
+ // have to then go and find it )
262
+ var userJson = store.makeFixture('user');
263
+ store.find('user', userJson.id).then(function(user) {
264
+ user.toJSON() ( pretty much equals ) userJson;
265
+ });
204
266
 
267
+ // and to setup associations ...
268
+ var projectJson = store.makeFixture('project');
269
+ var userJson = store.makeFixture('user', {projects: [projectJson.id]});
270
+ // OR
271
+ var userJson = store.makeFixture('user');
272
+ var projectJson = store.makeFixture('project', {user: userJson.id});
273
+
274
+ // will give you the same result, but with fixture adapter all associations
275
+ // are treated as async ( by factory_guy_has_many.js fix ), so it's
276
+ // a bit clunky to get this associated data. When using DS.FixtureAdapter
277
+ // in view specs though, this clunk is dealt with for you. But remember,
278
+ // you don't have to use the Fixture adapter.
279
+ store.find('user', 1).then(function(user) {
280
+ user.toJSON() (pretty much equals) userJson;
281
+ user.get('projects').then(function(projects) {
282
+ projects.length == 1;
283
+ });
284
+ });
285
+
286
+ // and for lists
287
+ store.makeList('user', 2, {projects: [project.id]});
205
288
  ```
206
289
 
207
- Extra Goodies
208
- =============
290
+ ###Testing models, controllers, views
291
+
292
+
293
+ This section assumes you are testing the ( controllers and views ) in isolation.
209
294
 
210
295
  The code bundled in dist/ember-data-factory-guy.js includes a mixin named FactoryGuyTestMixin which
211
296
  can be used in your tests to make it easier to access the store and make fixtures.
@@ -219,7 +304,6 @@ TestHelper = Ember.Object.createWithMixins(FactoryGuyTestMixin);
219
304
 
220
305
  // Then in your tests you can use it like so:
221
306
 
222
-
223
307
  var testHelper, store;
224
308
 
225
309
  module('User Model', {
@@ -257,7 +341,85 @@ test("make a user using your applications default adapter", function() {
257
341
  ```
258
342
 
259
343
 
260
- Further Extra Goodies
261
- =====================
344
+ ###Integration Tests
345
+
346
+ Since it is recommended to use your normal adapter ( which is usually a subclass of RESTAdapter, )
347
+ FactoryGuyTestMixin assumes you will want to use that adapter to do your integration tests.
348
+
349
+ To do that you will still have to deal with ember data trying to create, update or delete records.
350
+
351
+ If you put models into the store ( with store#makeFixture ), the http GET call does not need to be mocked,
352
+ since that model is already in the store.
353
+
354
+ But what if you want to handle create, update or delete?
355
+ FactoryGuy assumes you want to mock ajax calls with the mockjax library,
356
+ and you will need to download and include that library to use the following feature.
357
+
358
+ Here is a sample of what you could do in a view test:
359
+
360
+ ```javascript
361
+
362
+ // create a view test helper using the FactoryGuyTestMixin
363
+ ViewTestHelper = Ember.Object.createWithMixins(FactoryGuyTestMixin,{
364
+ // override setup to do a few extra things for view tests
365
+ setup: function (app, opts) {
366
+ app.reset(); // reset ember app before test
367
+ $.mockjaxSettings.logging = false; // mockjax settings
368
+ $.mockjaxSettings.responseTime = 0; // mockjax settings
369
+ return this._super(app); // still call the base setup from FactoryGuyTestMixin
370
+ },
371
+ // override teardown to clear mockjax declarations
372
+ teardown: function() {
373
+ $.mockjaxClear();
374
+ this._super();
375
+ }
376
+ }
377
+
378
+ var viewHelper;
379
+
380
+ module('User View', {
381
+ setup: function() {
382
+ viewHelper = ViewTestHelper.setup(App); // set up helper
383
+ var user = viewHelper.make('user'); // create a user in the store
384
+ visit('/users/'+user.id); // visit the users route
385
+ },
386
+ teardown: function() {
387
+ Em.run(function() { viewHelper.teardown(); });
388
+ }
389
+ });
390
+
391
+ test("Creates new project", function() {
392
+ andThen(function() {
393
+ var newProjectName = "Gonzo Project"
394
+
395
+ click('.add-div div:contains(New Project)')
396
+ fillIn('.add-project input', newProjectName)
397
+ // This is the special sauce that makes this project really hum.
398
+ // Check out the FactoryGuyTestMixin to see what is going on here
399
+ viewHelper.handleCreate('project', {name: newProjectName})
400
+
401
+ /**
402
+ Let's say that clicking this '.add-project .link', triggers action in the view to
403
+ create project record and looks something like this:
404
+
405
+ actions: {
406
+ addProject: function (user) {
407
+ this.get('controller.store')
408
+ .createRecord('project', {
409
+ name: this.$('.add-project input').val(),
410
+ user: user
411
+ })
412
+ .save()
413
+ }
414
+
415
+ */
416
+ click('.add-project .link')
417
+
418
+ var newProjectDiv = find('.project:contains('+newProjectName+')')
419
+ equal(newProjectDiv[0] != undefined, true)
420
+ })
421
+ })
422
+
423
+ ```
424
+
262
425
 
263
- mockjax