ember integration test error. dealing with asynchronous side-effects

1.7k views Asked by At

I'm trying ember's integration testing package (http://emberjs.com/guides/testing/integration/) but I am getting this error

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 an Ember.run

I've made a JSBin to reproduce this error: http://jsbin.com/InONiLe/9, which we can see by opening up the browser's console.

I believe what's causing this error is the line data.set('isLoaded', true); in the load() method of App.Posts. (Link to code: http://jsbin.com/InONiLe/9/edit)

Now, if I wrap the data.set('isLoaded', true); line in an Ember.run(), then it will work as expected and the test will pass.

However, I am using this pattern for a lot of my models and I don't want to just wrap every .set() with an Ember.run() (transitions also trigger the same error). I also don't want to change application code for the sake of making the test work.

Is there something else I can do to fix the error?

Note: I am purposely not returning a promise in the model hook because otherwise the UI is blocked until the promise is resolved. I want the transition to the route to happen immediately so that I can display a loading spinner.

1

There are 1 answers

1
Marcio Junior On

When you use some methods, that triggers async code, like ajax, setInterval, the indexeddb api etc. You will need to delegate the resolved callbacks of theses methods to Ember.run, so ember will queue these operations in your runloop and it ensure that application is in sync. So changing your code for this is the correct way to handle this:

App.Posts = Ember.Object.create({
  load: function() {
    return new Ember.RSVP.Promise(function(resolve, reject) {      
      var data = Ember.Object.create();
      $.ajax({
        url: 'https://api.github.com/users/octocat/orgs'
      }).then(function() {
        data.set('isLoaded', true);
        Ember.run(null, resolve, data);        
      }, reject);      
    });    
  }
});

Other advise is to always use the Ember.RSVP.Promise, because is more compatible with Ember than $.Defered. $.Deferred is returned by $.ajax.

Here is an updated jsbin http://jsbin.com/InONiLe/10/edit

UPDATE

Because in your case you don't want to return a promise, so just drop it, and just return the data itself:

App.Posts = Ember.Object.create({
  load: function() {    
    var data = Ember.Object.create();    
    $.ajax({
      url: 'https://api.github.com/users/octocat/orgs'
    }).then(function() {        
      Ember.run(function() {
        data.set('isLoaded', true);
      });                
    }, function(xhr) {        
      Ember.run(function() {
        // if using some ember stuff put here
      });
    });
    return data;
  }
});

Here is the jsbin showing this working http://jsbin.com/InONiLe/17/edit

I hope it helps