4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-02-18

環境

  • 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('なんか書いた');
});

参考記事

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

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?