chai assertion always OK - node.js

I am trying to testing a node.js api with mocha and chai assertion.
My problem is that I always get a 'passed result'.
The test:
describe('TESTING /register', () => {
it('Should create a new account for chai-testing:chai-testing', () => {
let user = {
pseudo: "chai-testing",
mail: "chai#chai.com",
password: "chai-testing"
};
chai.request(server)
.post('/register')
.send(user)
.end((err, resp) => {
console.log(resp.body);
resp.body.should.have.property('success').eql(true);
done();
});
});
});
And the console output :
TESTING /register
✓ Should create a new account for chai-testing:chai-testing
chai-testing chai#chai.com chai-testing
1 passing (51ms)
{ favoris: [],
_id: 5abf6b5502c0f910439fec32,
pseudo: 'chai-testing',
mail: 'chai#chai.com',
password: '$2a$10$BPzQfp3wiDxU3mwgeXkG8Oh.B1ET8wTt5kg12oBwQ0obUxAyZQdLu',
admin: false,
__v: 0 }
POST /register 200 281.742 ms - 51
{ **success: false**, message: 'pseudo already taken' }
What I did do wrong in my test?

put there two assertion instead of this :
describe('TESTING /register', () => {
it('Should create a new account for chai-testing:chai-testing', () => {
let user = {
pseudo: "chai-testing",
mail: "chai#chai.com",
password: "chai-testing"
};
chai.request(server)
.post('/register')
.send(user)
.end((err, resp) => {
console.log(resp.body);
// if the resp has an attribute success then this
// assertion is true ( .eql(true) )
// that's why you get the test always passing
resp.body.should.have.property('success');
resp.body.success.should.eql(true);
done();
});
});
});

Related

Unit test with mocha and chai in nodejs alway return empty alter inserted

I am doing testing with my nodejs application with mocha and chai. I have a problem. When executing the command npm run test. The app registered a new user but the next api get always returns an empty array. I checked the database and found the added user. Can anyone point out where I'm going wrong. Thank you.
Result log:
{ success: true, data: [] }
I was expecting a result like this
{ success: true, data: [ { id: 1, username: 'test_user', password: 'xxx'} ] }
My script test:
//During the test the env variable is set to test
process.env.NODE_ENV = 'test';
//Require the dev-dependencies
let chai = require('chai');
let chaiHttp = require('chai-http');
let server = require('../app');
let should = chai.should();
chai.use(chaiHttp);
describe('/POST users', () => {
it('it should POST a user', (done) => {
let newUser = {
username: "test_user",
password: "test_password"
};
chai.request(server)
.post('/api/v1/auth/signup')
.send(newUser)
.end((err, res) => {
res.should.have.status(201);
done();
});
});
it('it should GET users', (done) => {
chai.request(server)
.get('/api/v1/users')
.end((err, res) => {
console.log(res.body)
res.should.have.status(200);
res.body.data.should.be.a('array');
done();
});
});
});
Service:
async function signup(username, password) {
await User.findOne({where: {username: username}}).then(user => {
if (user) {
throw new Error('That username is already taken')
}
bcrypt.hash(password, 10).then((hash) => {
User.create({
username: username,
password: hash
});
});
})
}
Controller:
const signup = async (req, res) => {
try {
await authService.signup(req.body.username, req.body.password);
res.status(201).send('')
} catch (err) {
apiResponse.failed(res, err.message);
}
};
Get users :
async function getUsers() {
return await User.findAll({attributes: ['id', 'username']}, {order: [['id', 'ASC']]});
}
My package.json
"test": "export NODE_ENV=test && sequelize db:migrate:undo:all && sequelize db:migrate && mocha --timeout 20000"

Chai-http is not checking second assertion when one inside one request

I am trying to get my token variable from /signing to provide it to the name change route. But the assertion is not always triggering. Can there be any better way to do this? Can I use async-await to solve this problem, if so, how?
describe("setName", function (done) {
it("/POST user setName", function (done) {
Users.remove({}, (err) => {
console.log(chalk.bgBlue(`Removing User`));
// done();
});
let user = {
"email": "tiwari.ai.harsh#gmail.com",
"password": "password",
"name": "Harsh Tiwari"
}
var requester = chai.request(app).keepOpen()
requester.post("/api/users/signin").send({
user
}).end((err_signin, res_signin) => {
let token = res_signin.body.user.token;
let name = "Name Changed"
requester.post("/api/users/setName").set({ authorization: `Token ${token}` }).send({
name
}).end((err, res) => {
res.should.have.status(200); <--------------------------- This is not working
});
done()
});
});
});
The current code will execute done before the requester.post("/api/users/setName") finish because it is an async execution.
To solve the issue, the done() should be specified after res.should.have.status(200);
describe('setName', function (done) {
// NOTE: I also moved remove function here to ensure user is removed correctly
before(function(done) {
Users.remove({}, (err) => {
console.log(chalk.bgBlue(`Removing User`));
done(); // NOTE: also specify done to tell mocha that async execution is finished
});
})
it('/POST user setName', function (done) {
let user = {
email: 'tiwari.ai.harsh#gmail.com',
password: 'password',
name: 'Harsh Tiwari',
};
var requester = chai.request(app).keepOpen();
requester
.post('/api/users/signin')
.send({
user,
})
.end((err_signin, res_signin) => {
let token = res_signin.body.user.token;
let name = 'Name Changed';
requester
.post('/api/users/setName')
.set({ authorization: `Token ${token}` })
.send({
name,
})
.end((err, res) => {
res.should.have.status(200);
done(); // NOTE: move here
});
});
});
});

Testing services with mocha / chai: Error testing login

