Node.js, Mocha, make globals in closures available - javascript

I am currently setting up some mocha tests using Node and in general they work. I now came across a problem I am not able to resolve.
I have a JS file containing the following: MyClass.js
(General CoffeeScript output for class MyClass + constructor: ->)
EDIT: This is browser code, I just want to use Node to test it. (Is that even desirable?)
(function() {
window.MyClass = (function() {
function MyClass() {
// Do something cool here
}
return MyClass;
})();
}).call(this);
I now require MyClass.js in my test file. Once I run it, it directly throws an error
Testfile:
var myclass = require('MyClass.js');
...
describe('MyClass', function() { ... });
Error:
ReferenceError: window is not defined.
So far, I understand why this is happening, window does not exist in Node. But I cannot come up with a solution. I actually do not need the real window object specifically, so I thought mocking it would be enough. But it is not...
var window = {},
myclass = require('myclass.js');
...
describe('MyClass', function() { ... });
This command is also not helping: $ mocha --globals window
I still end up with the same error.
Any idea is much appreciated!

You don't actually want the window object, what you want is the global object. Here is some code that can get it in the browser (in which case it will be the same as 'window') or in node (in which case it will be the same as 'global').
var global = Function('return this')();
Then set things on that rather than on 'window'.
Note: there are other ways of getting the global object, but this has the benefit that it will work inside strict mode code too.

With following code you can use your class-like object in web-browser environment and Node.js without modification. (Sorry, I don't know how to translate that to CoffeeScript)
(function (exports) {
var MyClass = (function() {
function MyClass() {
// Do something cool here
}
return MyClass;
})();
exports(MyClass);
})(function (exported) {
if (typeof module !== 'undefined' && module.exports) {
module.exports = exported;
} else if (typeof window !== 'undefined') {
window.MyClass = exported;
} else {
throw new Error('unknown environment');
}
});
As you already have a scope which doesn't pollute global name-space, you could reduce it to:
(function (exports) {
function MyClass() {
// Do something cool here
}
exports(MyClass);
})(function (exported) {
// see above
});
I'm not an expert in AMD, require.js and other module loaders, but I think it should be easy to extend this pattern to support other environments as well.
Edit
In a comment you said that the above solution is not working when translated back to CoffeeScript. Therefore, I suggest another solution. I haven't tried it but maybe this could be a way to solve your problem:
global.window = {}; // <-- should be visible in your myclass.js
require('myclass.js');
var MyClass = global.window.MyClass;
describe('MyClass', function() {
var my = new MyClass();
...
});
It's a horrible piece of code, but if it works, maybe for testing purposes it's sufficient.
Due to the module loading behaviour of node.js this only works if your require('myclass.js') is the first require of this file in the node process. But in case of testing with Mocha this should be true.

1) What you are looking for is the module.exports to expose things in Node:
http://openmymind.net/2012/2/3/Node-Require-and-Exports/
2) Also you don't need IIFE in Node, you can drop the (function() {...
3) You can alway look at some popular Node repo on Github to see examples, look at the Mocha code since you're using it, you'll learn a thing or two.

Something like jsdom is lighter than PhantomJS and yet provides quite a few things you need to test code that expects to be running with a proper window. I've used it with great success to test code that navigates up and down the DOM tree.
You ask:
This is browser code, I just want to use Node to test it. (Is that even desirable?)
It is very desirable. There's a point at which a solution like jsdom won't cut it but as long as your code is within the limit of what jsdom handles, might as well use it and keep the cost of launching a test environment to the minimum needed.

#hgoebl: As I'm not the OP, I can not add his original CoffeeScript code, but here is my example:
pubsub.coffee:
window.PubSub = window.PubSub || {}
PubSub.subscribe = ( subject, callback )->
now the test:
assert = require "assert"
pubsub = require './pubsub.coffee'
describe "pubsub.http interface", ->
it "should perform a http request", ->
PubSub.subscribe 1, 2
what works for me up to now is:
window.PubSub = window.PubSub || {}
window.PubSub.subscribe = ( subject, callback )->
and the test:
`window = {}`
assert = require "assert"
pubsub = require './pubsub.coffee'
describe "pubsub.http interface", ->
it "should perform a http request", ->
window.PubSub.subscribe 1, 2
The main drawback of the solution, is that I have to explicitly mention the window object in the implementation and the test. User code executed in a browser should be able to omit it.
I now came up with an other solution:
window = window || exports
window.PubSub = window.PubSub || {}
PubSub = PubSub || window.PubSub
PubSub.subscribe = ( subject, callback )->
and then in the test, simply requiring the PubSub namespace:
PubSub = require( './pubsub.coffee' ).PubSub
And finally, the solution from kybernetikos applied looks like this:
global = `Function('return this')()`
global.PubSub = global.PubSub || {}
PubSub.subscribe = ( subject, callback )->
As now, the PubSub namespace is in the global namespace, just a simple require is needed in the file that contains the mocha tests:
require( './pubsub.coffee' )

