I am implementing a simple directive that represents a form field with all its extras like label, error field, regex all in a single line.
The directive is as follow:
<div ng-controller="parentController">
{{username}}
<!-- the directive -- >
<form-field label="Username:" regex="someRegex" constrainsViolationMessage="someValidationMessage" model="username" place-holder="some input value">
</form-field>
</div>
Now, I want to test the data binding between the directive scope and the parent scope.
The test is:
it("should bind input field to the scope variable provided by parent scope ! ", function () {
var formInput = ele.find('.form-input');
formInput.val("some input");
expect(ele.find('p').text()).toEqual('some input');
});
This problem is that I don't know why test don't pass, even the directive works correctly. Here is a fiddle of the directive.
And here is the whole test and test set up.
var formsModule = angular.module('forms', []);
formsModule.controller('parentController', function ($scope) {
});
formsModule.directive('formField', function () {
var label;
var constrainsViolationMessage;
var placeHolder;
var model;
return {
restrict:'E',
transclude:true,
replace:false,
scope:{
model:'='
},
link:function (scope, element, attr) {
console.log("link function is executed .... ");
scope.$watch('formInput', function (newValue, oldValue) {
console.log("watch function is executed .... !")
scope.model = newValue;
});
scope.label = attr.label;
},
template:'<div class="control-group ">' +
'<div class="form-label control-label">{{label}}</div> ' +
'<div class="controls controls-row"> ' +
'<input type="text" size="15" class="form-input input-medium" ng-model="formInput" placeholder="{{placeHolder}}">' +
'<label class="error" ng-show={{hasViolationConstrain}}>{{constrainsViolationMessage}}</label>' +
'</div>'
}
});
beforeEach(module('forms'));
var ele;
var linkingFunction;
var elementBody;
var scope;
var text = "";
var placeHolder = "filed place holder";
var label = "someLabel";
var regex = "^[a-z]{5}$";
beforeEach(inject(function ($compile, $rootScope) {
scope = $rootScope;
elementBody = angular.element('<div ng-controller="parentController">' +
'<p>{{username}}</p>' +
'<form-field label="Username:" regex="someRegex" constrainsViolationMessage="someValidationMessage" model="username" place-holder="some input value"> </form-field>');
ele = $compile(elementBody)(scope);
scope.$digest();
}
));
afterEach(function () {
scope.$destroy();
});
iit("should bind input field to the scope variable provided by parent scope ! ", function () {
var formInput = ele.find('.form-input');
formInput.val("some input");
expect(ele.find('p').text()).toEqual('some input');
});
As you can see, I want to assert that form input is reflected in the scope variable set in the 'model' attribute provided by the parent scope.
Am I missing something here ? Thanks for helping me ... !
Use it only when necessary and beware of the performance implications. watch is lazy by default: the callback won't be called until the watched source has changed. But in some cases we may want the same callback logic to be run eagerly - for example, we may want to fetch some initial data, and then re-fetch the data whenever relevant state changes.
The default shell for watch is /bin/sh. Shells will not inherit exported variables or functions from other types of shell. If your system does not symlink /bin/sh to /bin/bash (or your current shell) then you can instruct watch to exec your shell by using -x or --exec:
The a variable is in the Expression box with a Value of 1. To evaluate an expression using the variable, type an expression such as a + b in the Expression box, and select Reevaluate. To add the variable or expression from QuickWatch to the Watch window, select Add Watch. Select Close to close the QuickWatch window.
It also allows you to stop the watcher early. Watchers declared using the watch option or the $watch () instance method are automatically stopped when the owner component is unmounted, so in most cases you don't need to worry about stopping the watcher yourself.
You're missing the scope.$apply()
call after you set the input value, so the change is never getting digested. In the regular application lifecycle this would happen automatically, but you have to manually trigger this in your tests
Take a look at https://github.com/angular/angular.js/blob/master/test/ng/directive/formSpec.js for a ton of examples.
Use $scope.$digest() after adding condition to execute watch. It will fire watch.
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