samedi 3 octobre 2020

Angular Testing: Get HTML Element inside child component that uses ng-content

I have a problem writing unit tests for a component that uses ngb-accordion to display its content. In this case, the accordion is only used for styling purposes, but I use it to provide design consitency across the app.

The most simplest template I could come up with to show the error:

<ngb-accordion #acc="ngbAccordion" activeIds="sample">
  <ngb-panel id="sample">
    <ng-template ngbPanelContent>
      <p class="myClass">Some Text</p> <!-- I want to access this element -->
    </ng-template>
  </ngb-panel>
</ngb-accordion>

The testcase looks as follows:

it('should find my element', () => {
    fixture = TestBed.createComponent(LoginComponent);

    component = fixture.componentInstance;
    fixture.detectChanges();
    const p = fixture.debugElement.query(By.css('.myClass')).nativeElement;
    p.id;
});

which throws an error:

TypeError: Cannot read property 'nativeElement' of null

Here is the beforeEach for my test:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LoginComponent, NgbAccordion ],
      providers : [FormBuilder, ...]
    })
    .compileComponents();
  }));

(where LoginComponent is the tested Component).

I dont think it has something to do with ng-template, as with the following html, the element is found correctly:

<div *ngIf="false else always">Should not show</div>

<ng-template #always>
  <p class="myClass">Some Text</p>
</ng-template>

I don't know why it doesn't work with ngbAccordion, could it be a timing issue? As I am not mocking the NgbAccordion class (and I dont want to!), I expect it's contents to be rendered correctly. Is it, because the html is probably rendered with 'ng-content' from within the 'NgbAccordion'? If so, what could I do to access my element?

Any help is greatly appreciated.

Aucun commentaire:

Enregistrer un commentaire