mocha test case for res.render not working - node.js

I'm writing a simple test case for a route. I've used mocha, chai-http and sinon to check if correct page is rendered or not. This is for contact page where the user provides their info. and contact page is rendered again for now. Below is my test case :
const chai = require('chai');
const chaiHttp = require('chai-http');
const sinon = require('sinon');
const ejs = require('ejs');
var app = require('../app');
var path = require('path');
var fs = require('fs');
var Contact = require('../models/contacts');
chai.use(chaiHttp);
var should = chai.should();
var expect = chai.expect;
describe('Contact', () => {
describe('/POST Contact', () => {
it('it should not POST a book without pages field', (done) => {
var spy = sinon.spy(ejs, '__express');
let contact = {
name: "my name",
msg: "my msg"
}
chai.request(app)
.post('/contact')
.send(contact)
.end((err, res) => {
console.log(res)
// / console.log(__dirname);
// console.log(__filname)
// var dir = __filename + './views/contact.ejs';
var dir = path.dirname(fs.realpathSync('./'));;
console.log(dir)
expect(spy.calledWithMatch(dir + '\views\contact.ejs')).to.be.true;
//expect(spy.calledWith(dir)).to.be.true;
spy.restore();
// Tell Mocha that our test case is done.
done();
// res.should.have.status(200);
//res.should.have.status()
// res.should.have.status(200);
// res.body.should.be.a('object');
//res.body.should.have.property('errors');
// res.body.errors.should.have.property('pages');
// res.body.errors.pages.should.have.property('kind').eql('required');
done();
});
});
});
});
The problem is i get an error response on res saying :
Failed to lookup view "contact" in views directory "C:\\Users\\My User\\Documents\\GitHub\\My Project\\test\\views
So basically it searches for view inside the test directory. Is there any way i can ask to view into the proper directory which is outside test ?

Related

AssertionError: expected undefined to equal 200

const express = require("express");
const app = express();
const router = express.Router();
router.get('/postp',(req,res)=>{
res.status(200);
})
app.listen(PORT, () => {
console.log(`Connected to PORT : ${PORT}`);
});
module.exports = app;
Test case :
const chai = require('chai');
const request = require('supertest');
const app = require('../app');
const post = require('../router/post');
const expect = chai.expect;
describe('Blog',function(){
it('get blogs', function(done){
const response = request(app).get('/postp');
expect(response.status).to.be.equal(200);
done();
})
})
What's the problem?
please specify, is it because I can't access app or something else.
why it's not running
Try using request from chai.
const chai = require('chai');
const request = require('supertest');
const app = require('../app');
const post = require('../router/post');
const expect = chai.expect;
describe('Blog',function(){
it('get blogs', function(done){
const response = chai.request(app).get('/postp')
.end((err, res) => {
res.should.have.status(200);
})
done();
})
})
I suggest you to check this link, it gives more details about assertion lib and chai.

How to stub function used on a server in mocha test suite

