【问题标题】:Writing Unit test for Password Matching directive为密码匹配指令编写单元测试
【发布时间】:2015-07-12 21:29:13
【问题描述】:

我在这里有一个指令,我正在尝试编写一个单元测试 - 第一次做这种类型的事情。我不知道该怎么做。这是指令代码和 HTML:

app.directive('passwordMatch', [function () {
    return {
        restrict: 'A',
        scope:true,
        require: 'ngModel',
        link: function (scope, elem, attrs, control) {
            var checker = function () {
                var e1 = scope.$eval(attrs.ngModel);
                var e2 = scope.$eval(attrs.passwordMatch);
                if(e2!=null)
                return e1 == e2;
            };
            scope.$watch(checker, function (n) {
                control.$setValidity("passwordNoMatch", n);
            });
        }
    };
}]);
<form name="signupForm">
<div class="form-group">
		
	    <div class="col-sm-7">
	        <span class="block input-icon input-icon-right">
	    <input type="password" class="register" name="password" placeholder="Password" ng-model="signup.password" required/>
			</span>
	    </div>
	</div>
	<div class="form-group">	
	    <div class="col-sm-7">
	        <span class="block input-icon input-icon-right">
			   <input type="password" class="register" name="password2" placeholder="Confirm Password" ng-model="signup.password2" password-match="signup.password" required/>                                
			   <small class="errorMessage" data-ng-show="signupForm.password2.$dirty && signupForm.password2.$error.passwordNoMatch && !signupForm.password2.$error.required"> Password do not match.</small>
			</span>
	    </div>
	</div>
</form>

这就是我正在尝试的测试。因此,读取 TypeError: 'undefined' is not an object (evalating 'scope.signup.password = '123'') 给我一个错误

describe('passwordMatch Directive - ', function() {
    
    var scope, $compile, $window, element;
       
    beforeEach(function() {
      module('myApp');
      inject(function(_$compile_, _$rootScope_, _$window_) {
        $compile = _$compile_;
        scope = _$rootScope_.$new();
        $window = _$window_;
      })
     
    })

    it('should indicate invalid when the passwords do not match.', function() {
        scope.signup.password = '123';
        scope.signup.password2 = '1234';
        element = $compile(angular.element('<input type="password" class="register" name="password" placeholder="Password" ng-model="signup.password" required/> <input type="password" class="register" name="password2" placeholder="Confirm Password" ng-model="signup.password2" password-match="signup.password" required/>'))(scope);
        scope.$apply();
        console.debug('element html - ' + element.html());
        expect(element.html().indexOf('ng-invalid')).toBeGreaterThan(0);
    });

    it('should indicate valid when the passwords do not match.', function() {
        scope.signup.password = '123';
        scope.signup.password2 = '123';
        element = $compile(angular.element('<input type="password" class="register" name="password" placeholder="Password" ng-model="signup.password" required/> <input type="password" class="register" name="password2" placeholder="Confirm Password" ng-model="signup.password2" password-match="signup.password" required/>'))(scope);
        scope.$apply();
        console.debug('element html - ' + element.html());
        expect(element.html().indexOf('ng-valid')).toBeGreaterThan(0);
    });
});

非常感谢您的帮助

编辑:我刚刚注意到在注释掉 scope.signup.password = '123' 等时,调试语句没有返回任何内容 - 只是 DEBUG: 'element html - ',所以 element.html() 没有做任何事情?

