как синхронизировать состояние компонента с html-вводом перед утверждением? - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь проверить взаимодействие между внутренними компонентами и его HTML.

В следующем тестовом коде у меня есть компонент приложения с полем ввода, который связан с атрибутом внутри компонентаиспользуя двустороннее связывание.

Тест1 проходит с использованием fixture.detectChanges и ожидает его стабильности.Таким образом, в этом тесте тестовый атрибут компонентов синхронизируется с полем ввода.

Однако test2 не выполняется из-за того, что компонент не был обновлен с новым значением атрибута теста.Итак, что я упускаю или делаю неправильно, чтобы синхронизировать изменения перед вводом в утверждение?

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  test = 'hello';
}

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import {BrowserModule, By} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {ComponentFixture} from '../../node_modules/@angular/core/testing';
import {detectChanges} from '../../node_modules/@angular/core/src/render3';
describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        FormsModule
      ],
      declarations: [
        AppComponent,
      ],
    }).compileComponents();
      fixture = TestBed.createComponent(AppComponent);
      component = fixture.componentInstance;
    });
  it('test1', () => {
    const inputElement = fixture.debugElement.query(By.css('input'));
    const el = inputElement.nativeElement;
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(el.value).toBe('hello');
    })

  });
  it('test2', () => {
    const inputElement = fixture.debugElement.query(By.css('input'));
    const el = inputElement.nativeElement;
    el.value = 'test';
    expect(el.value).toBe('test');
    el.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(component.test).toBe('test');
    })
  });
});
<div>
  <input [(ngModel)]="test" type="text">
  <p>{{test}}</p>
</div>

Я взял ответ ниже и посмотрел на минимальное из ответа, чтобы сдать мой тест.Похоже, что ключом было переместить fixture.detectChanges () в функцию beforeEach ().

Я считаю, что это был минимум, который мне нужно было включить для прохождения теста, в дополнение к добавлению fixture.detectChanges в beforeEach.Кажется, что готово и fixture.whenStable не является необходимым.

it('test2', () => {
   const inputElement = fixture.debugElement.query(By.css('input'));
   const el = inputElement.nativeElement;
   el.value = 'test';
   el.dispatchEvent(new Event('input'));
   expect(component.test).toBe('test');
});

Ответы [ 2 ]

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

Я думаю, что проблема с вашим тестом заключается в том, что вы никогда не звоните fixture.detectChanges() после того, как настроите fixture и component в своем beforeEach.

Check это stackblitz для рабочей версии вашего теста.

Я добавил вторую beforeEach, где вызывается fixture.detectChanges:

beforeEach(() => {
  fixture = TestBed.createComponent(AppComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

И вот неудачный(сейчас работает) тест:

it('test2', (done) => {
  const inputElement = fixture.nativeElement.querySelector('input');
  inputElement.value = 'test';

  const inputEvent = document.createEvent('Event');
  inputEvent.initEvent('input', true, true);
  inputElement.dispatchEvent(inputEvent);

  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(component.test).toBe('test');
    done();
  });
});
0 голосов
/ 20 января 2019

Во втором тесте вы должны добавить это:

el.dispatchEvent(new Event('input'));

перед выполнением ожидания, а не после

, а затем вы также должны добавить

fixture.detectChanges(); перед выполнением ожидания

, поэтому напишите свой второй тест следующим образом:

it('test2', async(() => {
    const inputElement = fixture.debugElement.query(By.css('input')).nativeElement;
    inputElement.value = 'test';
    inputElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(component.test).toBe('test');
    })
}));

Вы должны добавить async к функции it потому что ngModel является асинхронным.

В качестве альтернативы вы также можете использовать fakeAsync

...