rapid prototyping and easy testing with ember cli mirage

35
Rapid prototyping and easy testing with Ember CLI Mirage

Upload: krzysztof-bialek

Post on 10-Jan-2017

40 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Rapid prototyping and easy testing with ember cli mirage

Rapid prototyping and easy testing with

Ember CLI Mirage

Page 2: Rapid prototyping and easy testing with ember cli mirage

Me• Name: Krzysztof Białek• Github:

github.com/krzysztofbialek

• Twitter: drwrum

• Company: Rebased

Page 3: Rapid prototyping and easy testing with ember cli mirage

SPA and dynamic server data

• No backend api present yet

• Backend api not yet stable

• Mocking api in acceptance testing

Page 4: Rapid prototyping and easy testing with ember cli mirage

Dealing with it - testing with sinon

let project = JSON.stringify({ project: { id: 1000, links: { devices: '/web_api/projects/1000/devices' } } });

server.respondWith('GET', '/web_api/projects/1000', [200, {"Content-Type":"application/json"}, project]);

Page 5: Rapid prototyping and easy testing with ember cli mirage

Dealing with it - testing with sinon

/* global server */import Ember from 'ember';

export default Ember.Test.registerHelper('respondGET', function(app, url, payload) {

let data = JSON.stringify(payload); server.respondWith('GET', url, [200,

{"Content-Type":"application/json"}, data]);});

respondGET('/web_api/projects/1000/devices', { devices: [ {id: 1, name: "ipad"} ]});

Page 6: Rapid prototyping and easy testing with ember cli mirage

Dealing with it - Mocking with ember cli http mocks

//server/mocks/author.jsmodule.exports = function(app) { var express = require('express'); var authorRouter = express.Router();

var AUTHORS = [ { id: 1, name: 'Bad Motha Goose' }, { id: 2, name: 'Concrete Octopus' } ];

authorRouter.get('/', function(req, res) { var ids = req.query.ids; var authors;

if (ids) { authors = authors.filter(function(b) { return ids.indexOf(b.id.toString()) > -1; }); } else { authors = authors; }

res.send({"authors": authors}); });

app.use('/authors', authorRouter);};

Page 7: Rapid prototyping and easy testing with ember cli mirage

Dealing with it - the right way

Page 8: Rapid prototyping and easy testing with ember cli mirage

What can Ember CLI Mirage do for you?

• Mocking of api in development

• Mocking endpoints in testing

• With it’s own ORM it can mimic ember-data behaviour

• Bundled into application

• wraps around pretender.js

Page 9: Rapid prototyping and easy testing with ember cli mirage

Define simple route// mirage/config.jsexport default function() { this.namespace = 'api'; this.get('/authors', () => { return { authors: [ {id: 1, name: 'Zelda'}, {id: 2, name: 'Link'}, {id: 3, name: 'Epona'}, ] }; });};

Page 10: Rapid prototyping and easy testing with ember cli mirage

Define simple routethis.get('/events', () => { let events = []; for (let i = 1; i < 1000; i++) { events.push({id: i, value: Math.random()}); };

return events;});

this.get('/users/current', () => { return { name: 'Zelda', email: '[email protected]' };});

Page 11: Rapid prototyping and easy testing with ember cli mirage

Why so verbose?// mirage/config.jsexport default function() {

this.get('/authors', () => { return { authors: [ {id: 1, name: 'Zelda'}, {id: 2, name: 'Link'}, {id: 3, name: 'Epona'}, ] }; });};

// mirage/config.jsexport default function() { this.get('/authors', (schema) => { return schema.authors.all; });};

Page 12: Rapid prototyping and easy testing with ember cli mirage

Data layer

• In memory database

• Models

• Factories

• Serializers

Page 13: Rapid prototyping and easy testing with ember cli mirage

Going flexible with models

// mirage/models/author.jsimport { Model } from 'ember-cli-mirage';

export default Model;

// and use it in the route

// mirage/config.jsexport default function() { this.get('/authors', (schema) => { return schema.authros.all; });}

Page 14: Rapid prototyping and easy testing with ember cli mirage

Going flexible with models

// app/routes/some-routeEmber.createObject('author', { name: 'Link', age: 123 })

// payload send with the request to ‘authors’ route author: { name: 'Link', age: 123 }

// mirage/config.jsthis.post('/authors', (schema, request) => { let attrs = JSON.parse(request.requestBody).author;

return schema.authors.create(attrs);});

Page 15: Rapid prototyping and easy testing with ember cli mirage

Model associations// mirage/models/author.jsimport { Model, hasMany } from 'ember-cli-mirage';

export default Model.extend({ posts: hasMany()});

// mirage/config.jsthis.del('/authors/:id', (schema, request) => { let author = schema.authors.find(request.params.id);

author.posts.delete(); author.delete();});

Page 16: Rapid prototyping and easy testing with ember cli mirage

Dynamic routes and query params

this.get('/authors/:id', (schema, request) => {let id = request.params.id;

return schema.authors.find(id);});

this.get('/authors', (schema, request) => { let someQuery = request.queryParams[‘some_query’];

return schema.authors.where({name: someQuery});});

Page 17: Rapid prototyping and easy testing with ember cli mirage

What if API is weird?

Page 18: Rapid prototyping and easy testing with ember cli mirage

// mirage/serializers/application.jsimport { Serializer } from 'ember-cli-mirage';import Ember from 'ember';

const { dasherize } = Ember.String;

export default Serializer.extend({

keyForAttribute(key) { return dasherize(key); }

});

GET /authors/1

{ author: { id: 1, 'first-name': 'Keyser', 'last-name': 'Soze', age: 145 }}

