web-dev-qa-db-ja.com

Angular 2テスト内からの入力htmlフィールドの更新

Angular 2ユニットテスト内から入力フィールドの値を変更したいと思います。

<input type="text" class="form-control" [(ngModel)]="abc.value" />

ngModelオブジェクトはプライベートなので、abcを変更することはできません。

 private abc: Abc = new Abc();

Angular 2テストで、ユーザーが入力フィールドに入力するのをシミュレートして、ユニットテスト内でユーザーが入力した内容でngModelが更新されるようにできますか?

入力フィールドのDebugElementnativeElementを問題なく取得できます。 (入力フィールドのvaluenativeElementプロパティを設定するだけでは、ngModelを設定した内容で更新しないため、機能していないようです。値)。

多分 inputDebugEl.triggerEventHandlerを呼び出すことはできますが、特定の入力文字列を入力したユーザーをシミュレートするために、どの引数を指定するかわかりません。

30
Daniel

入力を設定するだけでなく、_'input'_イベントもディスパッチする必要があることは正しいです。テキストを入力するために今晩早く書いた関数は次のとおりです。

_function sendInput(text: string) {
  inputElement.value = text;
  inputElement.dispatchEvent(new Event('input'));
  fixture.detectChanges();
  return fixture.whenStable();
}
_

ここで、fixtureComponentFixtureであり、inputElementはフィクスチャのHTTPInputElementからの関連nativeElementです。これは約束を返すので、おそらくsendInput('whatever').then(...)を解決する必要があります。

コンテキスト: https://github.com/textbook/known-for-web/blob/52c8aec4c2699c2f146a33c07786e1e32891c8b6/src/app/actor/actor.component.spec.ts#L134


更新

これをAngular 2.1で動作させるためにいくつかの問題があり、new Event(...)を作成するのが好きではなかったので、代わりに行いました:

_import { dispatchEvent } from '@angular/platform-browser/testing/browser-util';

...

function sendInput(text: string) {
  inputElement.value = text;
  dispatchEvent(fixture.nativeElement, 'input');
  fixture.detectChanges();
  return fixture.whenStable();
}
_
44
jonrsharpe

Angular 2.4。で、受け入れられたソリューションはまったく機能しませんでした。detectChanges()が呼び出された後でも、設定した値が(テスト)UIに表示されませんでした。

動作させる方法は、次のようにテストを設定することでした。

_describe('TemplateComponent', function () {
  let comp: TemplateComponent;
  let fixture: ComponentFixture<TemplateComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ FormsModule ],
      declarations: [ TemplateComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TemplateComponent);
    comp = fixture.componentInstance;
  });

  it('should allow us to set a bound input field', fakeAsync(() => {
    setInputValue('#test2', 'Tommy');

    expect(comp.personName).toEqual('Tommy');
  }));

  // must be called from within fakeAsync due to use of tick()
  function setInputValue(selector: string, value: string) {
    fixture.detectChanges();
    tick();

    let input = fixture.debugElement.query(By.css(selector)).nativeElement;
    input.value = value;
    input.dispatchEvent(new Event('input'));
    tick();
  }
});
_

TemplateComponentコンポーネントには、この例ではpersonNameという名前のプロパティがあります。これは、テンプレートでバインドしているモデルプロパティです。

<input id="test2" type="text" [(ngModel)]="personName" />

13
Paul

また、Angular 2.4。で動作するようにjonrsharpeの回答を取得するのに問題がありました。fixture.detectChanges()およびfixture.whenStable()を呼び出すと、フォームコンポーネントがリセットされることがわかりました。テストの開始時にいくつかの初期化関数がまだ保留されていることを確認します。各テストの前にこれらのメソッドに追加の呼び出しを追加することでこれを解決しました。

beforeEach(() => {
    TestBed.configureTestingModule({
        // ...etc...
    });
    fixture = TestBed.createComponent(LoginComponent);
    comp = fixture.componentInstance;
    usernameBox = fixture.debugElement.query(By.css('input[name="username"]'));
    passwordBox = fixture.debugElement.query(By.css('input[type="password"]'));
    loginButton = fixture.debugElement.query(By.css('.btn-primary'));
    formElement = fixture.debugElement.query(By.css('form'));
});

beforeEach(async(() => {
    // The magic sauce!!
    // Because this is in an async wrapper it will automatically wait
    // for the call to whenStable() to complete
    fixture.detectChanges();
    fixture.whenStable();
}));

function sendInput(inputElement: any, text: string) {
    inputElement.value = text;
    inputElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    return fixture.whenStable();
}

it('should log in correctly', async(() => {

    sendInput(usernameBox.nativeElement, 'User1')
    .then(() => {
        return sendInput(passwordBox.nativeElement, 'Password1')
    }).then(() => {
        formElement.triggerEventHandler('submit', null);
        fixture.detectChanges();

        let spinner = fixture.debugElement.query(By.css('img'));
        expect(Helper.isHidden(spinner)).toBeFalsy('Spinner should be visible');

        // ...etc...
    });
}));
3
Philip Beber