Тестирование получения входных данных от других компонентов при использовании setTimeout - PullRequest
0 голосов
/ 12 июля 2019

Этот вопрос является продолжением своего рода из предыдущего вопроса ( ссылка здесь ). Я все еще работаю с теми же файлами с целью написания простых учебных пособий для тестирования Angular. Новая проблема связана с функцией setTimeout.

И в ngOnInit, и в ngAfterViewInit я реализую setTimeout (другие тесты, которые я напишу в будущем, делают это, так что это просто для создания базового примера). Функция внутри устанавливает значение переменной, которая передается дочернему компоненту через файл HTML. Затем переменная этого дочернего компонента проверяется на конкретное значение.

Я уже пытался работать с tick (value) и fixture.detectChanges (), чтобы попытаться вызвать содержимое функции setTimeout, но значение все еще не определено (см. Фрагменты кода).

random.test.component.ts

public dataThatGetsDelayed: any;

constructor() {

}

ngOnInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "OnInit";
    }, 100);
}

ngAfterViewInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "AfterView";
    }, 100);
}

random.test.component.html

[variableThatStoresDelayedData]="dataThatGetsDelayed"

random.test.component.child.ts

@Input() variableThatStoresDelayedData: any;

random.test.file.spec.ts

it('Testing if receiving input works properly with a time delay in ngOnInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    tick(100);
    fixture.detectChanges();

    fixture.whenStable().then(() => {
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("OnInit");
    });
}));

it('Testing if receiving input works properly with a time delay in ngAfterViewInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    //tick(100);
    //component.ngAfterViewInit();

    fixture.whenStable().then(() => {
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("AfterView");
    });
}));

Я читал, что должен был использовать whenStable в конце, но теперь я знаю, что это полностью пропущено. Без этого я получаю сообщение об ошибке «Ожидается, что неопределенное значение равно OnInit» / «AfterView». Я опустил второй тик, потому что он вызывает ошибку «1 таймер (ы) все еще в очереди».

Как сказать программе ждать, пока значение не будет установлено в функции setTimeout?

1 Ответ

0 голосов
/ 16 июля 2019

Хорошо, благодаря некоторым исследованиям и экспериментам я нашел решение. Комментарии кода объясняют более тонкие детали:

random.test.component.ts

public dataThatGetsDelayed: any = "Initial value"; //This is just to show how the value changes.

constructor(private detectorReference: ChangeDetectorRef) {
    //The detectorReference is used in ngAfterViewInit
}

ngOnInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "OnInit";
    }, 100);
}

ngAfterViewInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "AfterView";
        this.detectorReference.detectChanges(); //Needed to stop the error about changing the value.
    }, 200);
}

(Спасибо этому источнику за помощь!)

random.test.file.spec.ts

//This test is for the ngOnInit function
it('Testing if receiving input works properly with a time delay in ngOnInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("Initial value");

    component.ngOnInit();
    //tick(99); - This doesn't /quite/ run out the setTimeout function from the ngOnInit function.
    tick(100); //This does, though.
    fixture.detectChanges();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("OnInit");
}));

//This test is for the ngAfterViewInit function. Note that the value isn't set with ngOnInit first;
//only the explicit method call will perform the desired action.
it('Testing if receiving input works properly with a time delay in ngAfterViewInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("Initial value");

    component.ngAfterViewInit();
    //tick(199); - Again, this doesn't /quite/ run out the setTimeout.
    tick(200); //But, once again, this does.
    fixture.detectChanges();

    expect(componentInThePage.variableThatStoresDelayedData).toEqual("AfterView");
}));

Надеюсь, это поможет кому-то в будущем!

...