I am currently learning how to test Ember apps and I have an issue I cannot resolve for myself.
The problem is that when the test I wrote runs, it never ends. It just keeps running, like it has a promise that never resolves or something? This is the test:
test("User signs in and is redirected to his dashboard", function() {
visit('/');
fillIn('input#identification', 'test');
fillIn('input#password', 'test');
click('input#login');
andThen(function() {
ok(currentRouteName() === 'dashboard', 'redirected to dashboard');
});
});
The andThen function is never triggered, it seems like the promise of click never resolves. I made the routes and templates etc. so minimalistic as possible to avoid other interfering code.
Also I am using ember-simple-auth, maybe that this could explain any behaviour?
This is a screenshot of the problem:
Related
I'm having problem to make my Action resolve the promise.
I've read what looks like the most relevant posts.
Returning Promises from Vuex actions
I want to know when my action is finished, then my component can start doing other stuff.
The problem is, the Action never returns the Promise.
myComponent.vue
methods: {
loadUrls() {
this.$store.dispatch('getUrls').then(result => {
console.log("getUrls result", result)
})
},
vuex.js
actions: {
getUrls() {
console.log("getUrls")
return new Promise((resolve) => {
setTimeout(() => {
console.log("setTimeout in")
resolve("Resolved!")
}, 1000)
})
},
That's my console log:
I've used the "setTimeout" to make as simple as possible the problem. In real life I call an API.
I do not need to rely on the result of this promise. I'm aware about it. I use Vuex as the source of truth, but I need to track when the event in completed.
Thanks in advance =)
SOLVED! It worked after I delete my dist Folder, close VSCode and open a new Chrome instance using the new build local host URL.
Thanks #User-28. I saw his shared code and realised nothing was wrong with my code. Then I start looking at my environment.
My very first code didn't have Promise Resolve in the action. I compiled and I was testing it.
Then I found Returning Promises from Vuex actions which explained how to use the Promise in it. I compiled and I was TRYING to test it. Never success. Somehow the code without the Promise was always there. After clean up Dist folder, Close VS code and use a new Chrome instance, the new code was in place and worked.
I'm still don't know the actual problem, but at least it can keep going forward now.
I have a reasonably special use-case:
I have an input field which issues a search when the user has stopped typing for 500ms. This is developed as a reusable add-on.
I would like to write an acceptance test for this but I cannot make the tests pass properly. The first passes, the second doesn't.
Now, the Ember runloop has a nice description but it's behaviour is really "something else".
This is my helper to timeout the runloop:
import Ember from 'ember';
export default Ember.Test.registerAsyncHelper('pauseFor', function (time) {
return Ember.Test.promise(function (resolve) {
Ember.run.later(resolve, time);
});
});
And this is how I use it
it('should do something after 500ms', function () {
visit('/');
fillIn('.search-input', 'a');
pauseFor(500);
andThen(function () {
// do my assertions/expectations here...
});
});
This is the error I get:
The weird thing is that I have 2 test cases and the first passes happily.
I guess my question is:
How to do this properly? What am I missing here or what am I doing wrong? How can I just simply timeout the test case?
Thanks for the halp!
My app requires users to sign in by submitting a form. I wonder what is the best place to do it in my tests. I came up with some options:
sign-in in beforeEach block (and signout in afterEach block)
sign-in in beforeAll block of every describe (and signout in the last afterAll of every describe)
describe('APP', function () {
describe('FEATURE 1', function () {
beforeAll(function () {
//sign in
});
afterAll(function () {
//sign out
});
//...
});
});
sign-in once for the whole test run in beforeAll of main describe
describe('MY APP', function () {
beforeAll(function () {
//sign in
});
describe('my feature 1', function () {
//...
});
});
Number 1 is the slowest, Number 2 is faster and Number 3 is the fastest, but you are required to have a single entry point for your test runner - not ideal. So which do think is better and why?
It's a matter of different things.
The best practice is closing your browser after EACH test case and it will definitely be the slowest way to run your test. But you will achieve the most clear and the most fair tests. Sure, you can use selenium grid and paralleling your tests and this will be definitely not so long as you expect.
Sometimes you have an application, which logic is not so much dependent on each other and you will probably want to run UI tests into the pre-commit hook for not breaking anything into the branch. Then the approach n.3 will be not so bad (the only thing you should know is what cookies, session vars and other artifacts you should delete in browser after each test).
Anyway that's up to you, but a common and the really BEST practice is opening a clear new browser on every test.
Since start(), stop() will be removed in Qunit 2.0, what is the alternative for async setups and teardowns via the beforeEach, afterEach methods? For instance, if I want the beforeEach to wait for a promise to be finished?
QUnit basically wants people to stop using the global methods (not just start() and stop(), but also test(), expect(), etc). So, as of version 1.16.0, you should always use either the global namespace (QUnit) or the assert API argument passed into the test() functions. This includes the new async control:
QUnit.test( "testing async action", function( assert ) { // <-- note the `assert` argument here
var done = assert.async(); // tell QUnit we're doing async actions and
// hold onto the function it returns for later
setTimeout(function() { // do some async stuff
assert.ok( true, "This happened 100 ms later!" );
done(); // using the function returned from `assert.async()` we
// tell QUnit we're don with async actions
}, 100);
});
If you are familiar with the old start() and stop() way of doing things, you should see that this is extremely similar, but more compartmentalized and extensible.
Because the async() method call is on the assert argument into the test, it cannot be used in the beforeEach() function. If you have an example of how you were doing that before, please post it and we can try to figure out how to git it into the new way.
UPDATE
My mistake previously, the assert object is being passed into the beforeEach and afterEach callbacks on modules, so you should be able to do the same logic that you would do for a test:
QUnit.module('set of tests', {
beforeEach: function(assert) {
var done = assert.async();
doSomethingAsync(function() {
done(); // tell QUnit you're good to go.
});
}
});
(tested in QUnit 1.17.1)
Seeing that nobody has answered the beforeEach/afterEach part: a test suite is supposed to run as soon as the page loads. When that is not immediately possible, then resort to configuring QUnit:
QUnit.config.autostart = false;
and continue with setting up your test suite (initializing tests, feeding them to QUnit, asynchronously waiting for some components to load, be it AJAX or anything else), your site, and finally, when it's ready, just run:
QUnit.start();
QUnit's docsite has it covered.
Ember Qunit, has once exists beforeEach/setup, afterEach/teardown co-exist for a little while.
See PR: https://github.com/emberjs/ember-qunit/pull/125
I'm trying to connect to SoundCloud using CasperJS. What is interesting is once you signed in and rerun the login feature later, the previous login is still active. Before going any further, here is the code:
casper.thenOpen('https://soundcloud.com/', function() {
casper.click('.header__login');
popup = /soundcloud\.com\/connect/;
casper.waitForPopup(popup, function() {
casper.withPopup(popup, function() {
selectors = {
'#username': username,
'#password': password
};
casper.fillSelectors('form.log-in', selectors, false);
casper.click('#authorize');
});
});
});
If you run this code at least twice, you should see the following error appears:
CasperError: Cannot dispatch mousedown event on nonexistent selector: .header__login
If you analyse the logs you will see that the second time, you were redirected to https://soundcloud.com/stream meaning that you were already logged in.
I did some research to clear environments between each test but it seems that the following lines don't solve the problem.
phantom.clearCookies()
casper.clear()
localStorage.clear()
sessionStorage.clear()
Technically, I'm really interested about understanding what is happening here. Maybe SoundCloud built a system to also store some variables server-side. In this case, I would have to log out before login. But my question is how can I perfectly isolate and clear everything between each test? Does someone know how to make the environment unsigned between each test?
To clear server-side session cache, calling: phantom.clearCookies(); did the trick for me. This cleared my session between test files.
Example here:
casper.test.begin("Test", {
test: function(test) {
casper.start(
"http://example.com",
function() {
... //Some testing here
}
);
casper.run(function() {
test.done();
});
},
tearDown: function(test) {
phantom.clearCookies();
}
});
If you're still having issues, check the way you are executing your tests.
Where did you call casper.clear() ?
I think you have to call it immediately after you have opened a page like:
casper.start('http://www.google.fr/', function() {
this.clear(); // javascript execution in this page has been stopped
//rest of code
});
From the doc: Clears the current page execution environment context. Useful to avoid having previously loaded DOM contents being still active.