How I can retaining cookies with each request - node.js

I'm new on mocha and chai.
I'm writing integration test cases into NodeJS application using mocha and chai.
I was looking for a common solution.
Here I'm explaining what I'm doing.
In short, my point is
How to retain cookies to each request
My node server is running on the separate machine on port 3000 and Test Cases will be on another machine.
This is my application directory structure
First, login API test case
let chai = require('chai');
let chaiHttp = require('chai-http');
let expect = require('chai').expect;
chai.use(chaiHttp);
let agent = chai.request.agent(endpoint);
describe('/POST login ', function () {
it(' login ', function (done) {
let req = {
'email': 'email',
'password': 'password'
};
agent
.post(login)
.send(req)
.then(function (response) {
expect(response).to.have.status(200);
done();
}).catch(function (error) {
done(error);
});
});
});
Second, to get account list
let chai = require('chai');
let chaiHttp = require("chai-http");
let expect = chai.expect;
chai.use(chaiHttp);
describe('/POST account', function () {
it(' Account List ', async function () {
let response = await chai.request(endpoint)
.post(accounts)
try {
expect(response).to.have.status(200);
} catch (error) {
throw error;
}
});
});
I've created separate files for each module.
Well,
All APIs are authenticated based on the session.
So,
Is there any way to set cookies globally on chai-http plugin?
Basically,
Login test case will set the cookie and after that, each request will carry this cookie.
Thanks

Related

Mocha/ Supertest is not exiting on completion of tests

I am using the mocha testing framework, and after running the following test it does not exit.
I have tried Promises and async await with no luck. --exit at the end of the mocha command works, but I want to find the source of the issue.
I am wondering if it is the knex database connection when running beforeEach and afterEach functions. However, I do not know how to disconnect the db connection other than destroy(), and if this is used the following tests do not run.
Can anybody see anything within the code that could be causing this issue? Or recommend another way to remedy this?
const app = require('../../app');
const request = require('supertest');
describe('Route: /' + route, () => {
let token = '';
let route = 'user';
before(function (done) {
const user = {email: 'admin#email.com', password: 'password'};
request(app)
.post('/login')
.send(user)
.end((err, res) => {
token = res.body.token;
done();
});
});
beforeEach(async () => {
await knex.migrate.rollback();
await knex.migrate.latest();
await knex.seed.run();
});
afterEach(() => knex.migrate.rollback());
it(`should not be able to consume /${route} since no token was sent`, (done) => {
request(app)
.get(`/${route}`)
.expect(401, done)
});
it(`should be able to consume /${route} since a valid token was sent`, (done) => {
request(app)
.get(`/${route}`)
.set('Authorization', 'Bearer ' + token)
.expect(200, done);
});
});
For anyone who comes across this and has a similar problem.
Using the following links;
- GitHub mocha debug example
- Mocha docs -exit
- wtfnode
I was able to debug the problem.
wtfnode used within my test showed me that my database was still connected with the console reading.
const wtf = require('wtfnode');
after(wtf.dump()); // place within test describe body
Returned;
- Sockets:
- 127.0.0.1:58898 -> 127.0.0.1:5432
- Listeners:
- connect: Connection.connect # <user_path>/node_modules/pg/lib/connection.js:59
I am using knex to connect to the database, so I've added code below to the file helper.js in my test directory.
/test/helper.js
const knex = require('../database/db');
before(function () {
if (!knex.client.pool) return knex.initialize();
});
beforeEach(async function () {
await knex.migrate.rollback();
await knex.migrate.latest();
await knex.seed.run();
});
afterEach(function () {
return knex.migrate.rollback()
});
after(function () {
return knex.destroy();
});

reset a database before each test

I'm using node and supertest for a simple app. I got SQlite3 for the local test database. I did a simple test to get a super inserted into the database. I wanted to reset the database each time a test is run. I'm looking in the docs right now and can't seem to locate it. I figured I would ask here because it seems someone would most likely know the info.
const request = require('supertest');
const server = require('../server');
describe('Authentication', function() {
//database reset here
it('should create a new user /users/registration', function(done) {
request(server)
.post('/users/register')
.send({
username: 'user-name',
email: 'luser-name#gmail.com',
password: '12345'
})
.set('Accept', 'application/json')
.expect(201, done);
});
});
If you want to run any piece of code before each test, you can use beforeEach function in jest
describe('my test', () => {
beforeEach(() => {
// code to run before each test
});
test('test 1', () => {
// code
});
test('test 2', () => {
// code
});
});
So best way to do this is have some logic in your routing functions of your Api
Receive an API request
Check if ['X-MOCK-HEADER'] exists
If it does then route to the mock version of the endpoint
So your mock for create user would always return 201 OK - your mock endpoint would do something like this:
const routes = {
CREATE_USER_OK:() => { return {....} } // make sure these return proper http responses
CREATE_USER_BAD_REQUEST: () { return {...} }
}
return routes[HEADER_VALUE]()
The reason being you're testing the route not the database class in this instance, so you just want to return static data, if you wanna test something else then just change the X-MOCK-HEADER value to whatever you want and add the mock route to return the right http response/code - I'd need to know what the API code looked like to help you on the backend implementation.
If possible stay away from messing with staging databases for testing because down the road you will suffer a LOT of pain as it gradually gets filled with garbage.
Also if you're working with a front end app you can quickly prototype with static data - this is especially useful if you've got a front end team waiting for an API endpoint to say create a login screen.
There's no defined way to reset a sqlite db, just delete the db and recreate.
Sqlite: How do I reset all database tables?
I did this in the file and it works fine
const request = require('supertest');
const server = require('../server');
const knex = require('knex');
const dbConfig = require('../knexfile.js')['test'];
const db = knex(dbConfig);
describe('Authentication', () => {
beforeEach(async () => {
await db('users').truncate();
});
it('should create a new user /users/registration', function(done) {
request(server)
.post('/users/register')
.send({
username: 'user-name',
email: 'luser-name#gmail.com',
password: '12345'
})
.set('Accept', 'application/json')
.expect(201, done);
});
});

