INSIDE
Ember CLI Mirage
October 2015
@samselikoff
The Problem
1. Development
2. Testing
export default Ember.Route.extend({
model() {
return this.store.findAll('post');
}
});
The Problem
export default Ember.Route.extend({
model() {
return [
{id: 1, title: 'Rails is Omakase'},
{id: 2, title: 'Who needs JavaScript?'}
];
}
});
The Problem
export default Ember.Route.extend({
model() {
return this.store.findAll('post');
}
});
// mirage/config.js
export default function() {
this.get('/posts', () {
return [
{id: 1, title: 'Rails is Omakase'},
{id: 2, title: 'Who needs JavaScript?'}
];
});
}
Route handler
test('I can view the posts', function(assert) {
visit('/posts');
andThen(() => {
assert.equal(find('ul.posts li').length, 2));
});
});
Testing
-
FixtureAdapter
-
ED only
-
Doesn't test adapter layer
-
-
Mocks
Testing
test('I can view the posts', function(assert) {
pretender.get('/posts', () => {
let posts = [...];
return [200, {}, JSON.stringify(posts)];
});
visit('/posts');
andThen(() => {
assert.equal(find('ul.posts li').length, 2));
});
});
Testing
test('I can view the posts', function(assert) {
visit('/posts');
andThen(() => {
assert.equal(find('ul.posts li').length, 2));
});
});
// mirage/config.js
export default function() {
this.get('/posts', () {
return [
{id: 1, title: 'Rails is Omakase'},
{id: 2, title: 'Who needs JavaScript?'}
];
});
}
Testing
// mirage/config.js
export default function() {
this.get('/posts', (db, request) {
return db.posts;
});
}
test('I can view the posts', function(assert) {
server.createList('post', 2);
visit('/posts');
andThen(() => {
assert.equal(find('ul.posts li').length, 2));
});
});
Dynamic data
Testing
// mirage/factories/post.js
export default Factory.extend({
title(i) {
return `Post ${i}`;
}
});
Factories
// mirage/fixtures/posts.js
export default [
{id: 1, title: 'Rails is Omakase'},
{id: 2, title: 'Who needs JavaScript?'}
];
Fixtures
Today
Fixtures
Factories
Database
Route handler
f
{
posts: [
...
]
}
JSON
Issues
- Formatting
- Relationships
}
Formatting
// mirage/config.js
export default function() {
this.get('/posts', (db, request) {
return db.posts;
});
}
{
blog_posts: [
{id: 1, post_title: 'Title 1'},
{id: 2, post_title: 'Title 2'}
]
}
{
blog-posts: [
{id: 1, post-title: 'Title 1'},
{id: 2, post-title: 'Title 2'}
]
}
Formatting
// mirage/config.js
export default function() {
this.get('/posts', (db, request) {
return db.blogPosts;
// db.blog_posts ?
// db['blog-posts'] ?
});
}
Formatting
// mirage/factories/post.js
export default Factory.extend({
// post-title?
// post_title?
postTitle(i) {
return `Post ${i}`;
}
});
Formatting
Answer: Serializers
// mirage/config.js
export default function() {
this.get('/posts', (db, request) {
return db.blogPosts;
});
}
/*
{
blog_posts: [
{id: 1, post_title: 'Post 1'}
]
}
*/
// mirage/serializers/application.js
export default Serializer.extend({
root: true,
keyForAttribute(key) {
return camelize(key);
}
});
Relationships
// mirage/config.js
export default function() {
this.get('/posts/:id', ['post', 'comments']);
}
Assumes `comment.post_id`
/*
{
posts: [
...
],
comments: [
...
]
}
*/
Relationships
// mirage/fixtures/posts.js
export default [
{id: 1, title: 'Post 1'}
];
// mirage/fixtures/comments.js
export default [
{id: 1, title: 'Comment 1', post_id: 1},
{id: 2, title: 'Comment 2', post_id: 1}
];
Relationships
test('I can view the post and comments', function(assert) {
let post = server.create('post');
server.createList('comment', 3, {post_id: post.id});
visit(`/posts/${post.id}`);
andThen(() => {
assert.equal(find('ul.comments li').length, 3));
});
});
Relationships
Where should we store relationship information?
Relationships
Answer: ORM
// mirage/models/post.js
export default Model.extend({
comments: Mirage.hasMany()
});
// mirage/models/comment.js
export default Model.extend({
post: Mirage.belongsTo()
});
// mirage/config.js
export default function() {
this.get('/posts/:id', (schema, request) {
let id = request.params.id;
return schema.post.find(id);
});
// or, just the shorthand:
this.get('/posts/:id');
}
// mirage/seializers/post.js
export default Serializer.extend({
relationships: ['comments']
});
Relationships
Answer: ORM
// mirage/factories/post.js
export default Factory.extend({
title(i) {
return `Post ${i}`;
},
withComments: trait({
comments: hasMany()
})
});
test('I can view the post and comments', function(assert) {
server.create('post', ['withComments', 3]);
visit(`/posts/${post.id}`);
andThen(() => {
assert.equal(find('ul.comments li').length, 3));
});
});
// mirage/scenarios/default.js
export default function(server) {
let author = server.create('author');
let post = author.createPost({title: 'Rails is Omakase'});
post.createComment();
}
Relationships
Answer: ORM
// mirage/config.js
export default function() {
this.get('/posts');
this.post('/posts');
this.get('/posts/:id');
this.put('/posts/:id');
this.del('/posts/:id');
}
Tomorrow
Fixtures
Factories
Database
Route handler
f
{
posts: [
...
]
}
JSON
Schema
Serializer
Mirage Codebase
Thanks!
ember-cli-mirage.com
@samselikoff
Inside Ember CLI Mirage
By Sam Selikoff
Inside Ember CLI Mirage
- 3,908