How to test errors (createError) in validate function? (@nuxt/test-utils + @testing-library/vue)
I would like to integration test this part of my nuxt 3 page:
I use
vitest with environment: "nuxt" for testing. My test has following contents:
But it doesn't render my error page, it just renders an HTML body with some wrapper divs. I checked with screen.debug:
The validate function is actually called with the correct query params and it also executes this line:
(FYI: If I pass and code and email params it also renders the actual page.)
How can make it to render the error page here, instead of the empty body? I believe the issue is that in the context of the render component after renderSuspended there is no error.vue defined? How would you test such a case?
I basically search everywhere, including AI stuff and have no idea how to integration test errors with @nuxt/test-utils.. Any help is appreciated 🙂15 Replies
Hi @Flaneder. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
You're correct that when using
The knowledge sources do not provide a way to directly integration test the rendering of
@nuxt/test-utils and @testing-library/vue with renderSuspended, you may not see your custom error.vue rendered by default in integration tests—especially when testing error handling via createError in the validate function. This is a known limitation of the Nuxt testing environment, as the error boundary and error page rendering can behave differently in tests compared to a real browser environment.
Why is the error page not rendered?
- The Nuxt error page (error.vue) is not a route, but a special file that is rendered when Nuxt detects an unhandled error or a thrown error with createError (with fatal: true for client-side).
- In the test environment, especially with renderSuspended, the error handling mechanism may not trigger the full error page rendering as it does in production. Instead, the error may be caught and not propagated to the error boundary that would render error.vueerror.vue docs.
What do the docs say?
- The documentation describes how to use createError in both pages and API routes, and how the error page is rendered in real usage, but does not provide a direct example of testing the error page rendering in integration tests with @nuxt/test-utils and @testing-library/vuecreateError docs.
- The helpers like renderSuspended and mountSuspended are for mounting components in the Nuxt environment, but there is no explicit mention of how to test the error page rendering when an error is thrown in a lifecycle function like validateTesting helpers.
What can you do?
- Unit Test the validate function separately: You can test the logic of your validate function in isolation, asserting that it returns a createError object when expected.
- Test error boundary behavior: If you want to test the error boundary, you may need to simulate an error in a component and check if the error boundary (e.g., <NuxtErrorBoundary>) catches it and renders the error slot, as shown in the docsNuxtErrorBoundary.
- Check for error state: You can check if the error state is set (e.g., using useError() composable) after rendering, but the actual rendering of error.vue may not be testable with the current test utils.
Example: Unit test for validate
Example: Testing error boundary
Then in your test, trigger the error and check for the error message in the slot.
---
Summary:The knowledge sources do not provide a way to directly integration test the rendering of
error.vue via @nuxt/test-utils and @testing-library/vue when an error is thrown in validate. You can unit test the validate logic and test error boundaries, but full error page rendering is not currently supported in the test environment as it is in production. If you need to test the actual error page rendering, you may need to use end-to-end testing tools instead.
error.vue docs | createError docs | Testing helpers
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@136521231284436992> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai how would to create the error boundary template before passing it to the render function in a ts file?
Let me check the knowledge base for you again. One moment! :books:
----------------------
To create an error boundary template before passing it to the
renderSuspended function in a test file, you can define a wrapper component that uses <NuxtErrorBoundary> and slots your target component inside. This approach is shown in the Nuxt documentation:
In your test file, you can define this wrapper inline (using a string or a SFC), import it, and then pass it to renderSuspended:
This pattern is supported and described in the Nuxt documentation for <NuxtErrorBoundary> and its slots and events. You can also access error and clearError in the slot as shown above NuxtErrorBoundary docs.
If you need to define the wrapper in a .vue file, you can do so and import it into your test. The key is to ensure your component is wrapped in <NuxtErrorBoundary> so that errors are caught and rendered in the error slot during testing.
The knowledge sources do not provide a more advanced or alternative approach; this is the recommended method for testing error boundaries in Nuxt NuxtErrorBoundary docs.---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@136521231284436992> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai the #error slot is not rendered when the error happens.. maybe @nuxt/test-utils didn't configure something correctly here?
Let me check the knowledge base for you again. One moment! :books:
----------------------
You're correct to suspect that the
The knowledge sources do not provide enough information to confirm that
#error slot of <NuxtErrorBoundary> may not be rendered as expected in your test environment. According to the Nuxt documentation, <NuxtErrorBoundary> is designed to catch client-side errors that occur within its default slot and render the #error slot when such an error is thrown. However, the documentation does not provide explicit guidance or guarantees about how this works in the context of @nuxt/test-utils and @testing-library/vue integration tests, especially for errors thrown in Nuxt page lifecycle hooks like validate NuxtErrorBoundary docs.
The knowledge sources do not mention any special configuration required for @nuxt/test-utils to make the #error slot render in these cases, nor do they provide troubleshooting steps for this specific scenario. They do show that error boundaries work for errors thrown inside components, but not for errors thrown in page meta functions like validate NuxtErrorBoundary docs.
Therefore, based on the available documentation, it appears that this is a limitation of the current Nuxt test environment: errors thrown in validate may not propagate to the error boundary in a way that triggers the #error slot during tests. There is no documented workaround or configuration to change this behavior.
If you need to test this behavior, you may need to rely on end-to-end testing tools, or test the error boundary with errors thrown directly from within components, as shown in the docs.
Summary:The knowledge sources do not provide enough information to confirm that
@nuxt/test-utils can render the #error slot for errors thrown in validate, nor do they describe any configuration to enable this. This appears to be a limitation of the current testing setup.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@136521231284436992> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
I would like to know if it really isn't possible.. from a human? 😅 There must be a way to test errors right? it should be some common use case IMO
Can you mount your page and mock useRoute to have a missing query value and assert that createError was called?
You don't need to unit test that error.vue was rendered, just that createError was triggered with the correct params
@dwol How can I create a mock for
createError to see if it's called? It's used as a global in my project. I think for the most tests it would be sufficient to check if the function was called.. but for at least one test it would be greate to check the whole flow including the error page
btw. I also get this warning:
Which probably comes from this @nuxt/test-utils file: https://github.com/nuxt/test-utils/blob/bc2bb574bd6dbc041de13279d1ba66be91535802/src/runtime-utils/render.ts#L170
I guess it tries to re-render something if createError() is returned from validate and somehow calls this RenderHelper which indeed has no template.. would be great if I could somehow be able to avoid this warning as it would pollute test logs
I can mock this createError from h3 and also see the console.error:
but when i try to mock nuxt/app's createError nothing is mocked and console.error is not printing anything:
Something like this:
‘’’
const { mockCreateError } = vi.hoisted(() => ({ mockCreateError: vi.fn() }))
mockNuxtImport('createError', () => mockCreateError)
expect(mockCreateError).toHaveBeenCalledWith(…stuff)
‘’’
Not sure about the warning though.
@dwol
mockNuxtImport('createError', () => mockCreateError) is not mocking anything in my case .. it never calls the mock.. I already tried this before too. If you could mock the correct createError it would probably be sufficient in my case.
I tried to debug this a lot now and also checked @nuxt/test-utils source code. The main issue here is that the RenderHelper calls router.replace before rendering anything, so in case the route validation fails, router.replace throws an error. So basically the RenderHelper never renders the component which leads to this warning.
I was also able to mock useRouter and you can just catch the error of router.replace and it would render the component as if nothing was failing. It avoids the warning but is pretty hacky and ugly tbh.
You can also not wrap the component in a NuxtErrorBoundary because it will also not be rendered before the error. If you could add NuxtErrorBoundary to the wrapper component it would probably work but there is not an option in @nuxt/test-utils AFAIK .. I think it would be great if you could just say: for tests where I expect an error i want to have a "test" NuxtErrorBoundary and check if it renders the error slot. This way you would test the whole flow.
No clue how to handle the nicely.. I hope to find a good solution as I currenlty setup the base for our frontend tests.. and negative testing is really important to me too.Weird, I'm using that mock and it's working fine, not in a component test though.
If this is logging the error for you:
could you pass the mock to that instead?
Or keep it as is and use vi.mocked in the assertions?
If either of those don't work I'm out of ideas
@dwol thanks for all the hints 🙂 I finally had enough trying to rendere errored pages so i just to this now:
I don't render the component anymore, just manually trigger
router.replace