Angular JS Unit Testing using Jasmine - angularjs

I have a factory service as below
FamilyService.js
(function(){
'use strict';
angular.module('app')
.factory('ABC', FamilyService);
FamilyService.$inject = ['DEF'];
function FamilyService(DEF) {
function returnTrue() {
var a="true";
}
}
}());
I want to call returnTrue method in My test case
**TestFamilyService.js**
describe('testing my_controller.my_function', function () {
var mockedFactory, $rootScope, $controller;
beforeEach(module('app', function($provide) {
mockedFactory = {
save: jasmine.createSpy()
};
$provide.value('ABC', mockedFactory);
}));
it('should call the save function', function() {
expect(mockedFactory.returnTrue()).toHaveBeenCalled();
});
});
**specrunner.html**
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v2.4.1</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.4.1/jasmine_favicon.png">
<link rel="stylesheet" href="lib/jasmine-2.4.1/jasmine.css">
<script src="lib/jasmine-2.4.1/jasmine.js"></script>
<script src="lib/jasmine-2.4.1/jasmine-html.js"></script>
<script src="lib/jasmine-2.4.1/boot.js"></script>
<script src="lib/jasmine-2.4.1/angular.js"></script>
<script src="lib/jasmine-2.4.1/angular-mocks.js"></script>
<!-- include source files here... -->
<script src="src/Player.js"></script>
<script src="src/webapp/Mock.js"></script>
<script src="src/webapp/FamilyService.js"></script>
<!-- include spec files here... -->
<script src="spec/TestFamilyService.js"></script>
</head>
<body>
</body>
</html>
When i run specrunner.html in the browser it displays
Error: No module: app
TypeError: Unable to get value of the property 'returnTrue': object is null or undefined
Please Tel me whats wrong here?

In FamilyService.js
angular.module('app').factory('ABC', FamilyService);
you are creating a factory for the existing module app, but if the module doesn't exist you need to write
angular.module('app',[]).factory('ABC', FamilyService);
In your case just create a new file, where the angular module gets created
angular.module('app',[]);
UPDATE
Just include the dependencies of your module in the html
<script src="lib/angular-sanititze/angular-sanitize.js"></script>
If you want to mock these modules, you can do something like
beforeEach(function() {
angular.module('second',[]);
}
But in the case that you are using some methods of the third party library, you need to mock these methods as well.

Related

data to read my json file in IONIC

This world is sad to cry , am blocked for two hours with a problem that i couldnt define ,i can't retrieve data from my json file ,everything in my code seems correct.
This is my factory:
'use strict';
angular.module('starter.services')
.factory('userService',function ($http) {
return{
getUsers:function(){
return $http.get("http://localhost:26309/api/User/getAll/").then(function (response) {
return response.data;
});
}
}
});
and this controller :
'use strict';
angular.module('starter.controllers', ['starter.services'])
.controller('UsersCtrl', function($scope,userService) {
$scope.Users = [];
userService.getUsers().then(function (data) { $scope.Users= data.data; }); });
});
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/ionic/js/angular/angular-resource.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/UserControllerIonic.js"></script>
<script src="js/UsersServiceIonic.js"></script>
</head>
<body ng-app="starter" ng-controller="UsersCtrl">
<ion-view>
<div class = "list" >
<a class = "item" ng-repeat = "user in Users">
<h2>{{user.nom}}</h2>
</a>
</div>
</ion-view>
</body>
</html>
Thank you in advance
SOLUTION
i solved the problem by :
1- adding in the config.xml the permission <allow-navigation href="http://*/*"/>
2-installing cordova-plugin-whitelist ionic plugin add cordova-plugin-whitelist
3-add control-allow-origin extention to chrome :https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi/related?hl=en-US
and finally : specifying the type of data returned by the back-end controller by adding this code to my Global.asax in Application_start method :config.Formatters.JsonFormatter.SerializerSettings.Formatting =
Newtonsoft.Json.Formatting.Indented;
config.Formatters.Remove(config.Formatters.XmlFormatter);
hope this helps someone
You don't want to resolve your $http call inside factory.
JS:
angular.module('app',[])
.controller('MainCtrl', function($scope, MyService){
var url = "http://jsonplaceholder.typicode.com/users";
MyService.getData(url).then(function(res){
console.log(res.data);
$scope.data = res.data;
});
})
.service('MyService', function($http){
return {
getData: function(url){
return $http.get(url);
}
}
})
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="item in data">{{item.name}}</li>
</ul>
</body>
</html>
The issue is that you are resolving the promise in service with the value response.data, and again expecting the resolved value to have data property. Change your service code as below:
'use strict';
angular
.module('starter.services')
.factory('userService',function ($http) {
return {
getUsers: function(){
return $http.get("http://localhost:26309/api/User/getAll/").then(function (response) {
return response;
});
}
}
});
Or simply return the promise as below:
'use strict';
angular
.module('starter.services')
.factory('userService',function ($http) {
return {
getUsers: function(){
return $http.get("http://localhost:26309/api/User/getAll/");
}
}
});

