2013-07-13 35 views
19

Tôi có chỉ thị AngularJS sau đây tạo ra một yếu tố input. Đầu vào có thuộc tính ng-change chạy chức năng doIt(). Trong bài kiểm tra đơn vị chỉ thị của tôi, tôi muốn kiểm tra xem chức năng doIt có được gọi khi người dùng thay đổi đầu vào hay không. Nhưng thử nghiệm không vượt qua. Mặc dù nó hoạt động trong trình duyệt khi kiểm tra thủ công.Làm thế nào để kích hoạt ng-thay đổi trong kiểm tra chỉ thị trong AngularJS

Chỉ thị:

... 
template: "<input ng-model='myModel' ng-change='doIt()' type='text'>" 

Test:

el.find('input').trigger('change') // Dos not trigger ng-change 

sống bản demo (ng-change): http://plnkr.co/edit/0yaUP6IQk7EIneRmphbW?p=preview


Bây giờ, thử đi nếu tôi tự ràng buộc change sự kiện thay vì sử dụng thuộc tính ng-change.

template: "<input ng-model='myModel' type='text'>", 
link: function(scope, element, attrs) { 
    element.bind('change', function(event) { 
    scope.doIt(); 
    }); 
} 

sống bản demo (thủ công binding): http://plnkr.co/edit/dizuRaTFn4Ay1t41jL1K?p=preview


Có cách nào để sử dụng ng-change và làm cho nó kiểm chứng? Cảm ơn bạn.

+1

thay đổi ng được kích hoạt trên thay đổi mô hình, không phải sự kiện. tại sao không chỉ kiểm tra mã điều khiển cho "doIt" fn của bạn? – marko

+0

@marko, cảm ơn câu hỏi hay. Tất cả những gì tôi muốn làm trong bài kiểm tra của chỉ thị là kiểm tra xem doIt được gọi khi người dùng thay đổi đầu vào. DoIt chính nó sẽ được chế giễu trong thử nghiệm của chỉ thị, bởi vì nó đã được thử nghiệm trong kiểm tra của bộ điều khiển, như bạn đã đề xuất. – Evgenii

Trả lời

30

Từ lời chú thích của bạn:

Tất cả tôi muốn làm trong thử nghiệm chỉ là để kiểm tra xem doIt được gọi khi người dùng thay đổi các đầu vào.

hay không biểu hiện bằng ng-change được đánh giá một cách chính xác hay không thực sự là trách nhiệm của các chỉ thị ngModel, vì vậy tôi không chắc là tôi muốn thử nghiệm nó theo cách này; thay vào đó, tôi tin tưởng rằng chỉ thị ngModelngChange đã được triển khai và thử nghiệm chính xác để gọi hàm được chỉ định và chỉ kiểm tra việc gọi chính chức năng sẽ ảnh hưởng đến chỉ thị theo cách chính xác. Một bài kiểm tra đầu cuối hoặc tích hợp có thể được sử dụng để xử lý kịch bản sử dụng đầy đủ.

Điều đó nói rằng, bạn có thể có được giữ của các ví dụ ngModelController mà các ổ đĩa ngModel thay đổi callback và thiết lập giá trị quan điểm bản thân:

it('trigger doIt', function() { 
    var ngModelController = el.find('input').controller('ngModel'); 
    ngModelController.$setViewValue('test'); 
    expect($scope.youDidIt).toBe(true); 
}); 

Như tôi đã nói, tuy nhiên, tôi cảm thấy như thế này là đạt quá vượt qua trách nhiệm của ngModel, phá vỡ các black-boxing bạn nhận được với chỉ thị composable tự nhiên.

Ví dụ: http://plnkr.co/edit/BaWpxLuMh3HvivPUbrsd?p=preview


[Cập nhật]

Sau khi nhìn xung quanh tại nguồn AngularJS, tôi thấy rằng những điều sau đây cũng làm việc:

it('trigger doIt', function() { 
    el.find('input').trigger('input'); 
    expect($scope.youDidIt).toBe(true); 
}); 

Dường như sự kiện là khác nhau trong một số trình duyệt; input dường như hoạt động với Chrome.

Ví dụ: http://plnkr.co/edit/rbZ5OnBtKMzdpmPkmn2B?p=preview

Đây là relevant AngularJS code, trong đó sử dụng các dịch vụ $sniffer để tìm ra sự kiện để kích hoạt:

changeInputValueTo = function(value) { 
    inputElm.val(value); 
    browserTrigger(inputElm, $sniffer.hasEvent('input') ? 'input' : 'change'); 
}; 

Thậm chí có này, tôi không chắc là tôi muốn thử nghiệm một chỉ thị theo cách này.

+4

