Writing a jasmine test spec to a javascript closure function - javascript

I have a Javascript function in a view which is enclosed in a closure. The closure returns a function of the same name and also has some helpers. This is the structure of the method.
this.myMethod = (function () {
function helperMethod(){
....
return true;
}
return function myMethod(args){
helperMethod();
manipulate();
}
}
My question is how do I write a Jasmine Unit Test spec to this method. How can I invoke this method ?
Using the default way of methods does not work in this case as it is anonymous.
var view = new myView();
view.myMethod();
expect ( true ).toBeTruthy();
Please help in this regard. I am a beginner to Jasmine Framework.

By closing over the helperMethod function, you've made it inaccessible to your specs so you won't be able to test it directly. You can either test it indirectly by going through the existing public interface (myMethod) or by extracting the helperMethod from the closure in some way to make it accessible publicly, this could be as a prototype method on the view, or just on this, or on a completely different helpery object altogether.

Related

JSHint with ECMAScript6: method is not defined

I'm implementing a client-side application using ECMAScript6 and use JSHint for static code analysis. I often use the following pattern in my code:
class MyClass {
constructor() {
//This is how I would like to call myMethod
myMethod();
//This is how I should call myMethod to make JSHint analysis pass
this.myMethod();
}
myMethod(){
//Implementation
}
}
My primary language is Java so I expect that simply calling myMethod() should be ok. However without adding this to method call I'm getting "'myMethod' is not defined" warning from JSHint. My questions are:
Is it correct to make calls without this in such situation? (e.g. in PHP you always need to add $this-> to non-static method call)
If that's correct to make calls without this is there any way (any .jshintrc flag) to turn off this warning in JSHint?
No, this is and never was correct in JavaScript. Methods always need to be called on a receiver explicitly to make this work, and they need to be referred to using property access notation because methods are just functions on properties in javascript. They're not available as functions in the scope of your other methods. It's the same for properties, btw.
JsHint is right here, and there's no reason to turn that warning off. Even if that may possible, executing your program in spite of that would just make it not work.
Is it correct to make calls without this in such situation? (e.g. in
PHP you always need to add $this-> to non-static method call)
No, it is not. You always have to specify the receiver of the method.
If that's correct to make calls without this is there any way (any
.jshintrc flag) to turn off this warning in JSHint?
JSHint returns "'myMethod' is not defined" warning correctly as there is not function called myMethod in the scope of the constructor.
In the code you provided the identifier myMethod isn't defined, but the inherited property myMethod of instances of MyClass is defined.
If you define myMethod as a Function under a closure which isn't available elsewhere then you can access as it in the form you desire
var MyClass = (function () {
function myMethod() {
//Implementation
}
class MyClass {
constructor() {
myMethod();
}
}
return MyClass;
}());
I don't get to write much ES6 so I'm not sure if putting the function myMethod inside MyClass's definition is a SyntaxError
Please note however that this is required to reference your specific instance of MyClass, so you'll probably need to use it somewhere if you want MyMethod to act on the instance.
function myMethod(obj) {...}
// ...
myMethod(this);
If you read the MDN's description of class
JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JS classes provide a much simpler and clearer syntax to create objects and dealing with inheritance.
This is saying using class is just shorthand for the old way of doing it, not a new model, so it may be easier to think of what your current code would look like if written in ES5,
var MyClass = (function () {
function MyClass() {
this.constructor.apply(this, arguments);
}
MyClass.prototype = Object.create(null);
MyClass.prototype.constructor = function () {
myMethod(); // referenceError
this.myMethod(); // works
};
MyClass.prototype.myMethod = function () {
//Implementation
};
return MyClass;
}());

Javascript Jasmine Testing: Prevent tested function to call function from object that was created within tested function