I'm trying to stub auth.session when testing endpoint /allowUser2 on an express server app.js.
//--auth.js--
module.exports.session = (req, res, next) => {
req.user = null;
next();
};
//--app.js--
const express = require('express');
const auth = require('./auth');
const app = express();
app.use(auth.session);
app.get('/allowUser2', (req, res) => {
if (!req.user) return res.status(401).send();
if (req.user.user === 2) return res.status(200).send();
});
app.listen(4001).on('listening', () => {
console.log(`HTTP server listening on port 4001`);
});
module.exports = app;
If I just have this one test file test1.js in my test suite, auth gets stubbed successfully.
//--test1.js--
let app;
const sinon = require('sinon');
const auth = require('../../auth.js');
const chai = require('chai');
const chaiHttp = require('chai-http');
const { expect } = chai;
chai.use(chaiHttp);
let agent;
describe('should allow access', () => {
before(async () => {
// delete require.cache[require.resolve('../../app.js')]; // causes Error: listen EADDRINUSE: address already in use
sinon.stub(auth, 'session').callsFake((req, res, next) => {
req.user = { user: 1 };
next();
});
app = require('../../app.js');
agent = chai.request.agent(app);
});
after(async () => {
auth.session.restore();
});
it('should not allow access', async function () {
const response = await agent.get('/allowUser2');
expect(response.status).to.be.equal(200);
});
});
However, if I have more than one test file that requires app.js then I have a problem. If app.js was already required in another test file, such as test2.js below, node doesn't reload app.js when it's required again in test1.js. This causes app.js to call the old auth.session function, not the new stubbed one. So the user isn't authenticated and the test fails.
//--test2.js--
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../../app.js');
const { expect } = chai;
chai.use(chaiHttp);
const agent = chai.request.agent(app);
describe('route /allowUser2', () => {
it("shouldn't allow access", async function () {
const response = await agent.get('/allowUser2');
expect(response.status).to.be.equal(401);
});
});
I tried to reload the app.js by using delete require.cache[require.resolve('../../app.js')];. This worked when reloading a file with a plain function, but when the file is a server like app.js this causes an error: Error: listen EADDRINUSE: address already in use.
Recreate:
download Repo
npm i
npm test
How do you stub a function on the server?
One solution is turn app.js into a function that starts the server on a port number passed in as an argument. Then change the port randomly when requiring. I do not like this option because there may be some reason to keep the app on a specific port.
app.js
const express = require('express');
const auth = require('./auth');
module.exports = (port) => {
const app = express();
app.use(auth.session);
app.get('/allowUser2', (req, res) => {
if (!req.user) return res.status(401).send();
if (req.user.user === 2) return res.status(200).send();
});
app.listen(port).on('listening', () => {
console.log(`HTTP server listening on port ${port}`);
});
return app;
};
when requiring
app = require('../../app.js')((Math.random() * 10000).toString().slice(0, 4));
Instead of exporting the app in app.js, I export a function that launches the server and returns the server instance and app. By exporting the server instance I have the ability to close the server. The app is needed to pass into chai. Make sure const app = express(); is in this function and not before it or it won't recreate.
const express = require('express');
const auth = require('./auth');
const port = 4000;
module.exports = () => {
const app = express();
app.use(auth.session);
app.get('/allowUser2', (req, res) => {
if (!req.user) return res.status(401).send();
if (req.user.user === 2) return res.status(200).send();
});
app.post('/allowUser2', (req, res) => {
if (!req.user) return res.status(401).send();
if (req.user.user === 2) return res.status(200).send();
});
return {
server: app.listen(port).on('listening', () => {
console.log(`HTTP server listening on port ${port}`);
}),
app,
};
};
Then in my tests I can launch the server in before and close the server in after in both tests.
let app;
const sinon = require('sinon');
const auth = require('../../auth.js');
const chai = require('chai');
const chaiHttp = require('chai-http');
const { expect } = chai;
chai.use(chaiHttp);
let server;
describe('route /allowUser2', () => {
before(async () => {
// delete require.cache[require.resolve('../../app.js')]; // causes an error: `Error: listen EADDRINUSE: address already in use`.
sinon.stub(auth, 'session').callsFake((req, res, next) => {
req.user = { user: 2 };
next();
});
server = require('../../app.js')();
agent = chai.request.agent(server.app);
});
after(async () => {
server.server.close(() => {
console.log('Http server closed.');
});
auth.session.restore();
});
it('should allow access', async function () {
const response = await agent.get('/allowUser2');
expect(response.status).to.be.equal(200);
});
});
const chai = require('chai');
const chaiHttp = require('chai-http');
const { expect } = chai;
chai.use(chaiHttp);
let server;
let agent;
describe('route /allowUser2', () => {
before(async () => {
server = require('../../app.js')();
agent = chai.request.agent(server.app);
});
after(async () => {
server.server.close(() => {
console.log('Http server closed.');
});
});
it("shouldn't allow access", async function () {
const response = await agent.get('/allowUser2');
expect(response.status).to.be.equal(401);
});
});
working repo
UPDATE: Proposed Solution https://github.com/DashBarkHuss/mocha_stub_server/pull/1
One problem is the way you are using a direct method reference in app.js prevents Sinon from working. https://gist.github.com/corlaez/12382f97b706c964c24c6e70b45a4991
The other problem (address in use) is because each time we want to get a reference to app, we are trying to create a server in the same port. Breaking that app/server creation into a separate step alleviates that issue.