request rest api and return response values for a mocha test

Inside a meteor appliation, i want to test some rest functions, therefore i need to do some authentication.
In my testcase, i want to return some auth data from a function:
const supertest = require('supertest');
function loginUser(auth) {
return function(done) {
request
.post('/users/login')
.send({
username: 'user'
password: '123',
})
.expect(200)
.end(onResponse);
function onResponse(err, res) {
auth.token = res.body.token;
return done();
}
};
}
inside this test:
it('auth test by helper function', function () {
let auth = {};
auth = loginUser(auth)(done);
//access auth settings here like:
//auth.token
});
onResponse is never called and auth is always {}
I am using supertest for requests 3.0.0 and mocha 4.1.0 as testrunner (The rest api is simple:json-routes)
UPDATE
It seems like the return 'function(done)' is never called...
Ok i fixed the call to auth = loginUser(auth)(done);
Now the call is done but auth is undefined after the call
Your function loginUser(auth) returns another function. So you should call that function as well like this:
it('auth test by helper function', function (done) { // pass done so mocha knows it needs to wait for the response ...
let auth = {};
loginUser(auth)(function() {
//access auth settings here like:
//auth.token
done();
});
});

test POST mocha - chai : return 500

actually right now im writing API to create, get, update, and delete data using node js. my code working in a good shape.
i try it using postman to post data, it adding new data to my db.
then i want to use testing unit, named mocha - chai.
this my code :
let chai = require('chai');
let chaiHttp = require('chai-http');
let server = require('server');
let expect = require("chai").expect;
let should = require("should");
let request = require("superagent");
let util = require("util");
chai.use(chaiHttp);
describe('API Clinic Test', function() {
it('should add a SINGLE clinic on /api/v1/clinic POST', function(done) {
chai.request('http://localhost:5000')
.post('/api/v1/clinic')
.send({'clinic_name': 'Clinic Dummy', 'address': 'Bandung', 'phone':'888 888', 'fax':'888 888'})
.end(function(err, res){
expect(res.status).to.equal(200);
done();
});
});
});
if success it should return code 200.
but when i run mocha, i got this error.
i dont understad. i try using postman, it can added new data.
but why i got return 500 code when i using mocha?
is there something wrong in my codes?
please help me.
thank you.
Make your function asynchronous, testing function pretends to be executed both at the same time due to that some fail.
it('should add a SINGLE clinic on /api/v1/clinic POST', async function(done) {
await chai.request('http://localhost:5000')
.post('/api/v1/clinic')
.send({'clinic_name': 'Clinic Dummy', 'address': 'Bandung', 'phone':'888 888', 'fax':'888 888'})
.end(function(err, res) {
expect(res.status).to.equal(200);
done();
});

How do I launch server for multiple mocha chai-http test files?

I am starting my node server in my before block on my mocha chai-http tests.
I have it working perfect for single test files. However when I attempt to run multiple tests in a single command NODE_ENV=test mocha test/**/*.js I am getting an error.
I tried to have the node servers launch on different ports per test file. This didn't work, got node server start errors.
I'm now thinking it would be great if I can have a single mocha file that runs before my other test files to start the server and then a single file that runs after the other test files to kill/stop the server.
How would I go about this.
Below is some of my code:
Here is one of my test files for reference:
var chai = require('chai');
var chaiHttp = require('chai-http');
chai.use(chaiHttp);
var expect = chai.expect;
var Sails = require('sails');
describe('REST User API', function() {
var app; // for access to the http app
var sails; // for starting and stopping the sails server
before(function (done) {
Sails.lift({
port: 3001,
log: {
level: 'error'
}
}, function (_err, _sails) {
if(_err){
console.log("Error!", _err);
done();
}
else {
app = _sails.hooks.http.app;
sails = _sails;
done();
}
});
});
describe("user session", function () {
var res; // http response
var authenticatedUser;
before(function (done) {
chai.request(app)
.post('/users/signin')
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.send({ email: 'admin#test.com', password: 'secret'})
.end(function (_res) {
res = _res; // Record the response for the tests.
authenticatedUser = JSON.parse(_res.text); // Save the response user for authenticated tests
done();
});
});
it("should connect with a 200 status", function () {
expect(res).to.have.status(200);
});
it("should have a complete user session", function () {
var userSession = authenticatedUser;
expect(userSession).to.have.property('firstName');
expect(userSession).to.have.property('lastName');
expect(userSession).to.have.property('gender');
expect(userSession).to.have.property('locale');
expect(userSession).to.have.property('timezone');
expect(userSession).to.have.property('picture');
expect(userSession).to.have.property('phone');
expect(userSession).to.have.property('email');
expect(userSession).to.have.property('username');
expect(userSession).to.have.property('confirmed');
expect(userSession).to.have.property('status');
expect(userSession).to.have.property('authToken');
});
});
after(function (done) {
sails.lower(function() {
done()
});
});
});
From mocha v8.2.0, you can use GLOBAL FIXTURES to setup and teardown your web server for all test suites. Global fixtures are guaranteed to execute once and only once.

Resources