aieyan
aieyan

Reputation: 143

Jest: Testing React state change in useEffect

I am new at Jest and Enzyme, and am struggling to write a unit test to check if my component renders correctly when a certain state value exists.

Below is my code:

//Auth.js
export const Auth = ({ children }) => {
    const [authStatus, setAuthStatus] = useState('waiting')

    useEffect(()=>{
       const status = await getAuth()
       if (status) {
           setAuthStatus('Authed')
       }
       else{
           setAuthStatus('Unauthed')
       }
    },[])

    return (
       <>
          {authStatus === 'waiting' && <p>Loading...</p>}
          {authStatus === 'Authed' && <>{Children}</>
       </>
    )
}

In the above code, I wanted to test the Loading state when authStatus is default and I wanted to write a second test to test if the Children being passed in props are rendered when authStatus is Authed. I found a way to mock implement the state change, but that implementation is restricted to only one useEffect, as there may be multiple useEffects in the future, I do not want to go with this approach. Is there any better way to test this behavior?

Upvotes: 2

Views: 646

Answers (2)

Sakshi
Sakshi

Reputation: 1548

First mock getAuth and now You can have two separate test cases.

first test case-> your mocked getAuth function should return some defined value.This will help you in testing {authStatus === 'Authed' && <>{Children}</>. This will also cover the if (status) { setAuthStatus('Authed') } part.

second test case-> your mocked getAuth function should return some undefined value.This will cover your else{ setAuthStatus('Unauthed') } part

Upvotes: 1

Taghi Khavari
Taghi Khavari

Reputation: 6582

first, you can't just use await keyword in useEffect callback, it should be an async function which would do that like this:

//Auth.js
export const Auth = ({ children }) => {
    const [authStatus, setAuthStatus] = useState('waiting')

    async function checkAuth(){
       const status = await getAuth()
       if (status) {
           setAuthStatus('Authed')
       }
       else{
           setAuthStatus('Unauthed')
       }
    }

    useEffect(()=>{
       checkAuth();
    },[])

    return (
       <>
          {authStatus === 'waiting' && <p>Loading...</p>}
          {authStatus === 'Authed' && <>{Children}</>
       </>
    )
}

and then it's a best practice not to test implementation details like state.

usually, you want to mock api calls and imported modules like getAuth function.

so I think you should mock the getAuth function and then return your desired value in your mock so you can test if differnet state like loading will happen or not

Upvotes: 0

Related Questions