I am new in unit testing and now I am not able to call function which inside *ngFor
loop of an angular 12
app. There is a observable that contains an array of objects and it works fine. Whole data is iterated properly.
This is my HTML code.
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Category</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of games$ | async; let i = index">
<td>{{ i+1 }}</td>
<td>{{ item.name }}</td>
<td class="badge-cell">
{{ item.categoryId }}
</td>
<td class="center action-cell">
<button type="button"
class="delete-game btn"
(click)="deleteGame(item.id)">Delete</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- /.table-responsive-->
The problem rises while testing a function call inside loop. Thus, when I try to access nativeElement
property of a fixture
then the dynamic part of a table is null
. Therefore daleteGame
function is not available.
Here is the how console.log(fixture.nativeElement)
look like:
<div _ngcontent-a-c74="" class="table-responsive">
<table _ngcontent-a-c74="" id="dataTables-example" class="table table-striped">
<thead _ngcontent-a-c74="">
<tr _ngcontent-a-c74="">
<th _ngcontent-a-c74="">#</th>
<th _ngcontent-a-c74="">Name</th>
<th _ngcontent-a-c74="">Category</th>
<th _ngcontent-a-c74="">Action</th>
</tr>
</thead>
<tbody>
//----------NO ROWS IN THE LOG------------//
<!--bindings={
"ng-reflect-ng-for-of": null
}-->
</tbody>
</table>
</div>
Static data is used to simulate original array(see GAME_DATA
). This is how the tests look like:
describe('ListGamesComponent', () => {
let component: ListGamesComponent;
let fixture: ComponentFixture<ListGamesComponent>;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule, CommonModule],
declarations: [ListGamesComponent],
providers: [
RequestService,
],
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(ListGamesComponent);
component = fixture.componentInstance as any;
component.games$ = from([GAME_DATA]) as unknown as Observable<
IGameData[]
>;
});
})
);
it('should create', () => {
expect(component).toBeTruthy();
});
it('should check if deleteGame was called', fakeAsync(() => {
spyOn(component, 'deleteGame');
component.games$.subscribe((data: any) => {
// ---- logged an observable, a proper list of games is returned ----
console.log('data: ', data);
});
fixture.detectChanges();
let button = fixture.debugElement.query(By.css('.delete-game'));
button.triggerEventHandler('click', null);
fixture.detectChanges();
tick();
expect(component.deleteGame).toHaveBeenCalled();
}));
});
By the way, I logged an observable inside the test and it retrieves whole data from GAME_DATA
static file, so I don't understand why the whole table is not generated.
UPDATE
This is how games$
done in component:
export class ListGamesComponent implements OnInit {
ngOnInit(): void {
let pager: { index: number; size: number } = {
index: this.pageIndex,
size: this.pageSize,
};
this.games$ = this.gameService.getAllGames(pager).pipe(
tap((data) => {
this.totalRecords = data.totalItems;
this.gamesList = data.games;
this.setPage(1, false); // generate pagination
}),
pluck('games')
);
}
}
Any help is appreciated. Thanks!