Search code examples
angularjasminekarma-jasminesyncfusionangular-test

Angular test gives error - Failed: Cannot read property 'className' of undefined


Below is my spec.ts. It runs fine and all the test cases are a pass. Somehowout of 3 times 2 times the test fails with the error Failed: Cannot read property 'className' of undefined. I never used className anywhere in my file. But, I am using Syncfusion library for a dialog. I don't understand what is wrong. Once in a while, it gives me this error as well. Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL). I tried to use doneFn also increase interval. It still gives this error.

*sync.spec.ts

describe("SettingDialogComponent", () => {
  let component: SettingDialogComponent;
  let fixture: ComponentFixture < SettingDialogComponent > ;
  const elementId = "1234567890";
  const parentId = "0987654321";
  const relearnCommand = "Re-learning";
  let service: Service;
  const element = new Element(elementId, [new Data("limit", "2.00")], "", parentId, [], [], "");
  let heroDe: DebugElement;
  let heroEl: HTMLElement;

  beforeEach(
    waitForAsync(async() => {
      await TestBed.configureTestingModule({
          declarations: [DialogComponent, SettingDialogComponent],
          imports: [
            DialogModule,
            FormsModule,
            HttpClientModule,
            ReactiveFormsModule,
            TranslateModule,
            TranslateModule.forRoot({
              loader: {
                provide: TranslateLoader,
                useClass: TestTranslateLoader,
              },
            }),
          ],
          providers: [{
              provide: Service,
              useValue: {
                getElement: (): Observable < Element > => {
                  return of(element);
                },
                some: () => of (true),
                update: () => of (true),
                runCommand: () => of (true),
              },
            },
            HttpClient,
            TranslateService,
          ],
        })
        .compileComponents()
        .then(() => {
          fixture = TestBed.createComponent(SettingDialogComponent);
          component = fixture.componentInstance;
          component.elementId = elementId;
          service = fixture.debugElement.injector.get(AssetService);
          spyOn(service, "update").and.callThrough();
          spyOn(service, "getElement").withArgs(component.elementId).and.returnValue( of (element));
          spyOn(service, "runCommand").and.callThrough();
        });
    }),
  );

  it(
    "when show open modal",
    waitForAsync(async() => {
      fixture.detectChanges();
      await fixture.whenStable();

      component.show(); //opens syncfusion dialog
      fixture.detectChanges();

      const shownDialog = fixture.debugElement.queryAll(By.css(".e-popup-open"));
      expect(shownDialog).not.toBeNull();

      component.hide(); //hides syncfusion dialog
    }),
  );

});

Wherever I used fixture.debugElement.query(By.css("")); this error is shown. It says the value is null for the debugElement.

*My sync.ts file

@ViewChild("editor") public deviceEditor: DialogComponent;

public show(): void {
    this.thresholdSettings.reset();
    this.Service.getElement(this.elementId).subscribe((result) => {
      this.element = result;
      this.limit = getMetadataValue(this.element.data, "limit");
    });
    this.deviceEditor.show();
  }
<ejs-dialog #deviceEditor
            id="dialog"
            isModal="true"
            class="device-threshold-dialog">
</ejs-dialog>

Error stack trace:

TypeError: Cannot read property 'className' of undefined at removeClass (http://localhost:9877/karma_webpack/webpack:/node_modules/@syncfusion/ej2-base/dist/es6/ej2-base.es2015.js:5019:1) at DialogComponent.destroy (http://localhost:9877/karma_webpack/webpack:/node_modules/@syncfusion/ej2-popups/dist/es6/ej2-popups.es2015.js:3072:20) at http://localhost:9877/karma_webpack/webpack:/node_modules/@syncfusion/ej2-angular-base/src/component-base.js:149:1 at timer (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:2561:1) at ZoneDelegate.invokeTask (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:406:1) at AsyncTestZoneSpec.onInvokeTask (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:1180:1) at ProxyZoneSpec.onInvokeTask (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone-testing.js:315:1) at ZoneDelegate.invokeTask (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:405:1) at Zone.runTask (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:178:1) at invokeTask (http://localhost:9877/karma_webpack/webpack:/node_modules/zone.js/fesm2015/zone.js:487:1)


Solution

  • I used await fixture.whenRenderingDone() instead of await fixture.whenStable() on every test case including the component.toBeTruthy(); to solve this. Hope this might help.