adopted-ember-addons / ember-data-factory-guy Goto Github PK
View Code? Open in Web Editor NEWFactories and helper functions for (unit, integration, acceptance) testing + development scenarios with Ember Data
License: MIT License
Factories and helper functions for (unit, integration, acceptance) testing + development scenarios with Ember Data
License: MIT License
Is it possible to combine factory traits akin to FactoryGirl's implementation?
e.g. FactoryGuy.build('user', traits: ['admin', 'funny_name', 'unconfirmed'])
I'm writing integration style tests for my embercli project and have come across an issue where I think I've stubbed correctly but still see network requests.
This is my integration spec which visits a particular route that loads all the album
models so I've created a bunch of albums via store.makeList('album', 5)
which I was expecting to prevent any real ajax calls being made.
Despite this setup I still see GET http://localhost:4200/api/albums 404 (Not Found)
when I run the embercli tests in a browser. I've tried using the handleFind
function but that seems targeted towards an individual model and doesn't work either.
Am I missing part of the API that covers stubbing out things like @store.find('albums')
which loads all albums? It seems like those calls bypass anything in the store and always try to make an ajax call.
Any help would be appreciated. Other than this issue I'm really liking this library, seems to do most of the things I want and makes it very easy. Cheers.
`import Ember from 'ember'`
`import startApp from '../helpers/start-app'`
`import albumFactory from '../fixtures'`
App = null
testHelper = null
store = null
TestHelper = Ember.Object.createWithMixins(FactoryGuyTestMixin)
module 'Acceptance: Dashboard',
setup: ->
App = startApp()
testHelper = TestHelper.setup(App)
store = testHelper.getStore()
albums = store.makeList('album', 5)
teardown: ->
Ember.run -> testHelper.teardown()
Ember.run App, 'destroy'
test 'visiting /dashboard', ->
visit '/dashboard'
andThen ->
equal currentPath(), 'dashboard'
test 'displays top albums', ->
visit '/dashboard'
andThen ->
equal(find('.top-albums li').length, 5, "Displays the top 5 albums")
My model definition
`import DS from 'ember-data'`
Album = DS.Model.extend
name: DS.attr('string')
artist: DS.attr('string')
coverImage: DS.attr('string')
year: DS.attr('date')
playCount: DS.attr('number', {defaultValue: 0})
tracks: DS.hasMany('track', { async: true })
`export default Album`
and the fixtures file.
FactoryGuy.define('album', {
sequences: {
albumName: (num) ->
'Album' + num
artistName: (num) ->
'Artist' + num
},
default: {
name: FactoryGuy.generate('albumName'),
artist: FactoryGuy.generate('artistName')
}
});
`export default {}`
The API I'm working with uses single table inheritance. For example, we have a base task model, and various subclasses.
In my test I'm trying to do a handleFind(task)
. That task happens to be of type paper-editor-task
. The factory guy method mapFind
will always return a json payload keyed to the pluralized version of the model name resulting in paperEditorTasks
. My ember app expects tasks
.
As a workaround I've monkey patched the FactoryGuy code. Would you consider supporting this? Perhaps as an option to handleFind
? Or maybe by looking into the model's serializer instead of always using record.constructor.typeKey
.
Currently you can use afterMake on a model definition .. which will apply globally to all models of that type that are made through FactoryGuy.make. Would be nice to have afterMake also to be declared in named definitions which would take precedence or perhaps override? global afterMake ( if it exists )
Hi again!
JSbin here
Having this models
App.Unit = DS.Model.extend
lesson: DS.belongsTo 'lesson', async: true
App.Lesson = DS.Model.extend
steps: DS.hasMany 'step', async: true
App.Step = DS.Model.extend
lesson: DS.belongsTo 'lesson', async: true
And this fabrics:
FactoryGuy.define 'unit',
default:
lesson: FactoryGuy.belongsTo('lesson')
FactoryGuy.define 'lesson',
default:
steps: FactoryGuy.hasMany('step', 2)
FactoryGuy.define 'step',
default: {}
```coffeescript
I'm trying to create unit:
viewHelper.make 'unit'
But it's failing with this stacktrace:
stack trace:
```javascript
TypeError: Cannot read property 'typeKey' of undefined
at Ember.Object.extend.modelFor (http://builds.emberjs.com/canary/ember-data.js:11258:22)
at Ember.Object.extend.recordForId (http://builds.emberjs.com/canary/ember-data.js:10729:25)
at deserializeRecordId (http://builds.emberjs.com/canary/ember-data.js:11694:27)
at http://builds.emberjs.com/canary/ember-data.js:11672:11
at http://builds.emberjs.com/canary/ember-data.js:9458:20
at http://builds.emberjs.com/canary/ember-data.js:5295:33
at http://builds.emberjs.com/tags/v1.7.0/ember.js:14897:20
at Object.OrderedSet.forEach (http://builds.emberjs.com/tags/v1.7.0/ember.js:14739:14)
at Object.Map.forEach [as __super$forEach] (http://builds.emberjs.com/tags/v1.7.0/ember.js:14895:14)
at Object.mapForEach [as forEach] (http://builds.emberjs.com/canary/ember-data.js:5302:14)
I've added a namepace to my RESTAdapter:
DS.RESTAdapter.reopen({
namespace: 'api/v1'
});
FactoryGuyTestMixin request handlers ( e.g. FactoryGuyTestMixin#handleFind ) construct a url that's inferred from the name of the factory:
https://github.com/danielspaniel/ember-data-factory-guy/blob/c22a7c4bf459ba8c49e1be15afc520d66d95992b/src/factory_guy_test_mixin.js#L127
Would it be reasonable to add a configuration setting to FactoryGuyTestMixin for a base url and then prepend that to the url while building the mockjax request here?:
https://github.com/danielspaniel/ember-data-factory-guy/blob/c22a7c4bf459ba8c49e1be15afc520d66d95992b/src/factory_guy_test_mixin.js#L69
Is it possible to set the status code and response text for 'handleCreate'? I try to mock a create request that should produce a validation error on server side, therefor my response should be something like:
status: 422
respsonseText:
{
errors: {
attr1: [error1, error2, ...],
attr2: [error1, error2, ...]
}
}
The new documentation in the README includes this part about acceptance testing:
teardown: function () {
Ember.run(function () {
TestHelper.teardown();
App.destroy();
});
}
As part of the TestHelper.teardown
call, Factory Guy unloads all records from the store. The problem is that the app is still running at this point, and App.destroy
is asynchronous and does not destroy the app immediately. Unloading the records can therefore raise errors (e.g. in computed properties that depend on associations) and cause tests to fail.
The thing is, App.destroy
seems to already unload all records from the store. I tested this by commenting out the teardown line, and observing that the count of local records was reset to 0 by the time each new test started. I am not using the fixture adapter so maybe things would be different there, but in my case I was able to replace TestHelper.teardown()
with a simple $.mockjax.clear()
(since that is the other thing the teardown call does), and that resolved the intermittent failures.
I'm not sure if this means the record unloading could safely be removed for everyone, just noting that it caused a problem for me and doesn't seem to be strictly necessary.
As described at http://emberjs.com/guides/models/customizing-adapters/, each model can have its own adapter where you can customize the method pathForType.
Ember Data Factory Guy uses the default adapter during buildURL, so customizations in model-specific adapters in the pathForType method are not used when building the stub endpoint URL.
This may also be what's happening in #29, but I'm not certain of that so creating separate issue. Pull request to follow.
I'm running into this issue with trying to test a model that has an association on it. I found a temporary solution but I've yet to understand the root cause or how to test it (I'm new to ember). Anyway, here is what I hope is all of the relevant info
// app/group/model.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
users: DS.hasMany('user')
});
// app/user/model.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string'),
role: DS.attr('string'),
last_signed_in_at: DS.attr('datetime')
});
// tests/factories/group.js
import FactoryGuy from 'ember-data-factory-guy';
import faker from 'faker';
FactoryGuy.define('group', {
default: {
name: faker.company.companyName()
},
traits: {
with_users: { users: FactoryGuy.hasMany('user', 4) }
}
});
// tests/factories/user.js
import FactoryGuy from 'ember-data-factory-guy';
import faker from 'faker';
FactoryGuy.define('user', {
default: {
name: faker.name.findName(),
email: faker.internet.email(),
role: 'member',
last_signed_in_at: Date.now()
},
admin_user: {
role: 'admin'
}
});
// tests/unit/group/model-test.js
import Ember from 'ember';
import startApp from 'client/tests/helpers/start-app';
import { module, test } from 'qunit';
import { make } from 'ember-data-factory-guy';
var application;
module('Group model', {
beforeEach: function() {
application = startApp();
},
afterEach: function() {
Ember.run(application, 'destroy');
}
});
test('it exists', function(assert) {
let group = make('group');
assert.ok(!!group);
assert.ok(group.get('name'));
});
test('it can have user', function(assert){
let group = make('group','with_users');
assert.equal(group.get('users.length'), 4, '4 of them');
});
not ok 3 PhantomJS 1.9 - Group model: it can have user
---
actual: >
null
message: >
Died on test #1 at http://localhost:7357/assets/test-support.js:2809
at http://localhost:7357/assets/client.js:3188
at http://localhost:7357/assets/vendor.js:150
at tryFinally (http://localhost:7357/assets/vendor.js:30)
at http://localhost:7357/assets/vendor.js:156
at http://localhost:7357/assets/test-loader.js:29
at http://localhost:7357/assets/test-loader.js:21
at http://localhost:7357/assets/test-loader.js:40
at http://localhost:7357/assets/test-support.js:5578: 'undefined' is not an object (evaluating 'traits[trait]')
Log: >
...
What causing the error is the association line in my group factory trait for users. If I remove the hasMany
, I receive no error.
traits: {
with_users: { users: FactoryGuy.hasMany('user', 4) }
}
So what's bombing out there is model-definition.js
this.build = function (name, opts, traitArgs) {
var traitsObj = {};
traitArgs.forEach(function (trait) {
$.extend(traitsObj, traits[trait]);
});
...
For some reason, the extractArguments
method is actually setting traits = undefined
which is then causing that traitArgs
argument in build()
to equal an array with a single value of undefined ([undefined]
)
Now, I have no idea if that is desired or not, i've only dug around trying to get this to work for an hour or two. What got things to work for me was putting in a guard clause.
traitArgs.forEach(function (trait) {
if (!trait) return;
$.extend(traitsObj, traits[trait]);
});
If that really does fix it, great. Otherwise, I hope all of this rambling is enough to point you in the right direction of fixing the bug or telling me what obvious thing I missed. Thanks!
DEBUG: -------------------------------
ember.debug.js:5197DEBUG: Ember : 1.11.1
ember.debug.js:5197DEBUG: Ember Data : 1.0.0-beta.16.1
ember.debug.js:5197DEBUG: jQuery : 1.11.3
ember.debug.js:5197DEBUG: Ember Simple Auth : 0.8.0-beta.2
ember.debug.js:5197 DEBUG: Ember Simple Auth Devise : 0.8.0-beta.2
ember.debug.js:5197 DEBUG: Ember Simple Auth Testing : 0.8.0-beta.2
ember.debug.js:5197 DEBUG: -------------------------------
"ember-data-factory-guy": "1.0.5",
$ ember install:addon ember-data-factory-guy
version: 0.2.1
A new version of ember-cli is available (0.2.3). To install it, type ember update.
Could not find watchman, falling back to NodeWatcher for file system events.
Visit http://www.ember-cli.com/#watchman for more info.
Installed packages for tooling via npm.
Cannot read property 'name' of undefined
TypeError: Cannot read property 'name' of undefined
at /home/blieb/projects/akita/frontend/node_modules/ember-cli/lib/models/project.js:459:53
at find (/home/blieb/projects/akita/frontend/node_modules/ember-cli/node_modules/lodash-node/modern/collections/find.js:64:11)
at Project.findAddonByName (/home/blieb/projects/akita/frontend/node_modules/ember-cli/lib/models/project.js:458:20)
at Class.module.exports.Task.extend.findDefaultBlueprintName (/home/blieb/projects/akita/frontend/node_modules/ember-cli/lib/tasks/addon-install.js:63:30)
at Class.module.exports.Task.extend.installBlueprint (/home/blieb/projects/akita/frontend/node_modules/ember-cli/lib/tasks/addon-install.js:52:30)
at Class. (/home/blieb/projects/akita/frontend/node_modules/ember-cli/lib/tasks/addon-install.js:42:19)
at lib$rsvp$$internal$$tryCatch (/home/blieb/projects/akita/frontend/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:489:16)
at lib$rsvp$$internal$$invokeCallback (/home/blieb/projects/akita/frontend/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:501:17)
at lib$rsvp$$internal$$publish (/home/blieb/projects/akita/frontend/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:472:11)
at lib$rsvp$asap$$flush (/home/blieb/projects/akita/frontend/node_modules/ember-cli/node_modules/rsvp/dist/rsvp.js:1290:9)
{
"name": "akita",
"version": "0.1.0-SNAPSHOT",
"description": "Front end for user namagement through NED",
"private": true,
"directories": {
"doc": "doc",
"test": "tests"
},
"scripts": {
"start": "ember server",
"build": "ember build",
"test": "ember test"
},
"repository": "",
"engines": {
"node": ">= 0.10.0"
},
"author": "",
"license": "MIT",
"devDependencies": {
"bower": "^1.3.12",
"broccoli-asset-rev": "^2.0.0",
"broccoli-static-compiler": "0.2.1",
"ember-cli": "0.2.1",
"ember-cli-bootstrap-sass": "^0.2.11",
"ember-cli-content-security-policy": "0.3.0",
"ember-cli-dependency-checker": "0.0.8",
"ember-cli-document-title": "0.0.1",
"ember-cli-esnext": "0.1.1",
"ember-cli-htmlbars": "0.7.4",
"ember-cli-ic-ajax": "0.1.1",
"ember-cli-inject-live-reload": "^1.3.0",
"ember-cli-qunit": "0.3.9",
"ember-cli-sass": "^3.1.0-beta.5",
"ember-data": "git+https://github.com/emberjs/data#4c112b04bc14fa389cfa9c21420bec7e36c717da",
"ember-data-factory-guy": "1.0.2",
"ember-export-application-global": "^1.0.0",
"ember-validations": "^2.0.0-alpha.3",
"express": "^4.8.5",
"glob": "^4.0.5"
},
"dependencies": {
"ember-cli-app-version": "^0.3.3"
}
}
I want to use FactoryGuy in my Ember 1.8.1 app, but Bower freaks out every time I try to install because ember-data-factory-guy has a hard-coded dependency on Ember 1.7.0. Please allow other versions of Ember, too.
While writing acceptance tests for my application, I have noticed that handleCreate
, handleUpdate
methods are pretty indifferent to what they receive.
For example we have code:
test 'create post', ->
postData = FactoryGuy.build('post')
factoryGuyHelper().handleCreate('post', postData)
# fill form with data from "postData" and click on submit
# assert page contains data from "postData"
The problem is that we do not care what exactly has been sent to the server, we just accept anything and return post with postData
.
What do you think about adding (or changing existing) methods to handle only MATCHED requests?
$.mockjax
supports it by passing data
parameter.
$.mockjax({
url: "/posts",
data: { title: "foo" }
});
Possible API:
# will now respond only if post has title "foo"
factoryGuyHelper().handleCreate('post', { title: "foo" })
Hey,
I really am quite interested in using this library for dev/testing however in its current state I am unable to use it.
Issues:
Question:
If you are totally against strict and AMD then there is no point me spending time forking and patching.
Thanks
Davie
I want to use Factory Guy in a project, but I'd like it to have a license file first.
Looking at the package.json and bower.json files I can see the license is MIT, but I'd also like it to have a license file to reflect this.
Could someone add one?
When we will do integration with ember-cli, i think we need write some articles how we use ember-data-factory-guy in real projects. It's can help people write better tests.
@danielspaniel what do you think?
First off, thanks for writing this library. I think it will drastically clean up my tests.
I'm using handleCreate
to replace my existing sinon mock. After reading through the docs, I saw the match
option. This seems like a really cool feature, but I keep getting false positives when trying to use it.
For example:
TestHelper.handleCreate('project', {match: {name: "Not Tony"}});
I then proceed to write my test code to create an author with the name of "Tony". I would expect that to fail based on the match condition.
Upon closer inspection I saw the code inside MockCreateRequest
's calculate
method is calling tmpRecord.serialize(matchArgs)
. Looking at the ember data source, I see this for serialize
:
/*
Create a JSON representation of the record, using the serialization
strategy of the store's adapter.
`serialize` takes an optional hash as a parameter, currently
supported options are:
- `includeId`: `true` if the record's ID should be included in the
JSON representation.
@method serialize
@param {Object} options
@return {Object} an object whose values are primitive JSON values only
*/
serialize: function(options) {
return this.store.serialize(this, options);
},
So, it doesn't seem like the match args are actually going to survive beyond the call to serialize. That would explain my false positive. Am I interpreting your README correctly?
Thanks again :)
ember-data beta 16.1
ember 1.11.3
ember-data-factory-guy 1.0.7
ember-cli 0.2.3
I'm writing some tests using handleUpdate, but it keeps failing. I think it's because factory-guy returns an empty set on PUT requests.
The error message is the following:
"An adapter cannot assign a new id to a record that already has an id. <my-app@model:mymodel::ember882:1> had id: 1 and you tried to update it with null. This likely happened because your server returned data in response to a find or update that had a different id than the one you sent."
In this project I'm using ember-data-tastypie-adapter, ember 1.9.1 and ember-data beta.14. Maybe returning the id would solve, or serializing the hole object, not sure though. Maybe this specific for this adapter, or related to beta.14.
Consider the following data model:
Location = DS.Model.extend
name: DS.attr 'string'
currentFloorplan: DS.belongsTo 'floorplan', async: true
upcomingFloorplans: DS.hasMany 'floorplan', async: true
Floorplan = DS.Model.extend
name: DS.attr 'string'
location: DS.belongsTo 'location', async: true, inverse: null
A Floorplan
always belongs to a Location
, but the inverse association could be one of two different options, so we set it to null
because Ember only allows a single inverse. Unfortunately there's no clean way to deal with this situation in Factory Guy, so we end up doing this Em.run
workaround in every test that involves floorplans:
describe 'An association with multiple possible inverses', ->
it 'requires a clunky workaround', ->
location = factories.make 'location'
floorplan = factories.make 'floorplan', location: location
Em.run -> location.get('upcomingFloorplans').addObject(floorplan)
expect(location.get('upcomingFloorplans.length')).to.equal 1
In Factory Girl, this kind of thing is usually handled with callbacks that access transient attributes to execute some custom behavior. It would of course be a substantial effort to add these features to Factory Guy, so maybe there is an easier targeted solution.
Hello!
Do you think we need match only attributes that are not null?
Current code for handleCreate
is:
if (opts.match) {
var expectedRequest = {};
var record = this.getStore().createRecord(modelName, match);
expectedRequest[modelName] = record.serialize();
httpOptions.data = JSON.stringify(expectedRequest);
}
I believe it will not work if model is Post(title: 'Some title', body: 'Some body')
, handleCreate is match: {title: 'Some title'}
(let's say I don't care about body field here), it will match to title: 'Some title', body: null
so my request will not be handled.
This will fix the problem:
if (opts.match) {
var expectedRequest = {};
var record = this.getStore().createRecord(modelName, match);
expectedRequest[modelName] = record.serialize();
filteredExpectedRequest = {};
for(field in expectedRequest) {
if(expectedRequest[field] != null) {
filteredExpectedRequest[field] = expectedRequest[field];
}
}
httpOptions.data = JSON.stringify(filteredExpectedRequest);
}
I'm currently writing a integration spec for a ember-rails project where I want to test if our notfound
a.k.a 404 route is triggered when a resource is requested that does not exist.
this is what I have so far:
test('renders not-found page for nonexisting ids', function () {
expect(1);
visit('/products/1');
testHelper.handleFind('product', {id: "1"});
andThen(function () {
expectRouteToBe('not_found'); //custom helper that checks if currentPath() equals X
});
});
The problem is that I do want to mock the /products/1
endpoint BUT i want it to fail and return a 404. As far as I'm aware off this functionality isn't implemented as of this moment (but I could be wrong).
When I look at the API documentation I see that there is a .andFail
option for handleCreate()
and handleUpdate()
it would be nice to have this option for the handleFind()
helper as well.
I'm willing to create a PR for this (including specs), as long as you are interested in this functionality / use-case.
it happened again =) http://jsbin.com/wamana/edit?javascript,output
Same error as in #24
Now we have this models:
App.Progress = DS.Model.extend()
App.Step = DS.Model.extend
progress: DS.belongsTo 'progress',
inverse: null
async: true
App.Lesson = DS.Model.extend
steps: DS.hasMany 'step', async: true
I think inverse: null
might be the cause
Often a sequence function is used exactly once per factory (as the sequence is unique for an attribute), e.g. the sequence to generate a name of a customer. Those factories are not very DRY.
Example:
FactoryGuy.define('customer', {
sequences: {
name: function(num) { return "Customer" + num; },
customerNumber: function(num) { return 1000 + num; }
},
default: {
name: FactoryGuy.generate('name'),
customerNumber: FactoryGuy.generate('customerNumber')
}
});
Passing a function as a parameter to FactoryGuy.generate(...) would simplify the factories:
FactoryGuy.generate(function(num) { return "Customer" + num; })
I would have expected the following to work for hasMany
associations:
FactoryGuy.define('province');
FactoryGuy.define('country', {
'default': {
provinces: {}
}
});
Checking the implementation it looks like this feature is simply not supported. Is that right?
We override the useFixtureAdapter
call in FactoryGuyTestMixin
because it conveniently sets all fixtures to an empty array. If we don't call it, we get these errors:
Error: Error: Assertion Failed: Unable to find fixtures for model type App.ModelType)
We override the FactoryGuyTestMixin like this to fix the problem:
Ember.lookup.TestHelper = (Ember.Object.extend FactoryGuyTestMixin,
useFixtureAdapter: ->
@_super.apply(@, arguments)
FactoryGuy.resetModels(@getStore())
).create()
Is there any downside to having FactoryGuy do resetModels
when calling useFixtureAdapter
? I'm happy to do the PR if this behavior is acceptable.
Any chance we could get a patch release that incorporates 27ea2fc? The missing var
causes an error in strict mode, preventing us from running our Ember-CLI tests.
@danielspaniel could you please remove tags v4.0
and v4.1
. It leads to some troubles when using bower or other PM, they all treat v4.1
as the latest
On this line: https://github.com/danielspaniel/ember-data-factory-guy/blob/master/dist/ember-data-factory-guy.js#L221
it calls merge, but I cannot figure out why merge would be defined here on the model definition, and in fact I am getting an undefined function error on this line.
It would be nice to have FactoryGirl-style sequences.
In the meantime, I'm doing something like this:
FactoryGuy.define('user', {
default: {
name: 'Person 1',
email: '[email protected]'
},
sequence: {
name: function(n) { return 'Person ' + n },
email: function(n) { return 'person_' + n + '@example.com' }
},
});
// makeFixtureList
//
// - assumes a factory set up like this:
// FactoryGuy.define('user', {
// default: {
// name: 'Person',
// email: '[email protected]'
// },
// sequence: {
// name: function(n) { return 'Person ' + n },
// email: function(n) { return 'person_' + n + '@example.com' }
// },
// });
//
//
//
// makeFixtureList(count, model, sequence_fixture_name = 'sequence')
// e.g.
// makeFixtureList(10, 'user')
// - makes 10 users, using 'sequence' as the name generators, and 'default' to actually create the users
// - the equvalent of calling:
// store.makeFixture('user', { name: 'Person 1', email: '[email protected]' })
// store.makeFixture('user', { name: 'Person 2', email: '[email protected]' })
// ...
// store.makeFixture('user', { name: 'Person 10', email: '[email protected]' })
//
var makeFixtureList = function(count, model, sequence_fixture_name) {
var store = App.__container__.lookup('store:main'));
if (!sequence_fixture_name) sequence_fixture_name = 'sequence';
var attributes_generators = FactoryGuy.getModelInfo(model)[sequence_fixture_name];
for (var i = 1; i <= count; i++) {
var attributes = {};
for (var key in attributes_generators) {
var func = attributes_generators[key];
var text = func(i);
attributes[key] = text;
}
store.makeFixture(model, attributes);
}
}
I am having to manually include any factory file that I want to use. I can see the there is some kind of initializer in the source that is supposed to load them, but this doesn't seem to run. It ends up being commented out in my vendor.js
I can't install the newest version with bower
Have no idea what am I doing wrong here is well prepared jsbin – http://jsbin.com/wamana/12/edit
Having following models:
App.Lesson = DS.Model.extend
title: DS.attr 'string'
App.Unit = DS.Model.extend
lesson: DS.belongsTo 'lesson', async: true
And following fabrics:
FactoryGuy.define 'lesson',
default:
title: "Lesson"
FactoryGuy.define 'unit',
default:
lesson: FactoryGuy.belongsTo('lesson')
I'm trying to create unit
:
viewHelper.make 'unit'
viewHelper
it's and object created as described in docs – https://github.com/danielspaniel/ember-data-factory-guy#integration-tests
stack trace:
TypeError: Cannot read property 'typeKey' of undefined
at Ember.Object.extend.modelFor (http://builds.emberjs.com/canary/ember-data.js:11258:22)
at Ember.Object.extend.recordForId (http://builds.emberjs.com/canary/ember-data.js:10729:25)
at deserializeRecordId (http://builds.emberjs.com/canary/ember-data.js:11694:27)
at http://builds.emberjs.com/canary/ember-data.js:11672:11
at http://builds.emberjs.com/canary/ember-data.js:9458:20
at http://builds.emberjs.com/canary/ember-data.js:5295:33
at http://builds.emberjs.com/tags/v1.7.0/ember.js:14897:20
at Object.OrderedSet.forEach (http://builds.emberjs.com/tags/v1.7.0/ember.js:14739:14)
at Object.Map.forEach [as __super$forEach] (http://builds.emberjs.com/tags/v1.7.0/ember.js:14895:14)
at Object.mapForEach [as forEach] (http://builds.emberjs.com/canary/ember-data.js:5302:14)
Calling .reload()
causes weird request: GET http://localhost:7357/companies/1/tests/index.html 404 (Not Found)
.
comments?
It's a PITA to get Ember's store Object while in tests. You have to do something like:
App.__container__.lookup('store:main')
So it would be nice if FactoryGuy offered some syntactic sugar. Instead of this:
store.makeFixture('user');
maybe FactoryGuy could offer something like this:
FactoryGuy.makeFixture('user');
or even just:
makeFixture('user');
http://jsbin.com/qihin/1/edit?js,output
I'm using beta11
of ember-data.
Here are my models:
App.Progress = DS.Model
App.Unit = DS.Model.extend
lesson: DS.belongsTo 'lesson', async: true
App.Lesson = DS.Model.extend
steps: DS.hasMany 'step', async: true
progress: DS.belongsTo 'progress', { async: true, inverse: null }
App.Step = DS.Model.extend
progress: DS.belongsTo 'progress', { async: true, inverse: null }
As you see step
and lesson
both has progress
. And I use inverse: null
to indicate that I don't need other side. It's in public API actually -- http://emberjs.com/guides/models/defining-models/#toc_reflexive-relation
And here are my fabrics:
FactoryGuy.define 'progress',
default: {}
FactoryGuy.define 'step',
default:
progress: FactoryGuy.belongsTo 'progress'
FactoryGuy.define 'lesson',
default:
steps: FactoryGuy.hasMany 'step', 2
progress: FactoryGuy.belongsTo 'progress'
FactoryGuy.define 'unit',
default:
lesson: FactoryGuy.belongsTo('lesson')
Trying to create unit
leads to the same error:
TypeError: Cannot read property 'typeKey' of undefined
at Ember.Object.extend.modelFor (http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:11256:22)
at Ember.Object.extend.recordForId (http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:10727:25)
at deserializeRecordId (http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:11692:27)
at http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:11670:11
at http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:9456:20
at http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:5295:33
at http://builds.emberjs.com/tags/v1.7.0/ember.js:14897:20
at Object.OrderedSet.forEach (http://builds.emberjs.com/tags/v1.7.0/ember.js:14739:14)
at Object.Map.forEach [as __super$forEach] (http://builds.emberjs.com/tags/v1.7.0/ember.js:14895:14)
at Object.mapForEach [as forEach] (http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js:5302:14)
I have a test file with multiple test() calls. Inside two I have calls to handleCreate(). Each test run individually succeeds, but together they fail since only the first call to handleCreate() "takes" or "sticks".
https://gist.github.com/pixelterra/cd4e6d7ac3e4794bdf58
This is pretty surprising behavior to me. I would assume that only the "last" call to handleCreate() would be "active".
I suppose that I could work around this by using the match() method and tracking which data is used in each call, but this seems unnecssary and could get messy with many calls to handleCreate().
Is this the only option or am I missing something?
When using testHelper.handleCreate
in an acceptance test, I get an error that requires me to wrap it in an Em.run
call. It looks like this is because handleCreate
uses createRecord
, which can have asynchronous side effects.
i am using active model adapter and my test looks like this
import Ember from 'ember';
import startApp from '../../helpers/start-app';
import { moduleForModel, test } from 'ember-qunit';
import FactoryGuy, { make, build } from 'ember-data-factory-guy';
var application;
moduleForModel('user-notification', 'User Notification Model', {
needs: ['model:patient', 'model:payment', 'model:user'],
beforeEach: function() {
application = startApp();
},
afterEach: function() {
Ember.run(application, 'destroy');
}
});
test('practice_manager_payment_succeeded notification works correctly', function(assert) {
var store = this.store();
var user = make('user');
var patient = make('patient');
var payment = make('payment');
var messageJson = { user: user.get('id'), payment: payment.get('id'), patient: patient.get('id') };
messageJson = JSON.stringify(messageJson);
var userNotification = build('user-notification', {eventType: "practice_manager_payment_succeeded", messageJson: messageJson});
var model = this.subject(userNotification);
assert.strictEqual(model.get('message'), "Tommy Ton took a $20.00 payment from Richard Hendricks", 'User notification message is Tommy Ton took a $20.00 payment from Richard Hendricks');
});
and in my ember data user notification model, i have a computed property that gets triggered, the relevant bit of code is here
switch(this.get('eventType')) {
case "practice_manager_payment_succeeded":
debugger;
promiseHash = Ember.RSVP.hash({
user: self.store.find('user', messageJsonObject.user),
payment: self.store.find('payment', messageJsonObject.payment),
patient: self.store.find('patient', messageJsonObject.patient)
});
break;
}
the self.store.find throws
Unable to find fixtures for model type (subclass of DS.Model). If you're defining your fixtures using `Model.FIXTURES = ...`, please change it to `Model.reopenClass({ FIXTURES: ... })`.
checking the store at this point (debugger line above) shows me the relevant records that were set up using the factory guy make are available, is there any to get around this?
your example model test shows you don't use moduleForModel, is this intentional?
https://github.com/danielspaniel/ember-data-factory-guy/blob/master/tests/unit/models/user-test.js
versions
ember 1.9.1
ember-data 1.0.0-beta.16.1
ember-cli 0.2.3
I think, it's very useful, when we generate model in ember-cli create a factory file for tests.
@danielspaniel what you think?
There is such thing in ember-data as custom transforms
Basically it lets you add new data types when string
, number
and date
isn't enough.
Factory guy have some problems when you add object
data type. Example: http://jsbin.com/fajaru/3/edit
This is the line that caused problem https://github.com/danielspaniel/ember-data-factory-guy/blob/3d4728ed931a23feb42b67e8c05cb616dda47b3c/src/model_definition.js#L73
I recently came across this library, and am very interested in using it!
Are there any known issues when using it with Ember CLI? Any specific things I should know about integration?
Does anyone else have experience here?
Factory Guy currently locks Ember Data to 1.0.0-beta.12 exactly – current version is 1.0.0-beta.14.1. Any chance this constraint could be relaxed? I did a quick run of the Factory Guy test suite against the new version and had only one failure, something to do with the fixture adapter, though I'm not sure how to approach fixing that since I'm very new to Ember.
What do you think about migrating to ES6 and using Broccoli as the build chain? As that seems to be the default for all ember related projects.
If that is something you would like to have on the project I can work on a PR for that.
How handleUpdate
builds the url for mocking doesn't seem to take into account the namespace preference supplied on an adapter.
If try mocking out an update from ember-data like this testHelper.handleUpdate('album', 1, {type: 'PUT'})
it builds a url for the model /albums/1' when it should really be
/api/albums/1. I'm not really sure if this is an ember-data-factory-guy bug or something wrong with ember since it seems to be using the per adapter
buildUrl()` function which should work.
Also it seems that the default type for handleUpdate
should be PUT since that's what ember-data uses by default when you do a save() on en existing model.
test 'update playCount', ->
testHelper.handleUpdate('album', 1, {type: 'PUT'})
# really gives testHelper.stubEndpointForHttpRequest('/albums/1', "{}", {type: 'PUT'})
# should be testHelper.stubEndpointForHttpRequest('/api/albums/1', "{}", {type: 'PUT'})
visit '/album/1'
click 'button.play-album' # Generates a PUT to the server to update the album
andThen ->
equal find('#playCount').text(), "Played 1 times", "Updates the play count"
`import DS from 'ember-data'`
Album = DS.Model.extend
name: DS.attr('string')
artist: DS.attr('string')
coverImage: DS.attr('string')
year: DS.attr('date')
playCount: DS.attr('number', {defaultValue: 0})
tracks: DS.hasMany('track', { async: true })
`export default Album`
-------------------------------
`import DS from 'ember-data'`
AlbumAdapter = DS.RESTAdapter.extend
namespace: 'api'
`export default AlbumAdapter`
I'm setting up a new Ember project for integration testing with Factory Guy, and couldn't get a very simple test to work. It went like this:
testHelper.handleFindMany('location', 1, name: 'DummyLoc')
visit '/'
click 'a[href="/locations"]' # This route loads all locations and displays them
andThen ->
# Page body does not include 'DummyLoc'!
In the console I saw the mock being triggered, but no data was returned. Looking at the current code for handleFindMany
, it looks like the mock request intentionally always returns nothing? This seems very odd. The mock did return actual data in the past, but that was changed in 63aee77. The tests don't catch this because they go directly to the data store rather than hitting the mocks.
For now I am using this workaround, since handleFindQuery
does mock requests correctly:
location = testHelper.build('location', name: 'DummyLoc')
testHelper.handleFindQuery('location', null, [location])
visit '/'
click 'a[href="/locations"]' # This route loads all locations and displays them
andThen ->
# Now the page body includes 'DummyLoc'
This fix fore new ember data 1.0.beta9
a8bb74c737879dcdae5274d76b62f54607f4c81f
The examples show the id being included in the return value of toJSON() like this:
// returns a User instance that is loaded into your application's store
var user = store.makeFixture('user');
user.toJSON() // => {id: 2, name: 'Dude', style: 'normal'}
However, ember data's json serializer doesn't return the id unless {includeId: true} is used like this:
// returns a User instance that is loaded into your application's store
var user = store.makeFixture('user');
user.toJSON({includeId: true}) // => {id: 2, name: 'Dude', style: 'normal'}
So, maybe the README should be changed (I can submit a pull request), or maybe I'm just doing something wrong. Please advise.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.