Jest Test - mocking current User

Hey,
I’m trying to write some test for my component. This component is displaying the currentUser.name variable and a form to submit a message.

Here is a part of the component, where the name of the current user is called.

...
return (
    <>
        <p>Dein Name: {currentUser.name}</p>
        <Form
          onSubmit={submitForm}
          formMethods={formMethods}
...

Then I tried to write some test. I followed those information in the “Testing” Doc → https://redwoodjs.com/docs/testing#mockcurrentuser-on-the-web-side.

Here is my test:

describe('NotForm', () => {
  it('renders the name of the current User', async () => {
    mockCurrentUser({name: 'Rob'})

    const onSubmit = jest.fn()
    render(<NotForm onSubmit={onSubmit} />)

    expect(await screen.findByText('Dein Name: Rob')).toBeInTheDocument()
  })
})

It’s always failing with
Error: Uncaught [TypeError: Cannot read properties of null (reading ‘name’)]

It seems that the currentUser is still “null”. Even if i waited with an await or an waitFor(()- fuction. I found sth. similar in an older github issue

Do you have an idea, what is missing in this test? Thanks :slight_smile:

Hi @joriswill

Welcome to the Redwood community, and solid question.

The issue here is that the test isn’t waiting for current user to be populated - lets break it down into two problems:

1. Component always assumes current user is present
The way Redwood’s auth system works, is that it first tries to render your page, and if you use currentUser in an unauthenticated page, its advisable to always check if currentUser exists, before trying to access properties in your component.

e.g.

<p>{currentUser?.name}</p>

2. You need to waitFor currentUser to become available
For the above reason, and quoting the docs on this:

The async behavior here is important. Even after setting the user with mockCurrentUser(), currentUser may be null during the initial render because it’s being resolved. Waiting for a render update before passing/failing the exception gives the resolver a chance to execute and populate currentUser.

So to make your test wait till the render has finished:

    await waitFor(() => {
    expect(await screen.findByText('Dein Name: Rob')).toBeInTheDocument()
    })

Hope this helps!

2 Likes

Thanks :slight_smile:
It really helps. All tests are now passing :+1:

The combination of <p>{currentUser?.name}</p> and await waitFor(() => { fixed the problems.

Thank you very much.

2 Likes