AngularJS에서 격리 된 범위 지시문을 단위 테스트하는 방법
AngularJS에서 격리 된 범위를 단위 테스트하는 좋은 방법은 무엇입니까?
지시어 스 니펫
scope: {name: '=myGreet'},
link: function (scope, element, attrs) {
//show the initial state
greet(element, scope[attrs.myGreet]);
//listen for changes in the model
scope.$watch(attrs.myGreet, function (name) {
greet(element, name);
});
}
지시문이 변경 사항을 수신하고 있는지 확인하고 싶습니다 . 격리 된 범위 에서는 작동 하지 않습니다 .
it('should watch for changes in the model', function () {
var elm;
//arrange
spyOn(scope, '$watch');
//act
elm = compile(validHTML)(scope);
//assert
expect(scope.$watch.callCount).toBe(1);
expect(scope.$watch).toHaveBeenCalledWith('name', jasmine.any(Function));
});
업데이트 : 예상되는 감시자가 자식 범위에 추가되었는지 확인하여 작동하도록했지만 매우 취약하고 아마도 문서화되지 않은 방식으로 접근자를 사용합니다 (예고없이 변경 될 수 있습니다!).
//this is super brittle, is there a better way!?
elm = compile(validHTML)(scope);
expect(elm.scope().$$watchers[0].exp).toBe('name');
업데이트 2 : 내가 언급했듯이 이것은 부서지기 쉽습니다! 아이디어는하지만 여전히 접근이 변경되었습니다 AngularJS와 새로운 버전의 작동 scope()
에 isolateScope()
:
//this is STILL super brittle, is there a better way!?
elm = compile(validHTML)(scope);
expect(elm.isolateScope().$$watchers[0].exp).toBe('name');
각도 요소 API 문서를 참조하십시오 . element.scope () 를 사용 하면 지시문의 범위 속성에 정의한 요소의 범위를 가져옵니다. element.isolateScope () 를 사용 하면 전체 격리 된 범위를 얻습니다. 예를 들어, 지시문이 다음과 같은 경우 :
scope : {
myScopeThingy : '='
},
controller : function($scope){
$scope.myIsolatedThingy = 'some value';
}
그런 다음 테스트에서 element.scope ()를 호출하면
{ myScopeThingy : 'whatever value this is bound to' }
그러나 element.isolateScope ()를 호출하면
{
myScopeThingy : 'whatever value this is bound to',
myIsolatedThingy : 'some value'
}
이것은 각도 1.2.2 또는 1.2.3에서 사실이며 정확히 확실하지 않습니다. 이전 버전에서는 element.scope () 만있었습니다.
var isolateScope = myDirectiveElement.scope()
격리 범위를 얻으려면 할 수 있습니다 .
하지만 $ watch가 호출되었는지 테스트 할 필요는 없습니다. 앱을 테스트하는 것보다 angularjs를 테스트하는 것이 더 많습니다. 하지만 질문에 대한 예일 뿐이라고 생각합니다.
로직을 별도의 컨트롤러로 이동합니다.
//will get your isolate scope
function MyCtrl($scope)
{
//non-DOM manipulating ctrl logic here
}
app.controller(MyCtrl);
function MyDirective()
{
return {
scope : {},
controller: MyCtrl,
link : function (scope, element, attrs)
{
//moved non-DOM manipulating logic to ctrl
}
}
}
app.directive('myDirective', MyDirective);
and test latter as you would any controller - passing the scope object in directly (see Controllers section here for an example).
if you need to trigger $watch in your test do:
describe('MyCtrl test', function ()
{
var $rootScope, $controller, $scope;
beforeEach(function ()
{
inject(function (_$rootScope_, _$controller_)
{
// The injector unwraps the underscores (_) from around the parameter names when matching
$rootScope = _$rootScope_;
$controller = _$controller_;
});
$scope = $rootScope.$new({});
$scope.foo = {x: 1}; //initial scope state as desired
$controller(MyCtrl, {$scope: $scope}); //or by name as 'MyCtrl'
});
it('test scope property altered on $digest', function ()
{
$scope.$digest(); //trigger $watch
expect($scope.foo.x).toEqual(1); //or whatever
});
});
I'm not sure it's possible with isolate scope (although I hope someone proves me wrong). The isolate scope that gets created in the directive is, well, isolated, so the $watch method in the directive is different from the scope that you're spying on in the unit test. If you change scope: {} to scope: true, the directive scope will inherit prototypically and your tests should pass.
I guess this isn't the most ideal solution, because sometimes (a lot of the time), isolate scope is a good thing.
참고URL : https://stackoverflow.com/questions/17371836/how-to-unit-test-isolated-scope-directive-in-angularjs
'Nice programing' 카테고리의 다른 글
외부 앱이 영구 모델 (서버 데이터베이스)을 변경 한 경우 AngularJS가 뷰를 자동 업데이트 할 수 있습니까? (0) | 2020.10.05 |
---|---|
JavaScript에서 직접 PDF 인쇄 (0) | 2020.10.05 |
Chrome이 로컬 jQuery 쿠키를 무시하는 이유는 무엇입니까? (0) | 2020.10.05 |
내 git 'master'브랜치의 이름을 'release'로 어떻게 바꾸나요? (0) | 2020.10.05 |
Gradle을 사용하여 aar 라이브러리에 대한 전이 종속성이 해결되지 않았습니다. (0) | 2020.10.05 |