mardi 8 décembre 2020

using ...prev in setState prohibits userEvent.type to type into input when react testing

I want to test my Log In Component, which consists of two input fields, whose values are determined by a single react state that is an object with two parameters. However, when I try the test only the first letter appears in the value of the selected input and not the rest of the word. I determined my use of ...prev when updating the state to be the issue. If I only use a single input field with one state it works fine!

Here is my component:

import {useState} from 'react';


export function Login () {
    //Login Credentials
    const [loginCredentials, setLoginCredentials] = useState({ name: '' });

    const handleChange = ({target}) => {
        setLoginCredentials({[target.name]: target.value});
    }

    return (
            <div className="login-container">
                <h1>Log In</h1>
                    <div className="login-label-input">
                        <label htmlFor="name">Account Name
                            <input
                            type="name"
                            id="name"
                            name="name"
                            onChange={handleChange}
                            value={loginCredentials.name}
                            />
                        </label>
                        <label htmlFor="name">Password
                            <input
                            type="password"
                            id="password"
                            name="password"
                            onChange={handleChange}
                            value={loginCredentials.password}
                            />
                        </label>
                  </div>
                  State name: {loginCredentials.name}. State password: {loginCredentials.password}.
             </div>
    )
}

This works but if I include the password state:

export function Login () {
    //Login Credentials
    const [loginCredentials, setLoginCredentials] = useState({ name: '', password: '' });

    const handleChange = ({target}) => {
        setLoginCredentials((prev) => ({...prev, [target.name]: target.value}));
    }
...

it does not pass the test. I does not throw an error but simply only adds the first letter of the string I am testing with:

test("log in with empty name input returns error message",  async () => {
    render(
            <Login />
        );
    const nameField = screen.getByLabelText(/account name/i);
    userEvent.type(nameField, 'test');
    await waitFor(() => expect(nameField).toHaveValue('test'));
});

with the error:

expect(element).toHaveValue(test)

    Expected the element to have value:
      test
    Received:
      t

Is using ...prev bad or is this is a bug or what is going on?

Aucun commentaire:

Enregistrer un commentaire