I want test my angular app with mocha,sinon and chai.
Especially I interest in submit function. How to create mock or stub for LoginResoure to test this function.
Thanks!
(function () {
'use strict';
class LoginController {
constructor($state,LoginResource) {
this.resource = LoginResource;
this.$state = $state;
this.credentials = {};
}
submit() {
let promise = this.resource.login(this.credentials);
promise.then(()=>{
changeState()
}
}
changeState() {
this.$state.go('home');
}
}
angular.module('app.login').controller('LoginController', LoginController);
})();
(function () {
'use strict';
class LoginResource {
constructor($resource, API_LOGIN) {
this.$resource = $resource(API_LOGIN,{'#id':id})
}
login(data) {
return this.$resource.save(data).$promise;
}
}
angular.module('app.login').service('LoginResource', LoginResource);
})();
EDIT:
Previously I do it with jasmine in next way:
let deferred = $q.defer();
deferred.resolve('Remote call result');
mockPeopleResource = {
createPerson: jasmine.createSpy('createPerson').and.returnValue(deferred.promise)
};
or if I want mock #resource
mockThen = jasmine.createSpy();
mockGetPeoplePromise = {then: mockThen};
mockUpdate = jasmine.createSpy().and.returnValue({$promise: mockPromise});
mockSave = jasmine.createSpy().and.returnValue({$promise: mockPromise});
mockGetPeopleQuery = jasmine.createSpy().and.returnValue({$promise: mockGetPeoplePromise});
mockResource = jasmine.createSpy().and.returnValue({
get: mockGet,
update: mockUpdate,
save: mockSave,
query: mockGetPeopleQuery
});
If you want to mock a service, you can create a test module when you set the mocked value:
beforeEach(function() {
angular.module('test', []).factory('LoginResource', function($q) {
return {
/* You can mock an easy login function that succeed when
data >= 0 and fails when data < 0 */
login: function(data) {
return $q(function(resolve, reject) {
if (data >= 0) return resolve();
reject();
});
}
};
});
module('app.login', 'test');
});
Related
For unit testing I use jasmine.I want to test the filterList function .
How could I do that ? The problem is I mock the service object, but how to declare the method inside the mock object so that I can test filterList function.
Ignore syntax , because I copy paste the code and delete some lines, so chances are high that there is lots of syntax error.
function (_,angular) {
'use strict';
var ngDependencies = ['StateService','$scope','$rootScope'];
var Constructor = function Constructor(StateService,$scope,$rootScope) {
var self = this;
self.defaultSelectedCompany = {};
self.companies = {
available: []
};
var ChangeListener = StateService.subscribe(function () {
self.companies.available = StateService.getAvailable('clients');
self.myCompanyList = _.map(self.companies.available, function companyList(user) {
return {
id: user.name};
});
self.filterList = function filterList($searchVal, $list) {
return _.filter($list, function (item) {
return item.displayValue.toLowerCase().indexOf($searchVal.toLowerCase()) >= 0 ||
item.secondaryValue.toLowerCase().indexOf($searchVal.toLowerCase()) >= 0;
});
};
self.updateDefaultCompany(self.myCompanyList[0]);
});
self.updateDefaultCompany = function updateDefaultCompanyPreference(selected) {
self.defaultSelectedCompany = selected;
};
$scope.$on('$destroy', ChangeListener);
};
Constructor.$inject = ngDependencies;
return Constructor;
And my spec files is as bellow
function (angular, _) {
'use strict';
var MockStateService = {
name: 'GlobalStateService',
subscribe: jasmine.createSpy('subscribe').and.callFake(function subscribe(state){
return {
filterList : function filterList($searchVal, $list) {
return _.filter($list, function (item) {
return item.displayValue.toLowerCase().indexOf($searchVal.toLowerCase()) >= 0 ||
item.secondaryValue.toLowerCase().indexOf($searchVal.toLowerCase()) >= 0;
});
}
};
})
};
describe('Controller', function () {
beforeEach(function () {
module(Module.name);
utils.useMocks([
MockStateService
]);
});
beforeEach(inject(function ($controller, $rootScope) {
this.scope = $rootScope.$new();
this.reqDrawerCtrl = $controller('SettingsController', {$scope: this.scope});
}));
describe('filterList', function () {
it('is a function', function () {
expect(typeof this.reqDrawerCtrl.filterList).toBe('function');
});
});
});
I am having a controller and service like below
(function () {
var mockController = function ($scope, MockService) {
$scope.message = "This is a text message";
$scope.getCities = function () {
$scope.places = [];
MockService.getCities().then(function (response) {
var places = response.data["weather-app:root"].city;
if (places) {
if (Array.isArray(places)) {
$scope.places = places;
} else {
$scope.places.push(places);
}
}
});
};
};
var mockService = function ($http) {
this.getCities = function () {
return $http.get("../rest/url", {
headers: {
'Accept': 'application/yang.data+json'
}
});
};
};
angular.module("MockApp", [])
.service("MockService", mockService)
.controller("MockController", mockController);
}())
I created a mock service like below for mocking the service for unit testing.
(function () {
angular.module('mock.service', [])
.service('MockService', function ($q) {
var mockService = {};
mockService.getCities = function () {
var mydata = {
"weather-app:root": {
"city": [
{
"city-name": "Chennai"
, "country-name": "India"
}
, {
"city-name": "Mangalore"
, "country-name": "India"
}
]
}
}
return $q.when(mydata);
};
return mockService;
});
}());
My test case is like
describe("MockController", function () {
var $scope;
beforeEach(function () {
module("MockApp");
beforeEach(module('mock.service'));
inject(function (_$controller_, _$rootScope_, _MockService_) {
$scope = _$rootScope_.$new();
controller = _$controller_("MockController", {
$scope: $scope
, MockService: _MockService_
});
});
});
describe("Test", function () {
it("Should be Bangalore", function () {
$scope.getCities();
console.log($scope.places);
});
});
});
the problem is that the then method in controller is not getting called. How can I resolve the issue ?
Three things to fix...
Don't nest the beforeEach calls. You can init multiple modules with module.
beforeEach(function() {
module('MockApp', 'mock.service');
// and so on
Your mock data does not quite match what you'd see from an $http based promise response
return $q.when({data: mydata});
In order to process promises, you need to trigger a digest cycle
it("Should be Bangalore", function() {
$scope.getCities();
$scope.$apply();
console.log($scope.places);
});
Is there a way to access a directive's controller using the .controller() method inside a Protractor test? In unit tests I can do
var el = angular.element(...);
$compile(el)(scope);
var component = el.controller('nameOfDirective');
but I can't seem to figure out how to do that in a Protractor test.
Here is the code I'm trying to test...
//registration.route.js
(function () {
'use strict';
angular.module('app.account.registration').run(appRun);
appRun.$inject = ['routerHelper'];
/* #ngInject */
function appRun(routerHelper) {
routerHelper.configureStates(getStates());
}
function getStates() {
return [
{
state: 'registration',
config: {
url: '/registration',
template: '<registration layout="column" flex/>',
title: 'registration'
}
}
];
}
})();
//registration.component.js
(function () {
'use strict';
angular.module('app.account.registration').component('registration', {
templateUrl: 'app/account/registration/registration.html',
controller: Controller
});
/* #ngInject */
function Controller($state, UserService, SweetAlert) {
var self = this;
this.$onInit = function () {
this.state = 'unverified';
this.processing = false;
};
this.register = function (formData) {
this.processing = true;
UserService.register(formData.email).then(function (response) {
self.state = 'verify';
self.email = response.data.email;
//response.data.token will only be returned on localhost for security reasons
self.token = response.data.token;
self.processing = false;
}).catch(function (error) {
if (error.status === 422) {
SweetAlert.error('Error!', formData.email + ' already exists. Please use a unique email.');
}
self.processing = false;
});
};
}
})();
If anyone needs the answer for this, here it is:
browser.executeScript(function () {
return window.angular.element(document.body)
.find('DIRECTIVE-TAG-NAME').controller('directiveName');
}).then(function (directiveControllerInstance) {
console.log(directiveControllerInstance);
});
For example, if your directive name is "testDirective", you would do:
browser.executeScript(function () {
return window.angular.element(document.body)
.find('test-directive').controller('testDirective');
}).then(function (directiveControllerInstance) {
console.log(directiveControllerInstance);
});
Is it posible to mock object for service? Is it posible to mock value of cfg.user.core.token? Im mocking httpBackend like this:
$httpBackend.when("GET","/check/").respond({
data: ['success']
});
This is my code:
.service("session", function ($window, $location, $http, cfg) {
var service = {};
service.check = function () {
$http.get("/chceck/" + cfg.user.core.token).then(function (response) {
if (response.data && response.data.success !== true) {
service.logout();
}
});
};
return service;
})
my part of test:
it("check ", function () {
spyOn(session, 'check').and.callThrough();
session.check();
expect(session.check).toHaveBeenCalled();
$httpBackend.flush();
});
Assuming cfg is an angular constant:
angular.module('mymodule')
.constant('cfg', {
user: {
core: {
token: 'token'
}
}
});
So in the Jasmine tests you can stub this constant:
describe('mytest', function () {
var
cfgStub = {
user: {
core: {
token: 'stubToken'
}
}
};
beforeEach(module('mymodule'));
beforeEach(module(function($provide) {
$provide.constant('cfg', cfgStub);
}));
...
});
And use cfgStub wherever you want in the tests.
How to create Jasmine unit test for one function in AngularJS service provider. I want to create mock data for myObject and test function getObjectShape() with that mock data as parameter. How to achieve that?
(function () {
'use strict';
angular.module('objectShapes')
.provider('shapesResolver', shapesResolver);
function shapesResolver() {
this.$get = function () {
return resolver;
};
function resolver(myObject) {
var service = {
getObjectShape: getObjectShape
};
function getObjectShape() {
return myObject.Shape;
}
}
}
})();
Here's a skeleton of a test for your service.
describe('shapesResolver service', function() {
var shapesResolver;
beforeEach(module('objectShapes'));
beforeEach(inject(function(_shapesResolver_) {
shapesResolver = _shapesResolver_;
}));
it('should do something, but what?', function() {
var mockMyObject = {};
shapesResolver(mockMyObject);
// shapesResolver doesn't return anything, and doesn't
// have any side effect, so there's nothing to test.
expect(true).toBeTruthy();
});
});