Skip to content

Instantly share code, notes, and snippets.

@abuiles
Created February 24, 2016 17:01
Show Gist options
  • Save abuiles/4a672ccc8b5371c09ea7 to your computer and use it in GitHub Desktop.
Save abuiles/4a672ccc8b5371c09ea7 to your computer and use it in GitHub Desktop.
Mirage TILS

Version: ^0.2.0-beta.5

How can I check the serialized version of a model?

server.get('api/employee's, function(schema, request) {
  employee = schema.employee.find(1);
  this.serializerOrRegistry.serialize(employee, request);

  return foo;
});
What is this useful for?

As I was getting started with mirage, this was super helpful for debugging, but also, at this point I’m not sure how to include meta-data in the response, and one of our endpoints returns pagination in the meta key. What I did was generate the payload and then add meta manually.

this.get('api/employees', function(schema, request) {
  let employees = schema.employee.all();
  let response =  this.serializerOrRegistry.serialize(employees, request);

  response.meta = {
    total: employees.length,
    totalPages: 1
  };


  return new Mirage.Response(200, {}, response);
});

How do I make assertions in a request and build a new model with the serializer?

As I was moving away from a mix of Factory Guy and Pretender, we had a bunch of request where we were matching that it was “done” and then returning a new model.

miragejs/ember-cli-mirage#556

// import the following from mirage

import BaseShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/base';

server.post('/api/employees', function(schema, request) {
  assert.ok(true, 'did post');

  let handler = new BaseShorthandRouteHandler(schema, this.serializerOrRegistry);

  return schema.employee.create(handler._getAttrsForRequest(request, 'employee'));
})

polymorphic models

Let’s say you have the models “car” and “motorcycle” which inherit from “vehicle” and you want to return all available “vehicles” through the end-point `/api/vehicles`. The following can help you.

this.get('/api/vehicles', function(schema, request) {
  // fetch all the cars, it returns a mirage collection
  let collection = schema.car.all();

  // push all the motorcycles into the mirage collection
  collection.push(...schema.motorcycle.all());

  // Make sure there is a serializer for vehicle `ember g mirage-serializer vehicle`
  // since we are using JSONAPI, it will use the model.type to create the
  // final response.
  //
  // This will probably work only with JSONAPI :P

  collection.modelName = 'vehicle';

  return collection;
});

How to return a 204?

server.delete('/api/employees/:id', function() {
  return new Mirage.Response(204);
});

Stop settings expectations inside requests.

Sam recommends to let mirage shortcut do their job and then match against mirage’s DB. Let’s see an example.

before

andThen(function(){
  server.patch('/api/employee/1', function(schema, request) {
    var data = JSON.parse(request.requestBody).data;
    assert.equal(data.attributes.name, 'Sam', 'name is Sam');

    return new Mirage.Response(204);
  });
});
click('thing that fires post');
after

The snippet above is removed letting mirage takes care of the patch via shortcuts.

andThen(function(){
  assert.equal(
    server.schema.employee.find(1).name,
    'tom',
    'Name is Tom'
  );
});
click('thing that fires put');
andThen(function(){
  assert.equal(
    server.schema.employee.find(1).name,
    'Sam',
    'Name was updated to Sam'
  );
});

Now we check against mirage’s db that it was updated.

There are scenarios where we might still need to intercept the request and do something inside of it, but for most of the cases we can let mirage do its magic.

Stop matching against your “API format”

Let’s say we still want to have assertions inside requests. It is common to see tests that depend on the API format, this can be really problematic if we decide to change the format of our API. suppose we are using AMS and have something like the following:

server.post('/api/employees', function(schema, request){
  var employee = JSON.parse(request.requestBody).employee;

  assert.equal(employee.name, 'Sam Selikoff', 'foo woot buu');
  assert.equal(employee.phone_number, '+14159353143', 'number is persisted');

  // ...
});

And then decide to move to JSON API.

server.post('/api/employees', function(schema, request){
  var employee = JSON.parse(request.requestBody).data;

  assert.equal(employee.attributes.name, 'Sam Selikoff', 'foo woot buu');
  assert.equal(employee.attributes['phone-number'], '+14159353143', 'number is persisted');

  // ...
});

But then realized everyone have been wrong and SOAP was actually what we needed. If you have only 1 tests then this is not a problem but if you have a lot of tests updating this is not a fun task.

Since mirage works with serializers, we can use that instead and then stop worrying about the format of the payload. The following can be used to achieve the same as the previous test, but this time is transparent to us if we are using JSON API, AMS or SOAP.

import BaseShorthandRouteHandler from 'ember-cli-mirage/route-handlers/shorthands/base';

server.post('/api/employees', function(schema, request){
  let handler = new BaseShorthandRouteHandler(schema, this.serializerOrRegistry);
  let employee = handler._getAttrsForRequest(request, 'employee');

  // employee has been normalized to mirage's DB format.

  assert.equal(employee.name, 'Sam Selikoff', 'foo woot buu');
  assert.equal(employee.phoneNumber, '+14159353143', 'number is persisted');

  // ...
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment