Uncaught Error: Assertion Failed: calling set on destroyed object
Asked Answered
N

4

44

working in ember-cli testing. After all tests passed it returns extra two test with errors.

Uncaught Error: Assertion Failed: calling set on destroyed object Source : '../dist/assets/vendor.js:13269'

this is one unit test configuration

import Ember from "ember";
import { test,moduleFor } from 'ember-qunit';
import startApp from '../helpers/start-app';

var App;

module('An Integration test',{
    setup:function(){
        App=startApp();
    },
    teardown: function() {
        Ember.run(App, 'destroy');
    }
});
Nannettenanni answered 5/8, 2014 at 14:49 Comment(1)
For me, I had to use async/wait while reading the object before destroying itWidener
H
52

This is either because in the result of a promise or any other deferred code you do not check the destroy status of an object, or because you didn't teardown something that has been setup and interact with DOM events or anything external to the core of Ember.

I used to have this especially on some jQuery plugins which I mapped to Ember, and during the tests the plugins were destroying too slowly and I was then either not using a run loop, or not checking the destroyed status of the Ember object I was manipulating.

You can do so with:

if ( !(obj.get('isDestroyed') || obj.get('isDestroying')) ) {
  // do your destroying code setting stuff
}

Also think about destroying any jQuery plugins that might have been initialised in the code of your views (anything setup in didInsertElement should be teardown in willDestroyElement for example).

Heteroousian answered 16/9, 2014 at 12:43 Comment(5)
What exactly do you mean by "// do you destroying code setting stuff"? I have the same issue where I am calling some this.$(document).on('click', '.myEl', function() { // do something });. I notice that this click handler doesn't work when the user navigates to a different route and comes back to the route that has the above code. Note that the click handler is within a view.Va
you should not listen to events like that. If the click event is relative to the view, you have to use the eventManager property of the view instead (see emberjs.com/api/classes/Ember.View.html#toc_event-managers). Anyway, you might have listened to some jQuery events and try to call some methods (including get/set) of ember objects. If so be sure to remove the event listeners in the willDestroyElement, and if you can't, surround your event function's body with this if I wrote, so that in case the Ember object is already destroyed or is destroying, you will not have errorsHeteroousian
I did wrap my jQuery selector inside the if statement you shared. I only replaced obj with 'this' which is the Ember object. Was that the right way to do it? I still see the error.Va
@Nagarjun I would add the linked answer as another answer to this question.Ostiole
Future travelers: for a robust way to avoid this problem throughout your Ember apps, explore ember-concurrency.comDeform
P
15

Ok i struggled with similar thing. So basically when you have "this.set()" inside a promise, it might happen that the promise takes too long to resolve, and the user already clicked away from that page, in this case you are trying to set something, that is already destroyed. I found the simplest solution to be just a simple check in the beginning of the promise.

if (this.isDestroyed) {
    return;
}
this.set('...');
...

Edit: alternatively you can use Ember.trySet.

Peduncle answered 30/5, 2016 at 14:5 Comment(1)
hi..what you did for thisCalculation
H
2

The issue is related to a promise not completely resolving and another test getting run immediately after.

You should give Ember Concurrency a try.

import { task, timeout } from 'ember-concurrency';

myFunction: task(function * () {

  // do somethinng

  yield timeout(1000); // wait for x milliseconds

  // do something else

}).drop(),
Hued answered 10/7, 2018 at 17:22 Comment(0)
A
0

I had a similar issue in an integration test. To resolve, in the integration test, I waited before performing the next action.

import wait from 'ember-test-helpers/wait';
wait().then(() => {
// perform action (which previously used to cause an exception)
});
Alainaalaine answered 13/3, 2018 at 1:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.