React-testing-library可以通过自定义挂钩呈现的文本测试

发布于 2025-01-21 08:15:18 字数 2484 浏览 0 评论 0原文

在我的React应用程序中,我使用自定义挂钩从带翻译的JSON文件中检索本地化文本。它可以正常工作,但是每当我使用测试图书馆运行期望找到文本的测试时,就找不到文本,因为挂钩在拍摄该组件的快照时尚未触发和填充文本。我想知道是否有一种正确测试的方法?

// locales json file

      "LABELS": {
        "WELCOME": {
          "title": "Welcome"
        },
   }

//homepage.ts

const homePageText = [
  {
    variableName: "welcomeText",
    key: "LABELS.WELCOME.title",
    defaultValue: "Welcome",
  },

// usegetLocalizedText自定义hook

import { useMemo, useState } from "react"
import { useSelector } from "react-redux"
import translate from "@localization/translate"
import intl from "react-intl-universal"

export const useGetLocalizedText = (moduleName: string) => {
  const [messages, setMessages] = useState([])
;(async () => {
    const msgArray = await import(
      `@localization/modules/${moduleName}.ts`
    ).then((msgs) => msgs)
    setMessages(msgArray?.default ? msgArray.default : [])
  })()

  const initComplete: boolean = testInitComplete ? testInitComplete : useSelector(
    (state) => state.localization.initComplete
  )
  const localizedText = useMemo(() => {
    const localizedTextTemp: any = {}
    messages?.length > 0 &&
      messages.forEach((msg) => {
        localizedTextTemp[msg.variableName] = translate(
          intl,
          msg.key,
          initComplete,
          msg.defaultValue
        )
      })
    return localizedTextTemp
  }, [initComplete, messages])

  return localizedText
}

export default useGetLocalizedText

//homepage.tsx

const HomePage = () => {
 const localizedText = useGetLocalizedText("homePage")

return (
  <div>
    <span> {localizedText.welcome} </span>
</div>
)
}

当我运行应用程序时,文本会正确显示,但是当我运行测试时,快照显示和空跨度,我会收到错误“ testinglibraryElementErmentErmenterror” :无法找到文本的元素:资金移动模板。

//homepage-test.tsx

import React from "react"
import { customRender } from "../testUtils"
import { screen } from "@testing-library/react"
import HomePage from "@pages/home/"


describe("Home Page", () => {

  it("renders without crashing", () => {

    customRender(
      <HomePage/>
    )
    expect(screen.getByText("Welcome")).toBeInTheDocument()

  })

//快照,

<div> <span> </span> <div>

所以我的问题是,有没有办法运行一个可以找到此文本/创建快照的测试,以便文本在那里?我知道我可以将硬编码文本作为仅用于测试的道具,但不要认为这是一个很好的解决方案。

In my react app, I use a custom hook to retrieve localized text from a JSON file with translations. It works fine, but whenever I use testing-library to run tests expecting to find text, the text cannot be found, because the hook has not fired and populated the text at the time that the snapshot of the component is taken. I am wondering if there is a way to properly test this?

//locales JSON file

      "LABELS": {
        "WELCOME": {
          "title": "Welcome"
        },
   }

//homepage.ts

const homePageText = [
  {
    variableName: "welcomeText",
    key: "LABELS.WELCOME.title",
    defaultValue: "Welcome",
  },

//useGetLocalizedText custom hook

import { useMemo, useState } from "react"
import { useSelector } from "react-redux"
import translate from "@localization/translate"
import intl from "react-intl-universal"

export const useGetLocalizedText = (moduleName: string) => {
  const [messages, setMessages] = useState([])
;(async () => {
    const msgArray = await import(
      `@localization/modules/${moduleName}.ts`
    ).then((msgs) => msgs)
    setMessages(msgArray?.default ? msgArray.default : [])
  })()

  const initComplete: boolean = testInitComplete ? testInitComplete : useSelector(
    (state) => state.localization.initComplete
  )
  const localizedText = useMemo(() => {
    const localizedTextTemp: any = {}
    messages?.length > 0 &&
      messages.forEach((msg) => {
        localizedTextTemp[msg.variableName] = translate(
          intl,
          msg.key,
          initComplete,
          msg.defaultValue
        )
      })
    return localizedTextTemp
  }, [initComplete, messages])

  return localizedText
}

export default useGetLocalizedText

//Homepage.tsx

const HomePage = () => {
 const localizedText = useGetLocalizedText("homePage")

return (
  <div>
    <span> {localizedText.welcome} </span>
</div>
)
}

When I run the app, the text appears correctly, but when I run the tests the snapshot shows and empty span and I get the error "TestingLibraryElementError: Unable to find an element with the text: Funds Movement Template. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible."

//homepage-test.tsx

import React from "react"
import { customRender } from "../testUtils"
import { screen } from "@testing-library/react"
import HomePage from "@pages/home/"


describe("Home Page", () => {

  it("renders without crashing", () => {

    customRender(
      <HomePage/>
    )
    expect(screen.getByText("Welcome")).toBeInTheDocument()

  })

//snapshot

<div> <span> </span> <div>

So my question is, is there a way to run a test that will find this text/create the snapshot so the text is there? I know I can pass in hardcoded text as a prop simply for testing but don't think that is a great solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忱杏 2025-01-28 08:15:18

我不知道customRender()助手内部有什么,但我可以猜想您没有提供正确运行钩子所需的东西。

也许您需要模拟redux商店以提供initcomplete的正确价值?

作为解决方案的一部分,我将使用@testing-library/react-钩子测试钩子本身以及钩子是否可以工作,以及是否需要知道钩子在组件的上下文中是否起作用,之后对组件进行测试。如果将钩子经过正确的测试,但是组件仍然会像您提到的那样遇到问题,那么发现错误会更容易。

I don't know what's inside the customRender() helper but I can guess that you don't provide something what is needed to run your hook properly.

Maybe you need to mock Redux store to provide proper value of initComplete?

As a part of the solution, I would use @testing-library/react-hooks to test the hook itself and if hook will work and if it will be needed to know if hook works in the component's context test the component afterwards. If hook would be tested properly but component will still make problems like the one you mentioned, it will be much easier to spot the bug.

卸妝后依然美 2025-01-28 08:15:18

您不应在测试中直接调用钩子。您应该使用renderhook

示例

renderHook(() => useTheme())

You should not call hooks directly inside your test. You should use renderHook to be

Example

renderHook(() => useTheme())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文