【问题讨论】:

    标签: javascript angularjs unit-testing


    【解决方案1】:

    我已经有一段时间没有进行测试了,但是您是否尝试过先定义 scope.signup 对象,可能是在您的 beforeEach 块中。所以,像,

    describe('passwordMatch Directive - ', function() {
    
        var scope, $compile, $window, element, elm;
    
        beforeEach(function() {
          module('myApp');
          inject(function(_$compile_, _$rootScope_, _$window_) {
            $compile = _$compile_;
            scope = _$rootScope_.$new();
            $window = _$window_;
          });
    
    
          // define scope.signup as an empty object literal to which
          // you can add properties later 
          scope.signup = {};
    
          // don't think you meant to have this so commenting it out
          //elm 
        })
    
        it('should indicate invalid when the passwords do not match.', function() {
            scope.signup.password = '123';
            scope.signup.password2 = '1234';
            element = $compile(angular.element('<input type="password" class="register" name="password" placeholder="Password" ng-model="signup.password" required/> <input type="password" class="register" name="password2" placeholder="Confirm Password" ng-model="signup.password2" password-match="signup.password" required/>'))(scope);
            scope.$apply();
            console.debug('element html - ' + element.html());
            expect(element.html().indexOf('ng-invalid')).toBeGreaterThan(0);
        });
    
        // etc...
    });
    

    编辑

    我认为您需要在表单中输入内容。试试这个...

    describe('passwordMatch Directive - ', function() {
    
        var scope, $compile, $window, element, html;
    
        beforeEach(function() {
    
          module('myApp');
    
          inject(function(_$compile_, _$rootScope_, _$window_) {
            $compile = _$compile_;
            scope = _$rootScope_.$new();
            $window = _$window_;
          });
    
          scope.signup = {};
    
          // inputs need to be within a form for you directive to work
          html =  '<form name="signupForm">' +
                   '<input type="password" class="register" name="password" placeholder="Password" ng-model="signup.password" required/>' +
                   '<input type="password" class="register" name="password2" placeholder="Confirm Password" ng-model="signup.password2" password-match="signup.password" required/>' +
                  '</form>';  
    
        });
    
        it('should indicate invalid when the passwords do not match.', function() {
            scope.signup.password = '123';
            scope.signup.password2 = '1234';
            element = $compile(angular.element(html))(scope);
            scope.$apply();
            console.debug('element html - ' + element.html());
            expect(element.html().indexOf('ng-invalid')).toBeGreaterThan(0);
        });
    
        it('should indicate valid when the passwords do not match.', function() {
    
            scope.signup.password = '123';
            scope.signup.password2 = '123';
    
            element = $compile(angular.element(html))(scope);
    
            scope.$apply();
            console.debug('element html - ' + element.html());
            expect(element.html().indexOf('ng-valid')).toBeGreaterThan(0);
        });
    });
    

    编辑 2

    您也可以直接从范围访问 FormController 属性并对这些属性进行断言,而不是使用element.html()。使其更具可读性。

    it('should indicate invalid when the passwords do not match.', function() {
    
    
            scope.signup.password = '123';
            scope.signup.password2 = '1234';
    
            element = $compile(angular.element(html))(scope);
            scope.$apply();
    
            // expect(element.html().indexOf('ng-invalid')).toBeGreaterThan(0);
    
            expect(scope.signupForm.$valid).toBe(false);
            expect(scope.signupForm.$invalid).toBe(true);
    
        });
    
        it('should indicate valid when the passwords do not match.', function() {
    
            scope.signup.password = '123';
            scope.signup.password2 = '123';
    
            element = $compile(angular.element(html))(scope);
    
            scope.$apply();
    
            //expect(element.html().indexOf('ng-valid')).toBeGreaterThan(0);
    
            expect(scope.signupForm.$valid).toBe(true);
            expect(scope.signupForm.$invalid).toBe(false);
        });
    

    【讨论】:

    • 嘿,是的,我试过了。我只是注意到,当我这样做时,我没有得到未定义的错误,但是测试失败了,并且调试语句显示 element.html() 没有做任何事情,所以这是另一个问题:(
    • 尝试将模板中的输入放入表单中。查看更新的答案。
    • 很高兴为您提供帮助。您还可以直接访问 FormController 属性并对这些属性进行断言,而不是使用 element.html()。我认为它使它更具可读性。查看更新的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 2015-01-09
    • 2015-02-16
    • 2021-03-12
    • 1970-01-01
    • 2018-10-27
    相关资源
    最近更新 更多