Service injection into controller having in seperate files with AngularJS

When i try to inject service into controller which I have in separate file mentioned in below code i get error:
TypeError: myService.getData is not a function
at new (controllers.js:18)
at Object.e [as invoke] (angular.min.js:39)
at M.instance (angular.min.js:80)
at D (angular.min.js:61)
at g (angular.min.js:55)
at g (angular.min.js:55)
at angular.min.js:54
at angular.min.js:20
at r.$eval (angular.min.js:133)
at r.$apply (angular.min.js:134)
index.html
load all js files in this html page
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>title</title>
<link rel="stylesheet" href="styles/all.css">
<script src="libs/angular.min.js"></script>
<script src="libs/jquery.js"></script>
<script src="js/service.js"></script>
<script src="js/controllers.js"></script>
<script src="js/myApp.js"></script>
<script src="libs/bootstrap/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
</body>
</html>
This is the main file where we load controllers and services at once
myApp.js
var app = angular.module('app', ['app.service', 'app.controllers']);
service.js
here i tried to get data from server and wants to use in controller
var app = angular.module("app.service", []);
app.service('myService', function($http) {
function getData (callbackFunc) {
$http({
method: 'GET',
url: "url"
}).success(function(data){
callbackFunc(data);
}).error(function(){
alert("error");
});
}
});
controllers.js
This file include all logic and inject myService from service.js file.
i use myService from service.js and tried to get data, but i got an error all the time
angular.module('app.controllers', ['app.service'])
.controller('myCtrl', ['$scope', '$http', '$timeout', 'myService',
function ($scope, $http, $timeout, myService) {
myService.getData(function(dataResponse) {
$scope.surveys = dataResponse;
});
}]);
Your service module declaration has problem.
You are getting module name without declaring it.
Try like this
var appSvc=angular.module("app.service",[]);
appSvc.service('myService', function($http){});
bind Your method with this
Like this
this.getData =function (callbackFunc) {}

unable to inject custom service inside the run function of Angularjs application

