In my controller, I am checking if page is iframed or not by this condition:
var vm = this;
if ($window.self !== $window.top) {
//We are iframed
vm.weAreIFramed = true
}
else {
vm.weAreIFramed = false;
}
I want to write a unit test for it. I wrote something like this but the test is always failing:
var homeController, $httpBackend, $controller, $location, $rootScope;
var topObj = {};
var selfObj = {};
var windowObj = {
location: { href: '' },
top: topObj,
self: topObj
};
beforeEach(module("app"), function ($provide) {
$provide.value('$window', windowObj);
});
beforeEach(inject(function (_$httpBackend_, _$controller_, _$location_, _$rootScope_) {
$httpBackend = _$httpBackend_;
$controller = _$controller_;
$location = _$location_;
$rootScope = _$rootScope_;
homeController = $controller("homeController");
}));
afterEach(function () {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it("vm.weAreIFramed should be false if we are not iFramed", function () {
console.log(angular.mock.dump(windowObj));
expect(homeController.weAreIFramed).toEqual(false);
});
It fails with below error:
How to write the correct test to check if the page is iframed or not ?
The test fails because "" === "". In real window, top and self are objects.
It should be
var topObj = {};
var selfObj = {};
var windowObj = {
location: { href: '' },
top: topObj,
self: selfObj
};
And for the other condition, only topObj can be specified for both.
Related
I am trying to get/set "testModel.number" in my unit test but I can't seem to get it. When I run the test I get this error message:
Error: [$injector:unpr] Unknown provider: testModelProvider <- testModel
Here is the controller:
angular.module("TestApp", [])
.controller("IndexController", function ($scope, testModel) {
$scope.name = "test";
testModel = {
number: 0
}
if (testModel.number === 1) {
$scope.name = "test1";
} else {
$scope.name = "test2";
}
});
Here is the unit test:
describe('IndexController', function () {
var scope, createController;
beforeEach(module("TestApp"));
beforeEach(inject(function ($rootScope, $controller, testModel) {
scope = $rootScope.$new();
createController = function () {
return $controller('IndexController', {
'$scope': scope,
'testModel': testModel
})
}
}));
it('example test', function () {
var controller = createController();
testModel.number = 1;
expect(scope.name).toBe('test1');
});
});
I'm fairly new to unit testing so any suggestions would be great! Thanks in advance!
I think you need to pass the testModel object to the method creating the controller. Jasmine does not know how to inject custom providers.
describe('IndexController', function () {
var scope, createController;
beforeEach(module("TestApp"));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function (testModel) {
return $controller('IndexController', {
'$scope': scope,
'testModel': testModel
})
}
}));
it('example test', function () {
var testModel = { number: 1 };
var controller = createController(testModel);
expect(scope.name).toBe('test1');
});
});
If you will have multiple tests that will need the testModel object, you can also define it at a global level as follows:
describe('IndexController', function () {
var scope, createController;
var testModel = { number: 1 };
beforeEach(module("TestApp"));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function () {
return $controller('IndexController', {
'$scope': scope,
'testModel': testModel
})
}
}));
it('example test', function () {
var controller = createController();
expect(scope.name).toBe('test1');
});
});
I'm trying to figure out these karma tests to test my Angular app. I can figure out simple things. But I am having problems with one that connects to my database.
I am wanting to test the $scope.getMultipleOptions function in the controller below:
$scope.options = [];
$scope.getMultipleOptions("form_field_1", $scope.options);
$scope.getMultipleOptions = function (key, opts) {
var id = key.replace("form_field_", "");
var promise = DynamicFormFactory.GetData('/DynamicForm/GetMultipleOptions?form_field_id=" + id);
promise.then(
function (success) {
angular.forEach(success, function (o) {
opts.push(o);
});
},
function (error) {
// Error
}
);
}
This is what my factory/service looks like:
dynamicFormApp.factory('DynamicFormFactory', ['$http', function ($http) {
return {
GetData: function (url) {
return $http.get(url)
.then(function (response) {
return response.data;
}, function (error) {
return error;
});
}
}]);
And this is what I've done to set up my karma test
describe('DynamicFormController', function () {
beforeEach(module('dynamicFormApp'));
var $controller;
var $rootScope;
beforeEach(inject(function (_$controller_, _$rootScope_) {
// The injector unwraps the underscores (_) from around the parameter names when matching
$controller = _$controller_;
$rootScope = _$rootScope_;
}));
describe('$scope.getMultipleOptions', function () {
var $scope, controller;
beforeEach(function () {
$scope = $rootScope.$new();
controller = $controller('DynamicFormController', { $scope: $scope });
$scope.fields = [];
});
it('$scope.getMultipleOptions', function () {
var key = "form_field_15";
var expectedResult = [{ desc: "DESCRIPTION", id: "ID" }];
$scope.getMultipleOptions(key, $scope.fields);
expect($scope.fields).toEqual(expectedResult);
});
});
});
The test always fails as $scope.fields is always empty. How do I do this?
I have a angularjs controller like this:
myApp.controller('SetCourseCtrl', function($scope, $http, $window,$sce) {
var path = $window.location.pathname;
path = path.split('/');
var courseID = path.pop();
$http.post('/course/getCourse', {
courseID: courseID
}).then(function(result) {
var trainerJSON = result.data.courseTrainer;
var trainers = [];
for (var i = 0; i < trainerJSON.length; i++) {
trainers.push(trainerJSON[i].text);
}
$scope.courseName = result.data.courseName;
$scope.courseTrainer = trainers;
$scope.courseTrainerPage = result.data.courseTrainerPage;
$scope.courseDescription = $sce.trustAsHtml(result.data.courseDescription);
$scope.courseCategory = result.data.courseCategory;
$scope.courseDocuments = result.data.courseDocuments;
});
});
I wrote a testcase for it by karma:
describe("SetCourseCtrl Unit testing #5", function() {
var controller, $controller, $scope, $rootScope, createController, $window;
beforeEach(angular.mock.module("myApp"));
beforeEach(inject(function($injector) {
$rootScope = $injector.get('$rootScope');
$controller = $injector.get('$controller');
$httpBackend = $injector.get('$httpBackend');
createController = {
setCourse: function() {
return $controller('SetCourseCtrl', {
$scope: $rootScope
});
}
}
}));
it('Test 2: post /course/getCourse', inject(function($controller) {
controller = createController.setCourse();
var path = $window.location.pathname;
path = path.split('/');
var courseID = path.pop();
var result = {
data: {
courseName: 'agile',
courseTrainerPage: 'trainer page',
courseDescription: 'description',
courseCategory: 'category',
courseDocuments: 'doc.pdf'
}
};
$httpBackend.whenPOST('/course/getCourse', {
courseID: courseID
}).respond(result);
$httpBackend.flush();
expect($rootScope.courseName).toBe(result.data.courseName);
expect($rootScope.courseTrainerPage).toBe(result.data.courseTrainerPage);
expect($rootScope.courseDescription).toBe(result.data.courseDescription);
expect($rootScope.courseCategory).toBe(result.data.courseCategory);
expect($rootScope.courseDocuments).toBe(result.data.courseDocuments);
}));
});
but when I run this test, an error happen:
PhantomJS 2.1.1 (Windows 8 0.0.0) SetCourseCtrl Unit testing #5 Test
2: post /course/getCourse FAILED
Error: Unexpected request: POST /course/getCourse
Can anyone explain it for me ? I think it happened because of the $window.location.pathname, I can not mock it, but I am not sure.
The error message said it, POST request to /course/getCourse is unexpected.
You need to insert an expect line like this:
$httpBackend.whenPOST('/course/getCourse', {
courseID: courseID
}).respond(result);
$httpBackend.expectPOST('/course/getCourse');
$httpBackend.flush();
Attempting to mock an http call but getting the error
Error: Unflushed requests: 1 in /Users/..etc/angular-mocks.js
here is my relevant code
describe('Tests for Group Controller', function() {
var $httpBackend;
beforeEach(function() {
module('App');
return inject(function($injector) {
var $controller;
$window = $injector.get('$window');
$window.ENV = 'http://here.com'
this.rootScope = $injector.get('$rootScope');
this.state = {};
this.stateParams = {};
this.UserService = $injector.get('UserService');
this.ProjectService = $q = $injector.get('ProjectService');
this.ModalService = {};
$httpBackend = $injector.get('$httpBackend');
this.GroupService = {};
$q = $injector.get('$q');
this.q = $q;
$controller = $injector.get('$controller');
this.scope = this.rootScope.$new();
this.controller = $controller('GroupController', {
'$scope': this.scope,
'$state': this.state,
'$stateParams': this.stateParams,
"UserService": this.UserService,
'ProjectService': this.ProjectService,
'ModalService': this.ModalService,
'GroupService': this.GroupService,
'$q': this.q
});
// this.scope.$digest();
$httpBackend.when('GET', 'http://here.com/api/user/2/Group/list?offset=0&max=10&sortField=name&ascending=true').respond({data: 'success'});
});
});
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should have controller defined', function() {
expect(this.controller).toBeDefined()
});
it('should initGroups', function() {
$httpBackend.expectGET('http://here.com/api/user/2/Group/list?offset=0&max=10&sortField=name&ascending=true');
$httpBackend.flush();
})
});
I'm doing the flush after the expectget but it still says I have an unflushed request. What am i doing wrong?
You create GET request before each test, but flush it only in 'Should initGroups' test.
I have written a unit test like below
describe('modals', function() {
beforeEach(module('DetailsApp'));
var controller, rootScope, templateCache, compile, http, httpBackend;
var uibModalInstance = {
dismiss: function(message) {
},
close: function(message) {
}
};
var plugins = {
get: function(plugin) {
if(plugin == 'Workorder'){
return {
'workorder_id': 'workorder_id'
};
} else if(plugin == 'CompanyInfo'){
return {
'company_name': 'company_name',
'company_id': 'company_id'
};
}
}
};
beforeEach(module(function($provide) {
$provide.value('$uibModalInstance', uibModalInstance);
$provide.value('plugins', plugins);
}));
beforeEach(inject(function($controller, $templateCache, $compile, $rootScope, $http, $httpBackend) {
controller = $controller;
templateCache = $templateCache;
compile = $compile;
rootScope = $rootScope;
http = $http;
httpBackend = $httpBackend;
}));
describe('When modal functions are called', function() {
it('they should be called correctly', function() {
var $scope = {};
var companyRatingHistory = controller('companyRatingHistory', { $scope: $scope });
spyOn(uibModalInstance, 'dismiss');
spyOn(uibModalInstance, 'close');
$scope.cancel();
expect(uibModalInstance.dismiss).toHaveBeenCalledWith('cancel');
$scope.close('close');
expect(uibModalInstance.close).toHaveBeenCalledWith('close');
});
}); });
and found that my code coverage shows an E in plugins else block like below
else if(plugin == 'CompanyInfo'){
return {
'company_name': 'company_name',
'company_id': 'company_id'
};
}
What i have missed in my test. Advance thanks and get any suggestions from anybody who helps me.