Ember Mirage: route answered only if debugger is ran - ember.js

I'm facing a weird issue with Ember mirage. I try to use it inside an integration test.
The code looks like this:
moduleForComponent('editors/steps/call-handler', 'Integration | Component | editors/steps/call handler', {
integration: true,
beforeEach: function () {
startApp();
this.server = startMirage();
...
},
afterEach: function () {
this.server.shutdown();
}
});
test('...', function (assert) {
...
this.server.post('/projects/12/actionwords/1/switch/', () => {
assert.ok(true, "switch route is called");
return {
... some JSON data
}
});
this.render(hbs`{{editors/steps/call-handler
...
}}`);
... and then some manipulation of the component
});
Now the test fails when I run it this way. The weird part is, if I place a debugger just before rendering the component, the test will pass.
I guess there are some timeout issues sooner or later that the debugger hides. Usually, I would only render the component in a callback to ensure the route has been correctly setup but this.server.post returns nothing not has any callbacks (except if I missed something in the doc).
I also tried setting the timing option (just in case) but it doesn't change anything (as expected).
I also tried to add an homemade sleep function to wait one second without the debugger and then the tests work fine. Of course if I can have a clean way to get them working, I'd prefer ;)
Did anyone face the same kind of issues and found a way to solve it ?
Best regards,
Vincent

Related

How to remove these deprecation on console on ember^2.0

while refreshing my site i am always getting some deprecation like this on console :
A property of <Ember.OutletView:ember666> was modified inside the didUpdate hook. You should never change properties on components, services or models during didUpdate because it causes significant performance degradation. [deprecation id: ember-views.dispatching-modify-property]
How to remove these deprecation on console on ember^2.0
I am not using Ember CLI.
Usually it means, that you need to do the work inside the didReceiveAttrs method, rather than the didUpdate. However, it you must have it in didUpdate, you can do something like this:
didUpdate() {
Ember.run.scheduleOnce('afterRender', this, => {
// some code
});
}
However it most likely will do some rendering twice (however it already does it twice - hence the deprecation).
Romans solution worked well for me, except for some syntax problems. I needed to set a default value to a child component. Heres the code:
initDefValue: function() {
const valEmpty = Ember.isEmpty(this.get("value"));
if (valEmpty) {
Ember.run.scheduleOnce('afterRender', this, () => {
this.sendAction("initValue", this);
});
}
}.on("didReceiveAttrs"),

Ember Integration Test Doesn't See the DOM

import Ember from 'ember';
import startApp from '../../helpers/start-app';
var App;
module('Integration | Authentication | Abilities', {
integration: true,
setup() {
App = startApp();
},
teardown() {
Ember.run(App, 'destroy');
}
});
test('Only SuperUsers, Researchers and AccountHolders can see messages', function(assert) {
visit('/');
assert.equal(find('div').text(), 'fsfsfd');
});
This is an integration test I'm trying to get working so I can test basic user interaction in our ember-cli app. The problem is that this simple test does only returns empty strings whenever I search the DOM. It is not hitting an unauthorized page or anything it's just returning nothing from any testHelpers. currentURL, currentPath return undefined.
Am I missing something absolutely fundamental in my understanding of how integration tests work?
I'm trying to test how ember-can gives and denies permissions to users based on their title. However, I may as well just be testing whether or not the logo shows up in the right corner because I can't see anything on the page at the moment.
I think what you're missing is that tests are asynchronous. Transitions involve promises (typically loading models) so you need to wait for the visit to complete. You can use the andThen helper:
test('Only SuperUsers, Researchers and AccountHolders can see messages', function(assert) {
visit('/');
andThen(function() {
assert.equal(find('div').text(), 'fsfsfd');
});
});
Here's more info in the guides
I'm posting because it turns out the problem was the way our website had been set up with a rootURL. I had to put this line inside our startApp.js file: setResolver(Ember.DefaultResolver.create({ namespace: "/cli/ea/" }));
It looks like the resolver was taking me to localhost:4201/ which is not actually going to be used because we are proxying from rails (which is localhost:3000). Therefore, nothing was coming back from any DOM interaction because there was no route and no template set. currentURL and other helpers returning undefined I guess was the only piece that was unusual in hindsight.

Can't figure out how to wrap function in Ember run loop

I have a component that integrates 2 third-party libraries, imagesLoaded and Isotope.
I get conflicting test failures when running tests in the browser and cli mode. The error is:
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 a run
or
TypeError: 'undefined' is not an object (evaluating 'self.$().isotope')
When I try to wrap callbacks in an ember run loop, they pass in cli-mode, but then fail in browser mode. I can't seem to find the right combination. The issue seems to happen in the callback of imagesLoaded, as if I remove that plugin, it seems to pass fine.
I've tried multiple combinations, but here is my latest code. If anyone has insight on how to properly use the run loop in this component, that would be helpful.
handleLoad: function() {
let self = this;
Ember.run.scheduleOnce('afterRender', this, function(){
self.$().imagesLoaded( function() {
Ember.run(function() {
self.$().isotope({itemSelector: ".card-container"});
self.$().isotope('shuffle');
});
}); // imagesLoaded
}); // Ember.run
}.on('didInsertElement')
You'll have to wrap your existing code in a
Ember.run(function () {
// Ember.run.scheduleOnce('afterRender....
});
as this tells Ember where the run loop starts and ends - in production/development this is done for you by Ember itself, but in testing you have to wrap it.
As an alternative you can start & end a run loop manually by calling it explicitly (see the API Docs):
Ember.run.begin() // <-- tell Ember that your starting a run loop
//Ember.run.scheduleOnce('afterRender', ...
//more ember run loops here
Ember.run.end(); // <-- tell Ember that the run loop ends here

Uncaught Error: Assertion Failed: calling set on destroyed object

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');
}
});
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).
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.
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(),
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)
});

Errors from debounced function calls in testing ember application

I'm testing an relatively large Ember application (http://wheelmap.org/map) with QUnit and having problems with debounced calls e.g. changing the url to have a permalink of a map view inside the app or doing a manual AJAX request while testing.
I followed the documentation at http://emberjs.com/guides/testing/integration/
Now when I reset the application state by calling App.reset() in the module setup it resets all bindings, etc. to variables and dependant controllers.
module('Map', {
setup: function() {
App.reset();
}
});
This seems to be good to have a clean working environment, but leads to errors where variables are accessiable by Ember.set and Ember.get e.g. this.get('controllers.toolbar'):
Cannot call method 'set' of null
So the first test allways runs great, but further tests break because of debounced function calls from the first test. So what I think I have to do is stop this debounced calls somehow.
Other options would be checking if all needed variables are set in this function calls. But this seems to be cumbersome when adding conditions only for testing.
What do you think?
Thank you in advance!
I found the answer by searching through the RunLoop source files:
Ember.run.cancelTimers()
It's not part of the documentation. Maybe a problem of poor documentation or not beeing part of the public API.
Now I just call it in the module test teardown function:
module('Map', {
setup: function() {
// ...
},
teardown: function() {
Ember.run.cancelTimers()
}
});
We ran into a similar problem and decided to disable debounce during testing.
You can check if in testing mode using if(Ember.testing){...}.