Search code examples
angularunit-testingtestingag-grid-angular

How to test AgRendererComponent component in Angular Ag Grid


I have a custom cell renderer component which wil convert the text to link. Its all working fine. I am trying to unit test the renderer component. The issue am facing in unit testing is Grid is displaying with link but its not available when I query through native element, I am getting the value as empty other grid values are already present I am able to see it. I think this is to do with the lifecycle of testing or AG Grid rendering. How do I tell the test framework to wait untill the component is rendered?

link renderer component

@Component({
    template: '<a [routerLink]="[params.inRouterLink,params.value]"  (click)="navigate(params.inRouterLink)">{{params.value}}</a>'
})
export class RouterLinkRendererComponent implements AgRendererComponent {
    params: any;

    constructor(
        private ngZone: NgZone,
        private router: Router) { }

    agInit(params: any): void {
        this.params = params;
    }

    refresh(params: any): boolean {
        return false;
    }
}

Test Component:

@Component({
  template: `
    <ag-grid-angular
      style="width: 500px; height: 500px;"
      class="custom-theme"
      [rowData]="rowData"
      [columnDefs]="columnDefs"
      (gridReady)="onGridReady($event)"
    >
    </ag-grid-angular>
  `
})
export class TestCustomComponent {
  columnDefs = [
    {
      headerName: 'Make',
      field: 'make',
      cellRendererFramework: RouterLinkRendererComponent,
      cellRendererParams: {
        inRouterLink: '/#'
      }
    },
    { headerName: 'Model', field: 'model' },
    { headerName: 'Price', field: 'price' }
  ];

  rowData = [
    { make: 'Toyota', model: 'Celica', price: 35000 },
    { make: 'Ford', model: 'Mondeo', price: 32000 },
    { make: 'Porsche', model: 'Boxter', price: 72000 }
  ];
}

Unit Testing

fdescribe('AgnavigatorComponent', () => {
  let component: TestCustomComponent;
  let fixture: ComponentFixture<TestCustomComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [RouterLinkRendererComponent, TestCustomComponent],
      imports: [
        RouterTestingModule,
        AgGridModule.withComponents([RouterLinkRendererComponent])
      ]
    }).compileComponents();
  }));

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

  it('should create', () => {
    const appElement = fixture.nativeElement;
    // here the values are empty only for the first column which uses custom renderer.
    const cellElements = appElement.querySelectorAll('.ag-cell-value');
  });
});

once the test execution completes I can see the column with proper value with href in it.


Solution

  • The issue is at the time of execution the component isnt loaded yet. so have to introduce a wait function as mentioned in SO.post that I have to wait untill this guy comes in.

    export const waitUntil = async (
      untilTruthy: () => boolean
    ): Promise<boolean> => {
      while (!untilTruthy()) {
        await interval(25)
          .pipe(take(1))
          .toPromise();
      }
      return Promise.resolve(true);
    };
    

    and the test is like below

      it('should render the component', async done => {
        let appElement: any;
        let cellElement: any;
        fixture.detectChanges();
        await fixture.whenStable();
        await waitUntil(() => {
          appElement = fixture.nativeElement;
          cellElement = appElement.querySelectorAll('.ag-cell-value');
          if (cellElement[0].textContent !== '') {
            return true;
          }
          return false;
        });
        expect(cellElement[0].children[0].children[0].href.split('/')[3]).toEqual(
          'Toyota'
        );
        done();
      });