Angular - Как я могу протестировать компонент контейнера с дочерним компонентом пользовательского ввода? - PullRequest
0 голосов
/ 14 января 2019

Задача

У меня есть компонент контейнера, который использует пользовательский компонент ввода. Он отлично работает при обслуживании или после сборки, но не работает на тестах.

Это ошибка, которую я получаю: Error: No value accessor for form control with name: 'name'


Вот упрощенная версия моих файлов:

Template

<app-modal>
  <form [formGroup]="myForm" novalidate>
    <app-input formControlName="name"></app-input>
  </form>
</app-modal>

Test

@Component({ selector: 'app-input', template: '' })
class InputStubComponent {}

beforeEach(async(() => {
  TestBed.configureTestingModule({
    schemas: [ NO_ERRORS_SCHEMA ],
    declarations: [
      InputStubComponent
    ],
    imports: [
      ReactiveFormsModule,
    ]
  })
  .compileComponents();
}));

Я также пытался: использовать CUSTOM_ELEMENTS_SCHEMA и не объявлять компонент.

1 Ответ

0 голосов
/ 14 января 2019

Есть два способа решения этой проблемы:

РЕКОМЕНДУЕТСЯ
1) Вы можете удалить ReactiveFormsModule из свойства imports и добавить FormBuilder к свойству providers. ReactiveFormsModule добавляет директивы formGroup и formControlName, которые выполняют проверки на уровне шаблона.

Вот как это будет выглядеть в вашем примере:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    schemas: [ NO_ERRORS_SCHEMA ],
    declarations: [
      InputStubComponent
    ],
    providers: [
      FormBuilder
    ]
  })
  .compileComponents();
}));

2) Если вы хотите протестировать свой дочерний компонент или оставить ReactiveFormsModule, вот функция, которая создает пустой компонент-заглушку со значением accessor:

const createAccessorComponent = (selector) => {
  @Component({
    selector: selector,
    template: '',
    providers: [
      {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => AccessorComponent),
        multi: true,
      },
    ],
  })
  class AccessorComponent implements ControlValueAccessor {
    writeValue(obj: any): void {}
    registerOnChange(fn: any): void {}
    registerOnTouched(fn: any): void {}
    setDisabledState(isDisabled: boolean): void {}
  }

  return AccessorComponent;
};

Вы можете использовать его следующим образом:

const InputStubComponent = createAccessorComponent('app-input');

beforeEach(async(() => {
  TestBed.configureTestingModule({
    schemas: [ NO_ERRORS_SCHEMA ],
    declarations: [
      InputStubComponent
    ],
    imports: [
      ReactiveFormsModule,
    ]
  })
  .compileComponents();
}));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...