ember-data-factory-guy
Version:
Factories for testing Ember applications using EmberData
407 lines (325 loc) • 11.7 kB
JavaScript
import { typeOf } from '@ember/utils';
import { assert } from '@ember/debug';
import Model from '@ember-data/model';
import FactoryGuy from '../factory-guy';
import MockUpdateRequest from './mock-update-request';
import MockCreateRequest from './mock-create-request';
import MockQueryRequest from './mock-query-request';
import MockQueryRecordRequest from './mock-query-record-request';
import MockFindRecordRequest from './mock-find-record-request';
import MockReloadRequest from './mock-reload-request';
import MockFindAllRequest from './mock-find-all-request';
import MockDeleteRequest from './mock-delete-request';
import MockAnyRequest from './mock-any-request';
import MockLinksRequest from './mock-links-request';
import RequestManager from './request-manager';
export function mock({ type = 'GET', url, responseText, status } = {}) {
assert('[ember-data-factory-guy] mock requires at least a url', url);
return new MockAnyRequest({ type, url, responseText, status });
}
export function mockLinks(model, relationshipKey) {
assert(
'[ember-data-factory-guy] mockLinks requires at least model and relationshipKey',
model,
relationshipKey
);
return new MockLinksRequest(model, relationshipKey);
}
/**
Handling ajax GET for handling finding a model
You can mock failed find by calling `fails()`
```js
// Typically you will use like:
// To return default factory 'user'
let mock = mockFindRecord('user');
let userId = mock.get('id');
// or to return custom factory built json object
let json = build('user', 'with_whacky_name', {isDude: true});
let mock = mockFindRecord('user').returns({json});
let userId = json.get('id');
// you could also make the model first and mock that find fails
let user = make('user')
let mock = mockFindRecord(user);
let userId = user.id // or mock.get('id')
// To mock failure case use method fails
mockFindRecord('user').fails();
// Then to 'find' the user
store.findRecord('user', userId);
// or in acceptance test
visit('/user'+userId);
```
@param {String} name name of the fixture ( or modelName ) to find
@param {String} trait optional traits (one or more)
@param {Object} opts optional fixture options
*/
export function mockFindRecord(...args) {
let modelName;
assert(
`[ember-data-factory-guy] mockFindRecord requires at least a model
name as first parameter`,
args.length > 0
);
if (args[0] instanceof Model) {
let model = args[0];
modelName = model.constructor.modelName;
return new MockFindRecordRequest(modelName).returns({ model });
}
modelName = args[0];
let json = FactoryGuy.build.apply(FactoryGuy, arguments);
return new MockFindRecordRequest(modelName).returns({ json });
}
/**
Handling ajax GET for reloading a record
You can mock failed find by calling fails
```js
// Typically you will make a model
let user = make('user');
// and then to handle reload, use the mockReload call to mock a reload
mockReload(user);
// to mock failure case use method fails
mockReload(user).fails();
```
@param {String} type model type like 'user' for User model, or a model instance
@param {String} id id of record to find
*/
export function mockReload(...args) {
let modelName, id;
if (args[0] instanceof Model) {
let record = args[0];
modelName = record.constructor.modelName;
id = record.id;
} else if (
typeof args[0] === 'string' &&
typeof parseInt(args[1]) === 'number'
) {
modelName = args[0];
id = args[1];
}
assert(
'[ember-data-factory-guy] mockReload arguments are a model instance or a model type name and an id',
modelName && id
);
let json = FactoryGuy.fixtureBuilder(modelName).convertForBuild(modelName, {
id: id,
});
return new MockReloadRequest(modelName).returns({ json });
}
/**
Handling ajax GET for finding all records for a type of model.
You can mock failed find by passing in success argument as false.
```js
// Pass in the parameters you would normally pass into FactoryGuy.makeList,
// like fixture name, number of fixtures to make, and optional traits,
// or fixture options
let mockFindAll = mockFindAll('user', 2, 'with_hats');
// or to return custom FactoryGuy built json object
let json = FactoryGuy.buildList('user', 'with_whacky_name', {isDude: true});
let mockFindAll = mockFindAll('user').returns({json});
store.findAll('user').then(function(users){
// 2 users, first with whacky name, second isDude
});
```
@param {String} name name of the fixture ( or model ) to find
@param {Number} number number of fixtures to create
@param {String} trait optional traits (one or more)
@param {Object} opts optional fixture options
*/
export function mockFindAll(...args) {
let modelName = args[0];
assert(
`[ember-data-factory-guy] mockFindAll requires at least a model
name as first parameter`,
args.length > 0
);
let mock = new MockFindAllRequest(modelName);
if (args.length > 1) {
let json = FactoryGuy.buildList.apply(FactoryGuy, args);
mock.returns({ json });
}
return mock;
}
/**
Handling ajax GET for finding all records for a type of model with query parameters.
```js
// Create model instances
let users = FactoryGuy.makeList('user', 2, 'with_hats');
// Pass in the array of model instances as last argument
mockQuery('user', {name:'Bob', age: 10}).returns({models: users});
store.query('user', {name:'Bob', age: 10}}).then(function(userInstances){
// userInstances will be the same of the users that were passed in
})
```
By omitting the last argument (pass in no records), this simulates a findQuery
request that returns no records
```js
// Simulate a query that returns no results
mockQuery('user', {age: 10000});
store.query('user', {age: 10000}}).then(function(userInstances){
// userInstances will be empty
})
```
@param {String} modelName name of the mode like 'user' for User model type
@param {String} queryParams the parameters that will be queried
@param {Array} array of Model records to be 'returned' by query
*/
export function mockQuery(modelName, queryParams = {}) {
assert(
'[ember-data-factory-guy] The second argument ( queryParams ) must be an object',
typeOf(queryParams) === 'object'
);
return new MockQueryRequest(modelName, queryParams);
}
/**
Handling ajax GET for finding one record for a type of model with query parameters.
```js
// Create json payload
let json = FactoryGuy.build('user');
// Pass in the json in a returns method
mockQueryRecord('user', {name:'Bob', age: 10}).returns({json});
store.query('user', {name:'Bob', age: 10}}).then(function(userInstance){
// userInstance will be created from the json payload
})
```
```js
// Create model instance
let user = FactoryGuy.make('user');
// Pass in the array of model instances in the returns method
mockQueryRecord('user', {name:'Bob', age: 10}).returns({model:user});
store.query('user', {name:'Bob', age: 10}}).then(function(userInstance){
// userInstance will be the same of the users that were passed in
})
```
By not using returns method to return anything, this simulates a
store.queryRecord request that returns no records
```js
// Simulate a store.queryRecord that returns no results
mockQueryRecord('user', {age: 10000});
store.queryRecord('user', {age: 10000}}).then(function(userInstance){
// userInstance will be empty
})
```
@param {String} modelName name of the mode like 'user' for User model type
@param {String} queryParams the parameters that will be queried
@param {Object|Model} JSON object or Model record to be 'returned' by query
*/
export function mockQueryRecord(modelName, queryParams) {
if (queryParams) {
assert(
'The second argument ( queryParams ) must be an object',
typeOf(queryParams) === 'object'
);
}
return new MockQueryRecordRequest(modelName, queryParams);
}
/**
Handling ajax POST ( create record ) for a model.
```js
mockCreate('post')
mockCreate('post').match({title: 'foo'});
mockCreate('post').match({title: 'foo', user: user});
mockCreate('post').returns({createdAt: new Date()});
mockCreate('post').match({title: 'foo'}).returns({createdAt: new Date()});
mockCreate('post').match({title: 'foo'}.fails();
```
match - attributes that must be in request json,
returns - attributes to include in response json,
fails - can include optional status and response attributes
```js
mockCreate('project').fails({
status: 422, response: {errors: {name: ['Moo bad, Bahh better']}}
});
```
Note:
1) Any attributes in match will be added to the response json automatically,
so you don't need to include them in the returns hash.
2) As long as all the match attributes are found in the record being created,
the create will succeed. In other words, there may be other attributes in the
createRecord call, but you don't have to match them all. For example:
```js
mockCreate('post').match({title: 'foo'});
store.createRecord('post', {title: 'foo', created_at: new Date()})
```
2) If you match on a belongsTo association, you don't have to include that in the
returns hash either.
@param {String} modelName name of model you're creating like 'profile' for Profile
*/
export function mockCreate(...args) {
let model, modelName;
if (args[0] instanceof Model) {
model = args[0];
modelName = model.constructor.modelName;
} else {
if (typeof args[0] === 'string') {
[modelName] = args;
}
}
assert(
`[ember-data-factory-guy] To mockUpdate pass in a model instance or a modelName`,
modelName
);
return new MockCreateRequest(modelName, { model });
}
/**
Handling ajax PUT ( update record ) for a model type. You can mock
failed update by calling 'fails' method after setting up the mock
```js
// Typically you will make a model
let user = make('user');
// and then to handle update, use the mockUpdate call to mock a update
mockUpdate(user);
or
// mockUpdate('user', user.id);
or
// just the model type
// mockUpdate('user');
// and to mock failure case use method fails
mockUpdate(user).fails();
```
@param {String} type model type like 'user' for User model, or a model instance
@param {String} id id of record to update
@param {Object} options options object
*/
export function mockUpdate(...args) {
let model, modelName, id;
if (args[0] instanceof Model) {
model = args[0];
id = model.id;
modelName = model.constructor.modelName;
} else {
if (typeof args[0] === 'string') {
[modelName, id] = args;
}
}
assert(
'[ember-data-factory-guy] To mockUpdate pass in a model instance or a modelName and an id or just a modelName',
modelName
);
return new MockUpdateRequest(modelName, { id, model });
}
/**
Handling ajax DELETE ( delete record ) for a model type. You can mock
failed delete by calling 'fails' method after setting up the mock
@param {String|Model} type|model model type like 'user' for User model or Model record
@param {String} id optional id of record to delete
*/
export function mockDelete(...args) {
let model, modelName, id;
if (args[0] instanceof Model) {
model = args[0];
id = model.id;
modelName = model.constructor.modelName;
} else if (typeof args[0] === 'string') {
[modelName, id] = args;
}
assert(
`[ember-data-factory-guy] mockDelete requires at least a model type name`,
modelName
);
return new MockDeleteRequest(modelName, { id, model });
}
/**
Returns the Pretender instance used for the mocks.
*/
export function getPretender() {
return RequestManager.getPretender();
}