I have an atypical use case for the cypress test runner, where I need to start the server from within the cypress.
I'm doing that by defining the before:spechook in cypress plugins/index.jslike so:
module.exports = (on, config) => {
on('before:spec', async(spec) => {
// the promise will be awaited before the runner continues with the spec
return new Promise((resolve, reject) => {
startServer();
// keep checking that the url accessible, when it is: resolve(null)
while (true) {
getStatus(function(statusCode) {
if (statusCode === 200)
break
})
};
resolve(null)
I'm struggling to implement this while loop that is supposed to keep checking if the url is accessible before fulfilling the before:spec promise.
I have the following function for checking the url:
function getStatus (callback) {
const options = {
hostname: 'localhost',
port: 8080,
path: '/',
method: 'GET'
}
const req = http.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
callback(res.statusCode}
})
req.on('error', error => {
console.error("ERROR",error)
})
req.end()
};
Any help implementing that loop or other suggestions how to achieve the task of checking the url before fulfilling the before:specpromise appreciated.
Ideally your startServer function should return a promise and in the before:spec hook you simply await startServer();. Or at least should accept a callback which called when the server initialisation is complete. But lets assume that is not possible, so here is another solution for the given code:
function getStatus() {
return new Promise((resolve, reject) => {
const options = {
hostname: 'localhost',
port: 8080,
path: '/',
method: 'GET'
}
const req = http.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
resolve(res.statusCode);
})
req.on('error', error => {
console.error("ERROR", error);
reject(error);
})
req.end()
});
};
module.exports = (on, config) => {
on('before:spec', async (spec) => {
// the promise will be awaited before the runner continues with the spec
startServer();
// keep checking that the url accessible, when it is: resolve(null)
while (await getStatus() !== 200) {
await (new Promise(resolve => setTimeout(resolve, 50)));
}
});
}
Your original try with while loop had serious flaws as you can't break like that and you flooded your server with requests.
There is only one strange part in the current one, await (new Promise(resolve => setTimeout(resolve, 50))); . This is simply to prevent flooding, lets give 50ms if the service was not yet ready. If you know your service is really slower to start feel free to adjust this, but much lower values doesn't make much sense. Actually it is not even strictly necessary, as the condition in while loop ensures that only one request will be running at a time. But I felt a bit safer this way, pointless to try to server too often if it is still warming up.
Also please note that you may want to resolve(500) or omit resolve/reject in req.on('error') as I don't know if your server is immediately ready to return proper status code, it depends on the implementation of startServer.