Taming API with serialiser

Page 19: Rapid prototyping and easy testing with ember cli mirage

Lets fake some data!

• Fixtures

• Factories

Page 20: Rapid prototyping and easy testing with ember cli mirage

Fixtures - quick and rigid

// /mirage/fixtures/authors.jsexport default [ {id: 1, firstName: 'Link'}, {id: 2, firstName: 'Zelda'}];

// /mirage/fixtures/blog-posts.jsexport default [ {id: 1, title: 'Lorem', authorId: 1}, {id: 2, title: 'Ipsum', authorId: 1}, {id: 3, title: 'Dolor', authorId: 2}];

// mirage/scenarios/default.jsexport default function(server) { server.loadFixtures();};

Page 21: Rapid prototyping and easy testing with ember cli mirage

But…

Page 22: Rapid prototyping and easy testing with ember cli mirage

Factories - also quick but flexible

// mirage/factories/author.jsimport { Factory } from 'ember-cli-mirage';

export default Factory.extend({ name(i) { return `Author ${i}`; }, age: 20, admin: false});

server.createList('author', 3);

{id: 1, name: "Author 1", age: 20, admin: false}{id: 2, name: "Author 2", age: 20, admin: false}{id: 3, name: "Author 3", age: 20, admin: false}

Page 23: Rapid prototyping and easy testing with ember cli mirage

Factories - making data up since… not so long ago

// mirage/factories/author.jsimport { Factory, faker } from 'ember-cli-mirage';

export default Factory.extend({ firstName() { return faker.name.firstName(); }, lastName() { return faker.name.lastName(); }, age() { // list method added by Mirage return faker.list.random(18, 20, 28, 32, 45, 60)(); },});

Page 24: Rapid prototyping and easy testing with ember cli mirage

Factories - seeding data in development

// mirage/scenarios/default.jsexport default function(server) { server.createList('blog-post', 10);

let author = server.create('author', {name: 'Zelda'}); server.createList('blog-post', 20, { author });};

Page 25: Rapid prototyping and easy testing with ember cli mirage

Factories - seeding data in tests

test('I can view the photos', assert => { server.createList('photo', 10);

visit('/');

andThen(function() { assert.equal( find('img').length, 10 ); });});

Page 26: Rapid prototyping and easy testing with ember cli mirage

Acceptance testing - overriding defaults

// mirage/factories/photo.jsimport Mirage from 'ember-cli-mirage';

export default Mirage.Factory.extend({ title(i) { // Photo 1, Photo 2 etc. return `Photo ${i}`; }});

test("I can view the photos", assert => { server.createList('photo', 10);

visit('/');

andThen(() => { assert.equal( find('img').length, 10 ); });});

Page 27: Rapid prototyping and easy testing with ember cli mirage

Acceptance testing - overriding defaults

test("I see the photo's title on a detail route", assert => { let photo = server.create('photo', {title: 'Sunset over

Hyrule'});

visit('/' + photo.id);

andThen(() => { assert.equal( find('h1:contains(Sunset over

Hyrule)').length, 1 ); });});

Page 28: Rapid prototyping and easy testing with ember cli mirage

Acceptance testing - make sure server was

calledtest("I can change the lesson's title", assert => { server.create('lesson', {title: 'My First Lesson'})

visit('/'); click('.Edit') fillIn('input', 'Updated lesson'); click('.Save');

andThen(() => { // Assert against our app's UI assert.equal( find('h1:contains(Updated lesson)').length, 1

);

// Also check that the data was "persisted" to our backend assert.equal( server.db.lessons[0].title, 'Updated

lesson'); });});

Page 29: Rapid prototyping and easy testing with ember cli mirage

Acceptance testing - testing errors

test('the user sees an error if the save attempt fails', function(assert) {

server.post('/questions', {errors: ['There was an error']}, 500);

visit('/'); click('.new'); fillIn('input', 'New question'); click('.save');

andThen(() => { assert.equals(find('p:contains(There was an

error)').length, 1); });});

Page 30: Rapid prototyping and easy testing with ember cli mirage

That could be enough to start…

Page 31: Rapid prototyping and easy testing with ember cli mirage
Page 32: Rapid prototyping and easy testing with ember cli mirage

Shorthands // Expanded this.get('/contacts', ({ contacts }) => { return contacts.all(); // users in the second case});

// Shorthand this.get('/contacts'); // finds type by singularizing urlthis.get('/contacts', 'users'); // optionally specify the collection as second

param

// Expanded this.del('/contacts/:id', ({ contacts }, request) => { let id = request.params.id; let contact = contacts.find(id);

contact.addresses.destroy(); contact.destroy();});

// Shorthand this.del('/contacts/:id', ['contact', 'addresses']);

Page 33: Rapid prototyping and easy testing with ember cli mirage

Easy peasy crud

// Resource this.resource('contacts'); // available in 0.2.2+

// Equivalent shorthands this.get('/contacts');this.get('/contacts/:id');this.post('/contacts');this.put('/contacts/:id');this.patch('/contacts/:id');this.del('/contacts/:id');

Page 34: Rapid prototyping and easy testing with ember cli mirage

Mix real api with fake endpoints

this.passthrough('/addresses', '/contacts');this.passthrough('/something');this.passthrough('/else');

// just some verbsthis.passthrough('/addresses', ['post']);this.passthrough('/contacts', '/photos', ['get']);

// other-originthis.passthrough('http://api.foo.bar/**');this.passthrough('http://api.twitter.com/v1/cards/**');

Page 35: Rapid prototyping and easy testing with ember cli mirage

Happy faking!!!

• http://www.ember-cli-mirage.com

• https://github.com/pretenderjs/pretender