Results:
Loading...

Angular Data GridTesting AG Grid

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

The first thing we need to do is to add AG Grid's AgGridModule to the TestBed.configureTestingModule:

beforeEach(async(() => {
     TestBed.configureTestingModule({
         imports: [
             FormsModule,
             AgGridModule
         ],
         declarations: [TestHostComponent]
     }).compileComponents();

     fixture = TestBed.createComponent(TestHostComponent);
     component = fixture.componentInstance;

 }));

Now that the test bed is aware of AG Grid we can continue with our testing. If however you wish to add any user provided components to the grid then you'll need to declare them here too.

beforeEach(async(() => {
     TestBed.configureTestingModule({
         imports: [
             FormsModule,
 +            AgGridModule
         ],
 +        declarations: [TestHostComponent, RendererComponent, EditorComponent]
     }).compileComponents();

     fixture = TestBed.createComponent(TestHostComponent);
     component = fixture.componentInstance;
 }));

Testing via the Grid API

The grid's API will only be ready after detectChanges has been run:

it('grid API is not available until  `detectChanges`', () => {
     expect(component.gridOptions.api).not.toBeTruthy();
 });

 it('grid API is available after `detectChanges`', () => {
     // 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.detectChanges();
     expect(component.gridOptions.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', () => {

     // 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.detectChanges();

     const appElement = fixture.nativeElement;
     const cellElements = appElement.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("84");
 });

Testing User Supplied Components

To test user supplied components you can access them via the grid API.

For example, given the following code:

@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;" class="ag-theme-alpine"
                 [columnDefs]="columnDefs"
                 [rowData]="rowData"
                 [stopEditingWhenCellsLoseFocus]="false"
                 [components]="components"
                 (gridReady)="onGridReady($event)">
             </ag-grid-angular>
         </div>`
 })
 class TestHostComponent {
     rowData: any[] = [{name: 'Test Name', number: 42}];

     columnDefs: ColDef[] = [
         {field: "name"},
         {field: "number", colId: "raw", headerName: "Raw Number", editable: true, cellEditor: 'editor'},
         {field: "number", colId: "renderer", headerName: "Renderer Value"}
     ];

     components = {
         'editor': EditorComponent
     };

     api: GridApi;
     columnApi: ColumnApi;

     public onGridReady(params: GridReadyEvent) {
         this.api = params.api;
         this.columnApi = params.columnApi;
     }
 }

We can test that the EditorComponent works as follows:

it('cell should be editable and editor component usable', () => {
     // 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.detectChanges();

     // 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();

     const appElement = fixture.nativeElement;
     const cellElements = appElement.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("200");
 });

Applying Styles To The Grid When Testing

Although not strictly necessary when unit testing the grid, it is still useful to see the grid rendered when debugging. In order for this to work you need to provide the CSS to karma.conf.js:

// not strictly required for testing but useful when debugging the grid in action
 files: [
     '../node_modules/ag-grid-community/styles/ag-grid.css',
     '../node_modules/ag-grid-community/styles/ag-theme-alpine.css'
 ]

Next Up

Continue to the next section to learn about Testing with FakeAsync parts of the grid.