TypeError: Object function.....has no method 'on' - javascript

I am new to node.js and trying to create my first module.
But i am getting an error
TypeError: Object function SetAstAppLog.....has no method 'on'
My module file contains following code :
var EventEmitter = require('events').EventEmitter;
var util = require('util');
module.exports = SetAstAppLog;
util.inherits(SetAstAppLog, EventEmitter);
function SetAstAppLog(logFolderPath,fileNamePrefix,fileSize,logStreamObject) {
EventEmitter.call(this);
.
.
.
.
this.emit('objCreated');
}
and in app.js i am doing following things :
var SetAstAppLog = require('astAppLog');
var fileSize = 1024;
SetAstAppLog.on('objCreated', function () {
console.log('an object was created');
});
SetAstAppLog.on('written', function () {
console.log('Write operation completed.');
});
var objCommLogger = new SetAstAppLog(logFolderPath,logCommFilePrefix,fileSize,logCommMsg);
var objErrorLogger = new SetAstAppLog(logFolderPath,logErrorFilePrefix,fileSize,logErrorMsg);
Here, i am using node js with v0.10.21.
I am not able to find out why i am getting this error even my module file contains EventEmitter
Can anyone help to solve this issue?

You are exporting the function without calling it. You need to call it:
var SetAstAppLog = require('astAppLog')();
Edit: I failed to notice that you called the function lower in your script. You should be attaching the event handlers to the instances, not the constructor.
var objCommLogger = new SetAstAppLog(logFolderPath, logCommFilePrefix, fileSize, logCommMsg);
objCommLogger.on(...);

Related

Cannot read property push of undefined in my node application

I am new to node and express. When I issue the command npm start to start my application, I am getting this error Cannot Read property push of undefined from my index.js file.
This is the code causing issue. Please help me:
proto.route = function route(path) {
var route = new Route(path);
var layer = new Layer(path, {
sensitive: this.caseSensitive,
strict: this.strict,
end: true
}, route.dispatch.bind(route));
layer.route = route;
this.stack.push(layer);
return route;
};
These are my imports in the file:
var Route = require('./route')
var Layer = require('./layer');
var methods = require('methods');
var mixin = require('utils-merge');
var debug = require('debug')('express:router');
var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var parseUrl = require('parseurl');
var setPrototypeOf = require('setprototypeof')
Please help me in fixing this. I am not getting any solution for this.
The problem is in the line this.stack.push(layer);. The element stack is defined elsewhere and in the function he cannot access it.

How to mock event handler method using sinon.js?

