Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you access an ember data store instance in an integration test?

This is for Ember 2.2.0. I want to test my component with live data from my API server using ember-data not mock data from a test helper, manual AJAX requests, or from a tool like ember-cli-mirage. Currently all I have in my test is this code:

import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';

moduleForComponent('checkbox-group', 'Integration | Component | checkbox group', {
  integration: true
});

test('it renders', function(assert) {
  this.render(hbs`{{checkbox-group}}`);
  assert.equal(this.$().text().trim(), '');
});

What I would like to do is something like this:

test('it renders', function(assert) {
  const store = getStoreFromSomewhere();
  const model = store.find('data').then(() => {
    this.render(hbs`{{checkbox-group data=model}}`);
    // Do testing on component with model from server
  });
});

The problem is I have no idea how to get the store instance, and additionally I don't know how ember does async testing.

The docs have been less than helpful :/. Could someone let me know how to get the store instance, and if that's not possible, another way to do this test with ember-data?

like image 373
m0meni Avatar asked Jan 13 '16 16:01

m0meni


2 Answers

That's more like acceptance testing than integration testing, I believe. Acceptance testing setups the whole application so that you can test that.

I believe in integration tests you're supposed to fake the models, like:

test('it renders', function(assert) {
  const modelValue = Ember.Object.create({
     prop1: value1,
     prop2: value2,
  });
  this.set('model', modelValue);
  this.render(hbs`{{checkbox-group data=model}}`);
  // Do testing on component with fake model
  });
});

With that said, And I think this I'm going to say is only valid up until Ember 2.2 (in Ember 2.3 is deprecated, I believe). You can do the following:

let store = this.container.lookup('service:store');

But, if you do this... you'll get an error when you use the store.

"Assertion Failed: You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in a run"

Which means that you need to wrap async code in an Ember.run

Ember.run(() => {
  let store = this.container.lookup('service:store');
  store.findAll('post').then((posts) => {
     //do stuff
  });
});

My two cents would be, don't use the store directly in integration tests.

like image 64
Pedro Rio Avatar answered Oct 17 '22 08:10

Pedro Rio


In a moduleForComponent spec I believe the cannonical way to do this is like so:

var store = Ember.getOwner(this).lookup("service:store");

as opposed to:

var store = this.container.lookup('service:store');

And, you can mock it like so inside of a beforeEach:

this.promise = new Ember.RSVP.Promise((resolve) => {
  var response  = anEmberObject; 
  resolve(response);
});

this.storeMock = Ember.Service.extend({
  save: ()=>{
    return this.promise;
  },
  reload: (query)=>{
    return this.promise;
  }
});


Ember.getOwner(this).register('service:store', this.storeMock);
Ember.getOwner(this).inject('component', 'store', 'service:store');
like image 3
ebrohman Avatar answered Oct 17 '22 08:10

ebrohman