I want to test a Javascript function with Jasmine that has a structure like this:
showEditUser: function (...) {
// more code here...
var editUserView = new EditUserView();
// more code here...
editUserView.generate(...);
}
editUserView.generate() causes an error. That does not matter because I don't want to test it. But how can I prevent it from being called?
EditUserView is a RequireJS Module that extends another Module called BaseView. The function generate() is defined in BaseView. There are other Modules that extend BaseView and I want all of them not to call generate while testing. How can I do that with Jasmine? It seems not to be possible with spyOn(...).and.callFake() because I don't have the editUserView Object when calling the function. Is there kind of a static way to tell Jasmine to callFake() the function generate in BaseView?
There is no "nice" way to solve this with jasmine. I think, to take a BaseView viewObj as parameter is a nicer coding style. It will reduce the dependencies of the method. So it don't have to know the specific BaseView-class, he will simply need a viewObj that has a generate-method.
showEditUser: function(..., viewObj) {
// ...
viewObj.generate(...);
}
Then you could create a ViewMock and put it into that function like this:
var viewMock = {};
viewMock.generate = jasmine.createSpy('generate() spy');
Then you will call it this way:
showEditUser(..., viewMock);
EDIT: Here is a similar question

Jasmine-node - Creating a spy on a constructor called inside other function

I'm novice in jasmine and I need to write some unit tests for node.js app in this framework.
I have some problems, one of them is this described below:
var sampleFunction = function(){
var loader = new Loader(params);
// rest of logic here
}
I want to write unit test for sampleFunction. To do this I need to create spy on Loader constructor and check what this constructor gets as params and what kind of object is it returning.
Any ideas how to do that? I tried to create spy on Loader.prototype.constructor but it wasn't a solution to this problem.
OK, so normally in client-side JavaScript you would use the window object like so jasmine.spyOn(window, 'Loader')
In node, however, there is no window object and despite claims to the contrary global is not a substitute (unless you are in the REPL which runs in global scope).
function MyConstructor () {}
console.log(global.MyConstructor); --> undefined
console.log(this.MyConstructor); --> undefined
So, in node you need to attach your constructor to an object. So just do something like this
var Helpers = {
Loader: Loader
};
var constSpy = jasmine.spyOn(Helpers, 'Loader').andCallThrough();
sampleFunction();
expect(constSpy).toHaveBeenCalled();
The andCallThrough call is only necessary if you want your constructor to do something (often with constructor you do).
This is a little hacky, but it works and seems to be the only way to achieve this through jasmine's implementation within node.

jQuery namespace declaration and modular approach

I have confusion on how to proceed with my project.
I am developing an enterprise app in which lots of modules are to be written.
Most of module will be using lots of jQuery plugins to create complex grids, draw graphs for different purposes which means modules will be appending divs, tables etc a lot to DOM.
I want to preserver namespace since this will be large app.
For that I came across prototype method and self-executing anonymous function.
self-executing anonymous function seems to be recommended a lot.
My questions are
Are self executing functions reusable ?I mean these are immediately executed so lets say a module draws a complex grid for a given JSON file. So will I be able to use same self-executing anonymous function for 3 different JSON files just like a jQuery plugin ?
when there will be lots of modules written , they will all self execute on start-up. Will it effect Ram/Processor usage? Shouldn't it be way that modules should be called when needed ? what significance will self execution do ?
My Project Scope:
Kindly help me understand this self executing thing in my project scope, which is My project Holds a main namespace say "Myapp" and and its modules like Myapp.moduleA, Myapp.moduleB.MyApp will trigger its modules on click etc.
What is best way to go for me ?
Self-Executing Anonymous Func
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.somevar = "Bacon Strips";
//Public Method
skillet.draw = function() {
//Draw a grid
};
//Private Method
function _grid( ) {
//
}
}
}( window.skillet = window.skillet || {}, jQuery ));
You cannot reuse a self executing function, it just executes immediately and that's it.
If you need to execute it multiple times, you should just declare a function.
A possible approach is this:
var MYNAMESPACE.Object = (function(){
// private methods
var somemethod = function(){};
// public methods
return {
somepublicmethod: function(){}
};
})();
Now you can call it like this:
MYNAMESPACE.Object.somepublicmethod();
As for executing upon startup. Provided you only create methods and don't DO anything immediately inside your declaration, it won't affect performance too much unless you have a really big amount of modules. If that's the case, you should probably look into the asynchronous module loader pattern (AMD). RequireJS is a good example of that: http://requirejs.org
I wrote an article about JS namespaces which could be interesting for you:
http://www.kenneth-truyers.net/2013/04/27/javascript-namespaces-and-modules/