Related

How to use this in javascript module pattern?

I'm studying module pattern and have a question.
I want to use 'settings' anywhere.
script1.js
var MODULE = (function() {
var t = {};
this.settings = { // this == Window
users: ['john', 'emma']
}
return t;
})()
script2.js
MODULE.dom = function() {
var t = this; // this == MODULE
document.querySelector('p').textContent = t.settings.users[0]; // error
function _say() {
return t.settings.users[1] // error
}
return {
say: _say
}
}
MODULE.DOM = MODULE.dom.call(MODULE)
When use this.settings = {...}, 'this' means Window so code doesn't work.
When use t.settings = {...}, 'this' means MODULE so code works but when write MODULE in dev console, settings is exposed in MODULE variable. Is it ok?
I'd greatly appreciate any help, thank you!
When use t.settings = {...}, 'this' means MODULE so code works
That's the right way to do it.
but when write MODULE in dev console, settings is exposed in MODULE variable. Is it ok?
It's mostly OK.
If you're worried about the client being able to type in the variable name and see the code that gets run - there's no way to avoid that. They can just look at the devtools to see what the network requests are, and what is downloaded - or look at the Sources panel.
If you're worried about running into naming collisions with larger scripts, then - sometimes, libraries deliberately assign themselves to the window to allow other parts of the code to access them. Perhaps you'd like your MODULE to be like this. If not, then you should utilize JavaScript modules instead, which allow for scripts to be imported inside other scripts without polluting the global namespace at all or having any possibility of naming collisions. For example, you could do
// script1.js
export const MODULE = {
settings: {
users: ['john', 'emma'];
}
};
// script2.js
import { MODULE } from './script1.js';
// proceed to use MODULE
And you can do import { MODULE } from './script1.js'; from any script file, not just script2.js.
Personally, I consider the IIFE module pattern in JavaScript to be mostly obsolete nowadays. For any reasonable-sized script, better to write code in separate files and then import and export as needed. (A 1000 line file is somewhat hard to debug and refactor. Ten 100 line files are easier to debug and refactor.)

Best way to test IIFE (Immediately Invoked Function Expression)

