Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Real World Fixtures

Real World Fixtures

Using http mocks during development of ember applications. Using http mocks allow you to keep the same adapters you're used to using, predict app behavior, ensure proper handling of ajax errors, and even drive the API spec for your app. They are extremely helpful for building out the front-end before moving on to implementing the API.

Chris Ball

August 14, 2014
Tweet

More Decks by Chris Ball

Other Decks in Programming

Transcript

  1. What we’ll talk about: Mock Server? HTTP Mock? Who can

    benefit Why mocks are better than fixtures Walkthrough developing a feature How to make your own ☼ ☼ ☼ ☼ ☼ ☼
  2. Tell a mock server to respond with an HTTP mock

    and you have a fake API Mock Server + HTTP Mock ☼
  3. this.server = sinon.fakeServer.create(); this.server.respondWith("GET", “/comments.json”, [200, { "Content-Type": "application/json" },

    '[{ "id": 12, "comment": "Hey there" }]’ ]); ! this.server.autoRespond = true; this.server.restore(); sinon.js
  4. var server = new Pretender(function(){ this.get('/photos', function(request){ var all =

    JSON.stringify( Object.keys(PHOTOS).map(function(k){return PHOTOS[k]}) ); return [200, {"Content-Type": "application/json"}, all] }); }); ! server.shutdown() pretender
  5. Mock Server - intercepts request and responds - ember-cli has

    one built in HTTP Mock - fake API response used by server ☼ ☼ Mock Server + HTTP Mock
  6. Keep the same adapters HTTP Mocks will allow you to

    use the same adapters as the rest of your app. ☼
  7. Why this helps “Use this as a mock response. The

    final API will look almost identical.”
  8. ☼ HTTP Mocks are better • Keep the same adapters

    • Predict app behavior • Make ajax requests • Drive the API spec • Moving to live API? Trash your stubs
  9. Venue Band Concert Ticket export default DS.Model.extend({ name: DS.attr(‘string’), address:

    DS.belongsTo(‘address’), openDate: DS.attr(‘date’), closeDate: DS.attr(‘date’) }); export default DS.Model.extend({ name: DS.attr(‘string’), members: DS.belongsTo(‘member’), }); export default DS.Model.extend({ date: DS.attr(‘date’), bands: DS.hasMany(‘band’), venue: DS.belongsTo(‘venue’) }); export default DS.Model.extend({ seat: DS.attr(‘string’), concert: DS.belongsTo(‘concert’) });
  10. # server/index.js var bodyParser = require('body-parser'); var globSync = require('glob').sync;

    var routes = globSync('./routes/**/*.js', { cwd: __dirname }).map(require); ! module.exports = function(app) { app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); ! routes.forEach(function(route) { route(app); }); }; We have a mock server!
  11. Concert HTTP Mock module.exports = function(app) { var express =

    require('express'); var concertRouter = express.Router(); concertRouter.get('/', function(req, res) { res.send({concerts:[]}); }); app.use('/concerts', concertRouter); };
  12. Concert HTTP Mock module.exports = function(app) { var express =

    require('express'); var concertRouter = express.Router(); concertRouter.get('/', function(req, res) { res.send({concerts:[]}); }); app.use('/concerts', concertRouter); };
  13. concertRouter.get(‘/:id', function(req, res) { res.send({concert: CONCERTS[req.params.id]}); }); concertRouter.post('/', function(req, res)

    { res.status(201).send({ concert: fakeConcert() }); }); concertRouter.post('/', function(req, res) { res.status(422).send({ errors: { concert: [“Those bands are lame.”] } }); });
  14. concertRouter.get(‘/:id', function(req, res) { res.send({concert: CONCERTS[req.params.id]}); }); concertRouter.post('/', function(req, res)

    { res.status(201).send({ concert: fakeConcert() }); }); concertRouter.post('/', function(req, res) { res.status(422).send({ errors: { concert: [“Those bands are lame.”] } }); });
  15. concertRouter.get(‘/:id', function(req, res) { res.send({concert: CONCERTS[req.params.id]}); }); concertRouter.post('/', function(req, res)

    { res.status(201).send({ concert: fakeConcert() }); }); concertRouter.post('/', function(req, res) { res.status(422).send({ errors: { concert: [“Those bands are lame.”] } }); });
  16. … var CONCERTS = [ { id: 1, date: new

    Date(‘2014-06-22’), band_ids: [1,2,3], venue_id: 999 }, { id: 2, date: new Date(‘2014-03-11’), band_ids: [1], venue_id: 999 } ]; ! var BANDS = [ { id: 1, name: “Bad Motha Goose” }, { id: 2, name: “Concrete Octopus” }, { id: 3, name: “Full Metal Chicken” }, ]; ! var VENUES = [ { id: 999, name: “Stubb’s”} ]; ! concertRouter.get('/', function(req, res) { res.send({ concerts: CONCERTS, bands: BANDS, venues: VENUES }); }); …
  17. … var CONCERTS = [ { id: 1, date: new

    Date(‘2014-06-22’), band_ids: [1,2,3], venue_id: 999 }, { id: 2, date: new Date(‘2014-03-11’), band_ids: [1], venue_id: 999 } ]; …
  18. … var BANDS = [ { id: 1, name: “Bad

    Motha Goose” }, { id: 2, name: “Concrete Octopus” }, { id: 3, name: “Full Metal Chicken” }, ]; …
  19. require(‘faker’); ! var fakeConcert = function() { { id: faker.Helpers.randomNumber(999),

    name: faker.Company.companyName() date: faker.Date.future(1) } };
  20. require(‘moment’); ! var fakeConcert = function() { { id: 123,

    name: “House of Blues”, date: moment.add(15, ‘days’) } };
  21. Let Ember drive the API If you’re implementing both front-end

    and back-end, wait to do the back-end code. ☼
  22. ☼ Developing a feature • Create an adapter • Add

    HTTP Mocks • Code • Let Ember drive the API • When API is ready, trash steps 1 & 2
  23. { "name": "mock-server", "description": “I’m scared of ember-cli“, "version": "0.0.1",

    "private": true, "dependencies": { "express": "4.1.x", "cors": "2.2.0" } } package.json
  24. var express = require('express'), cors = require('cors'), app = express();

    app.use(cors()); app.get('/concerts/:id', function(req, res){ res.json({concerts: CONCERTS[req.params.id]}); }); var server = app.listen(6005, function() { console.log('Listening on port %d', server.address().port); }); server.js
  25. App.ApplicationSerializer = DS.ActiveModelSerializer; ! App.Post = DS.Model.extend… App.Comment = DS.Model.extend…

    ! App.IndexRoute = Ember.Route.extend({ model: function() { var pushData = { posts: [ {id: 1, post_title: "Great post", comment_ids: [2]} ], comments: [ {id: 2, comment_body: "first"} ] }; ! this.store.pushPayload(pushData); return this.store.find('post', 1); } });
  26. App.ApplicationSerializer = DS.ActiveModelSerializer; ! App.Post = DS.Model.extend… App.Comment = DS.Model.extend…

    ! App.IndexRoute = Ember.Route.extend({ model: function() { var pushData = { posts: [ {id: 1, post_title: "Great post", comment_ids: [2]} ], comments: [ {id: 2, comment_body: "first"} ] }; ! this.store.pushPayload(pushData); return this.store.find('post', 1); } });
  27. App.ApplicationSerializer = DS.ActiveModelSerializer; ! App.Post = DS.Model.extend… App.Comment = DS.Model.extend…

    ! App.IndexRoute = Ember.Route.extend({ model: function() { var pushData = { posts: [ {id: 1, post_title: "Great post", comment_ids: [2]} ], comments: [ {id: 2, comment_body: "first"} ] }; ! this.store.pushPayload(pushData); return this.store.find('post', 1); } });
  28. App.ApplicationSerializer = DS.ActiveModelSerializer; ! App.Post = DS.Model.extend… App.Comment = DS.Model.extend…

    ! App.IndexRoute = Ember.Route.extend({ model: function() { var pushData = { posts: [ {id: 1, post_title: "Great post", comment_ids: [2]} ], comments: [ {id: 2, comment_body: "first"} ] }; ! this.store.pushPayload(pushData); return this.store.find('post', 1); } });
  29. App.ApplicationSerializer = DS.ActiveModelSerializer; ! App.Post = DS.Model.extend… App.Comment = DS.Model.extend…

    ! App.IndexRoute = Ember.Route.extend({ model: function() { var pushData = { posts: [ {id: 1, post_title: "Great post", comment_ids: [2]} ], comments: [ {id: 2, comment_body: "first"} ] }; ! this.store.pushPayload(pushData); return this.store.find('post', 1); } });
  30. Make your own Use a tiny express app - run

    it as another server ! Ember Data Alternative - pushPayload ☼ ☼
  31. What we talked about: Mock Server? HTTP Mock? Who can

    benefit Why mocks are better than fixtures Walkthrough developing a feature How to make your own ☼ ☼ ☼ ☼ ☼ ☼