Call function of app.js from within module in node.js? - javascript

Let's say I have the following app.js (obviously very simplified):
var express = require('express'),
app = express.createServer();
// include routes
require('./lib/routes')(app);
// some random function
var foo = function() {
return 'bar';
};
// another random function
var foo2 = function() {
return 'bar2';
};
And then I have the routes module:
module.exports = function(app){
app.get('/some/route', function(req, res){
var fooBar = foo(),
fooBar2 = foo2();
res.end(fooBar + fooBar2);
});
};
This obviously doesn't work since foo and foo2 weren't defined within the module. Is there a way to make this work, or at least a different pattern to better accomplish what this?

Well you can just put these two functions in an object and pass them on the initialization of the routes.js .
var express = require('express'),
app = express.createServer();
// some random function
var foo = function() {
return 'bar';
};
// another random function
var foo2 = function() {
return 'bar2';
};
var fns = {foo : foo, foo2: foo2}
// include routes
require('./lib/routes')(app, fns);
in routes:
module.exports = function(app, fns){
app.get('/some/route', function(req, res){
var fooBar = fns.foo(),
fooBar2 = fns.foo2();
res.end(fooBar + fooBar2);
});
};
This is how would I do it. You can also include them in the app object. Beside passing them in init functions, you can also export those two functions and require them in routes.js.
var express = require('express'),
app = express.createServer();
// some random function
var foo = function() {
return 'bar';
};
// another random function
var foo2 = function() {
return 'bar2';
};
module.exports = {foo : foo, foo2: foo2}
// include routes
require('./lib/routes')(app, fns);
in routes:
module.exports = function(app){
var fns = require('../app.js');
app.get('/some/route', function(req, res){
var fooBar = fns.foo(),
fooBar2 = fns.foo2();
res.end(fooBar + fooBar2);
});
};
But I don't like the idea of it, since it makes circular dependencies. Don't have any good feelings about them.

Related

How to mock a function defined with this keyword using sinon?

I have a function foo
var foo = function(){
this.doRandomStuff = function(callback){
//do Something
callback(false);
}
}
var bar = function(){
var fooInstance = new foo();
fooInstance.doRandomStuff(function(val){
//do Something with val
})
}
I want to write test for bar function and I am using mocha and sinon for this.
describe("Foo Test",function(){
it("testing foo",function(done){
var instance = new foo();
sinon.stub(instance,'doRandomStuff').callsArgWith(0,true); // This Doesn't work
sinon.stub(foo,'doRandomStuff').callsArgWith(0,true); // This also Doesn't work
bar();
done();
})
});
I get below Exception :
TypeError: Cannot stub non-existent own property doRandomStuff
Alternative approach to make it more testable is module approach as below:
foo.js
function doRandomStuff(callback) {
callback(false);
}
module.exports = {
doRandomStuff
}
bar.js
const foo = require('./foo');
module.exports = function() {
foo.doRandomStuff(function(val) {
console.log('test val', val); // for testing purpose
})
}
test.js
const sinon = require('sinon');
const foo = require('./foo');
const bar = require('./bar');
describe('Foo Test', function() {
it("testing foo",function(done){
sinon.stub(foo, 'doRandomStuff').callsArgWith(0,true);
bar(); // output: "test val true"
done();
});
});

How do i share my World instance across multiple step definition files in CucumberJS?

I am implementing a CucumberJS scenario which uses multiple steps across two different step definition files. The first step sets some variables on the World which have to be used by a step in the other step definition file.
The variable gets set correctly but when the step on the other file tries to read it it's undefined. Any ideas how to solve this apart from merging the step definition files?
example:
world.js
var World = function World() {
this.client = '';
};
module.exports.World = World;
test.feature
Given a variable A
Then some other step
step1.steps.js
module.exports = function () {
this.World = require(process.cwd() + '/test/features/support/world').World;
this.Given(/^a Variable A$/, function () {
this.client = 'abc';
});
};
step2.steps.js
module.exports = function () {
this.World = require(process.cwd() + '/test/features/support/world').World;
this.Then(/^some other step$/, function () {
console.log(this.client);
});
};
You are setting this.client instead of this.World.client. Moreover you should use an object and not a constructor in world.js:
world.js
module.exports = {
client: ''
};
step1.steps.js
var world = require('./test/features/support/world.js');
module.exports = function () {
this.Given(/^a Variable A$/, function () {
world.client = 'abc';
});
};
step2.steps.js
var world = require('./test/features/support/world.js');
module.exports = function () {
this.Then(/^some other step$/, function () {
console.log(world.client);
});
};
You could directly parameterise your test.feature :
Given a variable "abc"
Then some other step
now pass this variable in your step
step1.steps.js
module.exports = function() {
this.World = require(process.cwd() + '/test/features/support/world').World;
this.Given(/^a Variable "([^"]*)"$/, function(variable) {
this.client = variable;
});
};
step2.steps.js
module.exports = function() {
this.World = require(process.cwd() + '/test/features/support/world').World;
this.Then(/^some other step$/, function() {
console.log(this.client); // would print abc
});
};

Unable to use Mongoose Object Methods from non-Mongoose Object

