Testing Angular Factory with Jasmine is not working - javascript

I'm new to Jasmine. I've written a simple code to execute in JS Fiddle which is working perfectly fine. But, when I include jasmine code, its not working. Am I missing anything here?
var app = angular.module('sortModule', [])
app.factory('sortFactory', function(){
var sortedColors = []
var shouldPush = true;
return {
sortColors: function(colorsArray){
var colorsOrder = [{color:'green'},{color:'yellow'},{color:'blue'},{color:'red'}]
for(color in colorsOrder) {
for(objColor in colorsArray) {
shouldPush = colorsOrder[color].color === colorsArray[objColor].color ? true : false
if(shouldPush) {sortedColors.push(colorsArray[objColor]);}
}
}
return sortedColors;
}
}
});
app.controller('sortController', function($scope,sortFactory){
$scope.colorsArray = [{id: '1',color: 'red',code : '#ff0000'},{id: '2',color: 'blue',code : '#0000ff'},{id: '3',color: 'red',code : '#ff0000'},{id: '4',color: 'yellow',code : '#ffff00'},{id: '5',color: 'green',code : '#00ff00'}];
$scope.sortedColors = sortFactory.sortColors($scope.colorsArray)
});
describe('colors', function () {
beforeEach(module('sortModule'));
it('can get the actual sorted ordered colors list', inject(function(sortFactory) {
expect(sortFactory).toBeDefined();
}));
});
var NOT_IMPLEMENTED = undefined;
// load jasmine htmlReporter
(function() {
var env = jasmine.getEnv();
env.addReporter(new jasmine.HtmlReporter());
env.execute();
}());
Actual working fiddle without Jasmine
http://jsfiddle.net/SyedNizamChennai/kjuemhua/15/
New fiddle when Jasmine is included
https://jsfiddle.net/SyedNizamChennai/5d4f0hdL/3/

Test code contains module function
beforeEach(module('sortModule'));
This is function from ngMock module, you need include it as external resource.
https://jsfiddle.net/SyedNizamChennai/5d4f0hdL/3/
EDIT:
working example is here:
http://jsbin.com/lenogujesi/1/edit?html,output
(i used jsbin to better show dependencies and their order)
some notes:
if is jasmine loaded, angular mock expose function mock and others as global (see https://docs.angularjs.org/api/ngMock#function), otherwise function is undefined
angular and angular mock should have same version

Related

How do I unit test a custom ExtJS component using Jasmine

I’m writing jasmine tests for an ExtJS 4.1.1 client app. The server side code is Java. The client app doesn’t follow a strict MVC pattern; the models are separate but the view and controller code is co-mingled. The controllers don’t even inherit from Ext.app.controller. (Don’t blame me, I didn’t write it).
I’m able to test the Ext.app.Application object but keep getting null whenever I try to create a custom ExtJS layout object inside the Jasmine spec.
It's probably a basic error in my test ExtJS app or jasmine spec but I'm very new to ExtJS and can't pin point it.
Any help is really appreciated.
File structure:
/myapp (java code)
...
/webclient
/assets
/extjs-4.1.1
/myapp (same name as top level java code)
myapp.js
myapp-ui.js
/myapp-test
runspec.html
/lib
/jasmine-2.3.4
/specs
uispecs.js
/ui
/layouts
myappgrid.js
myapppanel.js
Here's the code for the ExtJS app (myapp-ui.js), Jasmine specs (uispecs.js), and spec runner (runspec.html)
myapp-ui.js
Ext.Loader.setConfig({
enabled : true,
paths : {
myapp : 'myapp'
}
});
var Application = null;
Ext.onReady(function() {
Application = Ext.create('Ext.app.Application', {
name: 'myappUI',
appFolder: 'myapp',
autoCreateViewport: true,
launch: function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.execute();
}
});
});
Here's the code for uispecs.js (Jasmine test spec)
describe("Basic Assumptions", function() {
var myLayout = null;
beforeEach( function() {
// This always returns null
myLayout = Ext.create('myappUI.ui.layouts.MyLayout');
});
// This test PASSES
it("myappUI is defined",function() {
expect('myappUI').toBeDefined();
});
// This test FAILS: myLayout is never created
it ('myLayout shouldn’t be null', function () {
expect ( myLayout != null).toBeTruthy();
});
});

How to test function within Angular click-handler

I'm currently unit-testing my Angular controllers and the only portion of my code coverage that is lagging behind are functions within click-handlers, and the statements within these functions.
As an example, function(cap)... states function not covered and playersService.setCap... states statement not covered in relation to the below click-handler:
vm.setCap = function(cap) {
playersService.setCap({playerId: playerId}, {limit: cap});
};
How would I go about testing a function like this, and the statement within it? I'm just looking for a basic test (expect(function).toHaveBeenCalled).
Alright to test this you would want to use a mock version of your playersService which you can then just inject into your controller.
describe("Controller: yourController", function () {
var mockResponse = {};
var mockService = {
setCap: function(playerId, limit){
mockResponse.playerId = playerId,
mockResponse.limit = limit
}
};
var mockParams = 'cap';
var $controller;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}))
it("Should call the service on click", function () {
spyOn(mockService, 'setCap').and.callThrough();
var testedController = $controller('yourController', { playersService:mockService });
testedController.setCap(mockParams);
expect(mockService.toHaveBeenCalled).toHaveBeenCalled();
expect(mockResponse.limit.limit).toBe(mockParams);
})
});
This will give you an example for both white and blackbox testing for the functionality.

Setting global variables in jasmine for angularjs

