angularjs:测试使用$ http和$ modelValue的指令

时间:2014-03-11 08:40:29

标签: angularjs angularjs-directive

我创建了一个检查URL是否确实存在的指令:

用法:

 <input name="urlName" type="text" url-checker  />
 <span class="danger" ng-show="urlForm.urlName.$error.urlChecker">invalid url</span>

和指令代码:

(function () {
'use strict';

var directiveId = 'urlChecker';
/**
* Purpose: check whether a model's value matches a valid url 
*/
angular.module('comp.directives').directive(directiveId, ['$http', directiveFunc]);

function directiveFunc($http) {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            element.bind('blur', function (e, n) {
                //check url starts with http:// or https://
                if (ngModel.$modelValue.indexOf('http://') === -1 || ngModel.$modelValue.indexOf('http://') === -1) {
                    ngModel.$setValidity('urlChecker', false);
                } else {
                    //check the url actually exists
                    $http.get(ngModel.$modelValue).success(function (result) {
                        ngModel.$setValidity('urlChecker', true);
                    }).error(function (error) {
                        ngModel.$setValidity('urlChecker', false);
                    });
                }
            });
        }
    };
}
})();

我不知道如何测试它。任何帮助,将不胜感激。到目前为止,我已经这样做了:

'use strict'
describe('urlChecker', function () {
var scope, compile, element;

beforeEach(function () {
    inject(function ($rootScope, $compile) {
        compile = $compile;
        scope = $rootScope;
    })
});

it('should should set the model validity to false', function () {

    scope.model = 'http://www.yahoo.fr';

    element = angular.element('<input type="text" ng-model="model" url-checker />');
    compile(element)(scope);
    scope.$digest();

    var elm = element[0];
    elm.blur();
});
});

1 个答案:

答案 0 :(得分:0)

结帐NgModelController:$parsers。您可能不应该绑定到输入'blur',因为您最终可能会与输入指令冲突。

link: function (scope, element, attrs, ngModel) {
    ngModel.$parsers.push(function(value){
        if (value.indexOf('http://') === -1 || value.indexOf('http://') === -1) {
            ngModel.$setValidity('urlChecker', false);
        } else {
            //check the url actually exists
            $http.get(value).success(function (result) {
                ngModel.$setValidity('urlChecker', true);
            }).error(function (error) {
                ngModel.$setValidity('urlChecker', false);
            });
        }
        return value;
    })
}

仔细阅读。如果您的解析器返回undefined,则ngModel将不会更新您的模型。解析器必须是同步的,因此你的异步处理程序不能暂停用户的输入。虽然您有潜在的竞争条件,但您可以在回调中设置有效性。

我可能会为这个指令创建一个控制器,只需将控制器方法推送到$解析器中,但你仍然可以这样测试。

compile(element)(scope);
scope.$digest();
var ngModel = element.controller('$ngModelController');
ngModel.$setViewValue('blah');
expect(ngModel.error['urlChecker']).toBeDefined()

您还可以通过注入$httpBackend

来测试$ http调用
$httpBackend.expectGET('blah').respond(500)
$httpBackend.flush()
// Now your http handler should have fired.