So I have an existing application which uses IIFEs extensively in the browser. I'm trying to introduce some unit testing into the code and keep with the pattern of IIFE for new updates to the code base. Except, I'm having trouble even writing a test which gives me a handle to the code. For example I see this type of logic all over the code base:
var Router = (function (router) {
router.routeUser = function(user) {
console.log("I'm in! --> " + user)
};
return router;
})(Router || {});
Then the JS file is included in a script tag in the markup:
<script src="js/RouteUser.js"></script>
and called like this in the production code:
Router.routeUser(myUser)
So my question is, how do I write a test which tests the method routeUser? I've tried this in my Mocha Test:
var router = require('../../main/resources/public/js/RouteUser');
suite('Route User Tests', function () {
test('Route The User', function () {
if (!router)
throw new Error("failed!");
else{
router.routeUser("Me")
}
});
});
But I get an exception:
TypeError: router.routeUser is not a function
at Context.<anonymous> (src\test\js\RouteUser.test.js:8:20)
Then I tried returning the method, which gives the same error:
var Router = (function (router) {
return {
routeUser: function (user) {
console.log("I'm in! --> " + user)
}
}
}
)(Router || {});
Can anyone point me the right direction here?
It sounds that...
you have a codebase of scripts that are only used in the browser context (usage of IIFE suggests this)
you'd like to introduce browserless unit tests (Jest, Mocha?) using node.js (good idea!)
but you probably don't want to migrate the whole codebase to a different coding style at this moment in time (can be a lot of work depending on the size of your codebase)
Given these assumptions, the problem is that you want your code to...
act as a script when used on production (set global window.Router etc)
act as a module when used in unit tests so that you can require() it in unit tests
UMD
UMD, or universal module definition, used to be a common way to write code so that it can work in multiple environments. Interesting approach, but very cumbersome, and I like to think UMD is a thing of the past nowadays...
I'll leave it here for completeness.
Just take UMD's idea
If the only thing you want for now to make a specific script act as a module too, so that it's importable in tests, you could do a small tweak:
var Router = (function (router) {
router.routeUser = function(user) {
console.log("I'm in! --> " + user)
};
if (typeof exports === "object") {
module.exports = router;
// now the Mocha tests can import it!
}
return router;
})(Router || {});
Long term solution
In the long run, you can get lots of benefits by rewriting all your code to use ONLY modules and use a tool like webpack to package it for you. The above idea is a small step in your direction that gives you one specific benefit (testability). But it is not a long term solution and you'll have some trouble handling dependencies (what if your Router expects some globals to be in place?)
If you intend to run your Mocha tests in the browser, you do not have to alter your existing code.
Let's walk through the IIFE pattern, because based on your code, I think you may misunderstand how it works. The basic shape is this:
var thing = (function() {
return 1;
})();
console.log(thing) // '1'
It's a var declaration setting thing equal to the value on the right side of the equals sign. On the right, the first set of parens wraps a function. Then, a second set of parens sits right next to it, at the end. The second set invokes the function expression contained in the first set of parens. That means the return value of the function will be the right-side value in the var statement. So thing equals 1.
In your case, that means that the outer Router variable is set equal to the router variable returned by your function. That means you can access it as Router in your tests, after including the script in the DOM:
suite('Route User Tests', function () {
test('Route The User', function () {
if (!Router) // <- Notice the capital 'R'
throw new Error("failed!");
else {
Router.routeUser("Me") // <- capital 'R'
}
});
});
If you intend to run your tests with node, see Kos's answer.

What is the benefit of this JavaScript pattern based on an IIFE?

I master the Javascript IIFE essence, but while reading this page, I'm kinda confused of the usage.
It sounds that the following JavaScript pattern is pretty common:
(function(something) {
something.foo = 123;
})(something || something = {})
A usage example:
(function(something) {
something.foo = 123;
})(something || something = {})
console.log(something); // {foo:123}
(function(something) {
something.bar = 456;
})(something || something = {})
console.log(something); // {foo:123, bar:456}
As something is defined in the global scope, what is the benefit of this pattern in relation to the following trivial code:
var something;
something.foo = 123;
something.bar = 456;
Which use case would it make sense to use it?
You get a closure over something which ensured that even though some other code overrides it's in global scope you will still have the right reference to that something, it's better illustrated with jQuery and jQuery.noConflict();:
<script src="/path/to/jquery.js"></script>
<script>
(function($) {
// Here $ is jQuery
// Something asynchrone is happening:
setTimeout(function() {
// But $ is still jQuery
}, 1000);
})($);
</script>
<script>
// Someone calls jQuery.noConflict();
jQuery.noConflict();
// And now $ is not jQuery
</script>
Lets say you have a namespace for your application myApp. You have several scripts that add functionality because like a good developer you've broken your application up into different chunks. Also like a good web developer you're loading those scripts asynchronously, you don't know what order they are going to be added in. So you have each module conditionally create the namespace for the app if it doesn't exist (the (myApp || {}) part). You also want to hide the internal functionality of the module from stuff that doesn't need to know about it, so you pass your 'namespace' object into a function that creates a closure and attaches the module's API to the namespace object myApp.
// async loaded script for the foo 'module'
(function(myApp) {
var myPrivate = 3; // hidden in the closure
myApp.getFoo = function() { return myPrivate; };
}(myApp || {});
This pattern is not without its flaws (what if myApp.foo depends on myApp.bar?) which is why its largely been replaced by browserify/require.js/webpack/etc.

How to use `require` and dependency injection, service location in JS (browser-side)?

So I've been playing with JS and browserify to allow to split my JS into smaller file chunks. It works great, however, I'm still lost on how to properly use the require function.
For me, it acts as a the Service Locator, because it looks for the proper "file" to load, and return an object. (For example in PHP, require somewhat load the file in the memory but doesn't construct).
Example:
var Foo = function() {
console.log("I'm the Foo object");
};
module.exports = Foo;
Then, to use it I'll do:
var Foo = require('foo');
and
var foo = new Foo();
Note, that the exported function is NOT constructed.
I could have done:
var foo = require('foo')();
None of those methods seems right to me (I may are wrong).
1) Is it common to do it like this? Or should exported the executed function?
Anyway, this introduction is to understand how I should play with the require function.
For example if I've a Foo object, which is depends of Bar, I've two way to do:
Service Location:
var Foo = function() {
var Bar = require('bar')();
Bar.doSomethingAwesome();
};
module.exports = Foo;
or I can do:
Dependency Injection
var Foo = function(bar) {
bar.doSomethingAwesome();
};
module.exports = Foo;
// And at a latter time
var foo = require('foo')(require('bar')); /// eurk
I obviously know that that's two different things and serve different purposes.
2) But I'm wondering what is the common/right way to do in JS, is there any commonly admitted rules?
Browserify allows you to program with modules, there's not much more to it. It's not really a DI container or service locator per se, although you can probably make it work like one.
So doing this is perfectly fine:
var Foo = require('foo');
var foo = new Foo();
In that case, it makes sense to simply place all require calls at the top of your file, similar like you would do with using in C# or import in Java. I personally wouldn't scatter require calls since don't help much with readability.
You can also export an instance which doesn't have to be newed up anymore, as long as that is appropriate for what you want to do (in that case module.exports = Foo() would lead to a singleton).
Also see this related question:
Dependency Injection with RequireJS
The rewire library provides module injection for Node.js.
A couple of solutions have been discussed and presented in this Github issue to support browserify.
Usage example from the project README:
var myModule = rewire("../lib/myModule.js");
myModule.__set__("fs", fsMock); // set private variable
Use Browserify so you can require npm packages from your browser just like node. Then you can use Weather.js or require it, then inject it in any way you like.

