All files / src/app/extensions/captcha/exports/lazy-captcha lazy-captcha.component.ts

57.5% Statements 23/40
60% Branches 9/15
70% Functions 7/10
56.41% Lines 22/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 1281x                         1x 1x 1x   1x   1x                                     1x                         4x   4x   4x     4x       1x       1x                                                                             4x 1x   3x 1x   2x 1x   1x           3x       2x      
import {
  AfterViewInit,
  ChangeDetectionStrategy,
  Component,
  DestroyRef,
  Injector,
  Input,
  OnInit,
  ViewChild,
  ViewContainerRef,
  createNgModule,
  inject,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { AbstractControl, FormArray, FormGroup, Validators } from '@angular/forms';
import { switchMap, take } from 'rxjs/operators';
 
import { whenTruthy } from 'ish-core/utils/operators';
 
import { CaptchaFacade, CaptchaTopic } from '../../facades/captcha.facade';
 
/**
 * The Captcha Component
 *
 * Displays a captcha form control (V2) or widget (V3) if the captchaV2 or the captchaV3 feature is enabled.
 * It expects the given form to have the form controls for the captcha (controlName) and the captcha action (actionControlName).
 * If the captcha is confirmed the captcha form control contains the captcha response token provided by the captcha service.
 *
 * The parent form supplied must have controls for 'captcha' and 'captchaAction'
 *
 * @example
 * <ish-lazy-captcha [form]="form" cssClass="offset-md-2 col-md-8" topic="contactUs"></ish-lazy-captcha>
 */
@Component({
  selector: 'ish-lazy-captcha',
  templateUrl: './lazy-captcha.component.html',
  changeDetection: ChangeDetectionStrategy.Default,
})
export class LazyCaptchaComponent implements OnInit, AfterViewInit {
  @ViewChild('anchor', { read: ViewContainerRef, static: true }) anchor: ViewContainerRef;
 
  /**
    form containing the captcha form controls
   */
  @Input({ required: true }) form: FormGroup | FormArray;
 
  @Input({ required: true }) topic: CaptchaTopic;
 
  /**
    css Class for rendering the captcha V2 control, default='offset-md-4 col-md-8'
   */
  @Input() cssClass = 'offset-md-4 col-md-8';
 
  private destroyRef = inject(DestroyRef);
 
  constructor(private captchaFacade: CaptchaFacade, private injector: Injector) {}
 
  ngOnInit() {
    this.sanityCheck();
  }
 
  ngAfterViewInit() {
    this.captchaFacade
      .captchaActive$(this.topic)
      .pipe(
        whenTruthy(),
        switchMap(() => this.captchaFacade.captchaVersion$),
        whenTruthy(),
        take(1),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(async version => {
        if (version === 3) {
          this.actionFormControl.setValue(this.topic);
 
          // eslint-disable-next-line @typescript-eslint/naming-convention
          const { CaptchaV3Component, CaptchaV3ComponentModule } = await import(
            '../../shared/captcha-v3/captcha-v3.component'
          );
 
          const moduleRef = createNgModule(CaptchaV3ComponentModule, this.injector);
          const componentRef = this.anchor.createComponent(CaptchaV3Component, { ngModuleRef: moduleRef });
 
          componentRef.instance.parentForm = this.form as FormGroup;
          componentRef.changeDetectorRef.markForCheck();
        } else Iif (version === 2) {
          this.formControl.setValidators([Validators.required]);
          this.formControl.updateValueAndValidity();
 
          // eslint-disable-next-line @typescript-eslint/naming-convention
          const { CaptchaV2Component, CaptchaV2ComponentModule } = await import(
            '../../shared/captcha-v2/captcha-v2.component'
          );
 
          const moduleRef = createNgModule(CaptchaV2ComponentModule, this.injector);
          const componentRef = this.anchor.createComponent(CaptchaV2Component, { ngModuleRef: moduleRef });
 
          componentRef.instance.cssClass = this.cssClass;
          componentRef.instance.parentForm = this.form as FormGroup;
          componentRef.changeDetectorRef.markForCheck();
        }
      });
  }
 
  private sanityCheck() {
    if (!this.form) {
      throw new Error('required input parameter <form> is missing for LazyCaptchaComponent');
    }
    if (!this.formControl) {
      throw new Error(`form control 'captcha' does not exist in the given form for LazyCaptchaComponent`);
    }
    if (!this.actionFormControl) {
      throw new Error(`form control 'captchaAction' does not exist in the given form for LazyCaptchaComponent`);
    }
    Iif (!this.topic) {
      throw new Error(`required input parameter <topic> is missing for LazyCaptchaComponent`);
    }
  }
 
  private get formControl(): AbstractControl {
    return this.form?.get('captcha');
  }
 
  private get actionFormControl(): AbstractControl {
    return this.form?.get('captchaAction');
  }
}