- 投稿日:2019-02-18T23:54:02+09:00
[Angular] テキストエリアとボタンを使ったコンポーネントのテストを書く
環境
- Angular CLI: 7.3.1
たぶん他のバージョンでも動く
準備
事前準備
テキストエリアやボタンを使うのにFormsModule必要です。
app.modules.tsimport { FormsModule } from '@angular/forms'; // ... imports: [ FormsModule, // ...app.component.spec.tsbeforeEach(async(() => { TestBed.configureTestingModule({ // ... imports: [ FormsModule // ...HTMLとTypeScriptの準備
app.component.html<div id="message">{{message}}</div> <textarea [(ngModel)]="input"></textarea> <button (click)="postMessage(input)">書く</button>app.component.tsimport { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { message = ''; input = ''; postMessage(message: string) { this.message = message; this.input = ''; } }あると便利なもの
app.component.spec.tsbeforeEach(async(() => { TestBed.configureTestingModule({ // ... providers: [ { provide: ComponentFixtureAutoDetect, useValue: true } // ...CompoentFixtureAutoDetectはある程度コンポーネント変更検知を自動検知してくれる。
何度もdetectChanges()書かなくて済む
まぁ、DOMイベントは自動検知してくれないけど(以下のサンプルでは必須)。本題
inputイベントが発行されたことをテストする
app.compoent.spec.tsit('should input to textarea', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; const htmlElement: HTMLElement = fixture.debugElement.nativeElement; const textarea = htmlElement.querySelector('textarea'); textarea.value = 'なんか書いた'; // 注目 textarea.dispatchEvent(new Event('input')); // 注目 fixture.detectChanges(); // 注目 expect(app.message).toBe('なんか書いた'); });ちなみにquerySelectorに渡す文字列はCSSのセレクターの指定の仕方と同じ
ボタンをクリックをテストする
app.component.spec.tsit('should post message by clicking button', () => { const fixture = TestBed.createComponent(AppComponent); const htmlElement: HTMLElement = fixture.debugElement.nativeElement; const textarea = htmlElement.querySelector('textarea'); const button = htmlElement.querySelector('button'); const message = htmlElement.querySelector('div#message'); textarea.value = 'なんか書いた'; textarea.dispatchEvent(new Event('input')); button.dispatchEvent(new Event('click')); // 注目 fixture.detectChanges(); expect(message.htmlContent).toBe('なんか書いた'); });エンターキーで投稿できるようにする
keydown.enterのコールバックを指定する
app.component.html<div id="message">{{message}}</div> <textarea [(ngModel)]="input" (keydown.enter)="postMessage(input)"></textarea> <button (click)="postMessage(input)">書く</button>KeyboardEventを発行してテストする
app.component.spec.tsit('should post message by pressing enter key', () => { const fixture = TestBed.createComponent(AppComponent); const htmlElement: HTMLElement = fixture.debugElement.nativeElement; const textarea = htmlElement.querySelector('textarea'); const message = htmlElement.querySelector('div#message'); textarea.value = 'なんか書いた'; textarea.dispatchEvent(new Event('input')); textarea.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter'})); // 注目 fixture.detectChanges(); expect(message.htmlContent).toBe('なんか書いた'); });参考記事
- Angular 日本語ドキュメンテーション - テスト
- HTMLElement - MDN - Mozilla
- HTMLTextAreaElement - MDN - Mozilla
- HTMLButtonElement - MDN - Mozilla
- KeyboardEvent - MDN - Mozilla
- JavaScriptでキーボードの入力値を別の値しようとしたらめちゃめちゃ苦しんだ話
間違いなどありましたら気兼ねなくご指摘ください