Javascript Module pattern - how to reveal all methods?

I have module pattern done like this:
var A = (function(x) {
var methodA = function() { ... }
var methodB = function() { ... }
var methodC = function() { ... }
...
...
return {
methA: methodA,
methB: methodB
}
})(window)
This code let's me call only methA and methB() on A which is what I want and what I like. Now the problem I have - I want to unit test it with no pain ot at least with minimal efforts.
First I though I can simply return this but I was wrong. It returns window object.(can someone explain why?).
Second - I found solution somewhere online - to include this method inside my return block:
__exec: function() {
var re = /(\(\))$/,
args = [].slice.call(arguments),
name = args.shift(),
is_method = re.test(name),
name = name.replace(re, ''),
target = eval(name);
return is_method ? target.apply(this, args) : target;
}
This method let's me call the methods like this: A.__exec('methA', arguments);
It is almost what I want, but quite ugly. I would prefer A.test.methA() where test would never be used in production code - just for revealing private methods.
EDIT
I see people telling me to test the big thing instead of the small parts. Let me explain. In my opinion API should reveal only the needed methods not a bunch of internal functions. The internals because of their small size and limited functionality are much easier to test then test the whole thing and guess which part gone wrong.
While I may be wrong, I would still like to see how I could return references to all the methods from the object itself :).
Answer to your first question(you return this, but it returns window, not the object you wanted): in javascript this inside the function returns global object unless this function is a method of the object.
Consider next examples:
1) this points to the global object ():
function(){
return this;
}
2) this points to the object:
var obj = {
value: "foo",
getThisObject: function(){
return this;
}
}
Your case is example #1, because you have a function, that returns an object. This function is not a method of any object.
The best answer to your second question is to test only public methods, but if
that is so important for you, I can propose next:
create your modules dynamically on server side.
How it works:
create separate scripts for functionality you want;
create tests for these separate scripts;
create method that will combine scripts into one however you want;
to load script, reference to the combining scripts method.
Hopefully, it can solve your problem. Good luck!
Why not use namespaces to add your modules and public methods to js engine. Like this:
window['MyApp']['MODULE1'] = { "METHOD1" : {}, "METHOD2" : {}};
I write modules like this Sample module in JavaScript.
And test it like this: Simple unit testing in JavaScript
The use of eval() is generally not good idea.

Categories

Resources