20190218のAngularJSに関する記事は1件です。

[Angular] テキストエリアとボタンを使ったコンポーネントのテストを書く

環境

  • Angular CLI: 7.3.1

たぶん他のバージョンでも動く

準備

事前準備

テキストエリアやボタンを使うのにFormsModule必要です。

app.modules.ts
import { FormsModule } from '@angular/forms';
// ...
  imports: [
    FormsModule,
// ...
app.component.spec.ts
  beforeEach(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.ts
import { 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.ts
  beforeEach(async(() => {
    TestBed.configureTestingModule({
// ...
      providers: [
        { provide: ComponentFixtureAutoDetect, useValue: true }
// ...

CompoentFixtureAutoDetectはある程度コンポーネント変更検知を自動検知してくれる。
何度もdetectChanges()書かなくて済む
まぁ、DOMイベントは自動検知してくれないけど(以下のサンプルでは必須)。

本題

inputイベントが発行されたことをテストする

app.compoent.spec.ts
it('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.ts
it('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.ts
it('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('なんか書いた');
});

参考記事

間違いなどありましたら気兼ねなくご指摘ください

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む