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

97.56% Statements 40/41
80% Branches 12/15
100% Functions 10/10
97.43% Lines 38/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                         6x   6x   6x     6x       3x       3x           3x 2x     4x       2x 2x   2x 2x 1x 1x 1x     2x       1x 1x   1x 1x 1x           6x 1x   5x 1x   4x 1x   3x           7x       6x      
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 = '';
 
  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 if (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');
  }
}