Search code examples
angularunit-testingag-gridag-grid-angular

ag-grid API Undefined in Angular unit testing


I am writing the unit test case for Ag-grid in angular.

test.component.ts:

public gridApi: GridApi; 
public gridColumnApi;

constructor(private service: Service) {
 this.initializeAgGrid(); // this method just initializing the grid
}

ngOnInit(): void {
 this.setHraDashboardData();
}

onGridReady(params) {
 this.gridApi = params.api;
 this.gridColumnApi = params.columnApi;
 this.gridApi.sizeColumnsToFit();
}

setHraDashboardData() {
 this.service.getData(1).then((data) => {
   this.uiData = data;
   this.rowData = this.generateRowData(this.data); // this method writing some logic for UI
   this.gridApi.setRowData(this.rowData);
 });
}

test.component.spec.ts

beforeEach(() => {
  fixture = TestBed.createComponent(HraFormComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

it('grid API is available after `detectChanges`', async() => {
  await fixture.whenStable().then(()=>{
    fixture.detectChanges();
    const elm = fixture.debugElement.nativeElement;
    const grid = elm.querySelector('#Grid');
    const firstRowCells = grid.querySelectorAll('div[row-id="0"] div.ag-cell-value');
    const values = Array.from(firstRowCells).map((cell: any) => cell.textContent.trim());

    // assert
    expect(component.rowData[0].title).toEqual(values[0]);
  });
});

Now above test case is getting failed to due to component.gridApi is undefined, so it's not able to assign value for the grid this.gridApi.setRowData(this.rowData).


Solution

  • When writing unit tests that involves the availability of the ag-grid api, two things can help you in this case:

    Instead of waiting for the gridReady event, you can try to use the this.gridOptions.api (this.gridOptions.api.setRowData ...) because most of the time, it is initialized sooner (before onGridReady firing)

    You can do that in combination of using a settimeout function as well, I used that multiple times when I got a similar issue as yours in the past:

    instead of:

    this.gridApi.setRowData(this.rowData);
    

    Try:

    setTimeout(() => { this.gridApi.setRowData(this.rowData);}, 100);
    

    You can increase the time for the settimeout to 200, 300, 500 or more, for me, most of the time just using the settimeout with a very small number (10 milliseconds) worked.

    The settimeout is not an ideal solution but that works in many cases. The first options should be more clean, and you can even add a timeout as well to get it to work.

    Use a fakeAsync zone instead of the async one will help as well.