Node/Express.js mocha setup not working - node.js

Here is my test file:
var request = require('superagent'),
expect = require('expect'),
sinon = require('sinon'),
app = require("../../../../app");
request = request(app);
describe("HealthCheck", function () {
describe("/health_check", function () {
it("should return a 200 status", function (done) {
request
.get("http://localhost:3000/health_check")
.end(function(err, res) {
expect(res).to.exist;
expect(res.status).to.equal(200);
expect(res.body).to.contain('OK');
return done();
});
});
});
})
The error I keep running into is
1) HealthCheck /health_check should return a 200 status:
TypeError: Cannot call method 'end' of undefined
Can't figure out what I am doing wrong
Here is my app.js:
require('coffee-script/register');
var express = require('express'),
config = require('./config/config'),
fs = require('fs');
var app = express();
require('./config/express')(app, config);
app.listen(config.port);
exports.app = app;

You're exporting app as app
Therefore, when you require the module, you'll need to require the name of the function you're exporting - in this case 'app'
So, you can either change your test
var request = require('superagent'),
expect = require('expect'),
sinon = require('sinon'),
app = require("../../../../app");
request = request(app.app);
Or change your app.js to exports a single function:
Change
exports.app = app;
to
module.exports = app;
There's a good article on this here: http://openmymind.net/2012/2/3/Node-Require-and-Exports/

Related

Deploying a Node app on Azure Functions

I am wondering about how it might be possible to deploy a Node.js app on Azure Functions.
Basically, I have a function setup and running a basic hello world http example that looks like:
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
context.res = {
// status: 200, /* Defaults to 200 */
body: "Hello " + req.params.name
};
context.done();
};
The app I am trying to deploy into a function is a simple moc client that uses swagger (basically takes a request and returns some xml). The app.js looks like:
const SwaggerExpress = require('swagger-express-mw');
const app = require('express')();
const compression = require('compression');
const configSwagger = {
appRoot: __dirname, // required config
};
SwaggerExpress.create(configSwagger, (err, swaggerExpress) => {
if (err) {
throw err;
}
// install middleware
swaggerExpress.register(app);
// server configuration
const serverPort = process.env.PORT || 3001;
app.listen(serverPort, () => {
//logger.info('Listening on port %s', serverPort);
});
app.use(compression());
});
module.exports = app; // for testing
The thing I am not sure about is how to handle module.exports = app when modeul.exports is used to establish the function (i.e. module.exports = function (context, req))
You can try to use azure-function-express to enable your swagger middleware.
Note that certain middleware will not function correctly (for example, body-parser). This is because the functions req is not a stream - it is injected into the function with a 'body' property already populated.

app is undefined in loopback custom js file

i am using nodejs loopback framework.i want to run a cron job.i created a custom js file for this cron job in server/boot folder.but when manually i run this file(xyz). app is undefined.my code is below
var app = require('../server.js');
console.log(">>>>>>>>>>>>>>in test")
var subscription = app.models.UserNotification;
console.log(">>>>>>>>>>>..in manage")
var datasource=subscription.dataSource;
var query="SELECT DISTINCT userId FROM users_subscription";
datasource.connector.query(sql,function (err, data) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>data is>>>>>",data);
})
here is my server.js file
var bodyParser = require('body-parser');
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
var passport = require('passport');
var bodyParser = require('body-parser').urlencoded({
extended: true
})
app.use(bodyParser)
app.use(loopback.context());
app.use(loopback.token());
var path = require("path");
var url = require('url');
var http = require('http');
var fs = require('fs');
var request = require('request');
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
app.use(loopback.static(path.resolve(__dirname, '../client')));
app.use(loopback.static(path.resolve(__dirname, '../admin')));
app.use(loopback.static(path.resolve(__dirname, '../other-dir')));
boot(app, __dirname, function(err) {
if (err) throw err;
if (require.main === module) app.start();
});
Thanks,
It's really impossible to say for sure since you don't include the code that is included with:
var app = require('../server');
(which would be the most important code to include if the require returns undefined) but if app is undefined then it means that the module is loaded but its module.exports is undefined.
Do you export anything from that module?
Are you sure that it is really app that is undefined and not, say, app.models?
Without knowing the code in question those are the most reasonable things to investigate.
Update
If you don't export anything from your server.js (which was my suspection in my answer above, but now you confirmed it with you code and comment) then after this line:
var app = require('../server.js');
you will not be able to use app.models.UserNotification
If you want to use app.models in the code that requires server.js, then you'll have to add:
module.exports.models = SOMETHING;
in your server.js code. You don't seem to have anything called models in server.js, you don't export anything as module.exports.models, so you can't expect app.models to be defined in your code that does:
var app = require('../server.js');