Về các sự kiện, tôi nghĩ 'đầu vào' là cho các đầu vào văn bản và tương tự và' thay đổi 'là dành cho các hộp chọn và nút radio. Ít nhất đó là những gì làm việc cho tôi chạy thử nghiệm trên PhantomJS. –

+1

Dường như browserTrigger chỉ xuất hiện trong angular-scenario.js. Điều này có nghĩa là nó chỉ dành cho thử nghiệm e2e, đúng không? Tôi không thể sử dụng chức năng này thành một bài kiểm tra đơn vị, đó là mục đích tôi tin. – unludo

+0

@unludo Có lẽ; quan điểm của tôi chỉ là nguồn AngularJS được viết để kích hoạt một sự kiện khác trong các trình duyệt nhất định. –

0

Tôi đang tìm dòng đơn giản này trong nhiều giờ. Chỉ để lưu lại ở đây.

Làm cách nào để chọn giá trị từ lựa chọn html, sử dụng Karma và do đó, hãy sử dụng chức năng ng-thay đổi?

HTML:

điều khiển hoặc chỉ thị JS:

$scope.itemTypes = [{name: 'Some name 1', value: 'value_1'}, {name: 'Some name 2', value: 'value_2'}] 

    $scope.itemTypeSelected = function() { 
    console.log("Yesssa !!!!"); 
    }; 

Karma kiểm tra đoạn:

angular.element(element.find("#selectedItemType")[0]).val('value_1').change(); 
    console.log("selected model.selectedItemType", element.isolateScope().model.selectedItemType); 

Console:

'Yesssa !!!!' 
'selected model.selectedItemType', 'value_1' 
0

Tôi googled "kích hoạt chỉ thị góc ng-thay đổi" và câu hỏi StackOverflow này là gần nhất tôi đã nhận được bất cứ điều gì hữu ích, vì vậy tôi sẽ trả lời "Làm thế nào để kích hoạt ng-thay đổi trong một chỉ thị", kể từ khi những người khác bị ràng buộc đất trên trang này và tôi không biết cách cung cấp thông tin này.

Bên trong chức năng liên kết trên các chỉ thị, điều này sẽ kích hoạt các chức năng ng thay đổi về yếu tố của bạn:

element.controller('ngModel').$viewChangeListeners[0](); 

element.trigger("change")element.trigger("input") không làm việc cho tôi, không phải làm bất cứ điều gì khác tôi có thể tìm thấy trực tuyến.

Như một ví dụ, kích hoạt các ng thay đổi trên làm mờ:

wpModule.directive('triggerChangeOnBlur', function() { 
    return { 
     restrict: 'A', 
     link: function (scope, element, attrs) { 
      element.on('blur', function() { 
       element.controller('ngModel').$viewChangeListeners[0](); 
      }); 
     } 
    }; 
}]); 

Tôi xin lỗi rằng điều này là không trực tiếp trả lời câu hỏi OP của. Tôi sẽ rất vui khi có một số lời khuyên âm thanh về nơi và cách chia sẻ thông tin này.

+1

Lý tưởng nhất là bạn sẽ đặt một câu hỏi riêng và sau đó tự trả lời (nghe có vẻ kỳ lạ, nhưng được khuyến khích). Tôi cũng đang tìm kiếm thứ gì đó không hoàn toàn là OP hoặc vấn đề của bạn và sẽ tìm câu trả lời nhanh hơn nếu có câu hỏi cụ thể về nó. –

0

đơn giản và nó hoạt động trong đơn vị kiểm tra env của bạn:

spyOn(self, 'updateTransactionPrice'); 


var el = compile('<form name="form" latest novalidate json-schema="main.schema_discount" json-schema-model="main._data"><input type="text" ng-model="main._data.reverse_discount" ng-class="{ \'form-invalid\': form.reverse_discount.$invalid }" ng-change="main.transactionPrice(form);" name="reverse_discount" class="form-control-basic" placeholder="" ng-disabled="!main.selectedProduct.total_price"></form>')(scope); 
el.find('input').triggerHandler('change'); 

expect(self.updateTransactionPrice).toHaveBeenCalled(); 
0

Đã cố gắng để có được điều này để làm việc, nhưng không thành công trên tất cả các nỗ lực. Cuối cùng kết luận rằng các tùy chọn ng-model-của tôi với một thiết lập debounce trên onUpdate, là vấn đề.

Nếu bạn bị lỗi, hãy đảm bảo rằng bạn đã xóa bằng dịch vụ $ timeout. Trong mô phỏng góc, dịch vụ thời gian chờ này đã được mở rộng với một hoạt động tuôn ra, xử lý tất cả các yêu cầu/hành động chưa được thực hiện.

var tobetriggered = angular.element(element[0].querySelector('.js-triggervalue')); 
    tobetriggered.val('value'); 
    tobetriggered.trigger('change'); 
    $timeout.flush(); 
Các vấn đề liên quan