Mocha fails with variable not defined - javascript

I use mocha to test a function in a file. The testable function is implemented like this:
math.js
(function (exports) {
var MY_APP_ = MY_APP || {};
MY_APP_.utils = MY_APP_.utils || {};
MY_APP_.utils.math = MY_APP_.utils.math || {};
MY_APP_.utils.math.randomValue = function (min, max) {
return Math.floor(Math.random() * (max + 1 - min) + min);
};
exports.math = MY_APP_.utils.math;
})(this);
And here is the test:
math_test.js
var assert = require("assert");
var math = require("../../js/utils/math.js");
describe('Math', function() {
describe('randomValue', function () {
it('should return random values', function () {
// Fill array with random values between 0 and 10
var values = [];
for (var i = 0; i < 10000; i++) {
values.push(math.math.randomValue(0, 10));
}
// Count numbers
var result = {};
values.forEach(function(number) {
var numberAsString = number.toString();
result[numberAsString] = result[numberAsString] + 1 || 1;
});
// There must be at least two of each number
assert.equal(Object.keys(result).length, 11);
Object.keys(result).forEach(function(key) {
assert.equal(true, result[key] > 1);
});
});
});
});
The problem is that var MY_APP_ = MY_APP || {}; fails with an error message: MY_APP is not defined.
Sure, MY_APP is not defined in the scope of this test because it is defined in an another file called app.js. When I build the app, this app.js file is included before math.js and both of them are concatenated into a single production.js file. This works without problem.
The test works, however, if I replace the failing line with the following:
var MY_APP = {};
if (typeof(MY_APP) !== 'undefined') {
MY_APP_ = MY_APP;
} else {
MY_APP_ = {};
}
This looks stupid in my opinion. I would like to know the reason why mocha is failing since the code works perfectly well when I run it in a browser.
EDIT:
I think I have made a mistake. var MY_APP_ = MY_APP || {}; seems to never work if MY_APP is not defined so the only option is to declare MY_APP before using math.js

From what you showed I would think that you would receive an error, and that your direct test works.
In your test you initialize MY_APP to an empty object which allows it to run. But in your math.js file MY_APP is never initialized, so when you set var MY_APP = MY_APP it would never be able to set it to anything.
I would suggest trying to initialize MY_APP before assigning it as a value for a variable.

Since the only purpose of app.js to just initialize var MY_APP = {}; to global scope I decided to do the same in the test file, so:
var assert = require("assert");
global.MY_APP = {};
var math = require("../../js/utils/math.js");
solves the problem

Related

Receive data from Nodejs Module.Exports

I have created a node module
Module file :
var functions = {};
functions.test = function(){
console.log("Invoked");
return "Hello";
}
module.exports = functions;
Main File :
const FUNCTIONS = require('./modulefile');
var x = FUNCTIONS.test();
console.log(x);
Now, here I can see "Invoked" means function is getting executed.
But x is undefined, seems value is not getting returned.
How can I return value from test() to main file.
You could use callbacks?
Hard to say what the underlying problem is considering people have got your code working.
Model file:
var functions = {
test: function(callback) {
console.log("Invoked");
callback("Hello")
}
}
module.exports = functions;
Other file:
var Functions= require('./functions');
var x
Functions.test(function (result) { x = result });
console.log(x);
Your code works just fine, I replicated it and it works
check it out here https://repl.it/#Muhand1/module-export

Possible failed dependency injection using require throws 'is not a function' error

I've looked through a few questions related to this error, and most of them seem to be a misunderstanding of what the keyword this means. I don't think I'm having that problem here. Mine might be some sort of circular dependency problem that I cannot articulate well enough to figure it out on my own.
I've tried to distill my problem into three files presented below.
something.js
var A = require('../lib/a');
var Something = function (type) {
this.type = type;
};
Something.prototype.setTemplate = function (template) {
this.template = template;
};
Something.prototype.applyTemplate = function () {
var templateResult = this.template.calculate();
};
var factory = {};
factory.createSomething = function(type) {
return new Something(type);
};
factory.createA = function (input) {
return A.Make(input);
};
module.exports = factory;
a.js
var S = require('../prof/something');
var _ = require('underscore');
var A = function (input) {
this.input = input;
};
A.prototype.calculate = function () {
var calculation = 0;
var _s = S.createSomething('hello world');
// do calculation using input
return calculation;
};
var factory = {};
factory.Make = function (input) {
var a = new A(input);
return a;
};
module.exports = factory;
a_test.js
describe('Unit: A Test', function() {
var S = require('../prof/something');
it('test 1', function() {
var a = S.createA({
//input
});
var s = S.createSomething('type1');
s.setTemplate(a);
s.applyTemplate(); // error
});
});
The error gets thrown from the top level in a_test.js on the line with the comment //error. At the lowest level, the 'is not a function ' error is thrown in a.js at the S.createSomething(type) method. It says that S.createSomething() is not a function.
I've put a breakpoint in at that line and tried to call functions from the underscore library, but it gives the same error. So it seems that the require statements inside a.js are not throwing errors, but none of the injected objects can be used to call functions from. The a_test.js file is being run with the karma library.
Am I violating some javascript paradigm by referencing back and forth between A and S? How can I do this properly?
Edit: I've done some further testing. It doesn't actually matter if the test file looks like this:
describe('Unit: A Test', function() {
var S = require('../prof/something');
it('test 1', function() {
var a = S.createA({
//input
});
a.calculate(); // error
});
});
An error is still thrown at the line indicated above.
The files in the question reference each other. This is called cyclic dependencies. The solution is to move the var S = require('../prof/something'); statement into the calculate function like so:
a.js
// move the line from here
var _ = require('underscore');
var A = function (input) {
this.input = input;
};
A.prototype.calculate = function () {
var S = require('../prof/something'); // to here
var calculation = 0;
var _s = S.createSomething('hello world');
// do calculation using input
return calculation;
};
var factory = {};
factory.Make = function (input) {
var a = new A(input);
return a;
};
module.exports = factory;

