I have a directive that builds a form:
app.directive('config', function() {
return {
restrict: 'E',
scope: {
data: '='
},
template: '<form name="configForm">' +
'<input type="number" max="10" ng-model="config.item" name="configItem"/>' +
'<div class="form-error" ng-show="configForm.$error.max">Error</div>' +
'</form>',
controller: 'ConfigDirectiveController',
};
});
What I want to do is validate via a unit test that the error message will show up given some input. With angular 1.2 I could modify $scope.config.item and it would update the view value and show the error.
As near as I can tell, with angular 1.3, if the model does not pass validation the view value does not get updated...so I need to modify the view value to make sure the error message shows up.
How can I get access to the "configItem" input so that I can set the view value to ensure that the error message will show up?
Edited to show unit test
I see that the value is set properly, but the error still has an ng-hide applied to the tag. When I am viewing the page and manually changing the input value, the ng-hide will be removed and the error will display if I enter in something greater than 10.
beforeEach(inject(function($compile, $rootScope) {
element = angular.element('<config data="myData"></config>');
$scope = $rootScope.$new();
$scope.myData = {};
element = $compile(element)($scope);
}));
it('should warn that we have a large number', function() {
var input = element.find('[name="configItem"]')[0];
$scope.$apply(function() {
angular.element(input).val('9000000001');
});
errors = element.find('[class="form-error ng-binding"]');
expect(errors.length).toBe(1);
})
fixture is a wrapper for our component's environment so we can control things like change detection. To trigger change detection we call the function fixture.detectChanges() , now we can update our test spec to: Copy it('login button hidden when the user is authenticated', () => { expect(el. nativeElement.
beforeEach is a global function in Jasmine that runs some setup code before each spec in the test suite. In this test suite, beforeEach is used to create a testing module using the TestBed object and declares any components that would be used in this testing module.
Test the Component logic using SpyOn. SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result. This example shows how spyOn works, even if we are still mocking up our service.
Here's how I've been unit testing my input-based directives (Lots of code omitted for clarity!) The important line you are after is:
angular.element(dirElementInput).val('Some text').trigger('input');
Here's the full unit test:
it('Should show a red cross when invalid', function () { dirElement = angular.element('<ng-form name="dummyForm"><my-text-entry ng-model="name"></my-text-entry></ng-form>'); compile(dirElement)(scope); scope.$digest(); // Find the input control: var dirElementInput = dirElement.find('input'); // Set some text! angular.element(dirElementInput).val('Some text').trigger('input'); scope.$apply(); // Check the outcome is what you expect! (in my case, that a specific class has been applied) expect(dirElementInput.hasClass('ng-valid')).toEqual(true); });
The previous answer is correct if you are using Angular with jQuery but for Angular without jQuery (using jqlite) you can use triggerHandler
instead (see here for full API)
it('foos to the bar', function() { el.val('Foo').triggerHandler('input'); // Assuming el is bound to scope.something using ng-model ... expect(scope.something).toBe('Foo'); });
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