Home > Software engineering >  React simple way to test axios response data trigger by submit button
React simple way to test axios response data trigger by submit button

Time:12-23

Is there a simple way to test axios response data trigger by submit button?

and in general, I'm really getting into trouble once it's a slightly more complex or asynchronous tests. Is there a simple tool that allows me to create tests in a simple and fluent way?

import React, { useEffect, useState } from "react"
import axios from "axios"
   const ContactForm = () => {

      const onSubmitFormHandler = (event) => {
      const url = process.env.REACT_APP_SERVER_API   "/lead"

      try {
      axios
      .post(url, {
       headers: {
         "Content-Type": "application/json",
       },
       params: {
        data: leadObj,
       },
     })
     .then(function (response) {
      if (response.status === 200) {
         // do simething 
     
      } else {
       // do simething else
      }
     })
     .catch((error) => {
   
     })
   }
 }
  return (
      <form onSubmit={onSubmitFormHandler}>
              <button data-testid="submit" type="submit">
                {!loader ? "send" : <Loader />}
              </button>     
      </form>
    )
  }
export default ContactForm

CodePudding user response:

I will try to explain it details so you get faster the idea and doesn't seems more complex to you anymore. To test your API service interaction with ReactApp, you should simulate the different case of the API service method/promise interaction, so it's either a success with some data , or a fail or a pending.

in the old long days, we create either a fake client, where we fake the call and return the mocked data similar to what an API gives back to your app when the real call is processed. we could use for example. jest.mock and then you do either a resolve or reject for your promise. (look in the example below)

jest.mock("../api/users", () => ({ getUsers: jest.fn(() => Promise.resolve(users)) }));

Nowadays, a better approach is to use msw/node, an npm package which do the mock for a server within your react app testing. since it's recommended by the react-testing-library docs , i would go with it and you find all about it here :

https://docs.dennisokeeffe.com/mock-service-worker/msw-with-react https://mswjs.io/docs/api/setup-server

CodePudding user response:

This is an example straight off the react-testing-library docs, I think that you'll be able to quite easily reimpliment it with your code example above. (Check the link below for further detail!)

https://testing-library.com/docs/react-testing-library/example-intro/

You should be able to replace your url with the below /greetings

You will need to do something when your api returns a 200, maybe just an alert like in the below example could be a good start? Unless you just cleared out the result for our viewing here.

If your onSubmit is the trigger, you should also be able to use screen.getByTestId instead of screen.getByText.

The react-testing-library has some great documentation, there is also a discord community you can join too! Hopefully this helps. Goodluck!

// __tests__/fetch.test.js
import React from 'react'
import {rest} from 'msw'
import {setupServer} from 'msw/node'
import {render, fireEvent, waitFor, screen} from '@testing-library/react'
import '@testing-library/jest-dom'
import Fetch from '../fetch'

const server = setupServer(
  rest.get('/greeting', (req, res, ctx) => {
    return res(ctx.json({greeting: 'hello there'}))
  }),
)

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

test('loads and displays greeting', async () => {
  render(<Fetch url="/greeting" />)

  fireEvent.click(screen.getByText('Load Greeting'))

  await waitFor(() => screen.getByRole('heading'))

  expect(screen.getByRole('heading')).toHaveTextContent('hello there')
  expect(screen.getByRole('button')).toBeDisabled()
})

test('handles server error', async () => {
  server.use(
    rest.get('/greeting', (req, res, ctx) => {
      return res(ctx.status(500))
    }),
  )

  render(<Fetch url="/greeting" />)

  fireEvent.click(screen.getByText('Load Greeting'))

  await waitFor(() => screen.getByRole('alert'))

  expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')
  expect(screen.getByRole('button')).not.toBeDisabled()
})
  • Related