-
-
Notifications
You must be signed in to change notification settings - Fork 125
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
Testing components that use useQueryState? #259
Comments
I've been wondering the same thing about how to unit-test the library itself to be honest. If anyone has suggestions, I'd be happy to add them to the README. |
Unfortunately ended up rewriting this(here) to make use of My initial hope was I'd just update the and do a PR, but there was some weirdness- likely with the [great work btw :)] |
Thanks for your work and feedback @karuhanga. The reason why I didn't use router.query was for optimisation: I did not want If this goes against the adage "make it work, make it right, make it fast, in that order", then I'd be happy to reconsider this decision. Your comment raised an interesting idea: why stub the underlying implementation of this library (the need for a router) when we could instead provide a mock of useQueryState, where routing behaviour can be controlled and spied on from test code ? |
I see. I think it might be possible to prevent these rerenders with a strict memoization, maybe based on
Yes. That was actually something I considered(e.g using Generally though, I think depending on two different sources of truth for what the queries are is not great. |
Can you provide information about how you ended up testing this? I'm having the same problem and rewriting the package itself is something I would prefer to avoid.
|
As I'm working on shipping an update that supports the app router, I'd like to collect some feedback and ideas on how to make it easier to test these hooks. In the upcoming API, the For testing components that use the hook, a black box approach would be recommended:
Points 1 and 2 are akin to testing regular Since URL updates are now asynchronous to support batching and throttling, it may become more difficult to test. However, as the library uses an event emitter internally, we could expose a special key that emits URLSearchParams when updates are applied to the URL. Test code could subscribe to this key using mock callbacks, and assert that they have been called with certain expected values. On the other hand, the initial issue had to do with testing the hook outside of a Next.js router context. It should 1 now be possible to rely only on the test environment providing a Web History API mock, which could also be hooked for assertions. Edit: initial attempts to mount a component using useQueryState in a RTL test fixture failed due to the dependency on Notes: some useful links to how to mock Footnotes
|
Any workarounds in the meantime? In particular, I'd like to be able to use |
Just another issue to add:
This is on a pages router in a page with no SSR functions defined ( I've localized the issue to |
Some updates on this front: the upcoming Adapters feature in #644 (which opens Here's a sneak peak of what a test (using Vitest & Testing Library) might look like: import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { NuqsTestingAdapter, type UrlUpdateEvent } from 'nuqs/adapters/testing'
import { describe, expect, it, vi } from 'vitest'
import { CounterButton } from './counter-button'
it('should increment the count when clicked', async () => {
const user = userEvent.setup()
const onUrlUpdate = vi.fn<[UrlUpdateEvent]>()
render(<CounterButton />, {
// Setup the test by passing initial search params / querystring:
wrapper: ({ children }) => (
<NuqsTestingAdapter searchParams="?count=42" onUrlUpdate={onUrlUpdate}>
{children}
</NuqsTestingAdapter>
)
})
// Act
const button = screen.getByRole('button')
await user.click(button)
// Assert changes in the state and in the (mocked) URL
expect(button).toHaveTextContent('count is 43')
expect(onUrlUpdate).toHaveBeenCalledOnce()
expect(onUrlUpdate.mock.calls[0][0].queryString).toBe('?count=43')
expect(onUrlUpdate.mock.calls[0][0].searchParams.get('count')).toBe('43')
expect(onUrlUpdate.mock.calls[0][0].options.history).toBe('push')
}) The feature is still in an RFC stage, if you want to join the discussion to give feedback: #620 |
Hi all, I got the solution from here: vercel/next.js#48937 (comment) |
I'm happy to announce that nuqs 2 was released, and with it a way to unit-test components that use its hooks, in isolation, with no mocking or framework runtime needed. Here are the docs: https://nuqs.47ng.com/docs/testing |
I'm curious if anyone has written unit tests for a component using this library? I'm using it in a Next.js app (works beautifully, by the way) but when I try to test the component, it bombs out with "Cannot read property 'replace' of null" from this line:
https://github.com/47ng/next-usequerystate/blob/064ecfdaf093bbde2cc72db008685d4a588efed5/src/useQueryState.ts#L108
The text was updated successfully, but these errors were encountered: