Save a new record using save()


#1

ember.js version: 2.18.0

route:

export default Route.extend({

  actions: {

    createBand: function() {
      var controller = this.get('controller');
      var band = this.store.createRecord('band', controller.getProperties('name'));

      band.save().then(() => {
        controller.set('name', '');
        this.transitionTo("bands.band.songs", band);
      });
    }
  }
});

New records can be saved sound and good in dev. The problem comes out during acceptance tests:

Assertion Failed: 'band' was saved to the server, but the response does not have an id and your record does not either.

the test code:

test('Create a new band', function(assert) {

  server = new Pretender(function() {

    this.get('/bands', function() {

      var response = {
        data: [
          {
            id: 1,
            type: 'bands',
            attribute: {
              name: 'Radiohead'
            }
          }
        ]
      };

      return [200, contentType, JSON.stringify(response)];

    });

    this.post('/bands', function() {

      var response = {
        data: [
          {
            id: 2,
            type: 'bands',
            attributes: {
              name: 'Long Distance Calling'
            }
          }
        ]
      };

      return [200, contentType, JSON.stringify(response)];

    });

    this.get('/bands/2/songs', function() {
      var response = { data: [] };
      return [200, contentType, JSON.stringify(response)];
    });

  });

  visit('/bands');
  fillIn('.new-band', 'Long Distance Calling');
  click('.new-band-button');

  andThen(function() {

    assert.equal(find('.band-link').length, 2, 'All band links are rendered.');
    assert.equal(find('.band-link:last').text().trim(), 'Long Distance Calling', 'Created band appears at the end of the list.');
    assert.equal(find('.nav a.active:contains("Songs")').length, 1, 'The Songs tab is active.');

  });
});

When I was debugging, I found the following function in the ember.js framework where internalModel did not have any properties and therefore the assert() got triggered in testing mode.

updateId: function updateId(internalModel, data) {
    var oldId = internalModel.id;
    var modelName = internalModel.modelName;
    var id = coerceId(data.id);

    // ID absolutely can't be missing if the oldID is empty (missing Id in response for a new record)
    (true && !(!(id === null && oldId === null)) && Ember.assert('\'' + modelName + '\' was saved to the server, but the response does not have an id and your record does not either.', !(id === null && oldId === null)));
// code that follows omitted here
}

Any ideas?


#2

Does your pretender payload actually match your development API payload? Which serializer/adapter are you using? Usually that error means Ember Data doesn’t know how to serializer the record properly (it can’t find the ‘id’), so my guess is either your payloads aren’t formatted correctly or your serializer needs some work.

Also, as a suggestion, you could consider using ember-cli-mirage instead of Pretender. It’s a much more robust way to use Pretender essentially and can save you a lot of the legwork for defining a “fake” server for testing.


#3

I changed the mock response to the following and somehow it was fixed:

var response = {
        data: {
          id: 1,
          type: 'songs',
          attributes: {
            name: 'Killer Cars'
          }
        }
      };

I just started learning ember.js so would like to start from a simple mockup.

I tried mirage but it is too complicated for me now.

Thank you anyway