Error while running angularJS unit test case in Karma-Jasmine - angularjs

MainCtrl.js
var app = angular.module('mailApp');
app.controller('MainCtrl', ['$scope','$http',function($scope,$http) {
$scope.sortType = 'date'; // set the default sort type
$scope.sortReverse = false; // set the default sort order
$scope.inboxDetails = [];
$scope.loadInboxData = function(a){
if(a==1){
$http.get('inboxData.json')
.then(function(response){
$scope.inboxData = response.data;
});}
else if(a==2){
$http.get('inboxData1.json')
.then(function(response){
$scope.inboxData = response.data;
});}
}
//-----------------------------------------------
testMainCtrl.js
'use strict';
describe('MainCtrl', function () {
var $controller;
beforeEach(module('mailApp'));
beforeEach(inject(function(_$controller_){
$controller = _$controller_;
}));
//Test cases to verify Inbox Data
describe('$scope.loadInboxData', function () {
it('Inbox data is called', function () {
var $scope = {};
var controller = $controller('MainCtrl', {$scope: $scope});
$scope.inboxData = [{"subject": "Angular Example 11", "date": "3/8/2016", "to": "test1", "from":"abcd1","details":"Test Message 1" },{ "subject": "Angular Example 21", "date": "3/8/2016", "to": "test2", "from":"abcd2","details":"Test Message 2" },{ "subject": "Angular Example 31", "date": "4/8/2016", "to": "test3", "from":"abcd3","details":"Test Message 3" },{ "subject": "Angular Example 41", "date": "5/8/2016", "to": "test3", "from":"abcd4","details":"Test Message 4" }];
var a=$scope.loadInboxData(1);
expect($scope.inboxData).toEqual(a);
});
});
});
//------------------------------------------------
Error :
Chrome 48.0.2564 (Windows 10 0.0.0) MainCtrl $scope.loadInboxData
Inbox data is called FAILED
Expected
[
Object( {
subject:'Angular Example 11',
date:'3/8/2016',
to:'test1',
from:'abcd1',
details:'Test Message 1'
} ),
Object( {
subject:'Angular Example 21',
date:'3/8/2016',
to:'test2',
from:'abcd2',
details:'Test Message 2'
} ),
Object( {
subject:'Angular Example 31',
date:'4/8/2016',
to:'test3',
from:'abcd3',
details:'Test Message 3'
} ),
Object( {
subject:'Angular Example 41',
date:'5/8/2016',
to:'test3',
from:'abcd4',
details:'Test Message 4'
} )
]
to equal undefined.

You have a hard dependency on $http in your test. You should mock a return value from the $http service.
Take a look at the documentation https://docs.angularjs.org/api/ngMock/service/$httpBackend.

This may help you, $httpBackend is mock of $http
'use strict';
describe('MainCtrl', function () {
var $controller,$httpBackend;
beforeEach(module('mailApp'));
beforeEach(inject(function(_$controller_){
$controller = _$controller_;
}));
beforeEach(inject(function($injector) {
$httpBackend = $injector.get('$httpBackend');
}));
//Test cases to verify Inbox Data
describe('$scope.loadInboxData', function () {
it('Inbox data is called', function () {
var $scope = {};
var controller = $controller('MainCtrl', {$scope: $scope});
$scope.inboxData = [{"subject": "Angular Example 11", "date": "3/8/2016", "to": "test1", "from":"abcd1","details":"Test Message 1" },{ "subject": "Angular Example 21", "date": "3/8/2016", "to": "test2", "from":"abcd2","details":"Test Message 2" },{ "subject": "Angular Example 31", "date": "4/8/2016", "to": "test3", "from":"abcd3","details":"Test Message 3" },{ "subject": "Angular Example 41", "date": "5/8/2016", "to": "test3", "from":"abcd4","details":"Test Message 4" }];
$httpBackend.when('GET', 'inboxData.json').respond(yourjsonresponseData1);
$httpBackend.when('GET', 'inboxData2.json').respond(yourjsonresponseData2);
var a=$scope.loadInboxData(1);
expect($scope.inboxData).toEqual(a);
});
});
});

Related

angular service test fails to return required response

I am trying to write tests for angular service using jasmine and karma. I have the following code for my service call:
angular.module('omdb', [])
.factory('myservice', MyService);
MyService.$inject = ['$http'];
function MyService($http) {
var vm = this;
var service = {};
service.getData = function() {
return $http.get('omdb/mydata.json').then(function(response) {
return response.data;
});
};
return service;
};
I am tesitng it using the following file for spec as:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_) {
myservice = _myservice_;
}));
it('should return search myservice data', function() {
expect(myservice.getData()).toEqual(mockservicedata);
});
});
which basically throws an error as:
Expected d({ $$state: Object({ status: 0 }) }) to equal [ Object({ name: 'value1', id: '1' }), Object({ name: 'value2', id: '2' }), Object({ name: 'value3', id: '3' }) ].
stack#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1482:17
buildExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1452:14
Env/expectationResultFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:583:18
Spec.prototype.addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:324:29 addExpectationResult#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:533:16
Expectation.prototype.wrapCompare/<#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1406:7
#http://localhost:59239/movie-app/spec/omdb/myservice.spec.js:14:9
attemptSync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1789:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1777:9 QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
Spec.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:353:5 executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2360:32 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
executeNode/<.fn#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2345:13 attemptAsync#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1819:9
QueueRunner.prototype.run#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1774:9
QueueRunner.prototype.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:1762:5
Env/queueRunnerFactory#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:627:7
TreeProcessor/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:2209:7
Env/this.execute#http://localhost:59239/movie-app/lib/jasmine-2.3.4/jasmine.js:678:7
window.onload#http://localhost:59239/movie-app/lib/jasmine-2.3.4/boot.js:110:5
I don't understand why it does not return data to the test. please help
Calling myservice.getData() won't actually give you the data you're expecting.
Since your getData method from MyService relies on $http's get method, you should be mocking it and then expecting that data returned.
So your test case should be like:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice = {};
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, _$httpBackend_) {
myservice = _myservice_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', "omdb/mydata.json").respond({
status: 200,
data: mockservicedata
});
}));
it('should return search myservice data', function() {
var response = myservice.getData()
response.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
$httpBackend.flush();
});
});
Hope this helps.
getData() will never return data instead it will return promise object.
If you want to test it then firstly you would have to mock the data for service then you can call it and match the result in the success handler.
Code is attached below:
describe('myservice', function() {
var mockservicedata = [{
"name": "value1",
"id": "1"
}, {
"name": "value2",
"id": "2"
}, {
"name": "value3",
"id": "3"
}];
var myservice, httpBackend;
beforeEach(module('omdb'));
beforeEach(inject(function(_myservice_, $httpBackend) {
myservice = _myservice_;
httpBackend = $httpBackend;
}));
it('should return search myservice data', function() {
httpBackend.when("GET", "omdb/mydata.json").respond(mockservicedata);
var promise = myservice.getData();
promise.then(function(response) {
expect(response.data).toEqual(mockservicedata);
});
httpBackend.flush();
});
});

