Full Time Skeleton
Full Time Skeleton

Reputation: 1740

Angular unit testing component ngIf element is null

I've a component with a few *ngIf statements throughout, most of them like the following

<ul *ngFor="let item of items">
<li> 
    <ng-container *ngIf="itemCount && item.GroupId == 4">
        <span class="bridge">{{itemCount}}</span>
    </ng-container>
</li>
... and so on

in my spec file I've a test that is trying to check on the scenario whereby the itemCount is not null /empty and the groupId = 4...then checking that the span contains the correct item count.

I've spent hours on variations of this but no matter what I try the attempt to get access to the span results in null and the test fails.

So here's an example of one of the tests

if('should show the correct item count', () =>{
    let component = fixture.componentInstance;
    component.itemCount = 4;
    fixture.detectChanges();

    let bridge = fixture.debugElement.query(By.css('.bridge'));
    expect(bridge).tobeTruthy();
});


As I say above, through many multiples of attempts this is ALWAYS null, no matter what. I've debugged the test and have confirmed that the correct groupId is being used have also confirmed the itemCount is not null or empty so both conditions of the *ngIf should be fulfilled -but the span doesn't exist so I have to presume there's something amiss.

Please excuse typos, I'm copying the code manually but it does run currently, just doesn't succeed.

Any pointers?

Update:

Here's more info, the beforeEach where the component is populated with dummy data.

const ItemServiceStub = jasmine.createSpyObj('ItemService', ['getItems']);

beforeEach(() =>{
    TestBed.configureTestingModule({
        declarations: [ItemComponent],
        providers: [{provide: ItemService, useValue: ItemServiceStub}]
    }).compileComponents();
});

beforeEach(() => {
    itemService = Testbed.inject(ItemService);

    spyOn(itemService, 'getItems').and.callFake(() => of(fakeItems));

    fixture = TestBed.createComponent(ItemComponent);
    fixture.autoDetectChanges();
});

Update 2 Here's the fake data being set

describe('item tests', () => {

let fakeItems: Item[];

fakeItems = [
   {GroupId: '2', ItemName: 'test', isExternal: false},
   {GroupId: '3', ItemName: 'testing', isExternal: false},
   {GroupId: '4', ItemName: 'test item', isExternal: false}
];

});


Upvotes: 0

Views: 5307

Answers (1)

AliF50
AliF50

Reputation: 18809

Try this:

it('should show the correct item count', () =>{
    let component = fixture.componentInstance;
    component.items = [...fakeItems];
    component.itemCount = 4;
    fixture.detectChanges();

    let bridge = fixture.debugElement.query(By.css('.bridge'));
    console.log(bridge); // make sure it logs something to the console
    expect(bridge).toBeTruthy();
});

If this doesn't work, I am thinking there is an *ngIf on top of the ul where it is not true and therefore this ul is not being displayed.

To test this, try:

<ul class="dummy-class" *ngFor="let item of items">
<li> 
    <ng-container *ngIf="itemCount && item.GroupId == 4">
        <span class="bridge">{{itemCount}}</span>
    </ng-container>
</li>
it('should show the correct item count', () =>{
    let component = fixture.componentInstance;
    component.items = [...fakeItems];
    component.itemCount = 4;
    fixture.detectChanges();

    let bridge = fixture.debugElement.query(By.css('ul.dummy-class'));
    console.log(ul); // make sure it logs something to the console
    expect(ul).toBeTruthy();
});

Upvotes: 2

Related Questions