Testing component with useSearchParams
Answered
JeffBaumgardt posted this in #help-forum
I have a client component that has a caller to
Naive but you get the point. If the component is mounted and the uri has a query
Now, I'm trying to test this.
For starters I had to mock next/navigation just to keep
So I have
But I can't for the life of me figure out how to mock the response of
I would like to assert the actual value of the query param as well.
So something like
I am on Next 14 and using the app router.
Jest
React-testing-library
Typescript
useSearchParams
. I'm using this to add query params to the route for errorsexport default function Thing() {
const searchParams = useSearchParams()
const possibleError = searchParams.get('error')
return (
<div>
{possibleError ? <span>some error</span> : null}
<span>Stuff here</span>
</div>
)
}
Naive but you get the point. If the component is mounted and the uri has a query
error
I display an error. In practice this works. I have a component that conditionally renders an error when the search query is present.Now, I'm trying to test this.
For starters I had to mock next/navigation just to keep
TypeError: Cannot read properties of undefined (reading 'get')
errors from jest. So I have
jest.mock('next/navigation', () => {
return {
__esModule: true,
useSearchParams: () => ({
get: jest.fn(),
}),
}
})
But I can't for the life of me figure out how to mock the response of
get
in a single test. I would like to assert the actual value of the query param as well.
So something like
error=foo
and error=bar
I am on Next 14 and using the app router.
Jest
React-testing-library
Typescript
Answered by JeffBaumgardt
I got it.
I changed the mock to
And in the test I did this
I was trying to mock the get method off of the constructor of URLSearchParams which is the actual function in
So by changing the mock to mock out useSearchParams to itself being a mock implementing
I changed the mock to
jest.mock('next/navigation', () => {
return {
__esModule: true,
useSearchParams: jest.fn().mockImplementation(() => new URLSearchParams()),
}
})
And in the test I did this
;(useSearchParams as jest.Mock).mockImplementation(() => new URLSearchParams('signInError=invalidSession'))
I was trying to mock the get method off of the constructor of URLSearchParams which is the actual function in
useSearchParams
it's just a readonly version. So by changing the mock to mock out useSearchParams to itself being a mock implementing
URLSearchParams
I was able to then update the mock inside a single test.test('Should show an error', () => {
;(useSearchParams as jest.Mock).mockImplementation(() => new URLSearchParams('signInError=invalidSession'))
const {getByText} = render(<LoginModal header={<span>Testing Header</span>} />)
expect(getByText('Invalid Session. Please login agin.')).toBeInTheDocument()
})
1 Reply
I got it.
I changed the mock to
And in the test I did this
I was trying to mock the get method off of the constructor of URLSearchParams which is the actual function in
So by changing the mock to mock out useSearchParams to itself being a mock implementing
I changed the mock to
jest.mock('next/navigation', () => {
return {
__esModule: true,
useSearchParams: jest.fn().mockImplementation(() => new URLSearchParams()),
}
})
And in the test I did this
;(useSearchParams as jest.Mock).mockImplementation(() => new URLSearchParams('signInError=invalidSession'))
I was trying to mock the get method off of the constructor of URLSearchParams which is the actual function in
useSearchParams
it's just a readonly version. So by changing the mock to mock out useSearchParams to itself being a mock implementing
URLSearchParams
I was able to then update the mock inside a single test.test('Should show an error', () => {
;(useSearchParams as jest.Mock).mockImplementation(() => new URLSearchParams('signInError=invalidSession'))
const {getByText} = render(<LoginModal header={<span>Testing Header</span>} />)
expect(getByText('Invalid Session. Please login agin.')).toBeInTheDocument()
})
Answer