aws-sdk upload to S3 works in KOA but stops working when invoked via Mocha

I need to upload a file to s3 from koa, I'm pretty new to koa and probably missing something obvious. It actually does complete with 200, but the file never shows up on s3.
Here is a fragment from my app.js:
'use strict';
var jwt = require('koa-jwt');
var bodyParser = require('koa-bodyparser');
var koaBody = require('koa-body');
const app = module.exports = require('koa')()
.use(koaBody({multipart:true})) // this is to pase only multipart forms
.use(require('./routes/common'))
.use(require('./routes/auth'))
.use(require('./routes/users_public'))
.use(jwt({ secret: SECRET }))
//protected routes below this line
.use(require('./routes/subcontractors_private'))
.listen(process.env.PORT || 3000);
subcontractors_private.js looks like this:
'use strict';
var AWS = require('aws-sdk');
var fs = require('fs');
var zlib = require('zlib');
var S3_BUCKET = require('../consts').S3_BUCKET;
var S3_OPTIONS = require('../consts').S3_OPTIONS;
module.exports = require('koa-router')()
.post('/subcontractors/:subcontractor_id/coi', function *(next) {
var body = JSON.stringify(this.request.body, null, 2)
let subcontractor_id = this.params.subcontractor_id;
var file = this.request.body.files.coi.path;
var body = fs.createReadStream(file).pipe(zlib.createGzip());
var s3obj = new AWS.S3(
{params:
{
Bucket: 'coi-test',
Key: 'i/' + subcontractor_id + '.png.zgip'
}
});
s3obj.upload({Body: body})
.on('httpUploadProgress', function(evt) {
console.log(evt);
})
.send(function(err, data) {
console.log(err, data);
});
this.response.status = 200;
this.body = { "result": "subcontractor CIO successfully uploaded"};
})
.routes();
And finally, fragments of the subcontractor_private.js from the test folder:
'use strict';
const supertest = require('co-supertest'); // SuperAgent-driven library for testing HTTP servers
const expect = require('chai').expect; // BDD/TDD assertion library
require('co-mocha'); // enable support for generators in mocha tests using co
var uuid = require('uuid');
var db = require('../../consts').DB;
var moment = require('moment');
const app = require('../../app.js');
const request = supertest.agent(app.listen());
var assert = require('assert');
describe('/subcontractors private routes testing', function() {
it.only('should be able to upload COI for subcontractor', function*() {
const coi_expires_at = moment().add(1, 'd').format();
const response =
yield request.post('/subcontractors')
.set('Content-Type', 'application/json')
.set('Authorization', 'Bearer ' + token)
.send({name: "Joe Doh"})
.end();
//now try to upload the coi file
const response1 =
yield request.post('/subcontractors/' + response.body.subcontractor.id + "/coi")
.set('Authorization', 'Bearer ' + token)
.field('Content-Type', 'multipart/form-data')
.field('coi_expires_at', coi_expires_at)
.attach('coi', './assets/logo-big.png')
.end();
expect(response1.status).to.equal(200, response1.text);
expect(response1.body).to.be.an('object');
expect(response1.body).to.be.json;
expect(response1.body).to.contain.keys('result');
expect(response1.body.result).to.equal('subcontractor CIO successfully uploaded');
});
});
I tried the upload code as a standalone js file (ran via node) and it works fine. But when I run it as a node app from mocha test -- the method completes with response 200 and never finishes the upload. What am I doing wrong?
The problem is with asynchronous nature of this stuff. The test finishes w/o waiting for the request to finish (or even start properly).
I am not entirely clear how to do it correctly, but adding this:
it.only('should be able to upload COI for subcontractor', function*(done) {
(done callback argument) makes the test wait for the "done" callback to be invoked, thus allowing aws sdk to finish the request. I am not sure how to fix your test, however, because the this is twice-asynchronous. The controller method in your koa server returns asynchronously w/o waiting for S3 request to finish, so the mocha test has no way of waiting for S3 processing to complete.
(also see my related question:
aws-sdk s3 upload not working from mocha test)

not able to export variable( var app = express()) in nodejs using express

I need help in trying to solve this scenario
I have a file web.js. Over there I have
var express = require("express");
var app = express();
var web2 = require("./web2");
/* Code the start the server on the required port*/
app.get('/param1', function(req, res){
console.log("INSIDE GET METHOD OF WEB.JS");
});
module.exports.app = app
I have another file web2.js. over there I have
var web = require("./web");
app = web.app;
app.get('/param2', function(req, res){
console.log("INSIDE GET METHOD OF WEB2.JS");
});
While starting I get an error
TypeError: Cannot call method 'post' of undefined
If I remove the line 3 from web.js -- I am able to start the server, but a request for http:///param2 gives a 404
Updated scenario:
I am using pg database and I try to create a client that keeps an instance of the client(in web.js). I then pass this to other file(web2.js). In web.js I always get this client as null
in web.js I have the following code
var pg = require("pg");
var pgclient;
app.get('*', function(req,res,next){
pg.connect(process.env.DATABASE_URL, function(err, client, done) {
if(client != null){
pgclient = client;
console.log("Client connection with Postgres DB is established");
next();
}
}
}
require("./web2.js")(app, pgclient);
in web2.js, I have the following code
module.exports = function(app, pgclient){
app.get('/param1', function(req,res){
if(pgclient != null){
}
else{
res.send(500, "pgclient is NULL");
}
});
}
The code never reaches the if block(if(pgclient != null)) in web2.js
The problem is the cyclic dependency between web.js and web2.js. When web2.js requires web.js, web.js's module.exports hasn't been set yet. I would rather do something like this:
web.js
var express = require("express");
var app = express();
app.get("/param1", function (req, res) {
// ...
});
require("./web2")(app);
app.listen(/* port number */);
web2.js
module.exports = function (app) {
app.get("/param2", function (req, res) {
// ...
});
};

Node.js + Express passing an object

I'm building a small node.js/express project and have a function in configure.js that sets configuration options in my express app. For example:
server.js
var express = require('express');
var server = ('./configure');
var app = express();
server.configure(app);
configure.js
exports.configure = function(app) {
app.set('title', 'Server');
};
This doesn't work but I hope it explains what I'm trying to do. I want to make changes to the app instance in server.js. How do I do this?
EDIT:
Okay I think i can get this all working if i understand why this isn't working. Is it to do with timing of the callback? The second console.log() isn't called.
configure.js
var fs = require('fs');
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
function configure(app) {
var config = module.exports = {};
fs.readFile('config.txt', function (err, data) {
if (err) throw err;
config.title = decoder.write(data)
console.log(config.title)
});
if(config.title) console.log(config.title);
//app.set('title', config.title)
}
module.exports = function (app) {
configure(app);
};
server.js
var express = require('express');
var cfg = require('./configure');
var fs = require('fs');
var app = express()
cfg(app)
(config.txt is echo 'server' > config.txt)
What you have should actually work.
As for your question about using multiple functions, you can export and call each separately. This can be useful when timing is important (such as if other setup steps need to occur that aren't specified in configure.js):
// configure.js
exports.configure = function (app) {
// ...
};
exports.attachMiddlware = function (app) {
// ...
};
// server.js
var express = require('express');
var server = require('./configure');
var app = express();
server.configure(app);
server.attachMiddlware(app);
You can also define a single entry function as the exported object which calls the functions needed within configure.js. This can possibly keep server.js cleaner by isolating the maintenance within configure.js:
function configure(app) {
// ...
}
function attachMiddleware(app) {
// ...
}
module.exports = function (app) {
configure(app);
attachMiddleware(app)
};
var express = require('express');
var configure = require('./configure');
var app = express();
configure(app);
I would avoid that and just do a json object:
app.js
var cfg = require('./config');
app.set('title', cfg.title);
config.js
var config = module.exports = {};
config.title = 'Server';

Resources