Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yet another test stability improvements PR #4397

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
134 changes: 93 additions & 41 deletions packages/react-query/src/__tests__/useQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -873,20 +873,35 @@ describe('useQuery', () => {

states.push(state)

const { remove } = state

React.useEffect(() => {
setActTimeout(() => {
remove()
rerender({})
}, 20)
}, [remove])
return (
<>
<div>{state.data}</div>

return null
<button
onClick={() => {
state.remove()
rerender({})
}}
>
remove
</button>
</>
)
}

renderWithClient(queryClient, <Page />)
const rendered = renderWithClient(queryClient, <Page />)

await waitFor(() => {
rendered.getByText('data')
})

fireEvent.click(rendered.getByRole('button', { name: 'remove' }))

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here we need a longer sleep (100) after the button click. As the title suggests:

'should not get into an infinite loop when removing a query with cacheTime 0 and rerendering'

How do we detect an infinite loop? We wait a bit and wait what the states length is. If it's still 5 after 100ms, it's not an infinite loop. If it were, it would be anywhere between 30 and 50 or so :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await waitFor(() => {
rendered.getByText('data')
})

// required to make sure no additional renders are happening after data is successfully fetched for the second time
await sleep(100)

expect(states.length).toBe(5)
Expand Down Expand Up @@ -1518,17 +1533,27 @@ describe('useQuery', () => {

states.push(state)

React.useEffect(() => {
setActTimeout(() => {
setCount(1)
}, 10)
}, [])

return null
return (
<div>
<button onClick={() => setCount(1)}>increment</button>
<div>data: {state.data ?? 'undefined'}</div>
<div>count: {count}</div>
</div>
)
}

renderWithClient(queryClient, <Page />)
const rendered = renderWithClient(queryClient, <Page />)

await waitFor(() => rendered.getByText('data: 0'))

fireEvent.click(rendered.getByRole('button', { name: /increment/i }))

await waitFor(() => {
rendered.getByText('count: 1')
rendered.getByText('data: undefined')
})

// making sure no additional fetches are triggered
await sleep(50)

expect(states.length).toBe(3)
Expand Down Expand Up @@ -1812,26 +1837,41 @@ describe('useQuery', () => {

states.push(state)

const { refetch } = state
return (
<div>
<button onClick={() => state.refetch()}>refetch</button>
<button onClick={() => setCount(1)}>setCount</button>
<div>data: {state.data ?? 'undefined'}</div>
</div>
)
}

React.useEffect(() => {
refetch()
const rendered = renderWithClient(queryClient, <Page />)

setActTimeout(() => {
setCount(1)
}, 20)
await waitFor(() => {
rendered.getByText('data: undefined')
})

setActTimeout(() => {
refetch()
}, 30)
}, [refetch])
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))

return null
}
await waitFor(() => {
rendered.getByText('data: 0')
})

renderWithClient(queryClient, <Page />)
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))

await sleep(100)
await waitFor(() => {
rendered.getByText('data: 0')
})

fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))

await waitFor(() => {
rendered.getByText('data: 1')
})

// making sure no additional renders are triggered
await sleep(20)

expect(states.length).toBe(6)

Expand Down Expand Up @@ -2194,19 +2234,31 @@ describe('useQuery', () => {

states.push(state)

const { refetch } = state
return (
<>
<button
onClick={async () => {
await state.refetch()
}}
>
refetch
</button>

React.useEffect(() => {
setActTimeout(() => {
refetch()
}, 10)
}, [refetch])
return null
<div>{state.data}</div>
</>
)
}

renderWithClient(queryClient, <Page />)
const rendered = renderWithClient(queryClient, <Page />)

await sleep(30)
await waitFor(() => {
rendered.getByText('test')
})

fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))

// sleep is required to make sure no additional renders happen after click
await sleep(20)

expect(states.length).toBe(2)
expect(states[0]).toMatchObject({
Expand Down