1
votes

I'm trying to do a Jasmine test of ember-data (using the current master) using the DS.FixtureAdapter. I've tried dozens of variations on the below code (with and without trying to create an Application namespace). I've also gone into the ember-data source to try and see what's going on, as well as referenced the tests in ember-data itself as an example.

I've also tried variations of Person.find(1), using Ember.run blocks and Jasmine wait()'s.

Whatever I try, store.find(Person, 'test') returns a result but attempting to get one of the attributes results in null (test assertion fails). What is it I'm not seeing? Thanks for any help!

describe "a test", ->
  store = null
  Person = null

  beforeEach ->

    store = DS.Store.create
      revision: 11
      adapter: 'DS.FixtureAdapter'

    Person = DS.Model.extend
      firstName: DS.attr('string')
      lastName: DS.attr('string')
      age: DS.attr('number')

  it "works or does it", ->
    Person.FIXTURES = [{
      id: 'test'
      firstName: 'Kyle'
      lastName: 'Stevens'
      age: 30
      }]

    kyle = store.find(Person, 'test')
    expect(Em.get(kyle, 'firstName')).toEqual('Kyle')
1

1 Answers

3
votes

Whatever I try, store.find(Person, 'test') returns a result but attempting to get one of the attributes results in null (test assertion fails). What is it I'm not seeing? Thanks for any help!

This is a timing issue. When you call store.find() it runs query asynchronously and returns a model promise. That means the query is still running (or scheduled to run) when control returns to your test, resulting in a failed expectation.

This is what we love about ember, it means your app can treat kyle as if the data were present and trust that values will be updated automagically via bindings when the data becomes available.

Of course all this magic is not so great when it is preventing your test from passing. Here are some alternative approaches:

1) Register a didLoad callback

kyle = store.find(Person, 'test');
kyle.on('didLoad', function() {
  console.log('should = kyle: ', Em.get(kyle, 'firstName'));
});

2) Instead of didLoad could use more blackbox testing approach and just verify that the name is set propertly within 100 ms of having called find - of course this can lead to brittle tests Ember.run.later(this, function() { console.log('should = kyle: ', Em.get(kyle, 'firstName')); console.log('should = kim: ', Em.get(App.kim, 'firstName')); }, 100);

I believe that in a jasmine test you could wrap your setup code in a runs() method and use waitsFor to verify that the value has been set as expected:

  waitsFor(function() {
    return Em.get(kyle, 'firstName') == 'Kyle';
  }, "x to be set to 5", 100);

See this JSBIN for working (non-jasmine) example: http://jsbin.com/apurac/4/edit

See this post for tips on async testing with jasmine: http://blog.caplin.com/2012/01/17/testing-asynchronous-javascript-with-jasmine/

Also, be sure to set Ember.testing = true for all of your tests. See this SO post for detail: Is it recommended to set Ember.testing = true for unit tests?