Angular e2e testing - check template before OnInit executes

386 views Asked by At

In Angular 9 application, I have component that in

ngOnInit(): void {
  this.records$ = this.service.loadRecords();
}

loadReords() returns Observable that starts with null and next after Http request completes emit list of records.

In template there are conditions that if records$ is null so called 'loading' div would be visible, when changed list of records - table of records.

When I try to test it (e2e) with protractor after page.navigateTo(); what returns:

navigateTo(): Promise<unknown> {
 return browser.get(`${browser.baseUrl}${this.url}`) as Promise<unknown>;
}

I can traverse page that is completed (records already loaded - even proxy API call for those records is intentionally delayed).

How I can traverse page that is rendered with 'loading' phase - before records$ stream is loaded?

1

There are 1 answers

0
user52333 On

Is there a specific reason why you're using an e2e test for this instead of a more isolated test? The latter would enable you to spy on the service's method and add a delay so that you can make your assertions during the loading state:

describe('MyComponent', ()=>{
  let fixture: ComponentFixture<MyComponent>;
  let comonent: MyComponent;
  let myService: MyService;
  
  beforeEach(()=>{
    TestBed.configureTestingModule({
       declarations: [MyComponent]
    });
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    myService = TestBed.inject(MyService);
  });

  it('should show the loading <div>', fakeAsync(() => {
    // set up the fake service method with a delay
    const simulatedDelayMS = 500;
    const recordsStub = [{foo: 'bar'}, {foo: 'baz'}, {foo: 'qux'}];
    const recordsStubWithDelay$ = of(recordsStub).pipe(delay(simulatedDelayMS));
    spyOn(myService, 'loadRecords').and.returnValue(recordsStubWithDelay$);

    // perform the first change detection run
    fixture.detectChanges();
    const getLoadingDiv = () => fixture.debugElement.query(By.css('div.loading'))).nativeElement;

    // the <div> should be displayed
    expect(getLoadingDiv()).not.toBeNull();

    // simulate the enough time passing for the data to finish loading
    tick(1000);
    
    // the <div> should no longer be displayed
    expect(getLoadingDiv()).toBeNull();
  }));
})