Индикатор тестовой загрузки Angular 2 для observable с асинхронным каналом

#angular #testing #integration-testing

#angular #тестирование #интеграция-тестирование

Вопрос:

Проблемный компонент имеет бесконечный экран загрузки. Как вызвать observable для завершения?

В сервисе у меня есть простой метод, который возвращает observable из http GET запроса

Эта ссылка на методы назначается для rentalPoints $

И позже используется компонентом html с использованием асинхронного канала. И индикатор загрузки отображается во время загрузки.

Component.ts

 ngOnInit(): void {
    // Storing observable with rental points
    this.rentalPoints$ = this.rentalPointService.getRentalPoints();
}
 

Component.html

  <ng-container *ngIf="rentalPoints$ | async as rentalPoints; else loading">
    <div class="points">
        <h4>{{rentalPoints.availableAmount}}</h4>
    </div>
</ng-container>

<ng-template #loading>
    <div class="text-center h4">
        <i class="fas fa-spinner fa-spin"></i>
    </div>
</ng-template>
 

Тестовый компонент

 // Creating mocked cabinet service
const RentalPointServiceStub = {
    // Creating method for cabinet mocked service
    getRentalPoints() {
        // Returning observable with loyalty points information
        return scheduled([{
            pendingAmount: 1,
            availableAmount: 2
        }]
        , asyncScheduler);
    }
};

    describe('RentalPointsComponent', () => {
        // Declaring test variables
        let component: RentalPointsComponent;
        let fixture: ComponentFixture<RentalPointsComponent>;
        let debugElement: DebugElement;
        let nativeElement: any;

    // Setting up Test Bed ( Testing envirement )
    beforeEach(async () => {
        TestBed.configureTestingModule({
            imports: [
            ],
            providers: [
                { provide: RentalPointsService, useValue: RentalPointServiceStub },
            ],
            declarations: [
                RentalPointsComponent,
            ]
        }).compileComponents();
    });

    // Reseting variables each test
    beforeEach(() => {
        fixture = TestBed.createComponent(RentalPointsComponent);
        component = fixture.componentInstance;
        debugElement = fixture.debugElement;
        nativeElement = debugElement.nativeElement;
        fixture.detectChanges();
    });

       it('should show indicator while loading, and render view after', fakeAsync(() => {
        expect(debugElement.query(By.css('.fa-spinner')).nativeElement).toBeTruthy();
        tick(50000); // doesnt finish observable
        flush();  // doesnt finish observable
        fixture.detectChanges();
        // expect(nativeElement.query(By.css('.points')));
    }));
});
 

Ответ №1:

Пожалуйста, докажите, что я ошибаюсь.

По какой-то причине асинхронный канал в компоненте HTML не подписывается на observable в среде тестирования. Поэтому обещание или запрос не могут быть решены.

Я начал это обсуждение только потому, что хотел более чистый, более читаемый и более синхронизированный код.

Если кто-то борется с этим. Единственный способ проверить это, который я нашел, — это обернуть его в функцию done и подписаться на observable.

   it('should render loading indicator while data is loading', done => {
        component.rentalPoints$.subscribe(() => {
            expect(debugElement.query(By.css('.fa-spinner'))).toBeTruthy();
            fixture.detectChanges();
            expect(debugElement.query(By.css('.fa-spinner'))).toBeFalsy();
            done();
        });
    });