Skip to content
Advertisement

MockServerWorker is not handling responses when using fetch in react

I’m doing test driven development in react course –

I’m trying to development test for post request. Below is by react code.

import React from "react";
import axios from "axios";

class SignUpPage extends React.Component {

    state = {
    }

    onChange = (event) => {
        const {id, value} = event.target;
        this.setState({
            [id]:value
        })
    };

    onChangeUsername = (event) => {
        const currentValue = event.target.value;
        this.setState({
            username: currentValue,
          //  disabled: currentValue !== this.state.confirmPassword
        });
    };

    onChangeEmail = (event) => {
        const currentValue = event.target.value;
        this.setState({
            email: currentValue,
          //  disabled: currentValue !== this.state.confirmPassword
        });
    };
    
    onChangePassword= (event) => {
        const currentValue = event.target.value;
        this.setState({
            password: currentValue,
          //  disabled: currentValue !== this.state.confirmPassword
        });
    };

    onChangeConfirmPassword= (event) => {
        const currentValue = event.target.value;
        this.setState({
            confirmPassword: currentValue,
         //   disabled: currentValue !== this.state.password
        });
    };

    submit = (event) => {
        event.preventDefault();
      const {username, email, password } =  this.state;
      const body = {
          username, email, password
      }
      //axios.post('/api/1.0/users', body);
      fetch("/api/1.0/users", {
          method: 'POST',
          headers : {
              "Content-Type": "application/json"
          },
          body: JSON.stringify(body)
      });
    };

    render() {
        let disabled = true;
        const { password, confirmPassword} = this.state;
        if(password && confirmPassword) {
            disabled = password !== confirmPassword;
        }

        // setTimeout(() => {
        //     this.setState({disabled: false});
        //     console.log('updating disabled');
        // }, 1000);

        return (
        <div className="col-lg-6 offset-lg-3 col-md-8 offset-md-2">
            <form className="card mt-5">
            <h1 className="text-center card-header">Sign Up</h1>

            <div className="card-body">
            <div className="mb-3">            
            <label htmlFor="username" className="form-label">Username</label>
            <input id="username"onChange={this.onChange} className="form-control"/>
            </div>

            <div className="mb-3"><label htmlFor="email" className="form-label">E-mail</label>
            <input id="email" onChange={this.onChange} className="form-control mb-4"/>
            </div>
            <div className="mb-3"><label htmlFor="password" className="form-label">Password</label>
            <input id="password" type="password" onChange={this.onChange} className="form-control"/>
            </div>
            <div className="mb-3"><label htmlFor="confirmPassword" className="form-label">Confirm Password</label>
            <input id="confirmPassword" type="password" onChange={this.onChange} className="form-control"/>
            </div>
            <div className="text-right">
            <button disabled={disabled} onClick={this.submit} className="btn btn-primary">Sign Up</button>
            </div>
            </div>
            </form>
        </div>
        );
    }
}


export default SignUpPage;

and the test for the post request when the button is clicked is –

import SignUpPage from "./SignUpPage";
import {render, screen} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
const axios = require('axios').default; 
import { setupServer} from "msw/node";
import { rest } from "msw";

describe("Interactions", () => {
    

    it("sends username, email and password to backend after clicking the button", async () => {
        let reqBody;
        const server = setupServer(
            rest.post("/api/1.0/users", (req, res, ctx) => {
                console.log("the message is");
                reqBody = req.body;
                return res(ctx.status(200));
            })
        );

        server.listen();
        render(<SignUpPage/>);
        const usernameInput = screen.getByLabelText('Username');
        const emailInput = screen.getByLabelText('E-mail');
        const passwordInput = screen.getByLabelText('Password');
        const confirmPassword = screen.getByLabelText('Confirm Password');

        userEvent.type(usernameInput, 'user1');
        userEvent.type(emailInput, 'user1@mail.com');
        userEvent.type(passwordInput, 'P4ssw0rd');
        userEvent.type(confirmPassword, 'P4ssw0rd');
        const button = screen.queryByRole('button', {name: 'Sign Up'});
        expect(button).toBeEnabled();
        userEvent.click(button);


        await new Promise(resolve => setTimeout(resolve, 1500));

       // const firstCallofMockFunction = mockFn.mock.calls[0];
        //const body = JSON.parse(firstCallofMockFunction[1].body);


        expect(reqBody).toEqual({
            username: 'user1',
            email: 'user1@mail.com',
            password: 'P4ssw0rd'
        });

    });

    
});

When the test is run I get below error –

console.warn [MSW] Warning: captured a request without a matching request handler:

• POST http://localhost:3000/api/1.0/users

If you still wish to intercept this unhandled request, please create a request handler for it. Read more: https://mswjs.io/docs/getting-started/mocks

console.error Error: Error: connect ECONNREFUSED ::1:3000 at Object.dispatchError (/home/rajkumar/Coding/react/react-tdd/node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:63:19) at Request. (/home/rajkumar/Coding/react/react-tdd/node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:655:18) at Request.emit (node:events:539:35) at NodeClientRequest. (/home/rajkumar/Coding/react/react-tdd/node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:121:14) at NodeClientRequest.emit (node:events:539:35) at NodeClientRequest.Object..NodeClientRequest.emit (/home/rajkumar/Coding/react/react-tdd/node_modules/@mswjs/interceptors/src/interceptors/ClientRequest/NodeClientRequest.ts:284:22) at Socket.socketErrorListener (node:_http_client:454:9) at Socket.emit (node:events:527:28) at emitErrorNT (node:internal/streams/destroy:151:8) at emitErrorCloseNT (node:internal/streams/destroy:116:3) undefined

    ● Interactions › sends username, email and password to backend after clicking the button

    expect(received).toEqual(expected) // deep equality

    Expected: {"email": "user1@mail.com", "password": "P4ssw0rd", "username": "user1"}
    Received: undefined

      94 |         await new Promise(resolve => setTimeout(resolve, 1500));
      95 |
    > 96 |         expect(reqBody).toEqual({
         |                         ^
      97 |             username: 'user1',
      98 |             email: 'user1@mail.com',
      99 |             password: 'P4ssw0rd'

      at Object.<anonymous> (src/pages/SignUpPage.spec.js:96:25)

The complete code is on github here. When I use axios.post instead of fetch it is working fine. How can I fix this error –

Advertisement

Answer

The URL in fetch and rest.post should be similar Docs.

Either specify the exact URL to rest.post (similar to fetch) in the test.

rest.post("http://localhost:3000/api/1.0/users", (req, res, ctx) => {}

Or specify a path to fetch (similar to rest.post) inside the component.

fetch("/api/1.0/users", {})
Advertisement