Reputation: 11064
With Mocha and Jasmine, I am trying to unit test this service:
angular.module("main.loadbalancer").run(function($rootScope, $state, DeviceVal) {
$rootScope.$on("$stateChangeStart", function(event, toState) {
var checkUrlDirectEdit, device;
device = window.location.hash.split("/")[2];
checkUrlDirectEdit = function() {
return DeviceVal.previousDevice !== device && toState.name !== "main" && DeviceVal.lb.id === "undefined";
};
if (typeof DeviceVal.lb.id === "undefined" && toState.name !== "main" || checkUrlDirectEdit()) {
event.preventDefault();
DeviceVal.previousDevice = device;
$state.transitionTo("main", {}, {
location: false
});
}
if (DeviceVal.readonly && toState.name !== "main.loadbalancer.readonly") {
event.preventDefault();
$state.transitionTo("main.loadbalancer.readonly", {
id: DeviceVal.lb.id
}, {
location: true,
reload: true
});
}
return window.addEventListener("hashchange", function() {
return location.reload();
});
});
});
With this test:
describe("health check service", function() {
var HealthCheckSvc;
HealthCheckSvc = null;
beforeEach(function() {
return module("main.loadbalancer");
});
beforeEach(inject(function($rootScope, _$state_, _DeviceVal_) {
this.$rootScope = $rootScope;
$state = _$state_;
$DeviceVal = _DeviceVal_;
spyOn($state, "transitionTo")
spyOn(this.$rootScope, "$on")
}));
it("do some junk", function() {
toState = 'main.loadbalancer.nodes';
this.$rootScope.$broadcast("$stateChangeStart", "event", "toState");
expect(this.$rootScope.$on).toHaveBeenCalledWith("$stateChangeStart");
});
});
Right now, I am having a hard time makeing making a expect for $rootScope.$on("$stateChangeStart")
. I thought spyOn(this.$rootScope, "$on")
and expect(this.$rootScope.$on).toHaveBeenCalledWith("$stateChangeStart");
would do it, but I get:
Expected spy $on to have been called with [ '$stateChangeStart' ] but it was never called.
Error: Expected spy $on to have been called with [ '$stateChangeStart' ] but it was never called.
Upvotes: 0
Views: 2165
Reputation: 27012
It is possible, but I suspect the spy is being added after the run
block is being run. A way around this, is to provide your own mock $rootScope
object, with a stub/spied $on
function, to the dependency injection system, which you can do before run
has run.
describe('run block', function() {
var $rootScope = null;
beforeEach(module('plunker'));
beforeEach(module(function($provide) {
$provide.value('$rootScope', {
'$on': jasmine.createSpy('$on')
});
}));
beforeEach(inject(function(_$rootScope_) {
$rootScope = _$rootScope_;
}));
it('should call $on with $stateChangeStart and a function', function() {
expect($rootScope.$on).toHaveBeenCalledWith('$stateChangeStart', jasmine.any(Function));
});
});
This can be seen working at http://plnkr.co/edit/XovukFUxOY479muQu4WW
Sidebar: I'm not sure whether you need this test. I think it's more important to make sure it does what it should do when the event fires.
Upvotes: 1
Reputation: 48972
The $rootScope.$on("$stateChangeStart"
is called early and just to register an event listener.
When you call this.$rootScope.$broadcast("$stateChangeStart", "event", "toState");
, $rootScope.$on
is not called, but the code inside the handler (function(event, toState) {
)
Upvotes: 2