Is it possible to unit test javascript functions that exist within a closure, so for example, given the following:
(function() {
var a = function() {
//do something
}
window.b = function() {
// do something else
}
})();
Is it possible to unit test function a without exposing it? If not, is there a good way to expose a, but only in test mode?
Your anonymous function could take a parameter which would be undefined when not in test mode, and say this parameter would be an object, you could fill the object with a's without exposing a directly.
Just my .02$
The biggest question here is why do you want to keep it hidden? The fact that you have this function a that you want to test is an indicator that a has a responsibility of its own that should be tested. Pulling it out and getting it under test gains much more value when weighed against the minimal risk of exposing it. If you really want to keep it hidden, then I'd suggest something similar to Manux's response where you create an object that does what a does but doesn't expose a directly. Then you could test the behavior of a by testing that object.
Revisiting the question 4 years on, I now have a better solution.
Generate a testable version of your code as a build step.
Say I'm using Gulp to minify my JavaScript, and my code looks like this:
var a = function() {}
window.b = function() {}
Not the absence of a closure. Now I set up a gulp task and have it watch my code, like so:
gulp.task('js', function () {
return gulp.src([dirs.js.src, '*.js'].join('/'))
.pipe(wrap('(function() {\n<%= contents %>\n})();'))
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(gulp.dest(dirs.js.dest));
});
This will wrap my code in the IIFE producing the following output:
(function() {
var a = function() {}
window.b = function() {}
)();
Generating the testable version
Now I add another Gulp task, like this
gulp.task('testJs', function () {
return gulp.src([dirs.test.src, '*.js'].join('/'))
.pipe(wrap(
[
'(function() {',
'<%= contents %>',
'// Smuggle locals out of closure for testing',
'window.a = a;',
'})();'
].join('\n')
))
.pipe(concat(package.name + '.testable.js'))
.pipe(gulp.dest(dirs.test.dest));
});
This will generate the following unsafe but testable code right in my test directory:
(function() {
var a = function() {}
window.b = function() {}
// Smuggle locals out of closure for testing
window.a = a;
)();
Add a watch task...
gulp.task('watch', function() {
gulp.watch([dirs.js.src, '**', '*.js'].join('/'), ['js', 'testJs']);
});
...and you're done.
See here
See here for an example:
https://github.com/forwardadvance/ng-tweets
Related
Thus far I've worked only with relatively small projects (and mostly alone), but this time I have to collaborate with other programmers... basically because of that I must plan the structure of the website very carefully for the avoidance of spending hours debugging the code.
At this point I suppose doing that in the following manner. I divide my code in modules and store each module in a separate file inside an object (or a function) with a made-up name (lzheA, lzheB, lzheC etc.) to avoid conflicts whether an object with the same name was used in an another piece of code. When the document is loaded, I declare a variable (an object) that I use as a main namespace of the application. Properties of the object are the modules I defined before.
// file BI.lib.js
var lzheA = {
foo: function() {
},
bar: function() {
},
}
// file BI.init.js
function lzheK() {
BI.loadPage();
}
// file BI.loadPage.js
function lzheC() {
var result = document.getElementById('result');
result.innerHTML = "that worked";
}
// and so on
var lzheA,lzheB,lzheD,lzheE,lzheF,lzheG,lzheH,lzheI,lzheJ;
// doing the following when the document is loaded
var BI = {
lib: lzheA,
menu: lzheB,
loadPage: lzheC,
customScripts: lzheD,
_index: lzheE,
_briefs: lzheF,
_shop: lzheG,
_cases: lzheH,
_blog: lzheI,
_contacts: lzheJ,
init: lzheK,
}
BI.init();
https://jsfiddle.net/vwc2og57/2/
The question... is this way of structuring worth living or did I miss something because of lack of experience? Would the made-up names of the modules confuse you regardless of the fact that each one used only twice - while declaring the variable and assigning it to a property?
I consider the namespaces a good option when you want to modularize applications in Javascript. But I declare them in a different way
var myModule = myModule || {}; // This will allow to use the module in other places, declaring more than one specificComponent in other js file for example
myModule.specificComponent = (function(){
// Private things
var myVar = {};
var init = function() {
// Code
};
return {
init: init // Public Stuff
};
})();
If you want to call the init method, you would call it like this
myModule.specificComponent.init();
With this approach, i guarantee that the module will not be overwritten by another declaration in another place, and also I can declare internal components into my namespaces.
Also, the trick of just exposing what you want inside the return block, will make your component safer and you will be encapsulating your code in a pretty way.
Hope it helps
I'm building a midly size app using backbone and its friends jquery and underscore. My plan is to use QunitJS to create unittests.
I already have a Proof-Of-Concept of the app, so I basicly have a good grasp of how the code should look like without having to test it. It looks like that:
(function() {
// prepare some model
var Query = BackboneModel.extend({});
query = new Query();
// register some events
$('body.something').click(function() {
query.set('key', 'value');
# ...
});
// create some backbone view
var QueryView = Backbone.View.extend({...})
// init backbone view
query.view = new QueryView();
// add some plumbing here ...
// and so on...
})();
Otherwise said:
I wrap the module inside a function to avoid pollution
Class declaration and class use is interleaved
event registration is interleaved with the rest of the code
variables global to the module are reused inside the module
Now I need to test that. The problem is, I think, mainly about event registration and plumbing.
My plan is to wrap the code in functions and export every function and objects I want to test. The code will look like this:
var app = (function() {
var app = {}
// prepare some model
var Query = BackboneModel.extend({});
app.query = new Query();
// register some events
app.registerEvent = function() {
$('body.something').click(function() {
query.set('key', 'value');
# ...
});
};
app.registerEvent(); // XXX: call immediatly
// create some backbone view
app.QueryView = Backbone.View.extend({...})
// init backbone view
app.query.view = new QueryView();
// add some plumbing here ...
// wrapped in function with correct arguments and call it immediatly
// and so on...
// ...
return app;
})();
This is the first time I need to write tests in javascript for this kind of application so I'm wondering whether my approach to make the code testable is correct or can be improved. For instance, It seems silly to me to wrap the registration of events in function without arguments and call them immediatly.
Is there a javascript way to do this?
So I found an excellent way to test private functions while keeping my production code clean. I am not sure if you are using any build system like Grunt or Gulp, but if you are open to it you could do something like this:
//has a dependency of 'test' causing it to run testing suite first
gulp.task('js', ['test'], function() {
return gulp.src(source)
.pipe(plumber())
//create sourcemaps so console errors point to original file
.pipe(sourcemaps.init())
//strip out any code between comments
.pipe(stripCode({
start_comment: 'start-test',
end_comment: 'end-test'
}))
//combine all separatefiles into one
.pipe(concatenate('mimic.min.js'))
//minify and mangle
.pipe(uglify())
.pipe(sourcemaps.write('maps'))
.pipe(gulp.dest('dist/js'));
});
And the file could look like:
var app = (function () {
function somePrivateFunction () {}
function someotherPrivateFunction () {}
var app = {
publicFunction: function(){}
publicVar: publicVar
}
/* start-test */
app.test = {
testableFunction: somePrivateFunction
}
/* end-test */
}());
Everything between the test comments gets stripped out after the tests are run so the production code is clean. Grunt has a version of this and I assume any automated build system can do the same. You can even set a watch task so that it runs the tests on every save. Otherwise you'll have to manually remove the exported test object before deployment.
In the case of Backbone just attach a test object to the module and reference that object in the tests. Or if you really want to separate it, set the object in the global scope. window.testObject = { //list of objects and methods to test... }; and strip that code out before deployment.
Basically what I do is avoid any calls in the library I want to test. So everything is wrapped in a function and exported.
Then I have two other files one is main.js where I do the plumbing and should be tested using integration tests with selenium and tests.js which does unit testing.
I was probing my code for errors with JSLint and so far I managed to fix all bugs except the problem when my global application variable is undefined.
I was using this code before JSlint which worked properly:
var APP = APP || (function {
return {
init: function () {
}
};
}(window.document));
then I would call
APP.init();
to initialize. But JSlint doesn't like global variables so I changed my code to this:
(function (global){
var APP = {
init: function () {
}
};
return APP;
}(window.document));
This code passes the JSLint test with no problem, but then
when I call APP.init(); it says that APP is used before it was defined, which is true.
What would you recommend so that I don't use global variables but still create my application object, while my code passes JSlint test?
First code
In your original code, the actual error you would have gotten was
#1 'APP' used out of scope.
var APP = APP || (function() { // Line 1, Pos 11
It is not because JSLint hates global variables, but because it doesn't like the variable being assigned to it is defined in the same var statement.
Changing your code to use a different variable name would fix this problem
var app = APP || (function() {...}(..));
but then, one would expect that APP is already defined in the current scope. Otherwise you will get
#1 'APP' was used before it was defined.
Second code
It doesn't work because, APP is visible only inside the function object you created. It is not visible anywhere outside it. Since you want to define APP in the global scope, you just have to attach it to the window object, like this
(function(global) {
global.APP = {
init: function() {
}
};
}(window));
Then
APP.init()
will work fine.
Instead of going through all these, you can straight away define APP like this
window.APP = {
init: function () {
"use strict";
...
}
};
(function (global){
var APP = {
init: function () {
}
};
return APP;
}(window.document));
the above creates a scope/closure, so that only code inside your anonymous function can access the APP variable. JSHint has settings so you can set acceptable globals (such as jquery etc), I'd add APP to that and if the rest pass you know you only have that one variable/module as global. If you are using any 3rd party libs chances are you already have several global vars anyway
Before you give up on JSLint, know that it doesn't mind globals at all; it just wants you to declare them with a special format so that others reading your code know exactly what's going on.
The only "trick" here is if there's a chance your global APP isn't initialized yet and you really need to check for its "truthiness", as you do with APP = APP || (function.... Then you do need to use the window (or whatever your global object is -- it's different if you use Node, for example) prefix trick.
Here's how:
/*jslint white:true, sloppy:true, browser:true */
/*global APP */
window.APP = window.APP || (function () {
return {
init: function () {
window.alert('JSLint doesn\'t like empty blocks');
}
};
}(window.document));
APP.init();
And JSLint is happy!
I'm not against JSHint in theory, but that same flexibility that allows you to set all sorts of extra settings also tends to erode conformity, which is largely what I find the best benefit of a code linter to be. Give both a good, solid run, and see which you like best!
I did't found any realy working solution of this issue on Google, so...
There is a module called vm, but people say it is very heavy. I need some simple function, like PHP's include, which works like the code of an including file inserts right into the place in code you need and then executes.
I tryed to create such function
function include(path) {
eval( fs.readFileSync(path) + "" );
}
but it is not as simple... it is better if I'll show you why in example.
Let's say I need to include file.js file with content
var a = 1;
The relative file look like this
include("file.js");
console.log(a); // undefined
As you already realized a is undefined because it is not inherits from a function.
Seems the only way to do that is to type this long creepy code
eval( fs.readFileSync("file.js") + "" );
console.log(a); // 1
every time with no wrapper function in order to get all the functionality from a file as it is.
Using require with module.exports for each file is also a bad idea...
Any other solutions?
Using require with module.exports for each file is also a bad idea...
No, require is the way you do this in NodeJS:
var stuff = require("stuff");
// Or
var stuff = require("./stuff"); // If it's within the same directory, part of a package
Break your big vm into small, maintainable pieces, and if they need to be gathered together into one big thing rather than being used directly, have a vm.js that does that.
So for example
stuff.js:
exports.nifty = nifty;
function nifty() {
console.log("I do nifty stuff");
}
morestuff.js:
// This is to address your variables question
exports.unavoidable = "I'm something that absolutely has to be exposed outside the module.";
exports.spiffy = spiffy;
function spiffy() {
console.log("I do spiffy stuff");
}
vm.js:
var stuff = require("./stuff"),
morestuff = require("./morestuff");
exports.cool = cool;
function cool() {
console.log("I do cool stuff, using the nifty function and the spiffy function");
stuff.nifty();
morestuff.spiffy();
console.log("I also use this from morestuff: " + morestuff.unavoidable);
}
app.js (the app using vm):
var vm = require("./vm");
vm.cool();
Output:
I do cool stuff, using the nifty function and the spiffy function
I do nifty stuff
I do spiffy stuff
I also use this from morestuff: I'm something that absolutely has to be exposed outside the module.
What you are trying to do breaks modularity and goes against Node.js best practices.
Lets say you have this module (sync-read.js):
var fs = require('fs');
module.exports = {
a: fs.readFileSync('./a.json'),
b: fs.readFileSync('./b.json'),
c: fs.readFileSync('./c.json')
}
When you call the module the first time ...
var data = require('./sync-read');
... it will be cached and you wont read those files from disk again. With your approach you'll be reading from disk on every include call. No bueno.
You don't need to append each of your vars to module.exports (as in comment above):
var constants = {
lebowski: 'Jeff Bridges',
neo: 'Keanu Reeves',
bourne: 'Matt Damon'
};
function theDude() { return constants.lebowski; };
function theOne() { return constants.neo; };
function theOnly() { return constants.bourne; };
module.exports = {
names: constants,
theDude : theDude,
theOne : theOne
// bourne is not exposed
}
Then:
var characters = require('./characters');
console.log(characters.names);
characters.theDude();
characters.theOne();
I'm trying to write 'better' javascript.
Below is one pattern I've found, and am trying to adopt. However, I'm slightly confused about its use.
Say, for example, I've got a page called "Jobs". Any JS functionality on that page would be encapsulated in something like:
window.jobs = (function(jobs, $, undefined){
return {
addNew: function(){
// job-adding code
}
}
})(window.jobs|| {}, jQuery);
$(function(){
$('.add_job').on('click', function(event){
event.preventDefault();
window.jobs.addNew();
});
});
As you can probably deduct, all I've done is replaced all the code that would have sat inside the anonymous event-handler function, with a call to a function in my global jobs object. I'm not sure why that's a good thing, other than it's reduced the possibility of variable collisions and made the whole thing a bit neater, but that's good enough for me.
The - probably fairly obvious - question is: all my event-binding init-type stuff is still sitting outside my shiny new jobs object: where should it be? Inside the jobs object? Inside the return object inside the jobs object? Inside an init() function?
I'm just trying to get a sense of a stable, basic framework for putting simple functionality in. I'm not building JS apps, I'd just like to write code that's a little more robust and maintainable than it is currently. Any and all suggestions are warmly welcomed :)
You can break down your application in whatever number of modules / objects you like too.
For instance, you can have another object / module which caches and defines all your DOM nodes and another one, which just handles any event. So for instance:
(function ( win, doc, $, undef ) {
win.myApp = win.myApp || { };
var eventHandler = {
onJobClick: function( event ) {
event.preventDefault();
myApp.addNew();
}
};
var nodes = (function() {
var rootNode = $( '.myRootNode' ),
addJob = rootNode.find( '.add_job' );
return {
rootNode: rootNode,
addJob: addJob
};
}());
$(function() {
myApp.nodes.addJob.on( 'click', myApp.handler.onJobClick );
});
myApp.nodes = nodes;
myApp.handler = eventHandler;
}( this, this.document, jQuery ));
It doesn't really matter how you create singletons in this (module) pattern, either as literal, constructor, Object.create() or whatnot. It needs to fit your requirements.
But you should try to create as many specific modules/objects as necesarry. Of course, if makes even more sense to separate those singletons / modules / objects into multiple javascript files and load them on demand and before you can say knife, you're in the world of modular programming patterns, dealing with requireJS and AMD or CommonJS modules.
Encapsulation-wise, you're fine: you could even just declare addNew in the jQuery closure and you'd still avoid the global scope. I think what you're getting at is more of implementing something close to an MVC architecture.
Something I like to do is create an object that you instantiate with a DOM element and that takes care of its own bindings/provides methods to access its controls etc.
Example:
// (pretend we're inside a closure already)
var myObj = function(args){
this.el = args.el; // just a selector, e.g. #myId
this.html = args.html;
this.bindings = args.bindings || {};
}
myObj.prototype.appendTo = function(elem){
elem.innerHTML += this.html;
this.bindControls();
};
myObj.prototype.remove = function(){
$(this.el).remove(); // using jQuery
};
myObj.prototype.bindControls = function(){
for(var i in this.bindings){ // event#selector : function
var boundFunc = function(e){ return this.bindings[i].call(this,e); };
$(this.el).on(i,boundFunc);
}
};
The way you are doing it right now is exactly how I do it also, I typically create the window objects inside the anonymous function itself and then declare inside that (in this case: jClass = window.jClass).
(function (jClass, $, undefined) {
/// <param name="$" type="jQuery" />
var VERSION = '1.31';
UPDATED_DATE = '7/20/2012';
// Private Namespace Variables
var _self = jClass; // internal self-reference
jClass = window.jClass; // (fix for intellisense)
$ = jQuery; // save rights to jQuery (also fixes vsdoc Intellisense)
// I init my namespace from inside itself
$(function () {
jClass.init('branchName');
});
jClass.init = function(branch) {
this._branch = branch;
this._globalFunctionality({ globalDatePicker: true });
this._jQueryValidateAdditions();
//put GLOBAL IMAGES to preload in the array
this._preloadImages( [''] );
this._log('*******************************************************');
this._log('jClass Loaded Successfully :: v' + VERSION + ' :: Last Updated: ' + UPDATED_DATE);
this._log('*******************************************************\n');
};
jClass._log = function() {
//NOTE: Global Log (cross browser Console.log - for Testing purposes)
//ENDNOTE
try { console.log.apply(console, arguments); }
catch (e) {
try { opera.postError.apply(opera, arguments); }
catch (e) { /* IE Currently shut OFF : alert(Array.prototype.join.call(arguments, ' '));*/ }
}
};
}(window.jClass= window.jClass|| {}, jQuery));
The reason I leave them completely anonymous like this, is that let's say in another file I want to add much more functionality to this jClass. I simply create another:
(function jClass, $, undefined) {
jClass.newFunction = function (params) {
// new stuff here
};
}(window.jClass = window.jClass || {}, jQuery))
As you can see I prefer the object.object notation, but you can use object literals object : object, it's up to you!
Either way by leaving all of this separate, and encapsulated without actual page logic makes it easier to have this within a globalJS file and every page on your site able to use it. Such as the example below.
jClass._log('log this text for me');
You don't want to intertwine model logic with your business logic, so your on the right path separating the two, and allowing for your global namespace/class/etc to be more flexible!
You can find here a comprehensive study on module pattern here: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html It covers all the aspects of block-scoped module approach. However in practice you gonna have quite a number files encapsulating you code, so the question is how to combine them property. AMD... multiple HTTP requests produced by every module loading will rather harm your page response time. So you can go with CommonJS compiled to a single JavaScript file suitable for in-browser use. Take a look how easy it is http://dsheiko.github.io/cjsc/