Angular 2ユニットテスト内から入力フィールドの値を変更したいと思います。
<input type="text" class="form-control" [(ngModel)]="abc.value" />
ngModel
オブジェクトはプライベートなので、abc
を変更することはできません。
private abc: Abc = new Abc();
Angular 2テストで、ユーザーが入力フィールドに入力するのをシミュレートして、ユニットテスト内でユーザーが入力した内容でngModel
が更新されるようにできますか?
入力フィールドのDebugElement
とnativeElement
を問題なく取得できます。 (入力フィールドのvalue
にnativeElement
プロパティを設定するだけでは、ngModel
を設定した内容で更新しないため、機能していないようです。値)。
多分 inputDebugEl.triggerEventHandler
を呼び出すことはできますが、特定の入力文字列を入力したユーザーをシミュレートするために、どの引数を指定するかわかりません。
入力を設定するだけでなく、_'input'
_イベントもディスパッチする必要があることは正しいです。テキストを入力するために今晩早く書いた関数は次のとおりです。
_function sendInput(text: string) {
inputElement.value = text;
inputElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
return fixture.whenStable();
}
_
ここで、fixture
はComponentFixture
であり、inputElement
はフィクスチャのHTTPInputElement
からの関連nativeElement
です。これは約束を返すので、おそらくsendInput('whatever').then(...)
を解決する必要があります。
更新:
これを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();
}
_
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" />
また、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...
});
}));