如何在使用反應測試庫單擊父組件上的按鈕後測試子組件呈現文本? (How to test the child component render text after the button on the parent component click with react testing library?)


問題描述

如何在使用反應測試庫單擊父組件上的按鈕後測試子組件呈現文本? (How to test the child component render text after the button on the parent component click with react testing library?)

我有一個父組件 App 並且它有一個按鈕。單擊按鈕時,它將調用 axios 來獲取帖子,然後渲染帖子項目。App 有一個子組件 PostPost 有一個子組件 ListItem。在我的 App 測試文件中,我測試了 axios 在單擊按鈕後可以正確加載。但是,我無法測試呈現的內容。它找不到 data‑testidUnable to find an element by: [data‑testid="test‑axios‑content"]

我使用 react 測試庫

這是我的測試文件:

import React from "react"
import App from "../../App"
import { render, fireEvent, screen, waitFor, act } from "../utils/test‑utils"
import axios from "axios"

jest.mock("axios", () => {
return {
get: jest.fn()
}
})

describe("App test", () => {
afterEach(() => {
jest.resetAllMocks()
})
it("should load and display the data", async () => {
const { getByTestId } = render(<App />)

    axios.get.mockResolvedValueOnce({
        data: { title: &quot;hello there&quot;, body: &quot;abc&quot; }
    })
    await act(async () =&gt; {
        fireEvent.click(getByTestId(&quot;test‑axios‑button&quot;))
        expect(axios.get).toHaveBeenCalledTimes(1)
        const testingData = await waitFor(() =&gt; getByTestId(&quot;test‑axios‑content&quot;))
        expect(testingData).toHaveTextContent(&quot;hello there&quot;)
    })
})

})
</code></pre>

第一個 axios 調用時間是正確的,但我的測試找不到 testId test‑axios‑content。我把它放在 App.js 上的子組件上。

App.js

...
function App() {
    const [posts, setPosts] = useState([])
    const handleClick= async () => {
        const postsResult = await getPosts()
        setPosts(postsResult.data)
    }
    return (
        <div className="App" data‑test="appComponent">
            <button data‑testid="test‑axios‑button" onClick={handleClick}>
                get post from axios
            </button>
            <section>
                <div>Load Posts:</div>
                <Post posts={posts} data‑testid="test‑axios‑content" />
            </section>
        </div>
}
...

api getPosts:

import axios from "axios"
export const getPosts = async () => await axios.get("https://jsonplaceholder.typicode.com/posts?_limit=10")

Post:

import ListItem from "../listItem"

const Post= (props) => {
const posts = props.posts
return (
<>
{posts.length > 0 && (
<div>
{posts.map((post, index) => {
const { title, body } = post
return <ListItem key={title} title={title} desc={body} />
})}
</div>
)}
</>
)
}

export default Post
</code></pre>

列表項:

const ListItem = (props) => {
const { title, desc } = props
return (
<div>
<h2 data‑test="title" data‑testid="title">
{title}
</h2>
<div data‑test="desc" data‑testid="desc">
{desc}
</div>
</div>
)
}

export default ListItem
</code></pre>


參考解法

方法 1:

The first wrong part is that posts is one array, but on the axios mock, it's one object: { title: "hello there", body: "abc" }. The correct format is : [{ title: "hello there", body: "abc" }]

So, on the axios mock part of testing, the correct code is:

axios.get.mockResolvedValueOnce({
    data: [{ title: "hello there", body: "abc" }]
})

The second wrong part is rather than using await act, it should use trigger click first and then use await waitFor with a callback:

fireEvent.click(getByTestId("test‑axios‑button"))
await waitFor(() => {
    expect(axios.get).toHaveBeenCalledTimes(1)
    const renderData = screen.getByText("hello there")
    expect(renderData).toBeInTheDocument()
})

This is the final:

it("should load and display the data", async () => {
    const { getByTestId } = render(<App />)

    axios.get.mockResolvedValueOnce({
        data: [{ title: "hello there", body: "abc" }]
    })
    fireEvent.click(getByTestId("test‑axios‑button"))
    await waitFor(() => {
        expect(axios.get).toHaveBeenCalledTimes(1)
        const testingData = await waitFor(() => getByTestId("test‑axios‑content"))
        expect(testingData).toHaveTextContent("hello there")
    })
})

(by MoonMoon)

參考文件

  1. How to test the child component render text after the button on the parent component click with react testing library? (CC BY‑SA 2.5/3.0/4.0)

#Axios #reactjs #react-testing-library






相關問題

如何從 Contentful 中獲取單個條目並按字段值查詢? (How to fetch a single entry from Contentful and query by field value?)

VUE 中的 Axios 承諾失敗,無法讀取未定義的屬性“toUpperCase” (Axios promise in VUE failed with Cannot read property 'toUpperCase' of undefined)

Symfony 4 - 使用 Axios 提交表單? (Symfony 4 - Submit form with Axios?)

Laravel:帶有axios的表單不保存 (Laravel: form with axios not saving)

使用 axios 將用戶圖像上傳到strapi (uploading user image to strapi using axios)

我的 module.exports 返回為 [object Object] (My module.exports return as [object Object])

即使驗證要求無效,數據仍在發送,解決此問題的最佳方法是什麼? (Data is sending even if validation requirements are not valid, whats the best way to approach this?)

如何等到使用 Axios 上傳文件 (How to wait until file is uploaded using Axios)

axios 請求錯誤:使用 Heroku 的 ECONNREFUSED (axios request Error: ECONNREFUSED with Heroku)

為什麼我的 axios 調用即使在解決之後仍返回 undefined? (Why does my axios call return undefined even after then is resolved?)

為什麼在使用 axios.post 時我的頁面上有一個 OBJECT PROMISE (Why i have a OBJECT PROMISE on my page when using axios.post)

如何在使用反應測試庫單擊父組件上的按鈕後測試子組件呈現文本? (How to test the child component render text after the button on the parent component click with react testing library?)







留言討論