How to spy on another module in node with Javascript - javascript

I have this js module (simplified example):
var dbLoader = require('dbLoader');
function MyModule() {
this.build(){
return dbLoader.load('yipee');
}
}
module.exports = MyModule;
How on earth do I spyOn(dbLoader,'load') ??
Because when I try I get the error
spyOn could not find an object to spy upon for load()
Any help much appreciated...

You probably should export them both:
module.exports.MyModule = MyModule;
module.exports.dbLoader = dbLoader;
The you can import them as follows:
var MyModule = require('my-module').MyModule;
var dbLoader = require('my-module').dbLoader;

Related

TypeError: is not a constructor

I'm just using the code as a learning exercise regarding JavaScript classes.
The code produces a "TypeError: SimpleLogger is not a constructor". The class seems to be exported Ok but I can't instantiate it in the main.js file.
I've reduced the code to just show the issue. I was wondering if anyone can spot the problem. Thanks.
// In simplelogger.js
"use strict";
class SimpleLogger {
constructor(level) {
this.level = level || DEFAULT_LEVEL;
}
// .... other methods
}
const DEFAULT_LEVEL = 'info';
module.exports = {
SimpleLogger,
DEFAULT_LEVEL
}
// In main.js
"use strict";
const SimpleLogger = require('./simplelogger.js');
let log = new SimpleLogger('info');
The error is produced in the last line.
You're exporting an object containing both SimpleLogger and DEFAULT_LEVEL therefore to use it in main.js you need to reference it properly like so
const SimpleLogger = require('./simplelogger.js').SimpleLogger;
let log = new SimpleLogger('info');
If you only want to export SimpleLogger you can change your export like so
module.exports = SimpleLogger
Then you can require SimpleLogger as you do in your code.

Passing a parameter to a called module

My app.js contains:
var m1 = require("./m1");
m1.f1(...);
My m1.js contains:
var m1 = module.exports = {};
m1.f1 = function(...) { };
I would like to pass somevariable when loading m1 from app.js:
var m1 = require("./m1")(somevariable);
How can I write m1.js so that the function definition of m1.f1 can access somevariable?
If you want to be able to do this:
var m1 = require("./m1")(somevariable); // it is equivalent to var m = require("./m1"); and then m(someVariable); so m (the exports of the module m1.js) should be a function
then module.exports in m1.js should be a function:
// m1.js:
module.exports = function(theVariable) {
// use variable then return the following object:
return {
f1: function() { /* ... */ }
};
}
So now you can use the module in app.js like this:
// app.js:
var m1 = require("./m1")(someVariable);
m1.f1(/* ... */);
module.exports is the value that will be returned by the call to require when loading the module.
// app.js
require("./m1")(somevar);
// m1.js
module.exports = function(param) {
return "something";
}
The answer above by Ibrahim makes sense if you want to call m1 as a function. What it seems to me, though, is that your use case would be better served by using a JS class.
That way, you can import 'm1' the regular way with require('m1') and then create an instance of M1 with new m1(<whatever you want to pass in>);
Now when you want to call M1, just use m1.f1()
To support classes, your M1 should look something like:
export default class m1 {
constructor(param1, param2) {
this.param1 = param1;
this.param2 = param2;
}
f1() {
do whatever with params here
}
}
The biggest benefit of this is readability. Now when someone (or you) looks at your code, they will see where this input is coming from. Otherwise, it can be hard to track down where the params are coming from. Especially as your code gets more complex.

How to make a custom CasperJS module with custom parameter?

FileUtil.js:
exports.a = function(pre) {
var module = {}
module.writeStringToFile = function writeStringToFile() {
casper.log(pre + " succ");
};
return module
}
main.js:
var casper = require('casper').create();
var FileUtil = require('FileUtil').a('xxx')
FileUtil.writeStringToFile() //xxx succ
That works, but what I want is var FileUtil = require('FileUtil')('xxx') instead of require('FileUtil').a('xxx').
I tried exports = function(pre) ..., but it doesn't works.
So, how to make a custom CasperJS module with custom parameter?
If you want var FileUtil = require('FileUtil')('xxx') to be your object then you need to use module.exports. It can export a single object, which can even be a function:
module.exports = function(pre) {
var module = {}
module.writeStringToFile = function writeStringToFile() {
casper.log(pre + " succ");
};
return module
}
Of course, it would be a better form to rename the inner module variable to something else.

browserify modules and notation

Suppose I have a MyViewModel like this:
// MyViewModel.js module
function MyViewModel() {
};
exports.MyViewModel = MyViewModel;
And main.js using it:
// main.js
var MyViewModel = require('./MyViewModel');
var vm = new MyViewModel.MyViewModel(); // akward
it's weird to have new MyViewModel.MyViewModel().
What's the best way to handle this?
Found the answer myself:
// MyViewModel.js module
module.exports = function MyViewModel() {
};

Right way of writing and loading modules in node.js?

Currently, I write node.js modules like this:
//MyModule.js
function MyModule() {
...somecode
}
MyModule.prototype.someFunc = function() {...}
module.exports = MyModule
However, when I need to use the module, I have to write something like this:
//main.js
var MyModule = require('MyModule');
var myModule = new MyModule();
This seems terribly ugly. Isn't there some way to do something like this
//main.js
var myModule = require('MyModule').new();
Am I doing something wrong?
quick hack for something not ugly
module.js
function MyModule() {
console.dir('constructor');
}
module.exports = MyModule;
app.js
Function.prototype.new = function () {
return new this();
};
var MyModule = require('./module.js').new(); // 'constructor'
If your module consists solely of functions, it may not need to be created as an instance - just define your module as being an object filled with functions. Like so:
var MyModule = {
prepareHtmlContent: function() {
},
autoLoadActionInitiatorFunctions: function() {
}
};
The reason I suggest this is that you've referred to your object as 'MyModule'. If your intent is specifically to use it as a 'Class', and instantiate separate copies of it when they're needed, then you're doing it the correct way.
Here is what I use
(function(module) {
module.myFunction = function() {
}
module.createSomeObj = function() {
return {
foo: 1,
bar: 'bar'
};
}
}(module.exports));
Usage
var myModule = require('./myModule');
myModule.myFunction();
var myObject = myModule.createSomeObj();

Categories

Resources