Ana içeriğe geç

Angular uygulamasında bir bağlam ile yapısal direktif nasıl test edilir

Eğer "Yapısal direktifi nasıl test edilir" adlı yazıyı okumadıysanız, lütfen önce onu okuyun.

bilgi

Bağlam ile birlikte yapısal direktiflerin test edilmesinin farkı, özel şablonumuzda değişkenlerin bulunmasıdır.

const fixture = MockRender(
`<div *target="values; let value; let index = myIndex">
{{index}}: {{ value }}
</div>`,
{
values: ['hello', 'world'],
}
);

Bu direktif *ngFor davranışını simüle eder. Render edilen HTML’i kontrol ederek farklı doğrulamalar yapabiliriz ve values'ı değiştirdiğimizde direktifin nasıl davrandığını doğrulayabiliriz:

expect(fixture.nativeElement.innerHTML).toContain('0: hello');
expect(fixture.nativeElement.innerHTML).toContain('1: world');
fixture.componentInstance.values = ['ng-mocks'];
fixture.detectChanges();
expect(fixture.nativeElement.innerHTML).toContain('0: ng-mocks');
expect(fixture.nativeElement.innerHTML).not.toContain('0: hello');
expect(fixture.nativeElement.innerHTML).not.toContain('1: world');

Canlı örnek

https://github.com/help-me-mom/ng-mocks/blob/master/examples/TestStructuralDirectiveWithContext/test.spec.ts
import {
Directive,
Input,
TemplateRef,
ViewContainerRef,
} from '@angular/core';

import { MockBuilder, MockRender } from 'ng-mocks';

interface ITargetContext {
$implicit: string;
myIndex: number;
}

// Bu direktif neredeyse `ngFor` ile aynıdır,
// her öğeyi yeni bir satır olarak render eder.
@Directive({
selector: '[target]',
})
class TargetDirective {
public constructor(
protected templateRef: TemplateRef<ITargetContext>,
protected viewContainerRef: ViewContainerRef,
) {}

@Input() public set target(items: string[]) {
this.viewContainerRef.clear();

for (let index = 0; index < items.length; index += 1) {
const value = items[index];
this.viewContainerRef.createEmbeddedView(this.templateRef, {
$implicit: value,
myIndex: index,
});
}
}
}

describe('TestStructuralDirectiveWithContext', () => {
// Direktifi test etmek istediğimiz için, onu MockBuilder'ın ilk
// parametresi olarak geçiriyoruz. İkinci parametreyi atlayabiliriz,
// çünkü bağımlılık yok.
// MockBuilder'ın promise'ını döndürmeyi unutmayın.
beforeEach(() => MockBuilder(TargetDirective));

it('geçirilen değerleri render eder', () => {
const fixture = MockRender(
`
<div *target="values; let value; let index = myIndex">
{{index}}: {{ value }}
</div>
`,
{
values: ['hello', 'world'],
},
);

// 'değerlerin' beklenildiği gibi render edildiğini doğrulayalım
expect(fixture.nativeElement.innerHTML).toContain('0: hello');
expect(fixture.nativeElement.innerHTML).toContain('1: world');

// 'değerleri' değiştirelim ve yeni renderın
// her şeyin beklendiği gibi yapıldığını doğrulayalım.
fixture.componentInstance.values = ['ngMocks'];
fixture.detectChanges();
expect(fixture.nativeElement.innerHTML).toContain('0: ngMocks');
expect(fixture.nativeElement.innerHTML).not.toContain('0: hello');
expect(fixture.nativeElement.innerHTML).not.toContain('1: world');
});
});