I want to do precompiles my server-side webpack bundles before all tests. So I decide to add file 'helper.js' and put it in mocha.opt to do it.
in helper.js:
global.assert = require('assert');
before((done) => {
startWireMockApi().then(({service, port}) => {
startFrontenEndService(port)
.then(frontEndService => {
done();
})
.catch(error => done(error));
});
});
after(() => {
console.log("after all........", global.server);
});
but I don't know why I still get the error for before all hook: "Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves."
Can anyone help me to look at this? or do we have any other solution to do this?
Thanks very much!
I solve this problem by setting timeout to 30000(more than 2000).
Related
Cypress Code:
describe("/gradebook/", () => {
before(() => {
cy.login("username", "password");
cy.intercept("GET", "/api/**").as("getApi");
cy.visit("/home/");
cy.wait("#getApi");
cy.log("111");
});
after(() => {
cy.intercept("GET", "/api/**").as("getApi2");
cy.wait("#getApi2");
cy.log("333");
cy.logout();
});
it("Loads Page Title: Gradebook", () => {
cy.log("222");
});
});
The Problem:
Sometimes it throws an error undefined: undefined but it seems random.
Output Image (when it fails):
Only thing I can think of is that it's somehow logging out before the /api/gradebook/scores/ request finishes, which is why it 400s, but don't know how to fix that. It is intercepting the request, so it shouldn't be continuing to the logout until that's finished.
*Note: I found this Is there a way to check if there are any pending fetch requests? but it doesn't have any answers.
If I have the following module:
module.exports = kontinue => {
Promise.resolve({error:null})
.then(o => {
console.log('promise resolved');
// say something goes wrong here
if(true)
kontinue({error:'promise resolved but something else went wrong'});
else kontinue(o);
})
.catch(error => {
console.log('caught error');
kontinue({error:'promise rejected, or resolved but then continuation threw exception'})
});
};
And the following test:
const assert = require('assert').strict;
const target = require('./the_above_code.js');
it('should not timeout', (done) => {
target((sut) => {
console.log('continuation called');
assert.ok(false); // the test for sut.error === what I expected was failing
done();
});
});
It outputs:
promise resolved
continuation called
caught error
...
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
I realise this is because the .catch() is returning a new promise which is not resolving, but that's not what I really want during testing.
How do I test the object a promise resolves to, fail the test if necessary, have Mocha report that failure?
Perhaps there is somewhere else other than in the continuation (which never returns in the code that uses this module) that I can put the tests?
I'm sure monads can reduce the amount of boilerplate code here, but using them surely would violate Kernighan's maxim.
I am going to test backend server running with Jest.
It success sometimes, but other times it shows error like this.
So if I use --detectOpenHandles flag as suggested, It always success without showing eny error.
This is test code.
it("should be able to initialize a server (development)",async (done) => {
// Before main() is called there is no active connection:
expect(connection.readyState).toBe(0);
return main({
env: "dev",
port: PORT,
})
.then(async (server: ApolloServer) => {
// After main() got called, there is an active connection:
expect(connection.readyState).toBe(1);
await server.stop();
done();
})
});
afterAll(async () => {
await connection.close(); //connection is mongoose.connection
});
I am not sure why it fails when flag.
And it weird it sometimes success, and other times fails.
Thanks
I faced a similar issue and managed to resolve it by returning a promise in the function passed to afterAll. For example:
afterAll(() => {
return connection.close(); // connection.close() returns a promise
});
Docs for reference
Not related to the user's question, but causes the problem in the title nevertheless:
Switching from
testEnvironment: 'node', to testEnvironment: 'jsdom', in jest.config.js seemed to fix the issue.
As far as I can tell, using promises or callbacks in After hook prevents Command Queue from executing when using promises / callbacks. I'm trying to figure out why, any help or suggestions are appreciated. Closest issue I could find on github is: https://github.com/nightwatchjs/nightwatch/issues/341
which states: finding that trying to make browser calls in the after hook is too late; it appears that the session is closed before after is run. (exactly my problem). But there is no solution provided. I need to run cleanup steps after my scenarios run, and those cleanup steps need to be able to interact with browser.
https://github.com/nightwatchjs/nightwatch/wiki/Understanding-the-Command-Queue
In the snippet below, bar is never outputted. Just foo.
const { After } = require('cucumber');
const { client } = require('nightwatch-cucumber');
After(() => new Promise((resolve) => {
console.log('foo')
client.perform(() => {
console.log('bar')
});
}));
I also tried using callback approach
After((browser, done) => {
console.log('foo');
client.perform(() => {
console.log('bar');
done();
});
});
But similar to 1st example, bar is never outputted, just foo
You can instead use something like:
const moreWork = async () => {
console.log('bar');
await new Promise((resolve) => {
setTimeout(resolve, 10000);
})
}
After(() => client.perform(async () => {
console.log('foo');
moreWork();
}));
But the asynchronous nature of moreWork means that the client terminates before my work is finished, so this isn't really workin for me. You can't use an await in the perform since they are in different execution contexts.
Basically the only way to get client commands to execute in after hook is my third example, but it prevents me from using async.
The 1st and 2nd examples would be great if the command queue didn't freeze and prevent execution.
edit: I'm finding more issues on github that state the browser is not available in before / after hooks: https://github.com/nightwatchjs/nightwatch/issues/575
What are you supposed to do if you want to clean up using the browser after all features have run?
Try the following
After(async () => {
await client.perform(() => {
...
});
await moreWork();
})
When using two nested chai requests, session get lost.
chai.request(server)
.post('/api/v1/account/login')
.send({_email: 'test#test.com', _password: 'testtest'})
.end(function(err, res){
chai.request(server)
.get('/api/v1/user/me')
.end(function(err2, res2){
//here i should get the session, but its empty
res2.should.have.status(200);
done();
});
});
And i'm pretty sure that it's an error in my mocha test, because i tried it (the login and then retrieving the session) outside the test and the session is being setted.
express itself does not have any native session support. I guess you are using some session middleware such as https://github.com/expressjs/session.
Meanwhile, I guess you are using chai-http plugin to send HTTP request. In chai-http, in order to retain cookies between different HTTP requests (so that req.session can be available in express side), you need to use chai.request.agent rather than chai.
Here is a simple example for your code:
var agent = chai.request.agent(app);
agent.post('/api/v1/account/login')
.send({_email: 'test#test.com', _password: 'testtest'})
.then(function(res){
agent.get('/api/v1/user/me')
.then(function(res2){
// should get status 200, which indicates req.session existence.
res2.should.have.status(200);
done();
});
});
For chai.request.agent, you can refer to http://chaijs.com/plugins/chai-http/#retaining-cookies-with-each-request
In case anyone else comes across this issue, this approach worked for me using Mocha:
it("should...", () => {
return agent.post('/api/v1/account/login')
.send({_email: 'test#test.com', _password: 'testtest'})
.then(async res => {
const res2 = await agent.get('/api/v1/user/me')
res2.should.have.status(200);
})
.catch(error => {
throw error;
});
});