Chai Unit Testing Error

I am trying to write a unit test for the following file named a.js
var express = require('express');
var router = express.Router();
router.get('/getHCQ', function (req, res) {
res.send("OK");
});
module.exports = router;
Unit test file : a.spec.js
var chai = require('chai');
var chaiHttp = require('chai-http');
var should = chai.should();
var a = require('./a');
describe('Unit Test', function () {
it('should run this', function (done) {
chai.request(a)
.get('/getHCQ')
.end(function(err, res) {
res.should.have.status(200);
done();
});
});
});
I am running it using Mocha but getting the following error :
Uncaught TypeError: Cannot read property 'apply' of undefined
at Immediate.<anonymous> (node_modules/express/lib/router/index.js:635:14)
Can someone please help me to figure out what am I doing wrong here?
Perhaps you forgot to configure chai with chai-http
var chai = require('chai');
var chaiHttp = require('chai-http');
var should = chai.should();
chai.use(chaiHttp); // <-- add this
var a = require('./a');
describe('Unit Test', function () {
it('should run this', function (done) {
chai.request(a)
.get('/getHCQ')
.end(function(err, res) {
res.should.have.status(200);
done();
});
});
});

Mocha and Chai GET request test doesn't work

I'm trying to test the GET request on the home root '/'. The route doesn't exist in my file root.js because
I want that the test fails but it always succeeds.
I don't understand why. There are 3 files: ./test/test.js, ./server/server.js and ./server/routes/index.js
/*File: ./test/test.js */
/* eslint-env mocha */
const chai = require('chai')
const chaiHttp = require('chai-http')
const { expect } = chai
const app = require('../server/server.js')
chai.use(chaiHttp)
describe('GET Home', () => {
it('Should return Not found', () => {
chai
.request(app)
.get('/', (err, res) => {
const result = res.statusCode
expect(result).to.equal(200)
})
})
})
/*File: ./server/server.js */
const express = require('express')
const bodyParser = require('body-parser')
const config = require('./config.js')
const mainRoutes = require('./routes')
const app = express()
app.set('view engine', 'jade')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(mainRoutes)
app.listen(config.port, () => {
console.log(`The application is running on localhost:${config.port}`)
})
module.exports = app
/*File: ./server/routes/index.js*/
const express = require('express')
const router = express.Router()
// router.get('/', (req, res) => {
// res.render('home')
// })
module.exports = router
This is because get run async, you need to call done() for assertion expect(result).to.equal(200) to get checked, otherwise your test will always passed no matter your router exists or not. Checkout this page and search Caveat if you want to know more.
describe('GET Home', () => {
it('Should return Not found', (done) => {
chai
.request(app)
.get('/')
.end(function (err, res) {
const result = res.statusCode
expect(result).to.equal(200)
done()
})
})
})

Chai-http not working

Getting error Uncaught TypeError: Cannot read property 'apply' of undefined
at Immediate. (node_modules/express/lib/router/index.js:618:14)
Server and test files.
// server js file
'use strict';
var express = require('express'); // call express
var app = express();
var port = process.env.PORT || 8080;
// Routes for schedule API
var router = express.Router();
router.get('/', function(req, res, next) {
res.json({"msg":'Hello, World!'});
});
app.listen(port);
console.log('Application running on port ' + port);
module.exports=router;
// test.js
var chai = require('chai');
var chaiHttp=require('chai-http');
var server = require('../server');
var should = chai.should();
chai.use(chaiHttp);
describe('Scheduler', function () {
it('should return hello world', function (done) {
chai.request(server)
.get('/')
.end(function (err, res) {
res.should.have.status(200);
done();
};
});
});
Could anybody help me to track what went wrong here?
You can use expect instead of should it's more easier
var chai = require('chai'), chaiHttp = require('chai-http');
chai.use(chaiHttp);
var expect = chai.expect;
app.get('/check', function(req, res) {
//exemple
expect(req.query.ip,"IP Adress Mismatch").to.be.an.ip;
}

Resources