I'm trying to write a unit test that asserts the correct variable is being sent to the resolve
property of ui.bootstrap.modal
from the Angular-UI Bootstrap components. Here is what I have so far:
// Controller
angular.module('app')
.controller('WorkflowListCtrl', function ($scope, $modal) {
// Setup the edit callback to open a modal
$scope.edit = function(name) {
var modalInstance = $modal.open({
templateUrl: 'partials/editWorkflowModal.html',
controller: 'WorkflowEditCtrl',
scope: $scope,
resolve: {
name: function() { return name; }
}
});
};
});
It's worth noting that the resolve.name
property must be a function for the Angular-UI component to work correctly - previously I had tried resolve: { name: name }
but this didn't work.
// Unit Test
describe('Controller: WorkflowListCtrl', function () {
// load the controller's module
beforeEach(module('app'));
var workflowListCtrl,
scope,
modal;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
modal = {
open: jasmine.createSpy()
};
workflowListCtrl = $controller('WorkflowListCtrl', {
$scope: scope,
$modal: modal
});
it('should allow a workflow to be edited', function() {
// Edit workflow happens in a modal.
scope.edit('Barney Rubble');
expect(modal.open).toHaveBeenCalledWith({
templateUrl: 'partials/editWorkflowModal.html',
controller: 'WorkflowEditCtrl',
scope: scope,
resolve: {
name: jasmine.any(Function)
}
});
});
}));
});
At the moment, this is just checking that the resolve.name
property is a function, but what I'd really like to do is assert the resolve.name
function returns Barney Rubble
. This syntax obviously doesn't work:
expect(modal.open).toHaveBeenCalledWith({
templateUrl: 'partials/editWorkflowModal.html',
controller: 'WorkflowEditCtrl',
scope: scope,
resolve: {
name: function() { return 'Barney Rubble'; }
}
});
It seems like I somehow want to spy on the resolve.name
function to check it was called with Barney Rubble
but I can't figure out a way to do that. Any ideas?
So I have figured out a way to do this.
Define a 'private' function on $scope
:
$scope._resolve = function(item) {
return function() {
return item;
};
};
Modify the original $scope
function to call this 'private' method:
$scope.edit = function(name) {
var modalInstance = $modal.open({
templateUrl: 'partials/modal.html',
controller: 'ModalCtrl',
scope: $scope,
resolve: {
name: $scope._resolve(name)
}
});
};
Update your tests to mock this function and return the original value, then you can test it was passed in correctly.
it('should allow a workflow to be edited', function() {
// Mock out the resolve fn and return our item
spyOn($scope, '_resolve').and.callFake(function(item) {
return item;
});
// Edit workflow happens in a modal.
scope.edit('Barney Rubble');
expect(modal.open).toHaveBeenCalledWith({
templateUrl: 'partials/modal.html',
controller: 'ModalCtrl',
scope: scope,
resolve: {
name: 'Barney Rubble'
}
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With