How to set/redefine variable in external js file

How can I re-define variable in external js file 'js/sample.js'?
The main idea was not touch core file and be possible to pass a new value (to var COUNT_DEFAULT) on js load from my new module.
core js example:
(function(_, $) {
var COUNT_DEFAULT = 2;
...
Not sure if I understood you well, but you can do it like that.
var module = (function (myVal) {
var COUNT_DEFAULT = myVal || 2;
return {
val: COUNT_DEFAULT
};
});
var defaultVal = module();
var customVal = module(45);
console.log(defaultVal);
console.log(customVal);

How to have multiple imports under a same variable

I want to organize my project imports with browserify so that I have a global utils variable from which I can call and execute functions much like jquery's $.
So in the end I want something like:
window.utils = ...
So I can use utils.aFunction();
I also want to divide my dependencies in several files, as an example, this would be my project:
libs
|_ math.js //Implements randomInt and RandomFloat methods
|_ connection.js //Implements isConnected method
utils.js //Calls all the required dependencies
My idea so far is to have something like this:
In libs/math.js:
module.exports = {
randInt: function() {
return 4;
},
randFloat: function() {
return 4.1;
}
};
And then I would do in utils.js:
var math = require('./libs/math');
var connection = require('./libs/connection');
var libs = [math, connection];
var utils = {};
for (var i = 0; i < libs.length; i++) {
for (var key in libs[i]) {
utils[key] = libs[i][key];
}
}
window.utils = utils;
This actually works just fine, but I don't know if it wasn't already solved by a library.
I have a feeling there are more efficient ways of doing this, what would be the recommended approach with browserify?
The code for throwing things into util object is definitely odd looking, and I wouldn't recommend this looping over all your required util submodules.
var libs = [math, connection];
var utils = {};
for (var i = 0; i < libs.length; i++) {
for (var key in libs[i]) {
utils[key] = libs[i][key];
}
}
If you were using a common js approach with webpack/browserify, you would simply declare your util to be global in the configuration file, and simply add the needed module.exports inside of your util.js
//connect.js
module.exports = {
isConnected: function(){
return true;
}
};
//math.js
module.exports = {
randInt: function() {
return 4;
},
randFloat: function() {
return 4.1;
}
};
//utils.js
exports.math = require('./math');
exports.connect = require('./connect');
//test.js
var utils = require('./utils');
console.log(utils.math.randInt());
console.log(utils.connect.isConnected());

Are there any behavioural differences before and after this javascript refactoring?

I recently had to refactor a chunk of javascript that is using YUI.
So, originally it was something like this:
YAHOO.namespace('space.time');
YAHOO.space.time = (function() {
var b = document.getelementbyid("aifdsgyalierg");
function c(b) {
var a = new YAHOO.util.Anim(d, b); //just assume the parameters are correct here
a.method = YAHOO.util.Easing.easeOut;
a.animate();
};
return { c:c };
})();
For the sake of being able to inject dependencies, i refactored it to the below:
YAHOO.namespace('space.time');
YAHOO.namespace('space.timefn');
YAHOO.space.timefn = function(yuianim) {
var b = document.getelementbyid("aifdsgyalierg");
function c(d) {
var a = new yuianim(d, b); //just assume the parameters are correct here
a.method = YAHOO.util.Easing.easeOut;
a.animate();
};
return { c:c };
};
YAHOO.space.time = YAHOO.space.timefn(YAHOO.util.Anim);
So..
1) Ignoring any committed fallacies.. Will the behaviour of the two snippets differ?
2) What fallacies have i committed?

Categories