I'm writing tests for a login service. The test must pass if the login is correct. Before every test the bd is cleaned. So I first create a user and then try to login. The expected behavior is receive the status 200 in the response but instead I'm receiving status 401 which says I'm not creating the user correctly.
describe("Users", () => {
beforeEach(done => {
User.remove({}, () => {
done();
});
});
describe("/POST login", () => {
it("should return successful login", done => {
const user = new User({
username: "test",
email: "test#test.com",
password: "testpass"
});
const user2 = {
user: "test",
password: "testpass"
};
user.save(err => {
if (err) {
done();
}
chai.request(server)
.post("/users/login")
.send(user2)
.end((err, res) => {
expect(res).to.has.status(200);
done();
});
});
});
Test result:
Uncaught AssertionError: expected { Object (_events, _eventsCount, ...) } to have status code 200 but got 401
Any hint of what's going on here?

Mocha test failing when sending invalid data to the server

I'm working on a small todos app with nodejs and mongodb.
I have the model definition here:
const Todo = new Schema({
text: {
type: String,
require: true,
minlength: 5,
trim: true
},
completed: {
type: Boolean
},
createdAt: {
type: {type: Date, default: Date.now}
}
});
As you can see, the text property is required and it should throw an error if it's missing when it reads the request.
Over here, I'm send the data to my endpoint:
app.post('/todos', (req, res) => {
let todo = new Todo({
text: req.body.text,
completed: req.body.completed
});
todo.save()
.then((document) => {
res.send(document);
}, (error) => {
res.status(400).send(error);
})
});
And finally, this is my test for the specific scenario where the user sends a empty set of data to the server:
it('Should not create todo document with invalid body data', (done) => {
request(app)
.post('/todos')
.send({})
.expect(400)
.end((error, res) => {
if(error){
return done(error);
}
Todo.find()
.then((todos) => {
expect(todos.length).toBe(0);
done();
}).catch((error) => done(error));
});
});
After running the test, for some reason it throws the following:
1) POST /todos
Should not create todo document with invalid body data:
Error: expected 400 "Bad Request", got 200 "OK"
at Test._assertStatus (node_modules\supertest\lib\test.js:266:12)
at Test._assertFunction (node_modules\supertest\lib\test.js:281:11)
at Test.assert (node_modules\supertest\lib\test.js:171:18)
at Server.assert (node_modules\supertest\lib\test.js:131:12)
at emitCloseNT (net.js:1689:8)
at process._tickCallback (internal/process/next_tick.js:152:19)
I've been trying to debug this for the past hour and I can't find what's wrong with it. Can anyone give me a hand?
UPDATE
Other test:
it('Should create a new todo', (done) => {
let text = 'This is a string';
request(app)
.post('/todos')
.send({text})
.expect(200)
.expect((res) => {
let testString = res.body.text;
expect(testString).toBe(text);
expect(typeof testString).toBe('string');
expect(testString.length).not.toBe(0);
})
.end((error, res) => {
if(error) {
return done(error);
}
Todo.find()
.then((todos) => {
expect(todos.length).toBe(1);
expect(todos[0].text).toBe(text);
done();
}).catch((error) => done(error));
});
});
You should check if text and completed exist before using them:
app.post('/todos', (req, res) => {
let text = req.body.text;
let completed = req.body.completed;
if(!completed) { completed = false; }
if(!text) {
res.status(400).send("Request parameters missing");
} else {
let todo = new Todo({
text: req.body.text,
completed: req.body.completed
});
todo.save()
.then((document) => {
res.send(document);
}, (error) => {
res.status(400).send(error);
})
}
});
Also in your Schema it should be "required" instead of "require"

Scopes & Closures in Mocha/Chai Assertions

I'm writing some tests for an express app and I am wondering how to properly access a variable in one assertion block from another. The variable I am trying to access is this.token = res.body.token
Whenever I try to access it, it comes up undefined (other than when accessing it within the beforeEach block). How can I access this variable? I need to use the token to set the headers in my test for my POST request.
Code:
describe('CRUD: tests the GET & POST routes', () => {
beforeEach(done => {
chai.request('localhost:3000')
.post('/app/signup')
.send({ email: 'meow#test.com', password: 'testpass' })
.end((err, res) => {
if (err) return console.log(err);
this.token = res.body.token; // this variable holds a token when accessed within this scope (tested it with node debugger)
done();
});
});
it('should create with a new cat with a POST request', (done) => {
chai.request('localhost:3000')
.post('/app/cats')
.set('token', this.token) // when accessed here, it is undefined...
.send({ username: 'cat_user' })
.end((err, res) => {
expect(err).to.eql(null);
expect(res).to.have.status(200);
expect(res.body.name).to.eql('test cat');
expect(res.body).to.have.property('_id');
done();
});
});
EDIT: Here is a screenshot of my terminal in node debug mode. As you can see, when it hits the first debugger break and _token is accessed, it contains the token. In the next debugger break, however, it comes up empty... (maybe that means something else in the debugger?)
You can move your variable to the scope of your describe.
describe('CRUD: tests the GET & POST routes', () => {
let _token;
beforeEach(done => {
chai.request('localhost:3000')
.post('/app/signup')
.send({ email: 'meow#test.com', password: 'testpass' })
.end((err, res) => {
if (err) return console.log(err);
_token = res.body.token; // this variable holds a token when accessed within this scope (tested it with node debugger)
done();
});
});
it('should create with a new cat with a POST request', (done) => {
chai.request('localhost:3000')
.post('/app/cats')
.set('token', _token) // when accessed here, it is undefined...
.send({ username: 'cat_user' })
.end((err, res) => {
expect(err).to.eql(null);
expect(res).to.have.status(200);
expect(res.body.name).to.eql('test cat');
expect(res.body).to.have.property('_id');
done();
});
});
You should read this to understand this: http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/

Resources