React with Redux toDoList パート2
前回の記事の続きになります。また、以下の記事を参考に、進めていきます。
to doリストの画面を作っていきます
e2etest/test.js
const expect = require('chai').expect;describe('TodoList App', () => {
it('Should load with the right title', () => {
...
});
it('Should allow me to create a Todo', () => {
const todoText = 'Get better at testing';
browser.url('http://localhost:3000/');
browser.element('.todo-input').setValue(todoText);
browser.click('.todo-submit');
const actual = browser.element('.todo-text').getText();expect(actual).to.equal(todoText);
});
処理内容としては
- 指定したページに、browserがとびます
- .todo-inputの名前を持つ要素を探して、変数todoTextを入れます。
- .todo-submitをbrowserが押下
- .todo-text要素を探して、その値を定数acutualにいれます。
- 定数actualと変数todoTextを比較して、等しければtrueを返します。
ここで、 yarn run e2e-tests
を行い、failingすることを確認します。
では実際に上のエラーを出ないよう、コンポーネントを作成していきます。
まず、src/components/addTodo/配下にからファイルindex.jpをつくります
次に、テストを以下の用に書いていきます。
src/components/addTodo/test.js
/* global expect, it, describe */import React from 'react';
import { shallow } from 'enzyme';
import AddTodo from '.';describe('AddTodo component', () => {
it('Should render successfully', () => {
const component = shallow(<AddTodo />);
expect(component.exists()).toEqual(true);
});
});
処理内容としては、
AddTodoコンポーネントをshallow(コンポーネントそれ自体を)してきたものをcomponent変数に入れます。
その変数が存在してれば、つまりAddTodoコンポーネントがあれば、trueを返します。
上のテストを作り終えたら、 yarn run test
を行います。
testはエラーを出すので、それに合わせて、コードを書いていきます。
src/components/addTodo/index.js
import React from 'react';const AddTodo = () => (
<div />
);export default AddTodo;
以下同様に、submit/inputボタン、またフォームをそれぞれテストを書きながら作っていきます。
フォームのテスト、コードについて詳しく見ていきます。
src/components/addTodo/test.js
it('Should call the submitTodo function when clicked', () => {
const submitMock = jest.fn();
const component = mount(<AddTodo submitTodo={submitMock} />); expect(submitMock.mock.calls.length).to.equal(0);
component.find('form').simulate('submit');
expect(submitMock.mock.calls.length).to.equal(1);
});
変数submitMockにjest.fn()を代入することで、便利なヘルパー関数を使っていくことができます。
詳細については、こちらのドキュメントで確認出来ます。
また変数componentに、mount(full rendering)した<AddTodo submitTodo={submitMock} />を代入しているので、
event
から preventDefault()
といったフォームのsubmissionにアクセスできます。
また値を渡してもいるので、フォーム上でもsubmitMockが使えることができます。
次のコードが、上のテストに対応したAddTodoコンポーネントの表示になります。
src/components/addTodo/index.js
return (
<div>
<form
onSubmit={(event) => {
event.preventDefault();
submitTodo(input.value);
input.value = '';
}}
>
<input
className="todo-input"
ref={(element) => {
input = element;
}}
/>
<button type="submit" className="todo-submit">
Add Todo
</button>
</form>
</div>
);
ref={(element) => {
input = element;
}}
変数refにinputの値を入れることで、ReactはDOM要素に入力値をいれて、管理します。
つまり、コンポーネントの中にrefを使って保存することで、値のtrackingができるようになります。
<form
onSubmit={(event) => {
event.preventDefault();
submitTodo(input.value);
input.value = '';
}}
また、フォームはsubmitを押された時に上のコードは以下のように処理します。
- defaultの動作(submitされたらページの再読込)をしない
- フォーム内の値(input.value)を引数として、submitTodo、つまりsubmitMock関数が呼ばれる。
- フォームの値は空になる。
AddTodo.propTypes = {
submitTodo: PropTypes.func.isRequired,
};
propsの型タイプをvalidateしています。
これによって、propsのdefault値や、どの値ならvalidateするのかを設定しています。
ここでは、submitTodo関数は、関数を引数にとることが明記されています。
因みに、ここで上記のpropsのvalidationをしなかった場合、今までの全てのテストは通らないです。もちろん、eslintにも怒られます。
逆にいうと、eslintの設定さえちゃんと行っていれば、その場でエラーに気づくことができます。
参考リンク
自分用にまとめます。typecheckとrefの使い方に関しては、また後でまとめて、理解を深める必要があると感じました。
- typecheck
props の typecheckについて - Jest
mock function(jest.fn())の使い方 - Refs and DOM
コード内にでてきた、refの使い方。
感想
何も設定しなくてもテストができる
yarn run testが、かなり便利でした。今のところ、これあればwebdriverIOなくも困らないと感じるくらいです。
ただし、今回のコードは画面の作成だけなので、機能を付けていくのには、またwebdriver等が必要になるのかと思います。
また、テスト駆動での開発は楽しかったです。が、これを自分でテストを考えるとなると、また違って難しいように感じました。