reactjsunit-testingjestjsreact-testing-library

How to test values that comes from API in useEffect React-testing-library


i am new to react testing so, basically, i have totalCostakedBtc and btcPrice are in useState with initial value of 0. and in useEffect it is getting set from API call. and this is in my jsx file

 <div className={isConnected ? 'tvl-white' : 'App-tvl'} data-testid="loaded-TVL">
  <span>TVL</span>
  <span>${formatNumber(totalCostakedBtc * btcPrice)}</span>
</div>

it has testid as loaded-TVL and totalCostakedBTC and btcPrice is getting from useEffect so, how to deal this type of test case, where i want to check if it is greater than 0.

const tvlElement = await waitFor(() => getByTestId('loaded-TVL'), { timeout: 3000 })
    screen.debug()
    const tvlText = tvlElement.textContent

    // Define a regular expression to match the value after $
    const regex = /\$(\d+(\.\d+)?)/
    const match = tvlText.match(regex)

    // Ensure that the match is found and the value is not empty
    expect(match).toBeTruthy()
    expect(match[1]).toBeTruthy() // match[1] contains the captured value

    // You can further assert the format or specific value if needed
    // For example, to check if the value is a valid number:
    const valueAfterDollar = parseFloat(match[1])
    expect(valueAfterDollar).not.toBeNaN()
    expect(valueAfterDollar).toBeGreaterThan(0)

the upper code is written by GPT3.5

but this is failing as it is giving me 0, as both the values i have make it as 0 initially using useState. can anyone help me with this testing.


  const [btcPrice, setBtcPrice] = useState(0)

useEffect(() => {
    fetchBtcPrice()
      .then(data => {
        setBtcPrice(data)
      })
      .catch(error => console.log('failed to fetch BTC price', error))
    getTotalCostakedBtc()
  }, [])

and fetchBtcPrice is in ./Api.js

export const fetchBtcPrice = async () => {
  try {
    const response = await fetch(cryptocompareUrl)
    const data = await response.json()
    return `${data.USD}`
  } catch (error) {
    return error
  }
}

this is how btcPrice is set. similarly totalcostakedBtc is set.


Solution

  • so, i had 2 methods that are calling apis. so, mocking them in test

    
    jest.mock('../../helper/Api', () => ({
      fetchBtcPrice: jest.fn().mockResolvedValue('10'),
      getTotalCostakedBtc: jest.fn().mockResolvedValue([5, true]), // Assuming you want to simulate 'true' for show notification
    }))
    

    and check for expectation

    await act(async () => {
          const tvlElement = await waitFor(() => screen.getByTestId('loaded-TVL'), { timeout: 3000 })
          // screen.debug()
          const tvlText = tvlElement.textContent
          const expectedTotalValue = 5 * 10
          expect(tvlText).toEqual(`TVL$${expectedTotalValue}`)
        })
    

    that solves my doubt.