I am newbie to Node.js and I am writing DAO layer for HBase which will wrap thrift and provide clear interface to other layers. I am trying to write unit tests for it using sinon.js and mocha but not sure how to ensure mock one event of Thrift connection class and its event handler.
My DAO code is as follows:
var thrift = require('thrift');
var libDirRelativePath = "../../../lib";
var hbaseThriftDirPath = libDirRelativePath + "/hbase-gen-nodejs";
var hbase = require(hbaseThriftDirPath + '/THBaseService');
var hbaseTypes = require(hbaseThriftDirPath + '/hbase_types');
var thritfPrimaryServerAddress = 'nn2';
var thritfBackupServerAddress = 'backup-nn2';
var thriftServerPort = 9090;
exports.putRows = function(tableName, putObjectArray, callback) {
var primaryClusterConnection = thrift.createConnection(thritfPrimaryServerAddress, thriftServerPort, {
transport: thrift.TBufferedTransport,
protocol : thrift.TBinaryProtocol
});
console.log('DEBUG : connection object created.');
var client = thrift.createClient(hbase, primaryClusterConnection);
console.log('DEBUG : client object created.');
primaryClusterConnection.on('connect', onConnectOfPutRows);
primaryClusterConnection.on('connect', function() {
console.log('Connected to HBase thrift server at ' + thritfPrimaryServerAddress + ":" + thriftServerPort);
client.putMultiple(tableName, putObjectArray, callback);
connection.close();
});
primaryClusterConnection.on('error', function() {
console.log('Error occurred in HBase thirft server connection.');
});
}
For above code I Just want to create stubs primaryClusterConnection and client objects which I have managed but problem is that stub of primaryClusterConnection doesn't have any idea about connect event and its handler so console.log('Connected to HBase thrift server at '... line never gets executed. I want to test that part of the code as well. Can anyone please help me in writing proper stubs/mocks for this problem?
My test code is as follows:
var hbaseDao = require('../../../src/dao/hbase/HBaseDao.js');
var libDirRelativePath = "../../../lib";
var hbaseThriftDirPath = libDirRelativePath + "/hbase-gen-nodejs";
var hbase = require(hbaseThriftDirPath + '/THBaseService');
var chai = require('chai');
var should = chai.should();
var expect = chai.expect;
var sinon = require('sinon');
describe("HBaseDao", function() {
describe(".putRows()", function() {
it("Should execute callback after inserting objects in HBase.", function(done) {
var commonStub = sinon.stub();
var connection = {
close : function() {
console.log('connection closed.');
}
};
commonStub.withArgs('nn2', 9090).returns(connection);
var client = {};
commonStub.withArgs(hbase, connection).returns(client);
var tableName = 'DUMMY_READINGS_TABLE';
var callBackMethod = function() {
console.log('dummy callback function.');
};
commonStub.withArgs(tableName, [], callBackMethod).returns(0);
hbaseDao.putRows(tableName, [], callBackMethod);
expect(hbaseDaoSpy.callCount).to.equal(1);
done();
});
Let's start by simplifying the problem a bit.
it.only("Should execute callback after inserting objects in HBase.", function(done) {
var events = require('events');
var hbaseDao = new events.EventEmitter();
hbaseDao.putRows = function() {
console.log('putting rows');
this.emit('notify');
};
hbaseDao.on('notify', function(){
console.log('notify event fired');
done(); //here's where you call the callback to assert that the event has fired
});
sinon.spy(hbaseDao, 'putRows');
var commonStub = sinon.stub();
var tableName = 'DUMMY_READINGS_TABLE';
var client = {};
var connection = {
close : function() {
console.log('connection closed.');
}
};
var callBackMethod = function() {
console.log('dummy callback function.');
};
commonStub.withArgs('nn2', 9090).returns(connection);
commonStub.withArgs({}, connection).returns(client);
commonStub.withArgs(tableName, [], callBackMethod).returns(0);
hbaseDao.putRows(tableName, [], callBackMethod);
//assertions
assert(hbaseDao.putRows.calledOnce);
});
The above test will just work, because it creates a new "hbaseDao" from a simple event emitter and has the method and the notify event ready to go.
Because we're doing an async test, we need to have the done callback in the spec. Notice that this will only fire "done" when the event has occurred. Hence, the test will not pass unless the event fires. Also notice that we're spying specifically on the the hbaseDao 'putRows' and we're asserting that the its called once, another way to ensure that the test is working. Now consider this example and apply it to your original question.
I think you almost got it, but you need to put your done callback in the callback stub as so:
var callBackMethod = function() {
console.log('dummy callback function.');
done();
};
That way, when your primaryClusterConnection.on('connect') event is fired, the supplied callback will execute the done and complete the test.
That being said, you should leave your primaryClusterConnection intact and let the implementation details of hbaseDao not be considered in your test.
You mentioned that:
primaryClusterConnection doesn't have any idea about connect
But that can't be right, because you're creating a new connection in the test and there's nothing in your implementation that tells me you have changed the event handler for the connection.
So I think in the end, you're missing the point of the test, which is simply should execute callback... and you're stubbing out stuff that you don't even need to.
Try something like this:
//use it.only to make sure there's no other tests running
it.only("Should execute callback after inserting objects in HBase.", function(done) {
//get the class
var hbaseDao = require('../../../src/dao/hbase/HBaseDao.js');
//spy on the method
sinon.spy(hbaseDao, 'putRows');
//create a table name
var tableName = 'DUMMY_READINGS_TABLE';
//create callback method with done.
var callBackMethod = function() {
console.log('dummy callback function.');
done();
};
//run the function under test
hbaseDao.putRows(tableName, [], callBackMethod);
//assert called once
assert(hbaseDao.putRows.calledOnce);
});

local PDF file scraping in node.js

I have uploaded a pdf via a MEAN stack web application using fs. I want to extract certain fields from the pdf and display them on the web app. I have looked at a couple npm packages like pdf.js, pdf2json. I can't figure out the documentation and javascript callbacks used in the examples available. Please help!
I hope I can help answer your question. Using pdf2json can be used to parse a pdf and extract the text. There are a couple of steps that need to be taken to get it working. I have adapted the example from https://github.com/modesty/pdf2json.
The setup is to install pdf2json in the node app, and also underscore. The example page didn't explain the need to define your own callback functions. It also used self instead of this to register them. So, with the appropriate changes the code to extract all the text from the pdf will be something like this:
// Get the dependencies that have already been installed
// to ./node_modules with `npm install <dep>`in the root director
// of your app
var _ = require('underscore'),
PDFParser = require('pdf2json');
var pdfParser = new PDFParser();
// Create a function to handle the pdf once it has been parsed.
// In this case we cycle through all the pages and extraxt
// All the text blocks and print them to console.
// If you do `console.log(JSON.stringify(pdf))` you will
// see how the parsed pdf is composed. Drill down into it
// to find the data you are looking for.
var _onPDFBinDataReady = function (pdf) {
console.log('Loaded pdf:\n');
for (var i in pdf.data.Pages) {
var page = pdf.data.Pages[i];
for (var j in page.Texts) {
var text = page.Texts[j];
console.log(text.R[0].T);
}
}
};
// Create an error handling function
var _onPDFBinDataError = function (error) {
console.log(error);
};
// Use underscore to bind the data ready function to the pdfParser
// so that when the data ready event is emitted your function will
// be called. As opposed to the example, I have used `this` instead
// of `self` since self had no meaning in this context
pdfParser.on('pdfParser_dataReady', _.bind(_onPDFBinDataReady, this));
// Register error handling function
pdfParser.on('pdfParser_dataError', _.bind(_onPDFBinDataError, this));
// Construct the file path of the pdf
var pdfFilePath = 'test3.pdf';
// Load the pdf. When it is loaded your data ready function will be called.
pdfParser.loadPDF(pdfFilePath);
I am running the code out of my server side controller.
module.exports = (function() {
return {
add: function(req, res) {
var tmp_path = req.files.pdf.path;
var target_path = './uploads/' + req.files.pdf.name;
fs.rename(tmp_path, target_path, function(err) {
if (err) throw err;
// delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files
fs.unlink(tmp_path, function() {
if (err) throw err;
//edit here pdf parser
res.redirect('#/');
});
})
},
show: function(req, res) {
var pdfParser = new PDFParser();
var _onPDFBinDataReady = function (pdf) {
console.log('Loaded pdf:\n');
for (var i in pdf.data.Pages) {
var page = pdf.data.Pages[i];
// console.log(page.Texts);
for (var j in page.Texts) {
var text = page.Texts[j];
// console.log(text.R[0].T);
}
}
console.log(JSON.stringify(pdf));
};
// Create an error handling function
var _onPDFBinDataError = function (error) {
console.log(error);
};
pdfParser.on('pdfParser_dataReady', _.bind(_onPDFBinDataReady, this));
// Register error handling function
pdfParser.on('pdfParser_dataError', _.bind(_onPDFBinDataError, this));
// Construct the file path of the pdf
var pdfFilePath = './uploads/Invoice_template.pdf';
// Load the pdf. When it is loaded your data ready function will be called.
pdfParser.loadPDF(pdfFilePath);
},
//end controller
}

Uploading document in NodeJs using Fs module : Error: write after end

I have been trying to upload a document using the following code.
I did googled and could not find any solution as yet.
app.post('/documents', function (req, res) {
var document = {};
var fstream = null;
// populate fields
form.on("field", function (name, value) {
document[name] = value ;
});
form.on("part", function (part) {
if (!part.filename) {
return;
}
var path = __dirname + '/files/' + part.filename;
fstream = app.npm.fs.createWriteStream(path);
document.type = part.headers["content-type"]
document.name = part.filename;
document.size = part.byteCount;
document.path = path;
fstream.on("close", function () {
db.sequelize.models.Document.create(document).then(function (newDocument) {
res.send(newDocument)
res.end();
},
function (error) {
res.send(error);
});
});
part.pipe(fstream);
});
form.on("close", function (data) {
fstream.end();
fstream = null;
});
form.parse(req);
});
NOTE: I am using fs module. https://nodejs.org/api/fs.html
The first image works ok. but when I try to upload an another image, it throws an exception:
events.js:72
throw er; // Unhandled 'error' event
^
Error: write after end
at writeAfterEnd (_stream_writable.js:132:12)
at Form.Writable.write (_stream_writable.js:180:5)
at write (_stream_readable.js:601:24)
at flow (_stream_readable.js:610:7)
at IncomingMessage.pipeOnReadable (_stream_readable.js:642:5)
at IncomingMessage.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:426:10)
at emitReadable (_stream_readable.js:422:5)
at readableAddChunk (_stream_readable.js:165:9)
at IncomingMessage.Readable.push (_stream_readable.js:127:10)
Found the solution.
var form = new app.npm.multiparty.Form();
This was defined at global level.
Where as for every new request I should be creating a new instance of the form because stream is off in the previous call so I should create a new instance by getting latest contents.
The solution looks likes:
app.post('/documents', function (req, res) {
var document = {};
var form = new app.npm.multiparty.Form();
var fstream = null;
...
And the rest is same.

Can I mock console in NodeJs?

In my JS test, I need to check if the console.info is called. That's why I want to mock console. However, it seems that the console variable cannot be assigned with a different object. Did I make any mistake?
Here is the code I used:
var oldConsole = console;
var infoContent;
console = {
info: function(content) {
infoContent = content;
}
};
game.process('a command');
infoContent.should.equal('a command is processed');
console = oldConsole;
You can use rewire to replace the whole of console to silence it, or to inject a mock. I use deride but sinon would also work.
var rewire = require('rewire');
var deride = require('deride');
var Game = rewire('../lib/game');
describe('game testing', function() {
var stubConsole, game;
beforeEach(function() {
stubConsole = deride.stub(['info']);
stubConsole.setup.info.toReturn();
Game.__set__({
console: stubConsole
});
game = new Game();
});
it('logs info messages', function() {
game.process('a command');
stubConsole.expect.info.called.withArgs(['a command is processed']);
});
});
I find the solution. I can change the method info of console.
console.info = function(content) {
infoContent = content;
};
The question is now why console object itself cannot be reassigned?
you can use sinon npm to count the call to a function :
it("calls the original function only once", function () {
var callback = sinon.spy();
var proxy = once(callback);
proxy();
proxy();
assert(callback.calledOnce);
// ...or:
// assert.equals(callback.callCount, 1);
});
You can find the docs here : sinonjs.org
I thought I had the same problem and my solution was using this std-mocks module:
https://github.com/neoziro/std-mocks
This has the advantage of not taking over the global "console" but allows you to see what gets logged to the stdout / stderr. This solves the problem in a different way than the question was explicitly looking for; however I believe it is a good answer for the problem the question implies and may be useful for others.
const stdMocks = require('std-mocks');
stdMocks.use(); console.log('test'); stdMocks.restore();
// => undefined [nothing gets output, stdout intercepted]
const logged = stdMocks.flush();
console.log(logged)
// => { stdout: [ 'test\n' ], stderr: [] }

Categories