I have an Angular directive which sets the value of some $scope
property based on the value of an injected constant. I want to test that this value is being correctly initialized from the constant, so I would like to change the constant's value within an individual it
block. (Preferably within one, but changing the value between multiple blocks would be OK too)
Is this possible, and how can I do it?
simplified example:
//////// directive ////////
angular.module('myApp.directives', [])
.constant('THE_CONSTANT', 'hello world')
.directive('myDirective', ['THE_CONSTANT', function (THE_CONSTANT) {
return {
restrict: 'E',
link: function ($scope) {
$scope.propertyBasedOnConstant = THE_CONSTANT;
}
};
}]);
//////// test ////////
describe('myDirective', function () {
var $element, $scope;
beforeEach(module('myApp.directives'));
beforeEach(module(function ($provide) {
$provide.constant('THE_CONSTANT', 'foo');
}));
beforeEach(inject(function ($rootScope, $pile) {
$scope = $rootScope;
$element = angular.element('<my-directive></my-directive>');
$pile($element)($scope);
$scope.$digest();
}));
afterEach(function () {
$scope.$destroy();
$element.remove();
});
it("should correctly reflect the constant's value", function() {
expect( $scope.propertyBasedOnConstant ).to.equal('foo');
// now I want to change the constant's value and re-initialize the directive
});
});
I have an Angular directive which sets the value of some $scope
property based on the value of an injected constant. I want to test that this value is being correctly initialized from the constant, so I would like to change the constant's value within an individual it
block. (Preferably within one, but changing the value between multiple blocks would be OK too)
Is this possible, and how can I do it?
simplified example:
//////// directive ////////
angular.module('myApp.directives', [])
.constant('THE_CONSTANT', 'hello world')
.directive('myDirective', ['THE_CONSTANT', function (THE_CONSTANT) {
return {
restrict: 'E',
link: function ($scope) {
$scope.propertyBasedOnConstant = THE_CONSTANT;
}
};
}]);
//////// test ////////
describe('myDirective', function () {
var $element, $scope;
beforeEach(module('myApp.directives'));
beforeEach(module(function ($provide) {
$provide.constant('THE_CONSTANT', 'foo');
}));
beforeEach(inject(function ($rootScope, $pile) {
$scope = $rootScope;
$element = angular.element('<my-directive></my-directive>');
$pile($element)($scope);
$scope.$digest();
}));
afterEach(function () {
$scope.$destroy();
$element.remove();
});
it("should correctly reflect the constant's value", function() {
expect( $scope.propertyBasedOnConstant ).to.equal('foo');
// now I want to change the constant's value and re-initialize the directive
});
});
Share
Improve this question
asked Jul 7, 2015 at 20:58
tufftuff
5,1736 gold badges30 silver badges43 bronze badges
2 Answers
Reset to default 5You are providing the constant
into an undefined
module.
Change your beforeEach block to something like this and it should just work™:
var $scope, $element, MOCKED_CONSTANT;
beforeEach(function () {
MOCKED_CONSTANT = 'foo';
module('myApp.directives', function ($provide) {
$provide.constant('THE_CONSTANT', MOCKED_CONSTANT);
});
inject(function ($rootScope, $pile) {
$scope = $rootScope.$new(); // Don't forget to call .$new()!
var template = angular.element('<my-directive></my-directive');
$element = $pile(template)($scope); // Store the reference to the piled element, not the raw string.
$scope.$digest();
});
});
it("should correctly reflect the constant's value", function() {
expect( $scope.propertyBasedOnConstant ).to.equal(MOCKED_CONSTANT);
// expect( $scope.propertyBasedOnConstant ).to.equal('foo');
});
If you need to change the constant's value between it
's, I would extract the call to module
into a helper function, aswell as the inject
. Such as:
function setupModule (constant) {
module('myApp.directives', function ($provide) {
$provide.constant('THE_CONSTANT', constant);
});
}
function injectItAll () {
inject(function ($rootScope, $pile) {
$scope = $rootScope.$new(); // Don't forget to call .$new()!
var template = angular.element('<my-directive></my-directive');
$element = $pile(template)($scope); // Store the reference to the piled element, not the raw string.
$scope.$digest();
});
}
And then in your spec you would do:
it('equals banana', function () {
setupModule('banana');
injectItAll();
expect($scope.propertyBasedOnConstant).to.equal('banana');
});
By definition a constant is an identifier with an associated value which cannot be changed. Instead of changing the constant value why not inject the constant itself and use it within your expectations.
describe('myDirective', function () {
var $element, $scope,
THE_CONSTANT;
beforeEach(module('myApp.directives'));
beforeEach(module(function (_THE_CONSTANT_) {
THE_CONSTANT = _THE_CONSTANT_;
}));
beforeEach(inject(function ($rootScope, $pile) {
$scope = $rootScope;
$element = angular.element('<my-directive></my-directive>');
$pile($element)($scope);
$scope.$digest();
}));
afterEach(function () {
$scope.$destroy();
$element.remove();
});
it("should correctly reflect the constant's value", function() {
expect( $scope.propertyBasedOnConstant ).to.equal(THE_CONSTANT);
});
});