I am new to Angularjs and have written my app.js which has the run function defined. I also have a custom service called coreService which I need to inject into the run function. When I inject, I get an error stating
Error: [$injector:unpr] Unknown provider: $scopeProvider <- $scope <- coreService http://errors.angularjs.org/1.4.7/$injector/unpr?p0=%24scopeProvider%20%3C-%20%24scope%20%3C-%20coreService
I am using the angularjs-fullstack yeoman generator to develop the application. Please let me know where I am going wrong. Link to Plnkr - Plnkr link
I corrected your code you have many errors there.Take a look at PLUNKER You cannot call $scope inside service.
'use strict';
angular.module('myApp')
.service('coreService', function () {
var sayHi=function(){
console.log("Hi..");
}
return {
sayHi:sayHi
}
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.4.2" data-semver="1.4.2" src="https://code.angularjs.org/1.4.2/angular.js"></script>
<script src="https://code.angularjs.org/1.4.6/angular-route.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body ng-app="myApp">
<h1>Hello Plunker!</h1>
<script src="script.js"></script>
<script src="coreService.js"></script>
</body>
</html>
And rename your coreService to coreService.js
Rename coreService to coreService.js and include coreService.js after script.js.

Office.js getFilePropertiesAsync fails on second call in Angular.js

I have an Office Task Pane App written with Office Javascript API (Office.js) that calls Office.context.document.getFilePropertiesAsync and places the returned URL in an angular variable:
$scope.getDocumentUrl = function () {
Office.context.document.getFilePropertiesAsync(function (asyncResult) {
$scope.url = asyncResult.value.url;
});
};
I then have a button that calls this. This works file the first time, but when I press the button a second time, it never enters the callback and displays this error:
TypeError: Object expected at verifyAndExtractCall
(https://localhost:44304/scripts/office/1.1/o15apptofilemappingtable.js:11:54588)
at Anonymous function
(https://localhost:44304/scripts/office/1.1/o15apptofilemappingtable.js:11:83048)
at Anonymous function
(https://localhost:44304/scripts/office/1.1/o15apptofilemappingtable.js:11:86071)
at $scope.getDocumentUrl
(https://localhost:44304/AngularJs/controllers/sandpit.controller.js:130:6)
at $parseFunctionCall
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:12403:7)
at callback
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:21566:17)
at Scope.prototype.$eval
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:14466:9)
at Scope.prototype.$apply
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:14565:11)
at Anonymous function
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:21571:17)
at jQuery.event.dispatch (https://localhos
This is a simplified version of another situation that creates the same error. It also happens with getFileAsync. I know I need $scope.$apply to display the change. I know you can get the URL in other ways. I need to know the cause of the error.
I test your scenario in my local machine. I could not repro your issue.
My simple test app has two files: AngularTest.html and AngularTest.js.
Content in AngularTest.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
<script src="//ajax.microsoft.com/ajax/4.0/1/MicrosoftAjax.js" type="text/javascript"></script>
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js" type="text/javascript"></script>
<script src="AngularTest.js" type="text/javascript"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="getDocumentUrl()">Get Url!</button>
Url is: {{url}}
</div>
</body>
</html>
Content in AngularTest.js:
(function () {
"use strict";
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.url = "";
$scope.getDocumentUrl = function () {
Office.context.document.getFilePropertiesAsync(function (asyncResult) {
$scope.url = asyncResult.value.url;
});
};
});
Office.initialize = function (reason) {
};
})();
You can obtain the URL by clicking the button "Get Url". I tested it in Excel 2013 SP 1.

Bootstrapping AngularJS app dynamically

I have a problem with boostrapping an angularjs app - with initialization code in the controller. The simplified test-case is like this (index.js):
var myApp = angular.module( 'myApp', []);
myApp.controller( 'myAppController', [ '$scope', function($scope) {
console.log('never shown');
$scope.test = 'constructor called';
// removed more init code
}]);
$(document).ready(function(){
angular.bootstrap( document, ['myApp']);
console.log('Finished boostrapping.');
});
The HTML file for this test-case:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>TeST</title>
</head>
<body>
{{test}}
<script type="text/javascript" src="js/bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="js/bower_components/angular/angular.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
The result is that console output only says "Finished bootstrapping" - and the controller function is never invoked. .. This baffles me a little, but this is my first angular 1.2 app. I get the same result If I put ng-app="myApp" in the tag and let angular bootstrap the app automatically. ...
you never set ng-controller anywhere in your markup.
also, you should either put your script tags in the head, or after </body>.
edit: when using bootstrap this way, the placement of the <script> tags goes matter.
The first parameter to the angular.bootstrap method is an element. Currently you are passing in document, which is not an element.
Try
angular.bootstrap(document.documentElement, ['myApp']);
or
angular.bootstrap(document.body, ['myApp']);

Resources