We have an SPA application with a shared scope variable var WIDGET. Each module adds itself to the shared WIDGET object or creates the WIDGET if it was not created.
Using a couple of frameworks for unit tests the shared WIDGET is available but the variable on the required files do not point to it.
var WIDGET = WIDGET || {};
if I change this line of code to WIDGET = WIDGET || {} or if I remove it all together then the objects will work as expected in the unit test
things to know:
- we do NOT use nodejs in production, it is just for testing
- code executes properly in production
- test frameworks have been mocha and jest
Q1 what can I do to ensure the private variable is pointing to the shared object when unit testing?
Q2 why does this happen in testing but not in the DOM during application execution?
test application creation:
TypeError: Cannot read property 'getInstance' of undefined
at new widget_application (widgetApplication.js:23:41)
at Object.getInstance (widgetApplication.js:33:16)
at Context.<anonymous> (test\testApp.js:16:39)
first module that adds itself to the WIDGET object
var _WIDGET_ = _WIDGET_ || {};
//adds itself to the _WIDGET_ to be shared
_WIDGET_.widgetLogger = (function(){
var INSTANCE;
var _config = {};
var _widgetLog = {};
function widget_logger(config){
if(config){_config = config;}
}
widget_logger.prototype.stageLog = stageLog;
// widget_logger.prototype.startUpLog = startUpLog;
// widget_logger.prototype.dataRefreshLog = dataRefreshLog;
// widget_logger.prototype.widgetNotReadyLog = widgetNotReadyLog;
// widget_logger.prototype.finalizeLog = finalizeLog;
// widget_logger.prototype.getLog = getLog;
return {
getInstance:function(c){
if(!INSTANCE){
INSTANCE = new widget_logger(c);
}
return INSTANCE;
}
};
function stageLog(data) {
console.log("widget logger called to stage log");
if(data){
_widgetLog = {};
_legacyLog = {};
_widgetLog.widgetProgramCode = _config.versionData.programCode;
_widgetLog.widgetVersion = _config.versionData.version;
_widgetLog.startTime = data.startTime || new Date();
console.log("widget logger staged this log ",_widgetLog);
}
}
})();
//export is only for testing - nodejs NOT used in production
var module = module || {};
module.exports = _WIDGET_;
next module that adds itself and uses the logger module
var _WIDGET_ = _WIDGET_ || {};//remove this line of code and unit test run
var _API_ = _API_ || {};
_WIDGET_.smallApplication = (function(){
var INSTANCE;
var widgetLogger;
var _config = {
versionData:{
programCode:"smallApplication",
version:"1.0.2.0"
}
};
function widget_application(config){
console.log("make the instance ");
// var elem = document.getElementById('apprunning');
// elem.innerHTML += " smallApplication is online ";
if(config){_config = config;}
//expects to have a shared object already
//fails after this call because this module create a new _WIDGET_ variable
//this does not happen in production - all components are created
widgetLogger = _WIDGET_.widgetLogger.getInstance(_config);
}
widget_application.prototype.runApplication = runApplication;
return {
getInstance:function(c){
console.log("get instance was called");
if(!INSTANCE){
INSTANCE = new widget_application(c);
}
return INSTANCE;
}
};
//run some functions and hello world and all that happiness...
function runApplication(){
console.log("widget application runs - will call logger");
widgetLogger.stageLog(true);
}
})();
//export is only for testing - nodejs NOT used in production
var module = module || {};
module.exports = _WIDGET_;
mocha test script
var assert = require('assert');
_WIDGET_ = {name: 'small application'};
describe('small application',function(){
//_WIDGET_ = {name: 'small application'};
//var _WIDGET_ {name: 'small application'};
//global._WIDGET_ {name: 'small application'};
it('test logger creation',function(){
_WIDGET_ = require('../widgetLogger');
console.log('_WIDGET_');
});
it('test application creation',function(){
var app = require('../widgetApplication');
_WIDGET_ = require('../widgetApplication');
});
});
A2 to Q2 found at free code camp - require modules In a browser, when we declare a variable in a script like this:
var answer = 42;
That answer variable will be globally available in all scripts after the script that defined it.
This is not the case in Node. When we define a variable in one module, the other modules in the program will not have access to that variable. So how come variables in Node are magically scoped?
The answer is simple. Before compiling a module, Node wraps the module code in a function, which we can inspect using the wrapper property of the module module.