Stuck: AngularJs using factory with http call to json

I am struck and not able to understand the issue here.
I created a factory using http service call to my json file
Factory (accountInfo.json):
appRoot.factory('accountInfo', ['$http', function($http) {
return $http.get('../../accountInfo.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
controller(AccountsController.js)
appRoot.controller('AccountsController', ['$scope', 'accountInfo', function($scope, accountInfo){
accountInfo.success(function(data) {
$scope.rows = data;
});
$scope.totals = {
name: '',
marketValue: 0,
cash: 0,
legend: 'none'
};
for (var i = 0; i < $scope.rows.length; i++) {
$scope.totals.marketValue += $scope.rows[i].marketValue;
$scope.totals.cash += $scope.rows[i].cash;
}
$scope.addAccount = function() {
$scope.rows.push({
name: 'New Account',
marketValue: Math.random() * 100000,
cash: Math.random() * 400000,
legend: 'cyan'
});
}
}]);
My json (accountInfo.json)
[{
"name": "Brokerage Account 3",
"marketValue": 1999990,
"cash": 1995826,
"legend": "orange"
},
{
"name": "Account 3",
"marketValue": 1949990,
"cash": 1695856,
"legend": "darkorange"
},
{
"name": "Brokerage Account 1",
"marketValue": 1349990,
"cash": 1595866,
"legend": "red"
},
{
"name": "Brokerage Account 4",
"marketValue": 155990,
"cash": 160826,
"legend": "blue"
},
{
"name": "Brokerage Account 2",
"marketValue": 74560,
"cash": 19956,
"legend": "gray"
},
{
"name": "Account 4",
"marketValue": 55006,
"cash": 53006,
"legend": "salmon"
},
{
"name": "Account 13",
"marketValue": 37340,
"cash": 0,
"legend": "green"
},
{
"name": "Joint Account 1",
"marketValue": 28308,
"cash": 4167,
"legend": "darkblue"
},
{
"name": "Joint Account 2",
"marketValue": 10000,
"cash": 10000,
"legend": "teal"
}]
Error I am receiving is "$scope.rows is undefined"
Controller is not able to access $scope.rows outside success function.
Thanks :)
You need to resolve the promise in your controller, not in your factory, just return the promise:
appRoot.factory('account', ['$http', function($http) {
return {
info: function () {
return $http.get('../../accountInfo.json');
}
}
}]);
Then in your controller do:
appRoot.controller('AccountsController', ['$scope', 'account', function($scope, account){
account.info()
.success(function(data) {
$scope.rows = data;
})
.error(function(err) {
return err;
});
}]);
FYI, the success and error methods are deprecated:
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
See: https://docs.angularjs.org/api/ng/service/$http
Use the then method:
account.info().then(
function resolved (response) {
$scope.rows = response.data;
},
function rejected (response) {
alert(response.status + ': ' + response.statusText);
}
);
Here's a working example of the concept: http://plnkr.co/edit/UtJDpvBKKYl4rBzgXYo4?p=preview
You should return a function which fetches the data when you call it like so:
appRoot.factory('accountInfo', ['$http', function($http) {
return {
fetchData: fetchData
};
function fetchData() {
return $http.get('../../accountInfo.json');
}
}]);
then in your controller you can do:
accountInfo.fetchData()
.then(
function(data) {
console.log(data);
},
function(error) {
console.log(error);
}
);
Thank you all for the help.
I solved my issues by bootstraping the app. I was not able to access my data initially since the http call was not completed.
angular.element(document).ready(function() {
angular.bootstrap(angular.element(document), ['app']);
});

AngularJS deferred $http.get response, empty array

Please help in changing this code to be able to use $http.get html, at the moment the resulting array (html_controls) is empty. However, I can see the response in the console for all the request in $http.get. Thank you.
angular.module('exodus-grid').controller('DynamicPropertiesController', ['$scope', '$http', '$templateCache', '$q', 'coreFactory',
function($scope, $http, $templateCache, $q, coreFactory) {
//$scope.DynamicProperties = 'Property being added to the controller.';
//coreFactory.fetchData('http://uat.resources.newscdn.com.au/cs/networksales/products/latest/products.json', 'products');
// TODO: Change this harcoded value to the products.json in s3
$scope.products = [{
"id": "btyb",
"label": "BTYB + Superskin",
"description": "",
"name": "btyb",
"active": true,
"properties": [{
"bannerLink": [{
"tmp_prop_name": "bannerLink",
"label": "Header Tracking Link (Desktop)",
"type": "textbox"
}],
"superskinLink": [{
"tmp_prop_name": "superskinLink",
"label": "Sideskin Tracking Link (Desktop)",
"type": "textbox"
}],
"ImgUrl": [{
"tmp_prop_name": "ImgUrl",
"label": "Header Image Url",
"type": "textbox"
}]
}]
}, {
"id": "iframe",
"label": "iframe",
"description": "",
"name": "iframe",
"active": true,
"properties": [{
"link": [{
"tmp_prop_name": "link",
"label": "iFrame source Url",
"type": "textbox"
}]
}]
}];
var requests = [];
var html_controls = [];
var product = $scope.products[0];
var properties = angular.fromJson(product.properties);
//console.log(angular.toJson(properties));
angular.forEach(properties, function(property) {
angular.forEach(property, function(item) {
//console.log(angular.toJson(property));
if (item[0].type === "textbox") {
//console.log(angular.toJson(item));
//console.log(Object.getOwnPropertyNames(property));
//console.log(Object.keys(property));
$http.get("plugins/k-plugin-exodus-grid/templates/properties/textbox.html").success(function(html) {
html = html.replace("%%label%%", item[0].label);
html = html.replace("%%scope%%", item[0].tmp_prop_name);
//console.log(html);
html_controls.push(html);
console.log(html_controls);
var deferred = $q.defer();
requests.push(deferred.promise);
console.log(deferred, deferred)
}).then(function() {
//$scope.html = html_controls;
});
}
});
});
//console.log(html_controls);
//$scope.html = html_controls;
$q.all(requests).then(function(data) {
console.log("12312312 " , data);
$scope.html = html_controls;
});
}
]);
Looks like you are trying to resolve a array of empty promises. Since it is running async, when $q.all() us called, requests[] is still empty.
Try building an array of promises and then resolve this using q.all() instead:
var requests = []; // a list of promises
angular.forEach(properties, function(property) {
angular.forEach(property, function(item) {
var promise = $http.get("/yoururl"); // $http.get returns a promise
requests.push(promise); // add to list of requests as a promise
});
});
$q.all(requests).then(function (result) {
console.log('results' + result);
});

why httpbackend not working in angular?

I am trying to test $http webservice using $httpBackend ? I am getting a error in that . how to test service using $httpbackend ?
here is my code
http://plnkr.co/edit/S3LFymv8hrxtatWaCv1A?p=preview
it('call http service', function() {
authRequestHandler = httpBackend.when('GET', 'data.json')
.respond([{
"name": "hello"
}, {
"name": "hello12"
}, {
"name": "hello22"
}, {
"name": "hello45"
}]);
httpBackend.flush();
service.callData().then(function(response) {
console.log(response)
expect(response.data.length).toBe(4)
})
})
Try this
authRequestHandler = httpBackend.when('GET', 'data.json')
.respond([{
"name": "hello"
}, {
"name": "hello12"
}, {
"name": "hello22"
}, {
"name": "hello45"
}]);
service.callData().then(function(response) {
console.log(response)
expect(response.data.length).toBe(4)
})
httpBackend.flush();

$httpBackend .whenGet is not a function in Angular

I am trying to make a dummy service to get data in Angular, I am using ngMockE2E, and my code for the Mock looks like this:
(function () {
"use strict"
var app = angular
.module("productResourceMock", ["ngMockE2E"]);
app.run(function ($httpBackend) {
var products = [
{
"productId": 1,
"productName": "mobile1",
"productCode": "heh4",
"releaseDate": "May 21, 2013",
"description": "very nice mobile",
"cost": 200,
"price": 300,
"category": "Electronics",
"tags": ["mobile", "electronic"],
"imageUrl": "images/img1.jpg"
},
{
"productId": 2,
"productName": "mobile2",
"productCode": "heh4",
"releaseDate": "May 21, 2012",
"description": "not a nice mobile",
"cost": 100,
"price": 500,
"category": "Electronics",
"tags": ["mobile", "Electronic"],
"imageUrl": "images/img2.jpg"
}];
var productUrl = "/api/products";
$httpBackend.whenGet(productUrl).respond(products);
});
}());
I have defined my controller, and inside it, it has this code:
(function () {
"use strict"
angular
.module("productManagement")
.controller("ProductListCtrl",
["productResource",
ProductListCtrl]);
function ProductListCtrl(productResource) {
var vm = this;
productResource.query(function(data){
vm.products = data;
});
}
}());
And for my service that sends the REST requests, I have this code:
(function () {
"use strict"
angular
.module("common.services")
.factory("productResource",
["$resource", productResource]);
function productResource($resource) {
return $resource("/api/products/:productId");
}
}());
am still getting this error: Uncaught TypeError: $httpBackend.whenGet is not a function.
Any help is appreciated, or any clarification needed, please let me know.
Answer is simple: replace whenGet with whenGET
Be careful to write the http verb all in uppercase.
See ngMock documentation

Resources