iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
1
Modern Web

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

Day 25 測試 React 元件:使用 React Testing Library 體驗 Test Driven Development (TDD) - 5

前面幾天我們完成了 <Redirect /> 元件的基本功能。現在我們需要多加一個測試,這個測試負責驗證:若發送 API 發生錯誤的時候,是否預期顯示錯誤訊息給使用者。

首先,新增一個叫做 'renders an error message from the server' 的測試。使用 mockRejectedValueOnce() 來 mock 錯誤時收到的 data。

tests/post-editor.js

test('renders an error message from the server', async () => {
  const testError = 'test error'
  mockSavePost.mockRejectedValueOnce({data: {error: testError}})
  const fakeUser = userBuilder()
  const {getByText} = render(<Editor user={fakeUser} />)
  const submitButton = getByText(/submit/i)

  fireEvent.click(submitButton)
})

因為我們期望 error 的 dom 會是一個 role=alertdiv ,因此在測試中使用 findByRole() 來取得這個元素。而且我們要等待這個 promise 被 reject,所以要使用 await findByRole('alert') 來等待。

tests/post-editor.js

test('renders an error message from the server', async () => {
  const testError = 'test error'
  mockSavePost.mockRejectedValueOnce({data: {error: testError}})
  const fakeUser = userBuilder()
  const {getByText, findByRole} = render(<Editor user={fakeUser} />)
  const submitButton = getByText(/submit/i)

  fireEvent.click(submitButton)

  const postError = await findByRole('alert')
})

我們加上 assertions。使用 toHaveTextContent() 驗證 alert 的 error message;再使用 .not.toBeDisabled() 驗證 submit button 沒有 disabled。

tests/post-editor.js

test('renders an error message from the server', async () => {
  ...

  expect(postError).toHaveTextContent(testError)
  expect(submitButton).not.toBeDisabled()
})

目前,測試是 fail ❌。

我們現在回到 post-editor.js ,補上顯示 error message 的功能。

加上一個新的 error state,我們希望 error 有值的時候,render <div role="alert">{error}</div>

post-editor.js

const [error, setError] = React.useState(null)

function Editor({user}) {
  ...

return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="title-input">Title</label>
      <input id="title-input" name="title" />

      <label htmlFor="content-input">Content</label>
      <textarea id="content-input" name="content" />

      <label htmlFor="tags-input">Tags</label>
      <input id="tags-input" name="tags" />

      <button type="submit" disabled={isSaving}>
        Submit
      </button>
      {error ? <div role="alert">{error}</div> : null}
    </form>
  )
}

現在我們要爲 savePost().then() 加上第二個參數 response => {} 。裡面我們 handle 收到 error message 的情況,加上 setIsSaving(false)setError(response.data.error) ,設置 button disabled 的狀態及 error message 的狀態。

post-editor.js

function handleSubmit(e) {
  e.preventDefault()
  const {title, content, tags} = e.target.elements
  const newPost = {
    title: title.value,
    content: content.value,
    tags: tags.value.split(',').map(t => t.trim()),
    authorId: user.id,
  }
  setIsSaving(true)
  savePost(newPost).then(
    () => setRedirect(true),
    response => {
      setIsSaving(false)
      setError(response.data.error)
    },
  )
}

現在,測試又亮起了綠燈 ✅。


上一篇
Day 24 測試 React 元件:使用 React Testing Library 體驗 Test Driven Development (TDD) - 4
下一篇
Day 26 測試 React 元件:使用 React Testing Library 體驗 Test Driven Development (TDD) - 6
系列文
循序漸進學習 Javascript 測試30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言