I have a node/express application with a controller and service. While running the unit test for controller via Grunt/Jasmine, the test runs fine but after the coverage summary I get the following error:
error: Error on SAVE state TypeError: Cannot read property 'apply' of undefined
at /node_modules/express/lib/router/index.js:603:14
at next (/node_modules/express/lib/router/index.js:246:14)
at next (/node_modules/express/lib/router/route.js:100:14)
Controller.js
var express = require('express'),
router = express.Router();
module.exports = function(app) {
app.use('/api', router);
router.post('/save', function(req, res, next) {
// Service code is invoked here with the success/error callback
// on success - res.json(response);
// on error - res.status(err.status);
});
}
ControllerSpec.js
var app = require('../mockApp'); // the app.js and the express app is mocked here
var httpMocks = require('node-mocks-http');
var request = require('request');
describe("Controller SAVE Action", function () {
it("With Error", function () {
spyOn(service, "save").andCallFake(function (req, res, headers, callback) {
callback({category: "Error"});
});
var rout = app.getRouter("/state"); // the mocked app.js contains a getRouter function which returns the corresponding router which is simply express.Router()
var request = httpMocks.createRequest({
method: 'POST',
url: '/save',
headers: {"authorization": "success"}
});
var response = httpMocks.createResponse();
rout(request, response);
var data = JSON.parse(response._getData());
expect(data.code).toEqual(400);
});
});
Mocked app.js
var m = {};
var routers = {};
module.exports = {
get: function (name) {
return m[name];
}, set: function (name, obj) {
m[name] = obj;
}, use: function (path, router) {
if (router) {
routers[path] = router;
}
}, getRouter: function (path) {
return routers[path];
}
};
Mocked Express.js
var app = require('./app'); // Mocked app.js
var services = {};
var serviceFiles = glob.sync(rootPath + '/app/services/*.js');
serviceFiles.forEach(function (file) {
var service = require(file)(app);
services[service.serviceName] = service;
});
app.set("services", services);
var controllers = glob.sync(rootPath + '/app/controllers/*.js');
controllers.forEach(function (controller) {
require(controller)(app);
});
Related
I want to render to the ui / print to console log some object value from GET response.
I'm using Node JS for my server side and HTML + JS for my client side.
Because my goal is to render data and the request type is cross domain I can't use "fetch" function.
My only alternative to execute it is to send it by "JSONP" dataType.
Actually, the request is sent and the response receives by callback as well, but my code is print "null" to the console and not the response data.
When I've tried to used JSON.parse() it received a "parseerror".
The expected result it's to get only the image tag value (2.0.90) and to print this inside the console log / render it to the UI.
async function uiChecking() {
let index;
const hostsDock = [qa + dockers];
let lengthVal = hostsDock.length;
for (let hostIndxD = 0; hostIndxD < lengthVal; hostIndxD++) {
index = hostIndxD;
let url = hostsDock[hostIndxD];
$.ajax({
url: url,
dataType: 'jsonp',
}).done( function(data) {
console.log("A " + data);
});
}
}
**Server.js **
var express = require('express');
var cors = require('cors');
var app = express();
var path = require("path");
var fetch = require('fetch-cookie')(require('node-fetch'));
var btoa = require('btoa');
var http = require('http');
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
}else{
corsOptions = { origin: false } // disable CORS for this request
}
callback(null, data , corsOptions) // callback expects two parameters: error and options
};
app.engine('.html', require('ejs').__express);
app.set('views', __dirname + '/view');
app.set('view engine', 'html');
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res){
res.render('index');
res.render('logo');
res.writeHead(200, {'Content-Type': 'application/json'});
});
// app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
// res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
// });
app.get('/data/:id', function (req, res, next) {
var opts = {
host: config.alertService.host,
port: config.alertService.port,
method: 'GET',
path: '/DataService/rest/receiveData/' + req.params.id
}
var reqGet = http.request(opts, function (dataResponse) {
var responseString = '';
dataResponse.on('data', function (data) {
responseString += data;
});
var response = {x:[],y:[],z:[],t:[]};
dataResponse.on('end', function () {
var responseObject = JSON.parse(responseString);
var accs = responseObject.data.listPCS;
for(var i in accs){
response.x.push(accs[i].accX);
response.z.push(accs[i].accY);
response.y.push(accs[i].accZ);
response.t.push(accs[i].timestamp);
}
res.jsonp(response);
});
});
reqGet.end();
reqGet.on('error', function (e) {
console.error(e);
});
});
if (app.settings.env === 'production') {
app.error(function(err, req, res) {
res.render('new404.html', {
status: 500,
locals: {
error: error
}
});
});
}
app.listen(8033, function () {
console.log('CORS-enabled web server listening on port 8033')
});
You need to iterate through the response to return the result e.g..
$.each(data, function(index) {
console.log(data[index].ui);
console.log(data[index].id); console.log(data[index].Name);
});
I've got this little piece of code:
'use strict';
module.exports = MainCtrl;
function MainCtrl() {
this.defaultUrl = 'http://foo/';
}
MainCtrl.prototype.getPoi = function getPoi() {
request( 'http://foo/',function(error,response,body) {
console.log( body );
});
};
and on my route file I require like this:
var express = require('express');
var request = require('request');
var main_lib = require('../lib/main_ctrl.js');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/newroute', function(req,res) {
//var mainCtrl = new main_lib.MainCtrl();
main_lib.getPoi();
res.render('newroute', { title: 'New Route' });
})
module.exports = router;
As you can see is very simple, I'm on my first steps with ExpressJS and NodeJS but I don't know why I've got this error:
TypeError: Object function MainCtrl() { this.defaultUrl = 'http://foo/'; } has no method 'getPoi'
I've look at the definition of the view module on express lib and is the same as:
module.exports = View;
function View(name, options) { .. }
View.prototype.lookup = function lookup(name) { .. }
But I can't understand what I'm doing wrong.
You are getting error for calling function of MainCtrl you need to create object of this class.
Use following code
'use strict';
function MainCtrl() {
this.defaultUrl = 'http://foo/';
}
MainCtrl.prototype.getPoi = function getPoi() {
request( 'http://foo/',function(error,response,body) {
console.log( body );
});
};
//added function for getting instance
module.exports.getInstance = function () {
return new MainCtrl();
};
While adding controller in router use this:
var main_lib = require('../lib/main_ctrl.js').getInstance();
Now main_lib is object of your controller. So you can call like:
main_lib.getPoi();
If you want to use like View module then manually you have to create object for this. like
'use strict';
module.exports = MainCtrl;
function MainCtrl() {
this.defaultUrl = 'http://foo/';
}
MainCtrl.prototype.getPoi = function getPoi() {
request( 'http://foo/',function(error,response,body) {
console.log( body );
});
};
In route file:
var main_lib = require('../lib/main_ctrl.js');
var main_lib_object = new main_lib();//take a look here
main_lib_object.getPoi(parameter);
I'm testing forms-angular (http://www.forms-angular.org/).
I define a DataFormHandler variable in my index.js file. And also I need to get this variable in my controllers. How may I get it? This setter doesn't work app.set("formHandler", DataFormHandler).
Here is the code:
index.js
'use strict';
var formsAngular = require('forms-angular'); // require formsAngular
var kraken = require('kraken-js'),
app = require('express')(),
options = {
onconfig: function (config, next) {
//any config setup/overrides here
next(null, config);
}
},
port = process.env.PORT || 8000;
// Here I initialize FormHandler. It requires the app, so I initialize it here, in index.js
// HOW TO GET THIS VAR IN CONTROLLERS?
var DataFormHandler = new (formsAngular)(app);
app.set("fh", DataFormHandler); // THIS DOESN'T WORK. UNDEFINED in controller
app.use(kraken(options));
app.listen(port, function (err) {
console.log('[%s] Listening on http://localhost:%d', app.settings.env, port);
});
The setter app.set("fh", DataFormHandler) doesn't work. When I try to get fh from within a controller it is undefined:
app\controllers\index.js
'use strict';
var UserModel = require('../models/user');
module.exports = function (router) {
var user = new UserModel();
router.get('/', function (req, res) {
var DataFormHandler = req.app.get("fh");
DataFormHandler.addResource('user', UserModel);
console.log("DataFormHandler", DataFormHandler); // undefined
var model = {
hello: "Hello"
}
res.render('index', model);
});
};
How to get a variable in a controller?
I found one solution that works. But not sure that it's the correct one.
Instead of
app.set(key, value)
which doesn't work, I use
app.locals.key = value
that for some reason works.
I'm creating basic NodeJS/Express?MongoDb app. I have api module (controller) that basically checks the path and tells models to do things:
api.js
var users = require("../models/user");
module.exports = function(app, u) {
app.get('/api/v1/users/get-all', function(req, res, next) {
res.json({
users: users.getAll()
});
});
};
Users is another module that represents model. getAll method is called from api module and reads data from MongoDb:
users.js
Users = function() {
Users.prototype.getAll = function(req, res, next) {
var cursor = this.db.users.find();
// return all the users as json
cursor.toArray(function(err, items) {
return items;
});
}
Users.prototype.setDb = function(db) {
this.db = db;
}
};
module.exports = new Users();
I only realised that MongoDB this.db.users.find() call is asynchronous and so when getAll comes back from users module, my API module with res.json(..) got empty result to work with.
Now, I was thinking that one option would be to pass res. object from api module to users, and users would respond with data back to client when data would be ready:
api.js
var users = require("../models/user");
module.exports = function(app, u) {
app.get('/api/v1/users/get-all', function(req, res, next) {
users.getAll(res)
});
};
users.js
Users = function() {
Users.prototype.getAll = function(res) {
console.log("aaaaaaaaaaaaaaaa " + this.db);
var cursor = this.db.users.find();
// return all the users as json
cursor.toArray(function(err, items) {
res.json({
users: items
});
});
}
Users.prototype.setDb = function(db) {
this.db = db;
}
};
module.exports = new Users();
This seems to work however if I understand correctly model should not have to do anything twith this sort of work, returning stuff to client etc.
Then I thought about using promises for this and this what I came up with:
api.js
var users = require("../models/user");
module.exports = function(app, u) {
app.get('/api/v1/users/get-all', function(req, res, next) {
users.getAll().then(function(res) {
console.log("u=users " + (res));
res.json({
users: res
});
});
});
};
users.js
var Q = require("q");
Users = function() {
Users.prototype.getAll = function(req, res, next) {
console.log("aaaaaaaaaaaaaaaa " + this.db);
var cursor = this.db.users.find();
// return all the users as json
return new Q.Promise(function(resolve, reject) {
cursor.toArray(function(err, items) {
resolve(items);
});
});
}
Users.prototype.setDb = function(db) {
this.db = db;
}
};
module.exports = new Users();
I love the simplicity of promises and wanted to know if there is any obvious flaw in my implementation in how the modules are taking to each other rather than in details.
I am trying to close a http server associated with a socket.io instance, using mySocketIoInstance.close(), but I am getting the following error:
Uncaught TypeError: Object #<Server> has no method 'close'
at Socket.<anonymous> (/home/jackson/projects/tcg/test/server/ServerLobbySpec.js:35:20)
at Socket.Emitter.emit (/home/jackson/projects/tcg/node_modules/socket.io-client/node_modules/component-emitter/index.js:134:20)
at Socket.emit (/home/jackson/projects/tcg/node_modules/socket.io-client/lib/socket.js:128:10)
at Socket.onconnect (/home/jackson/projects/tcg/node_modules/socket.io-client/lib/socket.js:306:8)
at Socket.onpacket (/home/jackson/projects/tcg/node_modules/socket.io-client/lib/socket.js:206:12)
at Manager.<anonymous> (/home/jackson/projects/tcg/node_modules/socket.io-client/node_modules/component-bind/index.js:21:15)
at Manager.Emitter.emit (/home/jackson/projects/tcg/node_modules/socket.io-client/node_modules/component-emitter/index.js:134:20)
at Manager.ondecoded (/home/jackson/projects/tcg/node_modules/socket.io-client/lib/manager.js:270:8)
at Decoder.<anonymous> (/home/jackson/projects/tcg/node_modules/socket.io-client/node_modules/component-bind/index.js:21:15)
at Decoder.Emitter.emit (/home/jackson/projects/tcg/node_modules/socket.io-client/node_modules/socket.io-parser/node_modules/emitter/index.js:132:20)
Here's where I'm trying to close it:
'use strict';
var http = require('http'),
expect = require('chai').expect,
socketIo = require('socket.io'),
socketIoClient = require('socket.io-client'),
ServerLobby = require('../../source/server/ServerLobby');
describe('ServerLobby', function () {
var port = 2468,
uri = 'http://localhost:' + port;
describe('is connectable', function () {
it('should connect', function (done) {
var httpServer = http.Server().listen(port),
io = socketIo(httpServer),
lobby = new ServerLobby(io),
socket = socketIoClient(uri + lobby.namespace);
socket.on('connect', function () {
// HERE
io.close();
// HERE
done();
});
});
});
});
I tried commenting-out the lobby and socket code and just console.log'd io.close and got undefined.
My version is 1.0.6. According to socket.io/test/socket.io.js (also 1.0.6), I should be able to close the server in the following way:
var http = require('http').Server;
var io = require('..');
var expect = require('expect.js');
// ...
it('should be able to close sio sending a srv', function() {
var PORT = 54016;
var srv = http().listen(PORT);
var sio = io(srv);
var clientSocket = client(srv, {
reconnection: false
});
clientSocket.on('connect', function init() {
expect(sio.nsps['/'].sockets.length).to.equal(1);
// HERE
sio.close();
// HERE
});
});
My setup looks almost exactly like that. Please advise.
In the examples and in the test you have included, it shows a socket.io object being constructed with a server object that has been initialized in a different manner.
Try this:
var http = require('http').Server,
// ...
var httpServer = http().listen(port);
Full example taken from link at time of posting:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});