jestのチュートリアルをやってみる
はじめに
JavaScriptのユニットテストフレームワークでよく名前を聞くのが、jestですよね。
筆者はまだjestでユニットテストを書いたことが無いですが、ここ最近jest触ってみたいなと思っていたので、チュートリアルをやりたいと思います。
以下の公式チュートリアルで手を動かしていきます!
始めましょう
インストール
$ npm install -D jest
チュートリアルのソースはnodejsのソースぽいな。requireを使う。 import形式だとまた違うのかな。
//// sum.js function sum(a, b) { return a + b; } //// sub.test.js const sum = require('./sum'); // test, expectはrequireしなくても使える test('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3); }); //// packge.json "scripts" : { "test" : "jest" }
$ npm run test > jest_sample@1.0.0 test > jest PASS ./sum.test.js ✓ adds 1 + 2 to equal 3 (4 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 0.533 s, estimated 1 s Ran all test suites.
おー、テストが実行されましたね。簡単なもんだな。 これで、初jestテストの実績できたわ。
toBe()
はマッチャー、他のマッチャーは以下参照。
コマンドラインからの実行
- グローバルインストールしたら、jestコマンドでテスト実行できる
// なんかエラーになったな、何指定していいかよくわかってない。 // configファイルは必須なのかな。 $ jest ./jest_sample/ Error: Could not find a config file based on provided
エラーになったが、一旦良しとしよう。
追加設定
ここで、設定ファイルを作っていくのね。
基本の設定ファイルを生成する
jest --init
で設定ファイルを生成- 結構色々聞かれた。
- configファイルにTSを使うか、実行環境はnodeかとか。
- よくわかってないが。基本はデフォルト値にした
jest --init The following questions will help Jest to create a suitable configuration for your project ✔ Would you like to use Typescript for the configuration file? … no ✔ Choose the test environment that will be used for testing › node ✔ Do you want Jest to add coverage reports? … no ✔ Which provider should be used to instrument code for coverage? › v8 ✔ Automatically clear mock calls, instances and results before every test? … no
オプションなのか、以下の説明があるが、必ずしも使う必要は無いのか。。
- Babelを使用する
- webpackを使用する
- Parcelを使用する
- TypeScriptを使用する
- TypeScriptをBabel経由で使用する
- TypeScriptをts-jest経由で使用する
ちょっと、jestと上記の関係がわからんな。上記と一緒に使うこともできるよ、くらいか?
jestはテスティングフレームワークなので、babelとかでES5に変換してテストするとか?、テストランナーを他のツールから呼べるようにして、そのときにコードのトランスパイルが必要ならよろしくやるよ、ってことなのかな。
Matcherを使用する
Macherの完全なリファレンスはこちら
一般的なマッチャー
test('two plus two is four', () => { expect(2 + 2).toBe(4); });
expect(2 + 2)
は"expectation"オブジェクトを返す。toBe(4)
の部分がマッチャー- Jestが実行されると、失敗したマッチャーをすべて追跡し、エラーメッセージを表示することができる
わざとFailさせてみた。
$ npm run test > jest_sample@1.0.0 test > jest FAIL ./sum.test.js ✕ adds 1 + 2 to equal 3 (12 ms) ● adds 1 + 2 to equal 3 expect(received).toBe(expected) // Object.is equality Expected: 4 Received: 3 3 | 4 | test('adds 1 + 2 to equal 3', ()=>{ > 5 | expect(sum(1, 2)).toBe(4); | ^ 6 | }) at Object.<anonymous> (sum.test.js:5:23) Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 1.019 s, estimated 2 s
toBe
はObject.is
を使用して厳密な等価性をテストするtoEqual
は オブジェクトの値を確認する- deep equality らしいので、再帰的に確認するのかな。
not
で反対のテスト可能。expect(a + b).not.toBe(0)
- Object.isの比較は参照比較するぽい。
Object.is([],[]) => false
Object.is() - JavaScript | MDN
jestではexpectの引数はreceived
って読んでるんだね。actual
はjUnitの文化なのかな。
真偽値(およびそれらしく思える値)
undefined
,null
,false
を区別したい場合と、一緒として扱いたい場合がある- それに対応するマッチャーがある
toBeNull
:null
のみに一致toBeUndefined
:undefined
のみに一致toBeDefined
: toBeUndefinedの反対。(undefinedじゃなければ一致)toBeTruthy
: ifステートメントが真であるもとみなすものに一致toBeFalsy
: ifステートが偽であるとみなすものに一致
数値
toBeGreaterThan(x)
: より大きいtoBeGreaterThanOrEqual(x)
: 以上toBeLessThan(x)
: より小さい- `toBeLessThanOrEqual(x): 以下
toBe(x)
: 等しいtoEqual(x)
: 等しいtoBeCloseTo
: 丸め誤差に依存しないように
文字列
toMatch
: 正規表現でマッチするかを確認できる
配列と反復可能なオブジェクト
toContain()
: 配列や反復可能なオブジェクトに特定のアイテムが含まれているかどうかを確認できる
例外
toThrow
: ある関数が呼び出し時に例外を投げることをテストする- 例外をスローする関数は、ラッピング関数内で呼び出される必要がある
非同期コードのテスト
- JSでは非同期コードをよく書く。
- jestはテスト対象コードがいつ完了したかを別のテストに進む前に知る必要がある
- いくつか方法がある
コールバック
- fetchData(callback)のように、処理が終わったらcallback関数を呼び出す場合
- jestのテストはデフォルトでは一度最後まで実行したら完了
- callback関数の中でアサートしても呼ばれない
- テストがpassしたことになってしまう。
- callback関数の中でアサートしても呼ばれない
- テスト関数にdoneが引数として渡されるので、expectの後にdone()を呼ぶ
- 引数にdoneを書いた時点でテストの挙動が変わるな
- コールバック内でdone()を呼ばなかったら、タイムアウトする
- 引数にdoneを書いた時点でテストの挙動が変わるな
test('the data is peanut butter', done => { function callback(data) { try { expect(data).toBe('peanut butter'); done(); } catch (error) { done(error); } } fetchData(callback); });
Promises
- promiseを使用するコードなら、非同期テストをもっと簡単に処理できる
- むしろ、これが本筋というか、あるべきか?
- fetchData関数がpromiseを返すようにする
- テスト関数の中でも、promiseを返す。
test('the data is peanut butter', () => { return fetchData().then(data => { expect(data).toBe('peanut butter'); }); });
- promiseがrejectされることを期待するケース
test('the fetch fails with an error', () => { expect.assertions(1); // expectが1回呼ばれたことの確認? でもこの行なくてもエラーにならんな return fetchData().catch(e => expect(e).toMatch('error')); });
expect.assertions(1)
がよくわからん。この行なくてもエラーにならんぞ。でも、assertions(2)とかにするとエラーになるのか。だから、この行なくてもfailはしないけど、assertions(1)にして、assertがされなかったらエラーになるので、ちゃんとassertはされていることは確認が必要、ということね。
.resolves / .rejects
- expect宣言で、
.resolves
マッチャを使うこともできる- テストメソッドからreturnするのは必須
- resovle, rejectじゃなくて、resolves, rejectsで複数形なのが間違えそう
test('the data is peanut butter', () =>{ return expect(fetchDataPs()).resolves.toBe('peanut butter'); // returnは必須 }) test('the fetch fails with an error', () => { return expect(fetchDataPsError()).rejects.toMatch('error'); })
Async/Await
- asyncとawaitをテストで使用できる
- testに渡すアロー関数前にasyncキーワードを記述するだけ
- 圧倒的に、わかりやすい気がする。
- testに渡すアロー関数前にasyncキーワードを記述するだけ
- .resolves、.rejectsと組み合わせて使える
- returnでpromiseを返していたのをawaitキーワードつけて呼び出す
- うーむ。単純な例だとasyncを書く分、簡潔って感じではないな
- returnでpromiseを返していたのをawaitキーワードつけて呼び出す
test("the data is peanut butter (async/await ver)", async () => { const data = await fetchDataPs(); expect(data).toBe("peanut butter"); }); test('the fetch fails with an error (async/await ver)', async ()=> { expect.assertions(1); try { await fetchDataPsError() } catch (e) { expect(e).toMatch('error') } }) // resolveと併用 test("the data is peanut butter, (async/await and resove)", async () => { await expect(fetchDataPs()).resolves.toBe("peanut butter"); });
セットアップと破棄
- junitでいうところの、@beforeEachみたいな機能
- 共通的なセットアップ作業をまとめれる
テストごとにセットアップ作業を繰り返す実行する
beforeEach
関数、afterEach
関数を使用する- junitと同じやん
- 非同期コードでセットアップする場合はpromiseを返すかdoneパラメータを使う
ワンタイムセットアップ
- ファイルの先頭/最後で1回だけ実行されるセットアップ
beforeAll
,afterAll
スコープ
describe
を使って、複数のテストをグループ化できる。- describeの中で、beforeEach, afterEachを使うと、グループ内だけに適用される
- describeの外側で定義されているbeforeEach,afterEachはdescribe内のtestにも有効っぽい
- describeの外側のbeforeEachとかの方が、describe内よりも先に実行される
- describeの外側で定義されているbeforeEach,afterEachはdescribe内のtestにも有効っぽい
- describeの中で、
beforeAll
,afterAll
も使える
describeブロックとtestブロックの実行順序
- describeハンドラを実際の全てのテストを実行する前に実行する
- describeが全て実行された後に、testが実行されるということ
一般的なアドバイス
- テストが失敗した場合、テストが単体で実行した場合にも失敗するかどうかを確認する
test
をtest.only
に変更するとそのテストだけを実行できる
モック関数
- モック関数でできること
- 関数をモックする方法は2つある
- テストコードの中でモック関数を作成する
manual mock
を作成してモジュールの依存性を上書きする
モック関数を利用する
- モックコールバック関数の生成
mockCallback = jest.fn(x => 42 + x)
- 呼ばれた回数
- mockCallback.mock.calls.length
- 引数
- mockCallback.mock.calls[0][0] は 1回目の呼び出しの第一引数
- 返り値
- mockCallback.mock.results[0].valueは1回目の呼び出しの返り値
.mockプロパティ
- mock関数の生成
const myMock = jest.fn()
- 何もしない関数ということかな
- すべてのモック関数には
.mock
プロパティがあり、モック関数呼び出し時のデータと、関数の返り値が記録されている - thisの値も記録されている
一個上で列挙したプロパティか。
モックの戻り値
myMock.mockReturnValueOnce(1)
myMock()
の呼び出しで、定義した値が変える。
- 継続渡しスタイルで書ける
- `myMock.mockReturnValueOnce(10).mockReturnValueOnce('x')
モジュールのモック
import axios from 'axios' jest.mock('axios') // これでモック化される axios.get.mockResoledValue(xxx) // これでgetを呼ばれたときの返り値を定義できる
部分的なモック
ESMのサンプルコードになっているがローカルで動かない。。
stack overflowの記事と以下の公式ドキュメント見てみる。
結局、部分的なモックはよくわからんかったな。エラーになるし。。
モックの実装
- 指定された値を返すという能力を超えて、完全に実装をモック化する
jest.fn
かmockImplementationOnce
メソッドを使うconst myMockFn = jest.fn(cb => cb(null, true))
- myMockFnという関数を
cb => cb(null, true)
という実装でモック化するということか?
- myMockFnという関数を
mockImplementationOnce
メソッドは他のモジュールによって作成されたモック関数のデフォルトの実装を定義したいときに便利
jest.mock('../foo'); // これでrequire('../foo')はモック化される const foo = require('../foo'); foo.mockImplementation(() => 42); foo() // => 42
mockImplementationOnce
- 関数への複数回への呼び出しで異なる結果を得るようにしたい場合に利用
test(" test multi mockImplementationOnce", () => { const myMockFn = jest .fn() .mockImplementationOnce(cb => cb(null, true)) .mockImplementationOnce(cb => cb(null, false)); myMockFn((erro, val) => expect(val).toBe(true)) myMockFn((erro, val) => expect(val).toBe(false)) })
- モック関数が
mockImplementationOnce
によって定義された実装をすべて使いきった場合jest.fn
のデフォルトの実装を実行する
test(" test default impl", () => { const myMockFn = jest .fn(()=> 'default') .mockImplementationOnce(() => 'first call') .mockImplementationOnce(() => 'second call'); expect(myMockFn()).toBe('first call'); expect(myMockFn()).toBe('second call'); expect(myMockFn()).toBe('default'); });
.mockReturnThis
this
を返すモックを実装するときの糖衣APIjest.fn().mockReturnThis()
モック名
jest.fn().mockName("hoge name")
でモック名をつけれる- テスト結果でエラーを出力しているモック関数を迅速に特定できる
試してみたけど、エラー時にモック名が出てるようには見えなかったなぁ。assertの種類によってことなるのかな。
カスタムマッチャ
- モック関数がどのように呼ばれたか検査するためのカスタムマッチャ
- これじゃない場合は、「mock」プロパティを検査する必要あある
mockFunc
がjest.fn()
で定義されている場合に、mockFunc.mock
に検証用の情報が格納されるやつ
snapshotだけよくわからんかったな。
test(" test custom matcher", () => { const myMockFn = jest.fn((arg1, arg2)=> console.log(`${arg1}_${arg2}`)); myMockFn(1,2) myMockFn(2,3) expect(myMockFn).toHaveBeenCalled(); expect(myMockFn).toHaveBeenCalledWith(1, 2); expect(myMockFn).toHaveBeenLastCalledWith(2, 3); expect(myMockFn).toMatchSnapshot(); });
てか、このカスタムマッチャーの方を普通は使いそう。.mock
プロパティを使うとだるすぎる。
Jestプラットフォーム
なんか、Jestを利用したツールとかを作るためのAPIぽいな。
- jest-changed-files
- jest-diff
- jest-docblock
- jest-get-type
- jest-validate
- jest-worker
- prettyFormat
- なんかモジュール読み込めなかったな。
jest community
へー、awesome jestなんてものがあったのか。
GitHub - jest-community/awesome-jest: 🕶Awesome Jest packages and resources
一旦備忘メモ
chromeでデバッグ
$ node --inspect-brk node_modules/.bin/jest --ru nInBand sum.test.js
chromeを開いて「chrome://inspect
」を開く。
スナップショットテスト
- UIが予期せず変更されてないかを確かめるのに非常に有用なツール
- 2つのスナップショットが一致しない場合は失敗する
たぶん、スナップショットって、文字列(HTMLとか)なんだと思う。
Jestにおけるスナップショットテスト
- reactの場合は
import renderer from 'react-test-renderer';
を使う - 初めて実行したときにsnapshot fileが生成される
- snapshot fileはレビューされるべき
- スナップショットテストができた経緯
- スナップショットテストの感覚を掴む
- 読んでない。あとで読むか。
スナップショットの更新
jest --updateSnapshot
- 失敗するすべてのスナップショットテストのスナップショットを更新する
--testNamePattern
で更新対象を限定できる
インタラクティブスナップショットモード
- 一つ一つ差分みながら、更新できる。
インラインスナップショット
- スナップショットを.snapファイルに出力するのではくてコード上に追記してくれる
Property Matchers
- IDとか、日付とか、実行毎に値が変わるものがある場合
- 具体的な値の代わりに、
Any<Number>
とかスナップショットに記載するとエラーにならない。- mockしたら良いのでは、と思った
ベストプラクティス
スナップショットをコードとして扱う
- レビューする
- テストがfailしたときに、何も考えずにスナップショットを再作成しないようにする
べき等性のあるテストを書く
- 何回実行しても同じ結果になるべき
Date.now = jest.fn(()=> 1482363367071);
のようにモック化するなど- 何回実行しても1482363367071を返すようになる
叙述的なスナップショット名を使う
- 「~である」という説明のような書き方
exports[ <username /> should render Alan Turing
] みたいな。- 何が描画されるか読んでわかる
よくある質問(で気になったもののメモ)
- スナップショットファイルはバージョン管理する
- スナップショットは出力が正しいかをテストするという目的でいつでも使える
- ビジュアル回帰テストとの違いは、ビジュアル回帰はwebページのスクリーンショットをとってピクセル単位で比較する、スナップショットはテキストファイルを比較する、目的が違う
- 2つともUIをテストするという点では同じ
- (目的が違う????)
- スナップショットを手動で作成することもできるがやりやすいものではない
- テスト駆動的に使うものではなくて、テスト対象のモジュールの出力が変更されたかをわかりやすくるもの
- コードカバレッジはスナップショットテストでも機能する
非同期の事例
- 事前準備としてjestでbabelのサポートを有効にする
$ mkdir jest_babel_sample $ cd jest_babel_sample $ npm init -y $ npm i -D jest $ npx jest --init #これはjest.config.jsを作るため、選択肢は適当に選んだ。てか結局中身は消した気がする。(module.exports = {}だけ残した) $ npm run test # jestが動くようになる。jest --initでそのように選択したら $ npm i -D babel-jest @babel/core @babel/preset-env ## babel.config.js # module.exports = { # presets:[['@babel/preset-env', {targets: {node: 'current'}}]], # }; # ./srcフォルダ以下に、sum.js, sum.test.jsを作成 # ESM形式で記述(import / export) $ npm run test # sum.test.jsが実行される。
あー、なるほど。Babelの設定がプロジェクト内にあれば、自動的にファイルをトランスパイルして、テストを実行してくれるみたい。
babel-jest
がそれを担っているのかな。
自動的にファイルをトランスパイルされたくない場合はjest.config.js
にtransform:{}
のようにtransformの設定を明示的にリセットする。
たしかに、webpackは不要か、バンドルした結果をテストするわけではなくて、テスト対象モジュールだけをトランスパイルできればよいので、jest側でトランスパイル処理をbabel経由でするのね。(TypeScriptもそうなのかも)
nodeコマンドを--input-type=module
指定で実行したらESMを実行できるかと思ったら、そんなことはなかったな。(できると書いてある記事もあったが、できなかった)
まぁ、そんなに困ることはないのか?
- プロダクションコード:webpackでバンドルするときにトランスパイル
- テスト:babel-jestでトランスパイル
という使い分けになるのかしら。。(package.jsonにtype=module指定したのを、src直下に置くとかもあるかも??)
非同期の事例
__test__
と__mock__
はモジュールと同階層に置く- jestでテスト実行時は勝手によみこんでテストを実行し、モックがあればモックも読む
- モック化するには
jest.mock("../request")
のように、モック化指定する
- 非同期ロジックのテストを書くときはアサーション(expect)が呼ばれたかをアサートする
expect.assertions(1)
タイマーモック
- jestはタイマー関数を自分で時間経過をコントロールできる関数に置き換えることができる
- setTimeout, setInterval, clearTimeout, clearInterval
- タイマーを任意時間で発火できるということかな?
jest.useFakeTimers(); //タイマーをコントロールするだけならこれだけでよさげ jest.spyOn(global, "setTimeout"); //setTimeoutが呼ばれたかなど検証したいならspyOnする // 全てのタイマーを実行する jest.runAllTimers // こういうふうにモック化して渡すから、toBeCallledとかで検証できるのかな const callback = jest.fn(); expect(callback).toBeCalled(); // 待機中のタイマーを実行する jest.runOnlyPendingTimers() // 1回待機中のタイマーを実行する、呼ぶたぶにタイマーが進むっぽいな。 // 指定した時間でタイマーを進める jest.advanceTimersByTime(msToRun)
マニュアルモック
- マニュアルモックはモックデータを返す機能をスタブするために使う
ユーザモジュールのモック
- モジュールのディレクトリ直下のmocksサブディレクトリにモックモジュールを作成
- ./src/user.jsというモジュールをモックするなら
./src/__mocks__/user.js
- mocksは小文字
Nodeモジュールのモック
- node_modulesと並列にmocksフォルダを作る
- lodash.jsをモックするなら
.__mocks__/lodash.js
という感じかな- モック実装する
- 簡単に実装する、
export default jest.createMockFromModule("lodash");
- 独自実装する
export default { isString : jest.fn() }
とか返すと、isStringだけモック化される- isString以外は、他のメソッドとかも消えている.
- 簡単に実装する、
- モック実装する
- lodash.jsをモックするなら
- 上記のモックモジュールを実装しなくてもテストケース側でimport前に以下実行でモック化できる
jest.mock("lodash");
- spyOnでもできる
- ES module importするときは、importの前にjest.mock("モジュール")しなきゃいけない
- jestが自動的に、jest.mockをコードの先頭に移動してくれる
- JSDOMに実装されていないメソッドのモック
ES6クラスのモック
- モック関数を使用することでモックを作成できる
- クラス構文はいくつかのコンストラクタ関数の糖衣構文らしい
自動モック
- jest.mock("モジュールファイル名")でモックコンストラクターになる
- これで、newとかできるんすねぇ。
マニュアルモック
- mocksディレクトリに
モジュールファイル名.js
で配置する - モックの実装としては
jest.fn().mockImplementation(() => { return {xxx} }) みたいに、クラスで生成されるインスタンスの形式のオブジェクトを返す、ただし、オブジェクトのプロパティで関数があったら、
jest.fn()`でモック化する
jest.mock()
をモジュールファクトリ引数で呼ぶ
- 第二引数にモジュールファクトリを渡す
- モジュールファクトリはモック関数を返す関数
jest.mock('./モジュールパス', () => { return jest.fn().mockImplementation(() => { return { xxxxx:yyyy} }); }); // mockImplementationは新規オブジェクトを返す関数を定義
jest.mock()は先頭に引き上げられるから、jest.mockより上で定義した変数を参照するとエラーになるよ、みたいなこと書いてある気がする。
クラスメソッドをモック化するシンプルな例
const playSoundFileMOck = jest .spyOn(SoundPlayer.prototype, 'playSoundFileI) .mockImplementation(()=>{ console.log("mocked function") });
クラス(関数)のプロトタイプメソッドをモック化する。
モックをスパイする
jest.fn()
でモック関数を作る
//default exportの場合 import Hoge from './hoge' jest.mock('./hoge', () => { return jest.fn().mockImplementation(() 0 => { return { fuga : () => {}} }) ) // default export以外を持っくする import { Hoge } from './hoge' jest.mock('./hoge', () => { return { Hoge : jest.fn().mockImplementation( () => { return { fuga: () => {}} }), } })
クラスのメソッドをスパイする
- クラスメソッドが期待した引数でよばれているかを確認するには、クラスメソッドをスパイする必要がある
テストでモックコンストラクタが呼ばれると、その都度新しいオブジェクトが生成される。すべてのオブジェクトのメソッド呼び出しをスパイするには、モックオブジェクトが参照するモック関数インスタンスを同一にする
const mockFuga = jest.fn() jest.mock('./hoge', () => { return jest.fn().mockImplementation(() 0 => { return { fuga : mockFuga} })
テスト間でのクリーンアップ
[モックオブジェクト].mockClear()
- 呼び出し記録をクリアする
備忘メモ
- モック関数は
jest.fn()
で定義する必要がある。- そうしないと、呼ばれたかどうかとかのアサートができない
- モックの実装をするには
- spyOnでスパイ実装、スパイはロジックを戻せる
- jest.mock("axios")でモジュールをモック
axios.get.mockResolveValue(xxxx)
でaxios.getが返す値を定義できる
参考リンク
モジュールモックのバイパス
jest.mock('hoge')
でモジュールをモックするが全部モックされてしまう- hogeモジュールのfuga関数だけは実際のロジックを利用ということもできる
jest.mock('hoge') import hoge from 'hoge' const { fuga } = jest.requireActual('hoge')
ECMAScript Modules
- experimantalな機能らしい。
- code transformsを明示的にdisableする。
transform: {}
node
を実行時に--experimenta-vm-modules
を付ける
こまかいところはちょっとわからんが。babelやTypeScriptで実行した方がサポートされているから良さそう。
Using with webpack
- webpackと利用する場合、ちょっと情報古そうな気もする。
- どういうケースで利用できるのかよくわからん
DOM操作
- 直接DOM操作するコードはテストが難しいとされる
- ボタンを押下したらバックエンドあらfetchしてdomにhtml追加とか
jest-environment-jsdom
を使うnpm i -D jest-environment-jsdom
これだけでいいんかな- testEnvironmentプロパティにjsdomを指定しないといけないっぽい
- テストメソッドの上部にコメントでenvironmentを指定する方法もあるみたいだけど、うまく認識してくれなかった。なぜでしょう
jsdomはJS上でDOMを再現(イベントの監視とか、domのデータ構造の再現とか)してくれるみたい。
サンプルコード実行してみたら、動いたな。テストコードではjsdomは意識しなくても良いみたいだ。testEnvironmentで指定しているからか、テストコード上でdocument.body.innerHTML
でHTMLを突っ込んだら、それがDOMとして認識してくれるみたい。
つまり、テストコード上でブラウザで実行しているのと同じ感覚で実装できるということか。
-
- ホワイトボードで説明してくれている動画、英語だからちょっと厳しい。。
よし、終わりにしよう!ながかった、気長にちょこちょこやってましたね。 jestだけでなくて、nodeでのモジュール機構のキャッチアップにもなったし、結構ためになった。
やっぱり、手を動かして動作確認しつつやってたのが良かった。