angularkarma-jasmineangular-componentsangular10angular-unit-test

Can not access child nodes inside a DIV with Angular Unit Test


I have an Angular (using Angular 10) component with a HTML snippet like below:

<div *ngIf="someCondition()" id="myID">
     <p>Line 1</p>
     <p>Line 2</p>
     <p>Line 3</p>
     <p>Line 4</p>
     <p>Line 5</p>
     <p>Line 6</p>
     <p>Line 7</p>
</div>

Now, while unit testing, I would like to figure out if *ngIf satisfies, the corresponding <div> will have 7 child elements.

In the spec file, I have the following :

it('should check for 7 elements', async () => {    
    spyOn(component, 'someCondition()').and.returnValue(true);
    fixture.detectChanges();
    await fixture.whenRenderingDone();

    const elements = fixture.debugElement.queryAllNodes(By.css('#myID'));
    // const elements = fixture.debugElement.queryAll(By.css('#myID'));    

    console.log('check elements.... ', elements);
  })

With the above, I can not get access to the child <p> tags or the number of the children! Also, it would be good, if I could test a specific <p> tag with expected value.

How can I achieve this?


Solution

  • the first thing that I noticed it is SPY

    it is not correct syntax: spyOn(component, 'someCondition()').and.returnValue(true);

    should be spyOn(component, 'someCondition').and.returnValue(true); - without function call

    also in general I would use variable instaed of mehtod - it is easier to manipulate

    Then you can do next

    
    const resultArray = fixture.debugElement.queryAll(By.css('p'));
    
    expect(resultArray[0].nativeElement.textContent.trim()).toBe('Line 1');
    expect(resultArray[1].nativeElement.textContent.trim()).toBe('Line 2');
    ...
    

    or you can check all values via loop

        resultArray.forEach((el, i) =>
          expect(el.nativeElement.textContent.trim()).toBe("Line " + (i + 1))
        );
    

    implementation via DIV

    
        const div = fixture.debugElement.query(By.css("#myID"));
    
        div.childNodes.forEach((el, i) =>
          expect(el.nativeNode.innerText.trim()).toBe("Line " + (i + 1))
        );
    

    demo:

    https://codesandbox.io/s/adoring-khayyam-hygtd?file=/src/app/app.component.spec.ts

    enter image description here