Here we give some hints on testing AG Grid as part of your application.
Using Jest with Angular (for example with an Nx/Angular project)
In order to test AG Grid with Jest you'll need to make the following configuration changes:
In jest.config.js
add the following line:
resolver: '<rootDir>myResolver.js',
Then create a file called myResolver.js
in the root directory of your project:
module.exports = (request, options) => {
return options.defaultResolver(request, {
...options,
packageFilter: pkg => {
const packageName = pkg.name;
if (packageName === '@ag-grid-community/angular') {
return {
...pkg,
};
}
const agDependency = packageName.startsWith("@ag-grid");
return {
...pkg,
// default to use the CommonJS ES5 entry point for Jest testing with AG Grid
main: agDependency ? './dist/cjs/es5/main.js' : pkg.module || pkg.main,
};
},
});
};
We will walk through how you can use testing AG Grid as part of your Angular application, using default build tools provided when using the Angular CLI.
Configuring the Test Module
Before we can test our component we need to configure the TestBed
. In this example we have a TestHostComponent
that wraps AgGridAngular
so we pass that to the TestBed
.
@Component({
selector: 'app-grid-wrapper',
standalone: true,
imports: [AgGridAngular],
template: `<ag-grid-angular
[rowData]="rowData"
[columnDefs]="columnDefs" />`,
})
export class TestHostComponent {
rowData: any[] = [{ name: 'Test Name', number: 42 }];
columnDefs: ColDef[] = [
{ field: 'name' },
{ field: 'number', colId: 'raw', headerName: 'Raw Number', editable: true, cellEditor: EditorComponent },
{ field: 'number', colId: 'renderer', headerName: 'Renderer Value', cellRenderer: PoundRenderer },
];
@ViewChild(AgGridAngular) public agGrid: AgGridAngular;
}
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TestHostComponent],
}).compileComponents();
fixture = TestBed.createComponent(TestHostComponent);
component = fixture.componentInstance;
});
Testing via the Grid API
The grid api will be available after detectChanges()
has run and the fixture is stable. This is true if you store a reference to the api
within onGridReady
or use a ViewChild
to access the AgGridAngular
component.
it('ViewChild not available until `detectChanges`', () => {
expect(component.agGrid).not.toBeTruthy();
});
it('ViewChild is available after `detectChanges`', async () => {
// Detect changes triggers the AgGridAngular lifecycle hooks
fixture.detectChanges();
// Wait for the fixture to stabilise
await fixture.whenStable();
// ViewChild now has a reference to the component
expect(component.agGrid.api).toBeTruthy();
});
Testing Grid Contents
One way to check the grid contents is to access the nativeElement
and query DOM elements from there:
it('the grid cells should be as expected', async () => {
fixture.detectChanges();
await fixture.whenStable();
const cellElements = fixture.nativeElement.querySelectorAll('.ag-cell-value');
expect(cellElements.length).toEqual(3);
expect(cellElements[0].textContent).toEqual("Test Name");
expect(cellElements[1].textContent).toEqual("42");
expect(cellElements[2].textContent).toEqual("£42");
});
Testing User Supplied Components
To test user supplied components you can access them via the grid API.
For example, given the following code:
@Component({
standalone: true,
template: `£{{params?.value}}`,
})
export class PoundRenderer implements ICellRendererAngularComp {
params: ICellRendererParams | undefined;
agInit(params: ICellRendererParams): void {
this.params = params;
}
refresh(params: ICellRendererParams) {
this.params = params;
return true;
}
}
@Component({
selector: 'editor-cell',
template: `<input #input [(ngModel)]="value" style="width: 100%">`
}
)
export class EditorComponent implements ICellEditorAngularComp {
private params: ICellEditorParams;
public value: number;
@ViewChild('input', {read: ViewContainerRef}) public input;
agInit(params: ICellEditorParams): void {
this.params = params;
this.value = this.params.value;
}
getValue(): any {
return this.value;
}
// for testing
setValue(newValue: any) {
this.value = newValue;
}
isCancelBeforeStart(): boolean {
return false;
}
isCancelAfterEnd(): boolean {
return false;
};
}
@Component({
template:
`<div>
<ag-grid-angular
style="width: 100%; height: 350px;"
[columnDefs]="columnDefs"
[rowData]="rowData"
[stopEditingWhenCellsLoseFocus]="false"
(gridReady)="onGridReady($event)" />
</div>`
})
class TestHostComponent {
rowData: any[] = [{name: 'Test Name', number: 42}];
columnDefs: ColDef[] = [
{field: "name"},
{field: "number", colId: "raw", headerName: "Raw Number", editable: true, cellEditor: EditorComponent},
{field: "number", colId: "renderer", headerName: "Renderer Value", cellRenderer: PoundRenderer}
];
api: GridApi;
public onGridReady(params: GridReadyEvent) {
this.api = params.api;
}
}
We can test that the EditorComponent
works as follows:
it('cell should be editable and editor component usable', async () => {
// Setup template bindings and run ngOInit. This causes the <ag-grid-angular> component to be created.
// As part of the creation the grid apis will be attached to the gridOptions property.
fixture.autoDetectChanges();
await fixture.whenStable();
// we use the API to start and stop editing - in a real e2e test we could actually double click on the cell etc
component.api.startEditingCell({
rowIndex: 0,
colKey: 'raw'
});
const instances = component.api.getCellEditorInstances();
expect(instances.length).toEqual(1);
const editorComponent = instances[0];
editorComponent.setValue(100);
component.api.stopEditing();
await fixture.whenStable();
const cellElements = fixture.nativeElement.querySelectorAll('.ag-cell-value');
expect(cellElements.length).toEqual(3);
expect(cellElements[0].textContent).toEqual("Test Name");
expect(cellElements[1].textContent).toEqual("100");
expect(cellElements[2].textContent).toEqual("£100");
});
Testing with Angular Testing Library
It is also possible to use Angular Testing Library to test AG Grid. Here is one example showing how to test a row click handler that displays the last clicked row above the grid.
<div data-testid="rowClicked">Row Clicked: {{ rowClicked?.make }}</div>
<ag-grid-angular [columnDefs]="columnDefs" [rowData]="rowData" (onRowClicked)="onRowClicked($event)" />
import { render, screen } from '@testing-library/angular';
import userEvent from '@testing-library/user-event';
it('Test cell clicked run row handler', async () => {
render(GridWrapperComponent);
const row = await screen.findByText('Ford');
await userEvent.click(row);
const rowClicked = await screen.findByTestId('rowClicked');
expect(rowClicked.textContent).toBe('Row Clicked: Ford');
});
All the tests above and more can be found in the following GitHub Repo.
End to End (e2e) Testing with Playwright
Playwright is another popular e2e testing framework that can be used to test AG Grid applications. A few examples of how to use Playwright with AG Grid can be found in this Github Repo.
Next Up
Continue to the next section to learn about Testing Async.