iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 17
1
Modern Web

循序漸進學習 Javascript 測試系列 第 17

Day 17 測試 React 元件:使用 React Testing Library 測試元件的狀態

昨天我們學習了如何在測試裡 render 元件,並使用 testing library 家族的 jest-domdom-testing-library 來強化 assertions,寫出更易讀、易維護的測試。

昨天完成的測試如下:

test/react-dom.js

import React from 'react'
import ReactDOM from 'react-dom'
import {getQueriesForElement} from '@testing-library/dom'
import {FavoriteNumber} from '../favorite-number'

test('renders a number input with a label "Favorite Number"', () => {
  const div = document.createElement('div')
  ReactDOM.render(<FavoriteNumber />, div)
  const {getByLabelText} = getQueriesForElement(div)
  const input = getByLabelText(/favorite number/i)
  expect(input).toHaveAttribute('type', 'number')
})

使用 React Testing Library 來 render 元件

現在我們進一步思考,在其他的元件測試中,也都會需要 render 元件,所以可以試著將 render 的部分抽出來,讓它成為一個可以重複使用的 function。

我們希望這個 function 叫做 render ,可以像這樣使用 const {getByLabelText} = render(<FavoriteNumber />) ,傳入 component 後回傳一系列 queries 方法:

test/react-dom.js

// 粗略將原本 test 裡面的程式碼搬進來
// render function 還未完成
function render() {
  const div = document.createElement('div')
  ReactDOM.render(<FavoriteNumber />, div)
  const {getByLabelText} = getQueriesForElement(div)
}

test('renders a number input with a label "Favorite Number"', () => {
  const {getByLabelText} = render(<FavoriteNumber />) // render 方法可重複使用
  const input = getByLabelText(/favorite number/i)
  expect(input).toHaveAttribute('type', 'number')
})

讓我們繼續完成 render function:

test/react-dom.js

function render(ui) {
  const container = document.createElement('div')
  ReactDOM.render(ui, container)
  const queries = getQueriesForElement(container)
  return {container, ...queries} // 回傳一系列 queries 方法
}

這個 render function 的功能,其實 testing library 家族的 React Testing Library 已經幫我們做好了,現在將它引入測試中,取代剛剛我們自己實作的 render function:

npm install --save-dev @testing-library/react

或

yarn add --dev @testing-library/react

import @testing-library/reactrender 進來,現在已不需要 'react-dom''@testing-library/dom' 了:

test/react-dom.js

import React from 'react'
// 移除 import ReactDOM from 'react-dom'
// 移除 import {getQueriesForElement} from '@testing-library/dom'
import {render} from '@testing-library/react'
import {FavoriteNumber} from '../favorite-number'

test('renders a number input with a label "Favorite Number"', () => {
  const {getByLabelText} = render(<FavoriteNumber />)
  const input = getByLabelText(/favorite number/i)
  expect(input).toHaveAttribute('type', 'number')
})

使用 debug Function 查看 DOM 的狀態

在寫元件測試的過程中,我們很需要清楚 DOM 當下的狀態是什麼。React testing library 提供一個 debug Function,它會幫我們在 console 中印出 DOM 的長相。

我們可以從 render function 回傳得到 debug method,呼叫 debug 可以印出當下 Jest render 出來的 DOM 狀態:

const {getByLabelText, debug} = render(<FavoriteNumber />)
debug()

如果我們只想印出特定的 DOM,也可以在 debug 裡面傳入那個元素:

test('renders a number input with a label "Favorite Number"', () => {
  const {getByLabelText, debug} = render(<FavoriteNumber />)
  const input = getByLabelText(/favorite number/i)
  debug(input) // 只印出 input 現在的 DOM 長相
})

通常 debug method 只是幫助我們在撰寫測試階段,快速掌握當下的 DOM 長相,當我們寫完測試後,就會將它刪除,不會留在 code base 裡面。


上一篇
Day 16 測試 React 元件:render 元件及使用 Jest DOM & dom-testing-library
下一篇
Day 18 測試 React 元件:測試元件的 Event Handlers
系列文
循序漸進學習 Javascript 測試30

尚未有邦友留言

立即登入留言