As part of that assignment, I created an Angular directive to validate the data in the "password" and "verification" text inputs. Here's what the Angular directive looked like:
// match password and verification
app.directive('match', [function () {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
scope.$watch('['+attrs.ngModel+', '+attrs.match+']',
function(value){
ctrl.$setValidity('match', value[0] === value[1]);
}, true);
}
};
}]);
But I wanted to use QUnit to test this directive. I spent a ton of time, trying a zillion things, which didn't work because I was a newbie to both Angular and QUnit (and using them together). But, finally, I found the correct combination.
// create test bed
var injector = angular.injector(['ng', 'ngMock', 'signupApp']);
var init = {
setup: function() {
this.$scope = injector.get('$rootScope').$new();
}
};
module('tests', init);
// test the 'match' directive
QUnit.test('match', function() {
var html = '<form id="myform" name="signupController" ng-controller="signupController"><input id="password" ng-model="password" match="verification"></input><input id="verification" ng-model="verification" match="password"></input></form>';
var $compile = injector.get('$compile');
var element = $compile(html)(this.$scope);
this.$scope.password = 'passw0rd';
this.$scope.verification = 'passw0rd';
this.$scope.$apply();
ok(element.scope().signupController.$valid, '$valid is false');
this.$scope.password = 'passw0rd';
this.$scope.verification = 'passw0rd2';
this.$scope.$apply();
ok(!element.scope().signupController.$valid, '$valid is true when it should be false');
});
My first mistake was that it took me a long time to figure out that I needed angular-mocks.js to create a fully functional test bed. The ngMock module is needed to add lots of support to the Angular test harness. While I could get a simple test harness running without angular-mocks.js, testing that required the controller (and probably ngModel) required angular-mocks.js.
My second mistake was that it took me a long time to realize that the Angular scope and the Angular controller are different. (Well, duh.) Finally, I discovered that, if I added a "name" attribute to the controller element, a property giving access to the controller would be available in the scope.
This may be obvious to Angular experts but I spent a ton of time traveling around on Google and I never found any posts that were on point.
No comments:
Post a Comment