Suppose we have a Mongoose object Foo.js.
var mongoose = require('mongoose');
var Bar = require('/path/to/bar');
var Foo = mongoose.Schema({});
Foo.statics.hello = function() {
console.log('hello from foo');
};
Foo.statics.useBar = function() {
Bar.hello();
};
module.exports = mongoose.model('Foo', Foo);
As well as a regular javascript object Bar.js.
var Foo = require('/path/to/foo');
var Bar = function() {};
Bar.hello = function() {
console.log('hello from bar');
};
Bar.useFoo = function() {
Foo.hello();
};
module.exports = Bar;
If we wanted to call methods in Bar from Foo, everything would be fine. Yet, if we wanted to call methods in Foo from Bar, we would receive an error.
app.use('/test', function(req, res, next) {
var Foo = require('/path/to/foo');
var Bar = require('/path/to/bar');
Foo.hello();
Bar.hello();
Foo.useBar();
Bar.useFoo();
});
The above yields:
hello from foo
hello from bar
hello from bar
TypeError: Foo.hello is not a function
Why does this happen?
Additionally, how do I create an object Bar that can call methods from Foo, but at the same time is not meant to be - and cannot be - persisted into mongodb?
The problem you are experiencing is circular/cyclic dependencies in node.js. It gives you an empty object.
If you change Bar.js like this:
var Bar = function() {};
module.exports = Bar;
var Foo = require('/path/to/foo');
Bar.hello = function() {
console.log('hello from bar');
};
Bar.useFoo = function() {
Foo.hello();
};
and then swap the order in app.use to
var Bar = require('/path/to/bar');
var Foo = require('/path/to/foo');
it works for me.
Look at this answer for more information: How to deal with cyclic dependencies in Node.js

Difference between multiple ways of referencing exported attribute

I'm using socket.io and need to export the io object for use in other files. Controller A works and successfully emits the message. What's weird is that Controller B and C do not reference the .io correctly. Is there any difference between the three ways of referencing .io?
// index.js
exports.register = function (server, options, next) {
var onlineUsers = {};
var io = require('socket.io')(server.select('collaboration').listener);
io.on('connection', function (socket) {
socket.on('is_online', Handlers.is_online.bind(null, socket));
socket.on('disconnect', Handlers.is_offline.bind(null, socket));
});
exports.io = io;
next();
};
// controllerA.js
var io = require('./collaboration/index');
function testFunc() {
io.io.emit('testing', {data: 'some data'});
}
// controllerB.js
var io = require('./collaboration/index').io;
function testFunc() {
io.emit('testing', {data: 'some data'});
}
// controllerC.js
var index = require('./collaboration/index');
var io = index.io;
function testFunc() {
io.emit('testing', {data: 'some data'});
}
This has to do with timing: exports.io is created only when the register() is called. Before that, exports.io is undefined.
This is also reflected in your controllers:
controllerA stores a reference to the exports object of index.js. At the time you require index.js, exports.io doesn't yet exist but that's not a problem because you reference it later, in testFunc (which does mean that register() has to be called before testFunc, otherwise io.io is still undefined);
controllerB and controllerC reference exports.io directly, at the time the require is called. At that time though, it doesn't exist yet. In other words, they are storing an undefined reference, and their testFunc's fail because of that;
Here's a simplification of what's happening:
// controllerA
var obj = {};
var io = obj;
obj.io = 'hello';
console.log(io.io);
// controllerB
var obj = {};
var io = obj.io;
obj.io = 'hello';
console.log(io);
// controllerC
var obj = {};
var index = obj;
var io = index.io;
obj.io = 'hello';
console.log(io);
This logs:
hello
undefined
undefined

How can I share module-private data between 2 files in Node?

I would like to have a module for Node.js that is a directory with several files. I'd like some vars from one file to be accessible from other file, but not from the files external to the module. Is it possible?
So let's suppose the following file structure
` module/
| index.js
| extra.js
` additional.js
In index.js:
var foo = 'some value';
...
// make additional and extra available for the external code
module.exports.additional = require('./additional.js');
module.exports.extra = require('./extra.js');
In extra.js:
// some magic here
var bar = foo; // where foo is foo from index.js
In additional.js:
// some magic here
var qux = foo; // here foo is foo from index.js as well
Additional and Extra are implementing some business logic (independent from each other) but need to share some module-internal service data which should not be exported.
The only solution that I see is to create one more file, service.js and require it from both additional.js and extra.js. Is it correct? Are there any other solutions?
Can you just pass the desired stuff in?
//index.js:
var foo = 'some value';
module.exports.additional = require('./additional.js')(foo);
module.exports.extra = require('./extra.js')(foo);
//extra.js:
module.exports = function(foo){
var extra = {};
// some magic here
var bar = foo; // where foo is foo from index.js
extra.baz = function(req, res, next){};
return extra;
};
//additional.js:
module.exports = function(foo){
var additonal = {};
additional.deadbeef = function(req, res, next){
var qux = foo; // here foo is foo from index.js as well
res.send(200, qux);
};
return additional;
};
Okay, you may be able to do this with the "global" namespace:
//index.js
global.foo = "some value";
and then
//extra.js
var bar = global.foo;
I'd like some vars from one file to be accessible from other file, but not from the files external to the module
Yes, it is possible. You can load that other file into your module and hand it over a privileged function that offers access to specific variables from your module scope, or just hand it over the values themselves:
index.js:
var foo = 'some value';
module.exports.additional = require('./additional.js')(foo);
module.exports.extra = require('./extra.js')(foo);
extra.js:
module.exports = function(foo){
// some magic here
var bar = foo; // foo is the foo from index.js
// instead of assigning the magic to exports, return it
};
additional.js:
module.exports = function(foo){
// some magic here
var qux = foo; // foo is the foo from index.js again
// instead of assigning the magic to exports, return it
};

Categories

Resources