The server is working (tested with postman). The code also works if I start the server and I delete the beforeAll and afterAll handlers. The console output is:
App listening on port 3200!
after server start
I don't understand where is the problem.
import request from 'request';
import { start, stop } from '../src/server';
describe('A suite', function () {
beforeAll(async () => {
await start();
});
afterAll(async () => {
await stop();
});
it('server test', async () => {
const data = { tableName: 'supply' };
console.log('after server start');
const response = await new Promise((resolve, reject) => {
request.post({
url: 'http://localhost:3200/getTable',
json: data
}, (error, response, body) => {
if (error) {
reject(body);
} else {
resolve(body);
}
});
});
console.log(response);
});
});
const start = async (): Promise<void> => {
await new Promise((resolve, reject) => {
server = app.listen(port, () => {
console.log(`App listening on port ${port}!`);
resolve();
});
});
}
const stop = async (): Promise<void> => {
await new Promise((resolve, reject) => server.close(() => {
console.log('App closed successfully')
resolve();
}));
}
I found out that the problem is that when I run the tests the connection to the database cannot be made. Any idea how can I create a connection to the database when I run jasmine? What's the difference between calling start() from the test or just running npm start. When I use npm start everything works fine but when I call it from jasmine the connection to db cannot be made.
It's a typescript problem, something like the tests are run with node, but they should run with ts-node. I run the test with the commands: tsc; jasmine.
I solved it using jasmine-ts. the problem was that I ran my tests with tsc; jasmine
Related
I have some task.
I'm creating my library which has a connection function written in it (several processes are included) and a creation function.
Need to clarify. The library doesn't deal with any http/https requests. Everything happens locally and without server requests.
Code from the testing side of the library
module.exports = async function connect(argument) {
const { save, models } = argument;
var prom = new Promise((resolve, reject) => {
setTimeout(() => {
checkDir(models);
// check models
checkBaseModels(models);
checkModels(models);
resolve();
});
});
prom.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
loadModels();
resolve();
}, 2000);
});
}).then(() => {
setTimeout(() => {
saveModels(save);
models_list();
});
});
};
const cloud = require('cloud');
const cloud = cloud.connect({ save: 1000 });
const create = cloud.create({
name: "Test",
description: "Abc"
});
What can be used to make other processes stop while the connection in my library is running.
I need to somehow fix this problem without using setTimeout and so on in the test. It is desirable to leave this code as it is.
I need to connect first, and then create.
The code on the test side, if possible, should preferably not be edited.
connect function is not returning the promise
module.exports.connect = async function connect(argument) {
// ...
return prom;
}
Connection file
(async () => {
const cloud = await cloud.connect({ save: 1000 });
const create = cloud.create({
name: "Test",
description: "Abc",
});
})();
When i execute my jest tests they succeed but don't stop.
For example i have this test:
const request = require('supertest')
let app = require('../index')
describe('make workflow tests work', () => {
test('Status code 200 for relayer', async () => {
const response = await request(app).get('/')
expect(response.statusCode).toBe(200)
})
})
In my app i just have a basic endpoint that returns 200.
app.get('/', function (req, res) {
res.send('200')
})
And some async jobs that run all the time:
;(async () => {
while (1) {
console.log("i am active the whole time")
}})()
})
Now the problem i have is that the test dont stop after succeeding i get the message:
PASS tests/workflow.test.js (8.359 s)
● Cannot log after tests are done. Did you forget to wait for
something async in your test?
I'm trying to get sublist3r to run in a node app. It runs, however, it only shows the banner and then exits out in about 5 seconds. The script is supposed to reach out to the web and takes about 30 seconds to run. If I don't use a promise, it will work just fine. Does it have something to do with pyrog.stdout.on('data') not waiting before it outputs? I've read around and tried 'end' with no luck.
Tried everything on this article if it didn't involve editing python script (I don't think I should need to ?!)
Also read the Node.js Child Process but it doesn't mention using promises with spawn, and I believe that's what I need to use for running a Python script.
sublist3r screen shot
Am I using Promises wrong?
Any help is much appreciated
Edit: Added await to runPy, verified same issue. Have also tried making it a variable, let test = await runPy ... with no success
var express = require('express');
var router = express.Router();
let runPy = new Promise((success, nosuccess) => {
const {spawn} = require('child_process')
const pyprog = spawn('python',['/path/to/sublist3r.py', '-d', 'domain.com'] )
pyprog.stdout.on('data', (data) => {
success(data)
})
pyprog.stderr.on('data', (data) => {
nosuccess(data)
})
pyprog.on('close', (code) => {
console.log(`child process ended with ${code}`);
})
})
/* GET home page. */
router.get('/', async (req, res) => {
// EDIT: Added await and verified same issue.
await runPy.then(fromRunPy => {
console.log(fromRunPy.toString());
})
// It works fine below, but I want a promise for no other reason that I can't get it to work...
// const { spawn } = require('child_process');
// const pyProg = spawn('python', ['/home/wayne/BugHunterJS/controllers/Sublist3r/sublist3r.py', '-d', req.body.domain]);
// console.log('inside post');
// pyProg.stdout.on('data', function(data) {
// let sublist3rData = data.toString();
// console.log(sublist3rData);
// });
});
module.exports = router
Not shortly after I asked, I found a solution if anyone is looking. I'm still not really sure how it works, got to figure that out later. I think pushing it to the array is the key.
const {
spawn
} = require('child_process')
const logOutput = (name) => (data) => console.log(`[${name}] ${data}`)
function run() {
return new Promise((resolve, reject) => {
const process = spawn('python', ['/path/sublist3r.py', '-d', 'domain.com']);
const out = []
process.stdout.on(
'data',
(data) => {
out.push(data.toString());
logOutput('stdout')(data);
}
);
const err = []
process.stderr.on(
'data',
(data) => {
err.push(data.toString());
logOutput('stderr')(data);
}
);
process.on('exit', (code, signal) => {
logOutput('exit')(`${code} (${signal})`)
if (code === 0) {
resolve(out);
} else {
reject(new Error(err.join('\n')))
}
});
});
}
(async () => {
try {
const output = await run()
logOutput('main')(output)
process.exit(0)
} catch (e) {
console.error('Error during script execution ', e.stack);
process.exit(1);
}
})();
Here are my HTTP routes
app.get('/', (req, res) => {
res.status(200).send('Hello World!')
})
app.post('/sample', (req, res) => {
res.status(200).json({
x:1,y:2
});
})
I would like to test for the following
1) GET request working fine.
2)the /sample response contains the properties and x and y
const request = require('supertest');
const app = require('../app');
describe('Test the root path', () => {
test('It should response the GET method', () => {
return request(app).get('/').expect(200);
});
})
describe('Test the post path', () => {
test('It should response the POST method', (done) => {
return request(app).post('/sample').expect(200).end(err,data=>{
expect(data.body.x).toEqual('1');
});
});
})
But I got the following error on running the test
Jest has detected the following 1 open handle potentially keeping Jest
from exiting:
return request(app).get('/').expect(200);
you need to call done() in the end() method
const request = require("supertest");
const app = require("../app");
let server = request(app);
it("should return 404", done =>
server
.get("/")
.expect(404)
.end(done);
});
This trick worked;
afterAll(async () => {
await new Promise(resolve => setTimeout(() => resolve(), 500)); // avoid jest open handle error
});
As described in this github issue.
Hi You can use the toEqual function as well
describe('Test the post path', () => {
test('It should response the POST method', () => {
return request(app).post('/sample').expect(200).toEqual({ x:1,y:2
});
});
})
There are lots of methods can be used instead.You can go throw the official documentation which covers every jest function https://jestjs.io/docs/en/expect
As a general tip to debug this error, add --detectOpenHandles to your npm script that runs Jest e.g.
"scripts": {
...
"test": "jest --detectOpenHandles"
}
This should tell you exactly which part of the code is causing the issue (probably some type of server connection, particularly if its async).
In general, if you can move the connection code to a separate function in a file outside of your tests, then import and call it in your tests, this will also fix the issue.
I want to just make sure that my server is running before I create PR's locally to test that nothing is broken.
worker.js
My server exports a promise
module.exports = Promise.all([
hbsPartialsLoaded,
])
.then(() => {
let server;
if (!isTestEnvironment) {
server = app.listen(config.port);
}
return { server, app };
});
tests
let { expect, request } = require('chai')
.use(require('chai-http'))
.use(require('chai-cheerio'));
const config = require('../../app/config');
const worker = require('../../app/worker');
describe('server response', function () {
worker.then(() => {
before(function () {
server.listen(config.port);
});
it('should return 200', function (done) {
request.get(`http://localhost:${config.port}`, function (err, res, body){
expect(res.statusCode).to.equal(200);
done();
});
});
after(function () {
worker.close();
});
})
});
Running Tests
NODE_ENV=test mocha --timeout 20000 --recursive test/ --compilers js:babel-core/register
0 passing (1ms)
My tests are never run. How can I get it so I wait for sever.js to finish its promises before the tests are run?
You didn't export the promise correctly, so the calling is bad, because you may not get callback if the require("worker.js") finished before calling .then, it should be worker().then not worker.then, but that's not the only problem.
The worker.js should return a function that launches the Promise.all. So change the module.exports = Promise.all... to module.exports = () => Promise.all...
Use before to launch the server and call it synchronously. Inside it you can use the asynchronous functions as you want.
The server.listen has a callback on second argument, that tells you when it finishes, so you can use promise and resolve it there.
An example:
var expect = require('chai').expect;
describe('x', () => {
before(() => new Promise((resolve, reject) => setTimeout(resolve, 500)));
it('should work', (done) => setTimeout(() => expect(0).to.be.above(0), 500));
});
Better example for your case:
var expect = require('chai').expect;
var app = require('express')();
describe('x', () => {
before(() => new Promise((resolve, reject) => {
app.listen(3000, () => {
console.log('The server launched');
resolve();
});
}));
it('should work', (done) => {
console.log('I got called after the server got launched! :)');
setTimeout(() => expect(1).to.be.above(0), 500)
});
});
it() functions should be called directly inside describe(). Nested inside a promise doesn't read well nor follow the standard testing process
let { expect, request } = require('chai')
.use(require('chai-http'))
.use(require('chai-cheerio'));
const config = require('../../app/config');
const worker = require('../../app/worker');
describe('server response', function () {
before(function () {
server.listen(config.port);
});
it('should return 200', function (done) {
worker.then(() => {
request.get(`http://localhost:${config.port}`, function (err, res, body){
expect(res.statusCode).to.equal(200);
done();
});
})
});
after(function () {
worker.close();
});
});