Не удалось прочитать свойство 'get' для нулевого тестирования компонента Реактивная форма с angular - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь создать модульный тест для моего input компонента, который обернут внутри Reactive FormBuilder

Это мой компонент

import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { RequiredInput } from 'src/app/core/decorators/required-input.decorator';
import { ControlContainer, FormGroupDirective, FormGroup } from '@angular/forms';

@Component({
  selector: 'es-input',
  templateUrl: './input.component.html',
  styleUrls: ['./input.component.scss'],
  viewProviders: [
    {
      provide: ControlContainer,
      useExisting: FormGroupDirective,
    },
  ],
})
export class InputComponent implements OnChanges {
  @Input()
  @RequiredInput
  esId: string;

  @Input()
  esType = 'text';

  @Input()
  esPlaceholder = '';

  @Input()
  esIsAutocompleteOn: boolean;

  @Input()
  esDisabled: boolean;

  @Input()
  esReadOnly: boolean;

  @Output()
  esOnInputChange: EventEmitter<string | number> = new EventEmitter();

  @Input()
  esPrepend: string;

  @Input()
  esAppend: string;

  @Input()
  esNoIcon: boolean;

  @Input()
  esHelp: string;

  @Input()
  esMaxLength: number;

  @Input()
  @RequiredInput
  esControlName: string;

  @Input()
  @RequiredInput
  esParentForm: FormGroup;

  constructor() {}

  ngOnChanges(changes: SimpleChanges): void {
    if (changes && changes.esDisabled) {
      if (changes.esDisabled.currentValue) {
        this.esParentForm.get(this.esControlName).disable();
      } else {
        this.esParentForm.get(this.esControlName).enable();
      }
    }
  }

  onInputChange(value: string | number): void {
    this.esOnInputChange.emit(value);
  }

  get required(): boolean {
    return (
      this.esParentForm.get(this.esControlName).hasError('required') &&
      this.esParentForm.get(this.esControlName).touched
    );
  }

  get invalid(): boolean {
    return (
      !this.required &&
      this.esParentForm.get(this.esControlName).errors &&
      this.esParentForm.get(this.esControlName).dirty
    );
  }

  get invalidLength(): boolean {
    return (
      this.esParentForm.get(this.esControlName).hasError('minlength') ||
      this.esParentForm.get(this.esControlName).hasError('maxlength')
    );
  }

  get inputLength(): string {
    return this.esParentForm.get(this.esControlName).value.length;
  }
}

Мой шаблон это

<input
      class="element"
      [type]="esType"
      [ngClass]="{
        'no-icon': esNoIcon,
        invalid: required || invalid
      }"
      [placeholder]="esPlaceholder"
      [id]="esId"
      [autocomplete]="esIsAutocompleteOn ? 'on' : 'off'"
      (input)="onInputChange($event.target.value)"
      [readonly]="esReadOnly"
      [formControlName]="esControlName"
    />

Это мой spec файл

import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';

import { InputComponent } from './input.component';
import { FormsModule, ReactiveFormsModule, FormGroupDirective, FormBuilder } from '@angular/forms';

describe('InputComponent', () => {
  let component: InputComponent;
  let fixture: ComponentFixture<InputComponent>;
  const formBuilder: FormBuilder = new FormBuilder();

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [FormsModule, ReactiveFormsModule],
      declarations: [InputComponent],
      providers: [
        FormGroupDirective,
        {
          provide: FormBuilder,
          useValue: formBuilder,
        },
      ],
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(InputComponent);
    component = fixture.componentInstance;
    component.esParentForm = formBuilder.group({
      basic: [''],
    });
    component.esControlName = 'basic';
    component.esId = 'basic-input';
    fixture.detectChanges();
  });

  it('should create 4', () => {
    expect(component).toBeTruthy();
  });
});

Даже я уже создал formBuilder.group до fixture.detectChanges();

Но я все еще получил TypeError: Cannot read property 'get' of null enter image description here

Как я могу это исправить или что я пропустил в моем файле spe c?

Спасибо!

1 Ответ

0 голосов
/ 10 февраля 2020

У меня такое ощущение, что где-то вы делаете this.esParentForm.get, this.esParentForm - это null либо в вашем ngOnChanges, либо во всех геттерах (get).

Я тоже чувствую, что на ngClass есть класс, который применяется, если эти методы получения истинны (required || invalid), но они относятся к this.esParentForm, поэтому класс нельзя применять, если форма еще не существует.

Попробуйте добавить *ngIf к элементу ввода, который будет нарисован только один раз esParentForm верно:

  <input
      *ngIf="esParentForm" // <=== This line
      class="element"
      [type]="esType"
      [ngClass]="{
        'no-icon': esNoIcon,
        invalid: required || invalid
      }"
      [placeholder]="esPlaceholder"
      [id]="esId"
      [autocomplete]="esIsAutocompleteOn ? 'on' : 'off'"
      (input)="onInputChange($event.target.value)"
      [readonly]="esReadOnly"
      [formControlName]="esControlName"
    />
...