Тестирование представленных данных от Angular Реактивная форма - PullRequest
0 голосов
/ 17 апреля 2020

На основе самого первого примера в https://angular.io/guide/reactive-forms я создаю следующий немой компонент:

@Component({
  selector: 'app-name-editor',
  templateUrl: './name-editor.component.html',
  styleUrls: ['./name-editor.component.css']
})
export class NameEditorComponent {

  name = new FormControl('');

  @Output('submitted') submitted = new EventEmitter<string>();

  onSubmit() { this.submitted.emit(this.name.value); }
}

... для которого я хотел бы написать модульный тест, который подтвердит, что значение передано. При этом используется TestHost, как предложено в https://angular.io/guide/testing#component -inside-a-test-host :

@Component({
  template: `
     <app-name-editor (submitted)=onSubmit($event)>
     </app-name-editor>
   `})
class TestHostComponent {
  submitted: string;
  onSubmit(data: string) { this.submitted = data; }
}

describe('NameEditorComponent', () => {
  let testHost: TestHostComponent;
  let fixture: ComponentFixture<TestHostComponent>;
  let editorDebugElt: DebugElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ NameEditorComponent, TestHostComponent ]
    });
    fixture = TestBed.createComponent(TestHostComponent);
    testHost = fixture.componentInstance;
    editorDebugElt = fixture.debugElement.query(By.directive(NameEditorComponent));
    fixture.detectChanges();
  });

  it('should capture data', () => {
    const compiled = fixture.debugElement.nativeElement;
    const nameInput = compiled.querySelector('input[type="text"]');
    expect(nameInput).toBeTruthy();
    nameInput.value = 'This is a test';
    fixture.detectChanges();

    // Find submit button
    const submitInput = compiled.querySelector('input[type="submit"]');
    expect(submitInput).toBeTruthy();

    // Trigger click action
    expect(testHost.submitted).toBeFalsy();
    submitInput.click();

    // Submitted
    expect(testHost.submitted).toBe('This is a test');    
  });
});

Тест не пройден, но я не понимаю, почему. Вход заполняется значением, как показано ниже результата теста. Любая помощь будет принята с благодарностью.

test fails but input is populated

Ответы [ 2 ]

1 голос
/ 18 апреля 2020

Вместо проверки, представленной с «Это тест». Вы можете следить за методом emit в testHost.submitted и проверять, вызывается ли он со значением элемента управления формы.

it('should capture data', () => {
  const compiled = fixture.debugElement.nativeElement;
  spyOn(testHost.submitted, 'emit')
  testHost.name.value('This is a test')
  const submitInput = compiled.querySelector('input[type="submit"]');
  submitInput.click();
  expect(testHost.submitted.emit).toHaveBeenCalled();
  expect(testHost.submitted.emit).toHaveBeenCalledWith(testHost.name.value)
});
0 голосов
/ 19 апреля 2020

Причина, по которой форма отправляет пустое значение, заключается в том, что реактивные формы являются асинхронными.

При редактировании формы и отправке сразу после этого отправляется пустая форма, поскольку редактирование происходит асинхронно. Теперь тест проходит, добавляя время ожидания 500 мс, но было бы неплохо узнать, как избежать ожидания:

    // Wait for asynchronous update on reactive form to happen
    setTimeout(() => {

      // Trigger click action
      expect(testHost.submitted).toBeFalsy();
      submitInput.click();

      // Submitted
      expect(testHost.submitted).toBe('This is a test');

    }, 500);
...