2014-11-26 15 views
7

Bir girişi doğrulamak için yazdığım yönergeleri test etmeye çalışıyorum ve bazı sıkıntılarım var. Yönerge tarafından yönetilen giriş geçerli bir onaltılık renk değeri içermeli ve kullanıcı geçersiz bir değerle değiştirirse, bu değişikliği iptal etmek istiyorum. Benim direktifi şudur ve beklendiği gibi çalışıyor:Birim test açısal yönergesi ngModel'i güncelleştirme

module.directive('colorValidate', function() { 
    return { 
     restrict: 'A', 
     scope: { 
      color: '=ngModel' 
     }, 
     link: function(scope, element) { 
      var previousValue = '#ffffff'; 
      //pattern that accept #ff0000 or #f00 
      var colorPattern = new RegExp('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$'); 
      element.on('focus', function() { 
       previousValue = scope.color; 
      }); 
      element.on('blur', function() { 
       if (!colorPattern.test(scope.color)) { 
        scope.$apply(function() { 
         scope.color = previousValue; 
        }); 
       } 
       else { 
        scope.$apply(function() { 
         scope.color = scope.color.toLowerCase(); 
        }); 
       } 
      }); 
     } 
    }; 
}); 

ve burada bu yönergesini kullanarak girdi bir örnektir:

<input color-validate type="text" ng-model="color.color"/> 

İlk soru: bir ngModel erişme ve değiştirme bu şekilde mi eleman doğru mu? Daha sonra temel sorun test kısmıdır.

describe('colorValidate directive', function() { 
    var scope, 
     elem, 
     compiled, 
     html; 

    beforeEach(function() { 
     html = '<input color-validate type="text" ng-model="color.color"/>'; 

     inject(function($compile, $rootScope) { 
      scope = $rootScope.$new(); 
      scope.color = {color: '#aaaaaa'}; 
      elem = angular.element(html); 
      compiled = $compile(elem); 
      compiled(scope); 
      scope.$digest(); 
     }); 
    }); 

    it('should permit valid 6-chars color value', function() { 
     elem.triggerHandler('focus'); 
     elem.val('#FF0000'); 
     elem.triggerHandler('blur'); 
     scope.$digest(); 
     expect(elem.val()).toBe('#FF0000'); 
    }); 

    it('should reject non valid color values', function() { 
     elem.triggerHandler('focus'); 
     elem.val('#F00F'); 
     scope.$digest(); 
     elem.triggerHandler('blur'); 
     expect(elem.val()).toBe('#aaaaaa'); 
    }); 
}); 

ilk test başarılı ve test edilmiş değer yerine '#aaaaaa' arasında '# F00F' olduğundan başarısız ikinci: Burada iki basit yazdım ve gerçekten çalışmayan testlerdir. Temel olarak, benim testlerimin hiçbiri yönerge tarafından işlenen ngModel değerini değiştirmiyor ...

cevap

7

Elem.val() çağrısı aslında kapsamın güncellenmesine neden olmaz. Başka bir deyişle, bu test başarısız olur: ngModel girişi önemli olayların bağlanır ve bu noktada modeli (kapsam) güncelleştirmesi nedeniyle

it("should set scope", function() { 
    elem.triggerHandler("focus"); 
    elem.val("#FF0000"); 
    scope.$digest(); 
    elem.triggerHandler("blur"); 

    //Will fail: expected #aaaaaa to be #ff0000 
    expect(scope.color.color).toBe("#ff0000"); 
}); 

budur. Öğede val() veya değeri çağırmak, açısal değişkenin bir şeyin değişeceğini düşündüğü bir olayı tetiklemez ($ digest döngüsünde bile). muhtemelen açısal zaten testleri yazılı olurdu, çünkü değer güncellenir olduğunu test etmek gerekmez

it('should permit valid 6-chars color value', function() { 
    elem.triggerHandler('focus'); 
    scope.color.color = '#FF0000'; 
    //need to trigger a digest here for the two-way binding 
    scope.$digest(); 
    elem.triggerHandler('blur'); 
    //Don't need a $digest here because you call scope.$apply() within the blur in both if/else conditions 
    //scope.$digest(); 
    expect(scope.color.color).toBe('#ff0000'); 
}); 

it('should reject non valid color values', function() { 
    elem.triggerHandler('focus'); 
    scope.color.color = '#F00F'; 
    //need to trigger a digest here for the two-way binding 
    scope.$digest(); 
    elem.triggerHandler('blur'); 
    expect(scope.color.color).toBe('#aaaaaa'); 
}); 

: Bu nedenle, model, değerlerini değiştirerek, onlar da kabul veya sıfırlama ediliyor iddia ederek testleri çalışıyor olması gerekir Yönergenin iki yönlü bağlaması (= ngModel) olduğunda, kapsam değerinin yönerge içinde değiştiğinde görünümün güncelleştirildiğinden emin olmak için.

+0

Teşekkürler, bu çok yardımcı olur! Aslında kapsamın konumu. $ Digest, ben de bulanıklık çizgisinden sonra çağırdığımdan beri bir problemdi. Dahası, benim sorumu güncelledim çünkü elem.blur() ve focus() kullanımım yanlıştı ve elem.triggerHandler ('focus') olmalıydı; – ValentinH

+0

Yanıt olarak test edilmiş testler. Yorum eklendi ... Ünite testlerindeki kapsam değerlerini değiştirip beklemeniz gerekiyor. Yukarıdaki iki test de triggerHandler ile yaptığınız değişikliklerden geçer. – Patrick

+0

Gerçekten de ikisi de geçer. Tekrar teşekkürler. – ValentinH