2016-12-20 23 views
7

Próbuję napisać test jednostkowy dla komponentu w Angular 1.5. Chcę przetestować ten komponent i jego węzły domena. Ten komponent zawiera komponent potomny, który jest dość złożony.Moduł testujący Angular 1.5 podczas ignorowania komponentów potomnych

Moim celem jest przetestowanie komponentu zewnętrznego bez kompilacji komponentu potomnego.

Ponieważ chcę przetestować DOM, nie wystarczy użyć $ componentController dla tego testu.

Oto krótki przykład tego, co chciałbym osiągnąć:

kod Składnik:

angular.module('app').component('myComponent', { 
    bindings: { 
    username: '<', 
    }, 
    template: ` 
    <span>{{ $ctrl.username }}</span> 
    <my-complex-component /> 
    ` 
    controller: function() {} 
}); 

testów jednostkowych dla mojego składnika:

it('my-component should render username', function() { 
    var template = '<my-component username="username"></my-component>', 
    element, 
    scope, 
    date; 

    scope = $rootScope.$new(); 
    scope.username = 'John'; 

    element = $compile(template)(scope); 
    scope.$digest(); 

    username = element.find('span'); 
    expect(username.text()).to.be.equal('John'); 
}); 

mój kompleks-komponentowego nie należy tworzyć instancji. Powinien stawić opór w szablonie takim jaki jest. Utworzenie elementu w teście jednostkowym powinno skutkować tym, że jest jakiś sposób to zrobić.

+0

Jak wiem, działa dokładnie tak, jak się spodziewałeś. Podczas kompilowania komponentu nie kompiluje się komponentów wewnętrznych. Wystarczy spojrzeć na 'console.log (element)'. –

+0

Niestety, mój-komponent i mój-złożony-składnik znajdują się w module aplikacji. Ponieważ muszę wywoływać angular.mock.module ("app") w celu wyśmiewania modułu, ładuje on oba komponenty i próbuje skompilować również mój złożony komponent. –

+0

możesz spróbować i wyśmiewać 'mój-złożony-komponent'. Zobacz [tę odpowiedź] (http://stackoverflow.com/questions/17533052/how-do-you-mock-directives-to-enable-unit-testing-of-higher-level-directive#answer-21923462) na szyderstwie dyrektywy, ale użyj [$ compileProvider.component] (https://docs.angularjs.org/api/ng/provider/$compileProvider#component) zamiast – user2718281

Odpowiedz

1

Jest sposób, żeby go przetestować, ale wynik końcowy będzie:

<span>John</span> 
<ng-transclude></ng-transclude> 

kod Składnik:

angular.module('app').component('myComponent', { 
    enter code herebindings: { 
    username: '<', 
    }, 
    template: ` 
    <span>{{ $ctrl.username }}</span> 
    <ng-transclude></ng-transclude> 
    `, 
    transclude: true, // Added property 
    controller: function() {} 
}); 

Jak widać Usunąłem <my-complex-component> i dodał <ng-transclude> zamiast.

To oznacza, że ​​możesz dodać informacje z zewnątrz, a zostanie ono wstawione w miejscu ng-transclude.

Na przykład tego w głównym HTML:

<my-component> 
    <my-complex-component></my-complex-component> 
</my-component> 

będzie w DOM w sposób, który chciał od początku:

<span>John</span> 
<my-complex-component></my-complex-component> 

Po że test powinien działać.

Mam nadzieję, że ta odpowiedź jest tym, czego chciałeś i że to ci pomoże.

+1

Nie jestem pewien czy zmiana znacznika komponentu jest właściwym podejściem. Dzięki temu marża staje się mniej intuicyjna. Co się stanie, jeśli istnieje więcej niż jeden element potomny? – isherwood

+0

Myślę, że jest to lepsze podejście, jeśli chcesz, aby twoje komponenty były bardziej testowalne, iw ten sposób możesz umieścić tak wiele komponentów w swoim głównym, bez przerywania testów. W ten sposób widać, że główny komponent nadal działa (lub nie), gdy wszystko zaczyna się łamać. – Alon

2

Here is a very good explanation testowania komponentu bez renderowania całego drzewa pod bieżącym komponentem.

Co chcesz nazywa

płytkie renderowania (unikać renderowania cały szablon komponentu dziecko)

i kątowe 1.5 nie oferuje go out-of-the-box.

Jeśli spojrzysz na powyższy link, Wojciech Zawistowski pokazuje, jak użyć pomocnika poniżej, aby uzyskać płytkie renderowanie.

export function componentSpyOn(name) { 
    function componentSpy($provide) { 
    componentSpy.bindings = []; 

    $provide.decorator(name + 'Directive', ($delegate) => { 
     let component = $delegate[0]; 

     component.template = ''; 
     component.controller = class { 
     constructor() { 
      componentSpy.bindings.push(this); 
     } 
     }; 

     return $delegate; 
    }); 
    } 

    return componentSpy; 
} 
0

Można po prostu zastąpić definicję modułu komponentów potomnych w teście jednostkowym pustym modułem.

// Unit Test Parent component 
describe('Unit Testing: myComponent Component',() => { 

    beforeEach(() => { 
    // overwrite module 
    angular.module('myComplexComponent', []); 
    module('myComponent'); 
    }); 
}); 

Teraz składnik rodzic będzie nadal próbować wstrzykiwać i renderowania komponentu dziecko, ale jako ten składnik dziecko jest całkowicie pusta nic się nie stanie.