I'm trying to create a standalone test suite using mocha, that in a perfect world would start up my express.js application, use zombie to render a page, check a bunch of stuff and then teardown/kill the express.js application.
Is there an easy/best way to do this?
NB. I could just have the express application server running prior to running the tests, but what good are Yaks if you're not going to shave them.
First, you need to move your actual app setting up into a module, and import that into the file that actually starts your app. Now that this is seperate, you can have the app in its complete state before actually listening.
You should move the actual setting up of your app into a separate file, let's call it app.js, can call listen from the file you run node off of, let's call it index.js.
So, app.js would look like:
var express = require('express')
, routes = require('./routes');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
and index.js would look like:
var app = require('./app');
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
This seperates loading of your app from actually having it listen, allowing you to load that app into your unit tests.
In your unit tests, you would do something in a setup method and teardown method to bring up and bring down the server.
In the file test/app_tests.js:
describe('app', function(){
var app = require('../app');
beforeEach(function(){
app.listen(3000);
});
// tests here
afterEach(function(){
app.close();
})
});
In addition to Oved D answer.
Describe your app in express-app.js or some other file:
module.exports = function (o) {
o = o || {};
var app = express();
// app.configure
// configure routes
if (o.someOption) {
// some additional test code
}
return app;
}
describe tests in test/01-some.js:
var expressApp = require('../express-app');
describe('some', function () {
// just describe needed vars
var app, server, port;
// describe setup
before(function (next) {
// create app when
app = expressApp({routes: /api\/some\/.*/ /* put here some test options ...*/});
// creating listener with random port
server = app.listen(function () {
// store port when it ready
port = server.address().port;
// and go to tests
next();
});
});
// tests
it('should return valid result', function (done) {
// do a simple request to /api/some
http.request({
host: 'localhost',
port: port,
path: '/api/some'
}, function (res) {
if (res.err) throw new Error(res.err);
done();
});
});
// teardown
after(function () {
// stop listening that port
server.close();
});
});
Done. ;-)
Now you can create any count of tests like that. Recommend you to enable only needed urls and services in tests with defining it by passing params to express-app.js module.
Update:
Not sure how it works in mocha but better to move before and after calls to init.js and load it with mocha --require init.js.
File should looks like that:
// use it in your mocha tests
global.setupEnv = function setupEnv (o, before, after) {
// just describe needed vars
var env = Object.create(null);
// setup
before(function (next) {
// create app
env.app = expressApp(o);
// creating listener with random port
env.server = env.app.listen(function () {
// store port when it ready
port = env.server.address().port;
env.app.log('Listening on ', env.port);
// and go to tests
next();
});
});
// teardown
after(function () {
// stop listening that port
env.server.close();
});
return env;
}
And in your tests:
// requiring dependencies
var request = require('request');
describe('api', function () {
// describe setup
var env = global.setupEnv({
routes: 'api/some'
}, before, after);
// tests
it('should pass', function (done) {
request('http://localhost:' + env.port, function (error, response, body) {
done();
});
});
});
Related
The thing I want to do is modify the response body.
For this I am using a middleware that gets called at every request.
To achieve it, I took a demo application from github https://github.com/ccoenraets/nodecellar . I added a middleware in the server.js similar to the example given on express logging response body.
Still I am unable to modify the response body, as res.send = function (string) does not get called.
Below mentioned is the code. Please let me know what wrong am I doing here.
var express = require('express'),
path = require('path'),
http = require('http'),
wine = require('./routes/wines');
var app = express();
app.configure(function () {
app.set('port', process.env.PORT || 4000);
app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */
app.use(express.bodyParser()),
app.use(express.static(path.join(__dirname, 'public')));
app.use(logResponseBody);
});
app.get('/wines', wine.findAll);
app.get('/wines/:id', wine.findById);
app.post('/wines', wine.addWine);
app.put('/wines/:id', wine.updateWine);
app.delete('/wines/:id', wine.deleteWine);
http.createServer(app).listen(app.get('port'), function () {
console.log("Express server listening on port " + app.get('port'));
});
function logResponseBody(req,res,next){
var send = res.send;
console.log("send resp is: "+send);
res.send = function (string) {
var body = string instanceof Buffer ? string.toString() : string;
console.log("Body found is: "+body);
body = body.replace(/<\/head>/, function (w) {
return 'Modified head' + w;
});
send.call(this, body);
};
res.on('finish', function(){
console.log("Finished " + res.headersSent); // for example
console.log("Finished " + res.statusCode); // for example
})
next();
}
PS: I am starting a new thread for a similar question as I have less than 50 reputation.Therefore cant add comments there.
The best way to add middleware to an express app is to use the app.use method, so you can remove the whole http.createServer block and replace it for something like
app.use(function(req, res, next) {
//do everything you want to happen on every request
next();
});
app.listen(app.get('port'), function() {
console.log('listening on port ' + app.get('port'));
});
For more info on app.use, check the express app use documentation.
I am not able to run socket.io code in node.js, console.log() is also not displaying when running the code. Below is the code.
app.js
var express = require('express');
var http = require('http');
var app = express();
app.set('port', process.env.PORT || 3000);
app.post('/testStream',test.testStream);
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
module.exports.appServer = server;
and I have created a test.js file where I am accessing this exported variable appServer.
var server = require('../app.js');
exports.testStream = function(req,res){
var io = require('socket.io').listen(server.appServer);
io.on('connection',function(socket){
console.log("in socket");
fs.readFile('E:/temp/testimg.png',function(err,buf){
socket.emit('image',{image: true,buffer: buf});
console.log("test image");
});
})
}
when the code runs it stucks and not showing the console.logs(). What I am doing wrong over here. Any help is very much appreciated.
I would suggest following the code structure as suggested in socket.io docs.
Also, you should not be calling io.listen or io.on('connection') inside your testStream express middleware. These are things you should only be doing once, and ideally they should happen during startup, inside app.js and not in reaction to a POST request. In fact, I'm not sure what the purpose of your testStream middleware is, its not even returning any response (eg res.end())
If you want to handle socket connections in a separate module you can, but instead of exporting your app's server the way you are, try passing the io instance as variable to your submodule. In short, try this:
app.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var test = require('./test')(io);
app.set('port', process.env.PORT || 3000);
server.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
test.js
module.exports = function(io) {
io.on('connection', function(socket) {
console.log("in socket");
fs.readFile('E:/temp/testimg.png', function(err, buf) {
socket.emit('image', {
image: true,
buffer: buf
});
console.log("test image");
});
});
};
I've been bouncing back and forth between socket.io and express.io - but settled for socket.io with Express 4, as I would like to use Namespaces.
I have worked on some examples of having an Express 4 Server using Socket.io - but most examples are based on one file with everything in it. I am trying to separate all my code to make it easier but I am at a loss as to how to add Socket.io (or where).
I have index.js which uses Cluster and basically calls server.js:
var server = require( "./server.js" );
var cluster = require('cluster');
var webApp={
run: function(){
console.log('Starting: Server');
server.listen();
}
};
if(cluster.isMaster){
cluster.fork();
cluster.on('exit',function(worker){
console.log('Worker ' + worker.id + ' died..');
setTimeout( function () { cluster.fork(); }, 1000 );
});
} else{
try {
webApp.run();
}
catch(e)
{
console.log(e);
process.exit(1);
}
process.on('uncaughtException', function(err){
console.log(err);
process.exit(1);
});
process.on( 'SIGINT', function () {
console.log( "\n SIGINT (Crtl-C)" );
//Kill worker
cluster.disconnect();
process.exit(1);
});
}
This then calls the server.js file:
var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var config = require('./config/config.js');
var router = require('./routes');
var Server = Object.subClass({
/**
* Constructor
*/
init:function(){
this.appServer = express();
var that = this;
var appServer = this.appServer;
appServer.use(express.static(__dirname + '/public'));
appServer.set('views', path.join(__dirname, 'views'));
appServer.set('view engine', 'ejs');
appServer.use(bodyParser.urlencoded({ extended: true }));
appServer.use(bodyParser.json());
appServer.get('/',router.root);
},
/**
* Listener HTTP
*/
listen:function(){
var port = config.rest.port;
console.log(':: on port:' + port);
this.appServer.listen(port);
}
});
module.exports = new Server();
I am only having one 'route', which is the '/' and is defined in routes.js file. The page loads fine but where do I add the server side socket.io? and do I add any socket.io namespace definitions in the routes.js file or in the javascript of the page being loaded?
There are so many ways of using sockets that I can't seem to work out the best approach for my multi-file approach.
Any help would be brilliant as I seem to be going in circles.
Enjoy our Saturday :)
Thanks again.
I've spent the morning looking at the Cluster/Worker approach and decided to use 'SocketCluster' as it seems to do what I need.
Enjoy your Sunday
i dont know why im getting this error:
this is my code
/*
Chat application for #node.js
express version.
*/
//Load modules.
var express = require('express'),
socket = require('socket.io'),
swig = require('swig'),
fs = require('fs');
//Load config.
console.log('Loading configuration.');
var config = fs.readFileSync('config.json');
var config = JSON.parse(config);
var port = config.port;
var views = config.views;
console.log('Configuration loaded.');
console.log(config);
//Initiate express module in app.
var app = express();
// app.get('/', function(request, response)
// {
// fs.readFile('./views/index.html', function(error, data)
// {
// if(error)
// {
// response.send('View cannot be rendered.');
// }
// response.type('html');
// response.send(data);
// });
// });
var test = "Hello";
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
swig.setDefaults(
{
cache: false
});
app.get('/', function(request, response)
{
response.render('index',
{
//Var to be named in the render : value;
'test': test,
'Title': 'Testing page',
});
});
//logger.
app.use(function(request, response, next)
{
console.log('%s %s', request.method, request.url);
next();
});
//Set directory for static files (css, js, img)
app.use(express.static(__dirname + '/public'));
//Run the app.
app.listen(port);
it might be some kind of error with the framework itself, but i dont get the clue why, i was using it last night with no error, now im getting this error this morning..
EADDRINUSE means another process is already listening on the same port. Probably this is an earlier run of your server that is still running/crashed and still using the port. Find that process, terminate it, and retry. This is not an error in your javascript code.
Also since you are binding port 80 and running windows, it could be that another web server such as IIS is running and using port 80.
The ports from 0 to 1024 are typically reserved for OS to use. Though its not a thumb rule not to use ports between these limits, its always safe to not use ports in this range to avoid accidental/occassional collision of using port#s.
I'm using Greg Franko's great Backbone-Require-Boilerplate and I was thinking about SEO so I found Phantom.js
Now I'm trying to integrate it and found.
http://backbonetutorials.com/seo-for-single-page-apps/
which looks like the answer but just couldn't make this work. I have PhantomJs installed.
and my server.js is
// DEPENDENCIES
// ============
var express = require("express"),
http = require("http"),
port = (process.env.PORT || 8001),
server = module.exports = express();
// SERVER CONFIGURATION
// ====================
server.configure(function() {
server.use(express["static"](__dirname + "/../public"));
server.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
server.use(server.router);
server.get(/(.*)/, respond);
});
// SERVER
// ======
// Start Node.js Server
var app = http.createServer(server);
app.listen(port);
So how would I ever plug Phantom.js in this?
if you are looking for a node integration with express, please look at this:
https://github.com/Obvious/phantomjs
EDIT:
and here is a working phantomjs node-module:
https://github.com/amir20/phantomjs-node
var phantom = require('phantom');
phantom.create().then(function(ph) {
ph.createPage().then(function(page) {
page.open('https://stackoverflow.com/').then(function(status) {
console.log(status);
page.property('content').then(function(content) {
console.log(content);
page.close();
ph.exit();
});
});
});
});