how to unit-test private methods in jquery plugins?

Perhaps this is a bit of a novice JQuery question but:
proper jquery plugins are written inside a closure
thus only methods defining the plugin interface are accessible from the outside
sometimes (or many times) one may need helper methods that it doesn't make sense to expose as part of plugin interface (for example because they alter internal state).
how do those get unit-tested?
For example, looking at blockUI plugin, how can methods install, remove, reset get unit-tested?
To draw a parallel, in Java I would:
create a BlockUI interface containing public methods only (by definition)
create a BlockUIImpl class implementing the above interface. This class would contain install(), remove(), reset() methods that could be public, or (package) protected
So, I would unit-test the Impl but client programmers would interact with the plugin via BlockUI interface.
The same applies here as with any other language and testing privates: To test private methods, you should exercise them via the public interface. In other words, by calling your public methods, the private methods get tested in the process because the public methods rely on the privates.
Generally private methods are not tested separately from the public interface - the entire point is that they are implementation details, and tests should generally not know too much about the specifics of the implementation.
Code written inside a function in JavaScript, or closure as you called it, is not necessarily isolated from the outside of that function.
It is useful to know that functions have visibility of the scope in which they are defined. Any closure you create carries the scope, and therefore functions, of the code that contains it.
This simple example with a jQuery plugin and an artificial "namespace" might serve to prove this assumption:
// Initialise this only when running tests
my_public_test_namespace = function(){};
jQuery.fn.makeItBlue = function() {
makeItBlue(this);
function makeItBlue(object) {
object.css('color','blue');
}
if(typeof my_public_test_namespace != "undefined") {
my_public_test_namespace.testHarness = function() {
return {
_makeItBluePrivateFn: makeItBlue
}
};
}
};
$("#myElement").makeItBlue(); // make something blue, initialise plugin
console.debug(my_public_test_namespace.testHarness()._makeItBluePrivateFn);
But don't forget you shouldn't really test privates. ;)
I came up with the same question and after navigating and finding answers that not really apply, here's what I ended up to solve a similar problem.
Problem: "I have a widget that has a behavior I want to test to ensure it's working as expected, some of the methods are called internally because they have to solve internal behavior, exposing them as public does not make sense because they wont be called from outside, testing the public methods means you wont test the internals of the widget, so finally what can I do?"
Solution: "Creata a test widget that exposes the methods you are interested in testing and use them in the qunit, here is the example:"
// Namespaces to avoid having conflicts with other things defined similarly
var formeditortest = formeditortest || {};
// widget that inherits from the container I want to test
$.widget( "app.testcontainer", $.app.container, {
executeDrop: function(drop, helper) {
var self = this;
self._executeDrop(drop, helper);
}
});
// Test cases
formeditortest.testDropSimple = function(assert) {
var container = $("<div />");
container.testcontainer();
container.testcontainer("drop", 0, 3);
assert.equal(true, $(innerDiv.children()[0]).hasClass("droparea"));
});
QUnit.test(name, function( assert ) {
formeditortest.testDropSimple(assert);
formeditortest.testDropBottom(assert);
});
Using this method the inherited testcontainer could have the preparation required to test elements and then the qunit will handle the test, this solves my problem, hope this works for someone else that is having troubles to approach these kind of tests.
Critics? welcome to comment, I want to improve this if I'm doing something silly!!!

Categories

Resources