I have an angular application with some global environment variables defined in an env.js file:
(function(sp) {
'use strict';
pk.env = pk.env || {};
// localhost
pk.env.baseUrl = 'http://localhost:8080/';
})(typeof exports === 'undefined' ? (this.pk = this.pk || {}) : exports);
These variables are used in multiple factories to make REST API calls:
'use strict';
angular.module('pkApp').factory('pkFactory', PKFactory);
function PKFactory($http) {
var urlBase = pk.env.baseUrl;
var apiUrl = 'v1/data';
var _pkFactory = {};
_pkFactory.getData = function() {
return $http.get(urlBase + apiUrl);
};
return _pkFactory;
}
I am writing unit tests for this factory using Jasmine and I keep getting the error:
ReferenceError: Can't find variable: pk
If I remove this variable reference from the factory, the tests run fine.
'use strict';
console.log('=== In pk.factory.spec');
describe('Unit: pkFactory', function() {
beforeEach(module("pkApp"));
var $httpBackend, $rootScope, pkFactory;
beforeEach(inject(function($injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
$httpBackend.when('GET', 'v1/data').respond('Not found');
pkFactory = $injector.get('pkFactory');
}));
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('expects getData method to be defined', function(){
expect(pkFactory.getData()).toBeDefined();
$httpBackend.flush();
});
})
How do I inject value of 'pk.env.baseUrl' into the factory? I have tried using $window, but it didn't work.
As pretty much already answered here, you can also declare a global variable within your test file
var globalVar = "something";
describe('Your test suit', function() {
...
});
and if you are using Karma you can edit the karma.conf.js file to define it
// list of files / patterns to load in the browser
files: [
...,
'file-containing-the-global-variable.js'
],
You should avoid using the globals in Angular completely.
Convert the file to an angular value or constant:
angular.module('pkApp').value('pk', pk);
now you can change pkFactory to get the pk object injected
function PKFactory($http, pk) {
// pk is no longer from global scope, but injected from angular as an argument
var urlBase = pk.env.baseUrl;
var apiUrl = 'v1/data';
var _pkFactory = {};
_pkFactory.getData = function() {
return $http.get(urlBase + apiUrl);
};
return _pkFactory;
}
and in tests, you can now mock the pk to a different value (or not do anything and use the one from code)

Referencing JavaScript files from Jasmine tests

I am writing some utilities that I intend to reuse across my JavaScript. This is also a learning exercise on my part. In an attempt to do this, I have the following file:
utilities.js
Object.prototype.AddPrefix = function(prefix) {
return prefix + this;
};
I intend to call this function in JavaScript like this:
var myString = 'agree';
myString = myString.AddPrefix('dis');
Please note, that is a contrived example. I'm just trying to demonstrate calling the function. Either way, I want to test the AddPrefix function. To do that, I'm using Jasmine. I have the following Jasmine file:
utilities.tests.js
'use strict';
describe('utilities', function() {
describe('add prefix', function() {
it('append dis to string', function() {
var v = 'agree';
var actual = v.AddPrefix('dis');
var expected = 'disagree';
expect(actual).toBe(expected);
});
});
});
The two files, utilities.js and utilities.tests.js are in the same directory. I am executing Jasmine via gulp with the following script:
gulpfile.js
var gulp = require('gulp');
var jasmine = require('gulp-jasmine');
gulp.task('default', function() {});
gulp.task('test', function() {
var testFiles = [
'utilities/utilities.tests.js'
];
return gulp
.src(testFiles)
.pipe(jasmine());
});
When I execute gulp test from the command-line, I get the following error:
[09:44:33] Using gulpfile C:\Projects\test\gulpfile.js
[09:44:33] Starting 'test'...
F
Failures:
1) utilities add prefix
1.1) TypeError: Object agree has no method 'AddPrefix'
1 spec, 1 failure
Finished in 0 seconds
[09:44:33] 'test' errored after 42 ms
[09:44:33] Error in plugin 'gulp-jasmine'
Message:
Tests failed
Its like utilities.tests.js does not know where utilities.js is located. However, I do not know how to reference it. How do I do this?
Your utilities.js file is never being executed. You need to require('./utilities') in utilities.tests.js:
'use strict';
require('./utilities');
describe('utilities', function() {
describe('add prefix', function() {
it('append dis to string', function() {
var v = 'agree';
var actual = v.AddPrefix('dis');
var expected = 'disagree';
expect(actual).toBe(expected);
});
});
});

Reusing mocha test code

I'm developing a NodeJS application and use Mocha for unit testing.
Let's say i have two very similar test suits.
In fact those are tests for two classes which
implement the same interface.
For example:
suit_a.js
var A = require('./a');
describe(function () {
var instance;
beforeEach(function () {
instance = new A();
});
it(function () {
assert(instance.getSomeValue() === 1);
});
});
suit_b.js
var B = require('./b');
describe(function () {
var instance;
beforeEach(function () {
instance = new B({option: "option-value"});
});
it(function () {
assert(instance.getSomeValue() === 1);
});
});
Is there a way to remove code repetition? Is there a way to have two
different test suits, using same assertion code, but with different configuration
or something like that?
The only idea I have right now is to use some kind of source code generation,
but I would like to avoid that if possible.
Move the inner function to an extra file and require it.
In your case you need new A() and new B(...) extra, so either make them available outside or include them as a parameter to the require-result:
var t = require('innerTestGen');
var t1 = t.create(new A())
describe(t1);
var t2 = t.create(new B(...))
describe(t2);
Hope that helps?

Categories