Reputation: 490
I would like to mock a functionality in Karma who returns a file after clicking a download button. I have the following AngularJS controller:
var secure = angular.module('secure', []);
secure.controller('ProcedureController', ProcedureController);
ProcedureController.$inject = ['$controller', '$rootScope', '$scope', '$http'];
function ProcedureController($controller, $rootScope, $scope, $http) {
... // Controller does more stuff
var href = window.location.href.split('/');
var baseUrl = href[0] + '//' + href[2];
var url = baseUrl + "/secure/regulations";
$http.get(url)
.success(function (data) {
$scope.questions = data[0];
})
$scope.download = function (msg) {
window.location = url + "/" + msg + "/attachment";
}
}
The window.location object just call a RESTful service who provides him the desired file directly. And this is, basically, my try-test:
describe('ProcedureController', function () {
beforeEach(module('secure'));
beforeEach(inject(function ($rootScope, $http, $controller, $injector) {
scope = $rootScope.$new();
ProcedureController = $controller('ProcedureController', {
$scope: scope,
$http: $http
});
}));
it ('should download something', function() {
expect(scope.download(1)).toBeDefined();
});
});
So, my idea is to check when scope.download function is called, if it returns the right url, namely, when I try scope.download(1), the expected answer would be /secure/regulations/1/attachment, roughly.
How should I mock it? Any help is appreciated!
Upvotes: 15
Views: 21493
Reputation: 6269
Use $window instead:
var secure = angular.module('secure', []);
secure.controller('ProcedureController', ProcedureController);
ProcedureController.$inject = ['$controller', '$rootScope', '$scope', '$http', '$window'];
function ProcedureController($controller, $rootScope, $scope, $http, $window) {
... // Controller does more stuff
var href = $window.location.href.split('/');
var baseUrl = href[0] + '//' + href[2];
var url = baseUrl + "/secure/regulations";
$http.get(url)
.success(function (data) {
$scope.questions = data[0];
})
$scope.download = function (msg) {
$window.location = url + "/" + msg + "/attachment";
}
}
describe('ProcedureController', function () {
var windowObj = {location: {href: ''}};
beforeEach(mock.module(function($provide) {
$provide.value('$window', windowObj);
}));
beforeEach(module('secure'));
beforeEach(inject(function ($rootScope, $http, $controller, $injector) {
scope = $rootScope.$new();
ProcedureController = $controller('ProcedureController', {
$scope: scope,
$http: $http
});
}));
it ('should download something', function() {
expect(scope.download).toBeDefined();
scope.download(1);
expect(windowObj.location.href).toEqual('/secure/regulations/1/attachment');
});
});
Upvotes: 13
Reputation: 67898
I guess there are a number of variables here, but let's start with the test. First, you don't really need to "mock it" because you're running a Jasmine test through Karma who is loading some form of browser. I hope you're using PhantomJS
instead of something like Chrome
.
But, let's start out with PhantomJS
. The code for your test should probably look something like this:
it ('should download something', function() {
scope.download(1);
expect(window.location).toBeDefined();
expect(window.location).toBe('some static URL that it should be');
});
However, you need to fix up the initialization for your controller. You need to make sure you can meet the need of this line:
var href = window.location.href.split('/');
This means that when you build your controller here:
ProcedureController = $controller('ProcedureController', {
you're going to need to set the window.location
to something before executing $controller
so that it builds the url
variable properly.
Now, if you're using Chrome
then you're likely to see real movement in the browser. I don't think this will cause any problems but it's just not necessary. It's going to be best to use PhantomJS
so that you can run those tests in the console.
Upvotes: 0