Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when an App is teared down with App.destroy #104

Closed
soeffing opened this issue Jul 1, 2015 · 9 comments
Closed

Error when an App is teared down with App.destroy #104

soeffing opened this issue Jul 1, 2015 · 9 comments

Comments

@soeffing
Copy link

soeffing commented Jul 1, 2015

Hi,

first of all, your library is awesome. I really enjoy it!

However, I have one problem. When I destroy an app after a test, I get this error:

Error: Assertion Failed: You can only unload a record which is not inFlight

Here is my code:

moduleFor('controller:awards', 'AwardsController', {
  needs: ['controller:application', 'controller:ads', 'component:flash-message'],

  setup: function () {
     Ember.run(function () {
      App = startApp();
      TestHelper.setup();
    });
  },

  teardown: function() {
    Ember.run(function () {
      TestHelper.teardown();
      // TODO: check why we get an error when we uncomment this line!
      App.destroy();
    });
  }
});

test('#selectAward assigns an ad to an award', function(assert) {
  var self = this;
  Ember.run(function(){
    var controller = self.subject();
    var award = make('award', 'pending');
    var ad = make('ad');
    TestHelper.handleUpdate(award);
    assert.equal(award.get('ad').get('id'), undefined);
    controller.send('selectAward', award, ad);
    assert.equal(award.get('ad').get('id'), '1');
  });
});

So the test run fine, when I comment the App.destroy statement. But when I run it (which I should) I get that error. I think the inFlight states gets assigned when a record is saved/commited to the backend but the server never responds (not with success nor failure).

Am I doing smth wrong or is this a bug?

Thanks

@danielspaniel
Copy link
Collaborator

@soeffing, Well, I think you forgot setup your test with async helper, like this:

test('#selectAward assigns an ad to an award', function(assert) {
  var done = assert.async();
  var self = this;
  Ember.run(function(){
    var controller = self.subject();
    var award = make('award', 'pending');
    var ad = make('ad');
    TestHelper.handleUpdate(award);
    assert.equal(award.get('ad').get('id'), undefined);
    controller.send('selectAward', award, ad);
    assert.equal(award.get('ad').get('id'), '1');
    done();
  });
});

Try that and let me know if that works.

What is happening is that your save method is called ( in the controller or wherever ) .. and then you finish test and destroy the model ( while its still inflight ) because you forgot to slow down and wait for save to finish ( which is what the done() ) part does.

@danielspaniel
Copy link
Collaborator

You could also clean it up a touch like this ( just for fun ):

test('#selectAward assigns an ad to an award', function(assert) {
  var done = assert.async();
  var self = this;
  Ember.run(function(){
    var controller = self.subject();
    var award = make('award', 'pending');
    var ad = make('ad');
    TestHelper.handleUpdate(award);
    assert.equal(award.get('ad.id'), undefined);
    controller.send('selectAward', award, ad);
    assert.equal(award.get('ad.id'), ad.id);
    done();
  });
});

and then alittle more:

test('#selectAward assigns an ad to an award', function(assert) {
  var done = assert.async();
  var self = this;
  Ember.run(function(){
    var controller = self.subject();
    var award = make('award', 'pending');
    var ad = make('ad');
    TestHelper.handleUpdate(award);
    assert.equal(award.get('ad'), undefined);
    controller.send('selectAward', award, ad);
    assert.equal(award.get('ad'), ad);
    done();
  });
});

@danielspaniel
Copy link
Collaborator

@soeffing, did you fall asleep on me? Can you let me know if this fixes it? I will close in a day or two if I don't hear back.

@soeffing
Copy link
Author

soeffing commented Jul 5, 2015

That fixed the issue. Sorry for replying to late, I got caught up in another project. Thank you very much @danielspaniel !

@soeffing soeffing closed this as completed Jul 5, 2015
@OpakAlex
Copy link
Contributor

@danielspaniel hello!

I have same problem. My component test looks like here:

import Ember from 'ember';
import hbs from 'htmlbars-inline-precompile';
import { moduleForComponent, test } from 'ember-qunit';
import instanceInitializer from 'intuo-ember/instance-initializers/ember-intl';
import FactoryGuy, {manualSetup, make, build } from 'ember-data-factory-guy';
import TestHelper from 'ember-data-factory-guy/factory-guy-test-helper';

moduleForComponent('x-add-media', 'Integration | Component | x-add-media', {
  integration: true,
  setup() {
    instanceInitializer.initialize(this);
    const intl = this.container.lookup('service:intl');
    intl.setLocale('en-us');
    manualSetup(this.container);
  }
});

test('#createMultipleChoice', function(assert){
  var done = assert.async();
  Ember.run(() => {
    let model = make('quiz', {questions: [], bucket: make('bucket')});
    this.set('model', model);
    this.render(hbs`{{x-add-question model=model}}`);
    TestHelper.handleCreate('question').andReturn({id: 11});
    this.$('.switch-option.int-multiple-choice-question').click();
    assert.equal(this.get('model.questions').toArray().length, 1);
    done();
  });
});

I see in console: ✘ Promise rejected after #createMultipleChoice: Assertion Failed: You can only unload a record which is not inFlight. <(subclass of DS.Model):ember1295:null>
http://localhost:7357/assets/vendor.js:15366

@OpakAlex OpakAlex reopened this Feb 22, 2016
@danielspaniel
Copy link
Collaborator

@OpakAlex .. This is a pretty funny example, because it is a bit of an abuse of component integration tests. Now I am all for doing whacky things, but maybe in this case you could avoid using the handleCreate and pass an action handler into that component:

 this.render(hbs`{{x-add-question model=model createQuestion=(action "createQuizQuestion")}}`);

and the just stub that action to show it was called?

seems like a way to avoid this issue, because I not sure how to fix it!!??

Also, not sure how these component tests handle asynchrony, whereas in an acceptance test this might work out better ??

@max-konin
Copy link

Hello

I have same problem too. But with ember-mocha

`import { describeModule, it } from 'ember-mocha'`
`import { describe } from 'mocha'`
`import { make, mockCreate} from 'ember-data-factory-guy'`
`import startApp from 'site/tests/helpers/start-app'`

describeModule "controller:contact-us", "ContactUsController", {
  integration: true
}, ->
  beforeEach ->
    Ember.run => @app = startApp()

  afterEach ->
    Ember.run @app, 'destroy'

  describe 'action createInquiry', ->
    it 'creates a new inquire', (done) ->
      Ember.run =>
        inquiry = make 'inquiry'
        controller = @subject()
        controller.set 'model', inquiry

        mockCreate('inquiry').returns {id: 1}
        controller.send('createInquiry')
        expect(controller.get('model.id')).to.eq '1'
        done()

ember-data-factory-guy: 2.8.0
ember-data: 2.4
ember-mocha: 0.8.11

@danielspaniel
Copy link
Collaborator

For component tests I use the wait helper
emberjs/guides#909
Only thing is, not sure it works in mocha .. have only used in ember-qunit tests .. but you should try it.
also in controller unit test like this you should NOT start the app ( waste of time ) .. use the manualSetup method from factory guy .. and therefore you don't need afterEach to destroy the app ( more waste of time )

@max-konin
Copy link

use of the wait helper has helped me. tnx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants