I have an NodeJS Express application which I want to unit test which uses cookies. So I want to use a beforeEach or before to create the Cookie.
Code which works without any problem (but without the before method):
import * as chai from 'chai';
import { expect } from 'chai'
import chaiHttp = require('chai-http');
import { app } from '../../server';
describe('Relaties', () => {
describe('Ophalen alle relaties met: GET /api/ehrm-klantnr/relatie', () => {
it('should get alle relaties', (done) => {
let agent = chai.request.agent(app)
agent
.put('/api/ehrm-klantnr/medewerker/login')
.send({ email: 'admin#sfgtest.com', wachtwoord: '<secret>' })
.then(function (res) {
expect(res).to.have.cookie('SESSIONID');
// The `agent` now has the sessionid cookie saved, and will send it
// back to the server in the next request:
return agent.get('/api/ehrm-klantnr/relatie')
.set('meta','1')
.then(function (res) {
expect(res).to.have.status(200);
expect(res.body.data[0].vestiging).to.equal('Slib Hoofdkantoor');
done();
});
});
});
});
});
What does not run is this:
import * as chai from 'chai';
import { expect } from 'chai'
import chaiHttp = require('chai-http');
import { app } from '../../server';
describe('Relaties', () => {
let agent = chai.request.agent(app);
describe('First this one', function () {
beforeEach(function () {
console.log('outer describe - beforeEach');
agent
.put('/api/ehrm-klantnr/medewerker/login')
.send({ email: 'admin#sfgtest.com', wachtwoord: '<secret>' })
.then(function (res) {
expect(res).to.have.cookie('SESSIONID');
});
});
});
describe('Ophalen alle relaties met: GET /api/ehrm-klantnr/relatie', () => {
it('should get alle relaties', (done) => {
return agent.get('/api/ehrm-klantnr/relatie')
.set('meta', '1')
.then(function (res) {
expect(res).to.have.status(200);
expect(res.body.data[0].vestiging).to.equal('Slib Hoofdkantoor');
done();
});
});
});
});
It is completely ignoring my before or beforeEach (both methods don't work).
Maybe chai-http does not have before or beforeEach support ?
What am I doing wrong ?
After restructuring.
describe('Relaties', () => {
const agent = chai.request.agent(app);
beforeEach(function (done) {
console.log('outer describe - beforeEach');
agent
.put('/api/ehrm-klantnr/medewerker/login')
.send({ email: 'admin#sfgtest.com', wachtwoord: '<secret>' })
.then(function (res) {
expect(res).to.have.cookie('SESSIONID');
done();
});
});
describe('Ophalen alle relaties met: GET /api/ehrm-klantnr/relatie', () => {
it('should get alle relaties', (done) => {
return agent.get('/api/ehrm-klantnr/relatie')
.set('meta', '1')
.then(function (res) {
expect(res).to.have.status(200);
expect(res).to.be.an('object');
expect(res.body.data).to.be.an('array');
expect(res.body.data[0]).to.be.an('object');
expect(res.body.data[0].id).to.equal(1);
done();
});
});
});
});
I still get errors about the promise.
If this is usefull for someone, this is the final solution:
describe('Relaties', () => {
const agent = chai.request.agent(app);
beforeEach(function (done) {
console.log('outer describe - beforeEach');
agent
.put('/api/ehrm-klantnr/medewerker/login')
.send({ email: 'admin#sfgtest.com', wachtwoord: '<secret>' })
.then(function (res) {
expect(res).to.have.cookie('SESSIONID');
done();
});
});
describe('Ophalen alle relaties met: GET /api/ehrm-klantnr/relatie', () => {
it('should get alle relaties', (done) => {
agent.get('/api/ehrm-klantnr/relatie')
.set('meta', '1')
.then(function (res) {
expect(res).to.have.status(200);
done();
});
});
});
});
Related
I will include both the files that are needed for the same
the main issue is that after every test I run I want no more entries to be added in my database and it should be cleaned after the test are done
so I used aftereach() but I suppose it is not working because of something wrong I did, can you help me with that.
here is my test.js
process.env.NODE_ENV = 'test';
// const mongoose = require('mongoose');
const chai = require('chai');
const chaiHttp = require('chai-http');
const Task = require('../config/model');
const server = require('../index');
const { expect } = chai;
chai.use(chaiHttp);
describe('Task', (done) => {
afterEach(() => {
Task.crud.drop();
done();
});
});
// Test Get Tasks
describe('/GET tasks', () => {
it('it should GET all the tasks', async () => {
const res = await chai.request(server)
.get('/task');
// .end((err, res) => {
expect(res).to.have.status(200);
// expect(res.body).to.be.a('array');
// done(err);
});
});
describe('/Post tasks', () => {
it('should Post the task', async () => {
const taskPost = {
task: 'run as fast as possible you idiot',
};
const res = await chai.request(server)
.post('/task')
.send(taskPost);
// .end((err, res) => {
expect(res).to.have.status(200);
// done();
});
});
describe('/GET/:ID', () => {
it('should Get the task by ID', async () => {
const tasks = new Task({ task: 'The Lord of the Rings' });
const task = await tasks.save();
const res = await chai.request(server)
.get(`/task/${task.id}`)
.send(task);
// .end((error, res) => {
expect(res).to.have.status(200);
// done();
// });
});
});
describe('/PUT/:ID task', () => {
it('it should UPDATE a task given the id', async () => {
const tasks = new Task({ task: 'The Chronicles of Narnia' });
const task = await tasks.save();
const res = await chai.request(server)
.put(`/task/${task.id}`)
.send({ task: 'The Chronicles of Sarvesh' });
// .end((error, res) => {
expect(res).to.have.status(200);
// });
});
});
and the files that is in /config/model
const mongoose = require('mongoose');
const Schema = new mongoose.Schema({
task: {
type: String,
required: true,
},
});
module.exports = mongoose.model('crud', Schema, 'crud');
I don't think model has any inbuilt drop method. You need to either use db.collection("collectionName").drop() for which you need handle of current db or use deleteMany and delete everything inside the collection. something like this
describe('Task', (done) => {
afterEach(() => {
Task.crud.deleteMany({}, (err, response) => {
done();
});
});
});
How can I mock fetch function in Node.js by Jest?
api.js
'use strict'
var fetch = require('node-fetch');
const makeRequest = async () => {
const res = await fetch("http://httpbin.org/get");
const resJson = await res.json();
return resJson;
};
module.exports = makeRequest;
test.js
describe('fetch-mock test', () => {
it('check fetch mock test', async () => {
var makeRequest = require('../mock/makeRequest');
// I want to mock here
global.fetch = jest.fn().mockImplementationOnce(() => {
return new Promise((resolve, reject) => {
resolve({
ok: true,
status,
json: () => {
return returnBody ? returnBody : {};
},
});
});
});
makeRequest().then(function (data) {
console.log('got data', data);
}).catch((e) => {
console.log(e.message)
});
});
});
I tried to use jest-fetch-mock, nock and jest.mock but failed.
Thanks.
You can mock node-fetch using jest.mock. Then in your test set the actual mock response
import fetch from 'node-fetch'
jest.mock('node-fetch', ()=>jest.fn())
describe('fetch-mock test', () => {
it('check fetch mock test', async () => {
var makeRequest = require('../mock/makeRequest');
const response = Promise.resolve({
ok: true,
status,
json: () => {
return returnBody ? returnBody : {};
},
})
fetch.mockImplementation(()=> response)
await response
makeRequest().then(function (data) {
console.log('got data', data);
}).catch((e) => {
console.log(e.message)
});
});
});
import fetch, { Response } from 'node-fetch';
jest.mock('node-fetch');
describe('fetch-mock test', () => {
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;
it('check fetch mock test', async () => {
const json = jest.fn() as jest.MockedFunction<any>;
json.mockResolvedValue({ status: 200}); //just sample expected json return value
mockFetch.mockResolvedValue({ ok: true, json } as Response); //just sample expected fetch response
await makeRequest();
expect(json.mock.calls.length).toBe(1);
})
})
I was working on a simple node project, and I came across this error. I can't seem to find a way through it, nor do I really understands what this means
const expect = require('expect');
const request = require('supertest');
const {app} = require('./../server');
const {Todo} = require('./../models/ToDo');
beforeEach((done) => {
Todo.remove().then(() => done());
});
describe('POST /todos', () => {
it('should create a new todo', (done) => {
var text = 'Test todo text';
request(app)
.post('/todos')
.send({text})
.expect(200)
.expect((res) => {
expect(res.body.text).toBe(text);
})
.end((err, res) => {
if(err) {
return done(err);
}
Todo.find().then((todos) => {
expect(todos.length).toBe(1);
expect(todos[0].text).toBe(text);
done();
}).catch((e) => done(e));
});
});
});
The error means your Todo is undefined. You can check like this.
beforeEach((done) => {
console.log(Todo); // put a breakpoint here if you want to inspect the variable
Todo.remove().then(() => done());
});
I have two describe blocks in my mocha-chai test, one for testing a POST API and another for a GET API. There is a dependency like the function for the GET API in turn calls the function for the POST API at first.
However, when I call both the functions one after another, both of them start simultaneously and thus failing.
The code looks like below :
var server;
var mongodb;
before(function (done) {
server = require('../../../app.js'); // same as "node app.js"
done();
})
after(function (done) {
server.close();
})
function this_is_post_call() {
describe('POST call', ()=> {
it('Creating project', (done) => {
chai.request(server)
.post('/create/myproject')
.send()
.end((err, res) => {
expect(res.statusCode).to.equal(200);
done();
});
});
});
}
function this_is_get_call() {
this_is_post_call();
describe('GET call', ()=> {
it('Reading project', (done) => {
chai.request(server)
.get('/read/myproject')
.send()
.end((err, res) => {
expect(res.statusCode).to.equal(200);
done();
});
});
}
this_is_post_call();
this_is_get_call();
Basically when I run this the standalone this_is_post_call() and the one inside this_is_get_call() , gets called simultaneously and it is failing as it tries to create same project twice.
What is the efficient way to call them sequentially so that they don't start until the previous one finishes.
Thanks.
something like this might work (not completely sure about the chai.request part)
var server;
var mongodb;
describe('server', () => {
before(function (done) {
server = require('../../../app.js'); // same as "node app.js"
done();
})
after(function (done) {
server.close();
})
beforeEach(() => {
// find a way to clear the database
// using mongodb variable maybe
})
describe('when you make a post', () => {
var postResult
beforeEach((done) => {
chai.request(server)
.post('/create/myproject')
.send()
.end((err, res) => {
var postResult = res
done();
});
})
})
it('should respond with OK', () => {
expect(postResult.statusCode).to.equal(200);
})
it('should let you make make a get', () => {
chai.request(server)
.get('/read/myproject')
.end((err, res) => {
expect(err).to.be.null;
expect(res.statusCode).to.equal(200);
done();
});
})
})
something like this might work too if you don't have a way to clear the database
var server;
var mongodb;
describe('server', () => {
before(function (done) {
server = require('../../../app.js'); // same as "node app.js"
done();
})
after(function (done) {
server.close();
})
it('should let you post and then get', () => {
var postResult
beforeEach((done) => {
chai.request(server)
.post('/create/myproject')
.send()
.end((err, res) => {
expect(postResult.statusCode).to.equal(200);
chai.request(server) // not sure if this is the correct chai.request format
.get('/read/myproject')
.end((err, res) => {
expect(err).to.be.null;
expect(res.statusCode).to.equal(200);
done();
});
});
})
})
})
I've got a simple function such as;
module.exports = {
fetchUser:function(myUserId) {
return new Promise((resolve, reject) => {
this.getUser(myUserId)
.then(user => {
// do logic // then return user
return user;
})
.then(resolve)
.catch(err => {
// whoops there has been an error
let error = { error: 'My Error' };
reject(error);
});
});
}
};
I want to unit test both the resolve and reject result.
A simple chai test would be;
var expect = require('chai').expect;
var user = require('./user');
describe('User module', function() {
it('test fetchUser', function() {
let _user = user.fetchUser('abc123');
return _user
.then(user => {
expect(data).to.be.an('object');
});
});
Using sinon or another library, how can I for the fetchUser function to throw that reject error?
With Mocha, Chai and Sinon it can be implemented with stubbed method getUser.
const User = require("./fetchUserModule");
describe('User module', () => {
beforeEach(() => User.getUser = sinon.stub());
afterEach(() => User.getUser.reset());
it('returns user if `getUser` returns data', () => {
const user = {name: 'John'};
User.getUser.withArgs("abc123").returns(Promise.resolve(user));
return User.fetchUser("abc123").then(result => {
expect(result).to.equal(user)
}).catch(error => {
expect(error).to.be.undefined;
})
});
it('throws error if `getUser` is rejected', () => {
User.getUser.withArgs("abc123").returns(Promise.reject());
return User.fetchUser("abc123").then(result => {
expect(result).to.be.undefined;
}).catch(err => {
expect(err).to.eql({error: 'My Error'})
})
});
});
Start with anything in your "logic" that can throw an error.
If not you would need to stub this.getUser to reject or throw an error instead of returning data. sinon-as-promised patches sinon.stub to include the .resolves and .rejects promise helpers.
const sinon = require('sinon')
require('sinon-as-promised')
Setup the stub for the failure tests.
before(function(){
sinon.stub(user, 'getUser').rejects(new Error('whatever'))
})
after(function(){
user.getUser.restore()
})
Then either catch the .fetchUser error or use chai-as-promised for some sugar.
it('test fetchUser', function() {
return user.fetchUser('abc123')
.then(()=> expect.fail('fetchUser should be rejected'))
.catch(err => {
expect(err.message).to.eql('whatever')
})
})
it('test fetchUser', function() {
return expect(user.fetchUser('abc123')).to.be.rejectedWith(Error)
})
or async if you live in the new world
it('test fetchUser', async function() {
try {
await user.fetchUser('abc123')
expect.fail('fetchUser should be rejected'))
} catch(err) {
expect(err.message).to.eql('whatever')
}
})
As a side note, you don't need to wrap something that already returns a promise in new Promise and be careful about losing error information when chaining multiple .catch handlers.
fetchUser: function (myUserId) {
return this.getUser(myUserId)
.then(user => {
//logic
return user
})
.catch(err => {
let error = new Error('My Error')
error.original = err
reject(error)
});
}