'I am getting this error "TypeError: this.reCaptchaApi.render is not a function" when I try to access elements of reactive form for unit testing

I am trying to write unit test cases for registration component in my project, but when I try to access a input ele by ID to test it's placeholder which is in the same form with ngx-recaptcha2, I this error TypeError: this.reCaptchaApi.render is not a function

HTML

<ngx-recaptcha2
            #captchaElem
            [siteKey]="siteKey"
            (success)="handleSuccess($event)"
            [useGlobalDomain]="false"
            size="100"
            formControlName="recaptcha"
          >
          </ngx-recaptcha2>

SPEC.TS(unit testing file)

import { async, ComponentFixture, TestBed } from "@angular/core/testing";
    import { FormBuilder, FormsModule, ReactiveFormsModule } from "@angular/forms";
    import { SpinnerVisibilityService } from "ng-http-loader";
    import {
      HttpClientTestingModule,
      HttpTestingController,
    } from "@angular/common/http/testing";
    import { AuthService } from "src/app/shared/services/auth.service";
    import { CookieService } from "src/app/shared/services/cookie.service";
    import { SharedService } from "src/app/shared/services/shared.service";
    import { RouterTestingModule } from "@angular/router/testing";
    import { RegistrationComponent } from "./registration.component";
    import { NgxCaptchaModule } from "ngx-captcha";
    import { DebugElement } from "@angular/core";
    import { By } from "@angular/platform-browser";
    
    fdescribe("RegistrationComponent", () => {
      let component: RegistrationComponent;
      let fixture: ComponentFixture<RegistrationComponent>;
      let el: DebugElement;
      beforeEach(async(() => {
        TestBed.configureTestingModule({
          imports: [
            FormsModule,
            ReactiveFormsModule,
            RouterTestingModule,
            HttpClientTestingModule,
            NgxCaptchaModule,
          ],
          declarations: [RegistrationComponent],
          providers: [
            AuthService,
            SharedService,
            CookieService,
            SpinnerVisibilityService,
          ],
        }).compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(RegistrationComponent);
        component = fixture.componentInstance;
        el = fixture.debugElement;
        fixture.detectChanges();
      });
    
      it("should create", () => {
        expect(component).toBeTruthy();
      });
    
      it("checking card heading", () => {
        const title = el.queryAll(By.css("#card-heading"));
        expect(title).toBeTruthy();
        expect(title[0].nativeElement.textContent).toBe("Create a new account");
      });
    
      it("fisrt name", () => {
        const title = el.queryAll(By.css("#firstName"));
        expect(title).toBeTruthy();
        expect(title[0].nativeElement.placeholder).toBe("First Name");
      });
    
    });

TS(typescipt file)

ngOnInit(): void {
this.siteKey = "6Lc0E2caAAAAAOMswzmbCRbYEYtH_rtFFMlc9SDE";
this.formInIt();
this.getCountryCode();
this.Form.valueChanges.subscribe(
  (value) => {
    if (value) {
      this.errorMessage = null;
    }
  },
  (error: any) => {
    this.catchServerError(error, this.Form);
  }
);

this.country.valueChanges.subscribe((value) => {
  const selectedCountry = this.totalCountryCode.find(
    (obj) => obj.name === value
  );
  this.selectedCountryCode = selectedCountry.dial_code;
  if (selectedCountry.regEx) {
    this.Form.get("phone").clearValidators();
    this.Form.get("phone").setValue("");
    this.Form.get("phone").setValidators(
      Validators.compose([
        Validators.required,
        Validators.pattern(selectedCountry.regEx),
      ])
    );
    this.Form.get("phone").updateValueAndValidity();
  }
});
  

}

  
  

formInIt() {
    this.Form = this.fb.group({
      firstName: [
        "",
        [Validators.required, Validators.pattern(AppSettings.FIRST_NAME)],
      ],
      lastName: [
        "",
        [Validators.required, Validators.pattern(AppSettings.LAST_NAME)],
      ],
      email: ["", [Validators.required, Validators.pattern(AppSettings.EMAIL)]],
      country: ["India", Validators.required],
      phone: [
        "",
        [Validators.required, Validators.pattern(AppSettings.PHONE_NUMBER)],
      ],
      websiteUrl: ["", [Validators.pattern(AppSettings.WEBSITE_URL)]],
      password: [
        "",
        [Validators.required, Validators.pattern(AppSettings.PASSWORD)],
      ],
      confirmPassword: ["", Validators.required],
      role: ["", Validators.required],
      recaptcha: ["",Validators.required],
      instructionsDeclarationAccepted: ["", Validators.required],
    });

    this.confirmPassword.valueChanges.subscribe(
      (value) => {
        if (this.password.value !== this.confirmPassword.value) {
          this.confirmPassword.setErrors({ MatchPassword: true });
        } else {
          return null;
        }
      },
      (error: any) => {
        this.catchServerError(error, this.Form);
      }
    );

    this.password.valueChanges.subscribe(
      (value) => {
        if (this.password.value !== this.confirmPassword.value) {
          this.confirmPassword.setErrors({ MatchPassword: true });
        } else {
          this.confirmPassword.setErrors({ MatchPassword: false });
          this.confirmPassword.updateValueAndValidity();
        }
        
      },
      (error: any) => {
        this.catchServerError(error, this.Form);
      }
    );
  }

Can anyone please help me out, how to approach this problem, should I mock it or is there any other way, please guide me.



Solution 1:[1]

I have tried with one solution. You need to apply some delay for the fixture detect changes. you can apply below solution in spec file. If you're using lodash then you can use

_.delay(() => {
      fixture.detectChanges();
    }, 2000);

above line should add in the beforeEach fixture detectChanges and if you're not using lodash then you should try

 setTimeout(() => {
           fixture.detectChanges();
}, 2000);

I hope this will help you to solve you're problem. Thank you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Harshad Jagdishbhai Ladva