N
Nuxt3w ago
zurg

Test Utils: wrapper.find Always Returns Empty DOMWrapper

I'm converting an app for Nuxt 2 to Nuxt 3. I've updated the unit test config to use Nuxt test utils and the Nuxt environment but wrapper.find only ever returns an empty DOMWrapper i.e. does not find anything, even though the wrapper.html looks correct vitest.config.ts
import { defineVitestConfig } from '@nuxt/test-utils/config'
import { configDefaults } from 'vitest/config'

export default defineVitestConfig({
test: {
environment: 'nuxt',
globals: true,
clearMocks: true,
setupFiles: ['./vitest.setup.ts'],
globalSetup: ['./vitest.global-setup.ts'],
exclude: [...configDefaults.exclude, './e2e/**']
},
assetsInclude: '**/*.lottie'
})
import { defineVitestConfig } from '@nuxt/test-utils/config'
import { configDefaults } from 'vitest/config'

export default defineVitestConfig({
test: {
environment: 'nuxt',
globals: true,
clearMocks: true,
setupFiles: ['./vitest.setup.ts'],
globalSetup: ['./vitest.global-setup.ts'],
exclude: [...configDefaults.exclude, './e2e/**']
},
assetsInclude: '**/*.lottie'
})
spec file
test('signInWithoutPasswordPage', () => {
function createWrapper() {
return mount(signInWithoutPasswordPage)
}

it('Renders the form and button', async () => {
const wrapper = createWrapper()

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')

expect(emailOrPhoneField.isVisible()).toBe(true)
})
test('signInWithoutPasswordPage', () => {
function createWrapper() {
return mount(signInWithoutPasswordPage)
}

it('Renders the form and button', async () => {
const wrapper = createWrapper()

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')

expect(emailOrPhoneField.isVisible()).toBe(true)
})
Test failure
FAIL pages/inventory/auth/sign-in-without-password.spec.ts > signInWithoutPasswordPage > Renders the form and button
Error: Cannot call isVisible on an empty DOMWrapper.
❯ Object.get ../node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:1574:27
❯ pages/inventory/auth/sign-in-without-password.spec.ts:46:30
FAIL pages/inventory/auth/sign-in-without-password.spec.ts > signInWithoutPasswordPage > Renders the form and button
Error: Cannot call isVisible on an empty DOMWrapper.
❯ Object.get ../node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:1574:27
❯ pages/inventory/auth/sign-in-without-password.spec.ts:46:30
I've tested with mount and mountSuspended, if I console.log(wrapper.html()) I can see the the element it's search for is in the dom, thanks for any help
6 Replies
kapa.ai
kapa.ai3w ago
Hi @zurg. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the information provided in the knowledge sources, I can offer some insights and suggestions to address your issue with wrapper.find() returning an empty DOMWrapper in Nuxt 3 unit tests. The problem you're experiencing is likely related to the way components are mounted in the Nuxt 3 environment. In Nuxt 3, we use @nuxt/test-utils which provides specific helpers for testing Nuxt applications. Instead of using mount directly from @vue/test-utils, you should use the mountSuspended helper provided by @nuxt/test-utils/runtime. This helper allows you to mount Vue components within the Nuxt environment, handling async setup and access to injections from Nuxt plugins Nuxt Testing Docs (https://nuxt.com/docs/getting-started/testing#mountsuspended). Here's how you can modify your test:
import { mountSuspended } from '@nuxt/test-utils/runtime'
import signInWithoutPasswordPage from './path-to-your-component'

test('signInWithoutPasswordPage', async () => {
async function createWrapper() {
return await mountSuspended(signInWithoutPasswordPage)
}

it('Renders the form and button', async () => {
const wrapper = await createWrapper()

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')

expect(emailOrPhoneField.isVisible()).toBe(true)
})
})
import { mountSuspended } from '@nuxt/test-utils/runtime'
import signInWithoutPasswordPage from './path-to-your-component'

test('signInWithoutPasswordPage', async () => {
async function createWrapper() {
return await mountSuspended(signInWithoutPasswordPage)
}

it('Renders the form and button', async () => {
const wrapper = await createWrapper()

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')

expect(emailOrPhoneField.isVisible()).toBe(true)
})
})
Note the following changes: 1. We import mountSuspended from @nuxt/test-utils/runtime. 2. The createWrapper function is now async and uses mountSuspended. 3. We await the createWrapper() call in the test. If you still face issues after making these changes, you might want to consider using the renderSuspended helper along with @testing-library/vue. This approach provides a different way of querying elements that might be more reliable in some cases Nuxt Testing Docs (https://nuxt.com/docs/getting-started/testing#rendersuspended). Here's an example of how you could rewrite your test using renderSuspended:
import { renderSuspended } from '@nuxt/test-utils/runtime'
import { screen } from '@testing-library/vue'
import signInWithoutPasswordPage from './path-to-your-component'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
await renderSuspended(signInWithoutPasswordPage)

const emailOrPhoneField = screen.getByTestId('identifier')

expect(emailOrPhoneField).toBeVisible()
})
})
import { renderSuspended } from '@nuxt/test-utils/runtime'
import { screen } from '@testing-library/vue'
import signInWithoutPasswordPage from './path-to-your-component'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
await renderSuspended(signInWithoutPasswordPage)

const emailOrPhoneField = screen.getByTestId('identifier')

expect(emailOrPhoneField).toBeVisible()
})
})
Remember to install @testing-library/vue if you choose this approach. If you're still encountering issues after trying these solutions, it might be helpful to check if there are any specific setup steps or configurations needed for your Nuxt 3 project that aren't covered in the standard setup. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@458955125701083146> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
zurg
zurgOP3w ago
@kapa.ai I've tried with mount, mountSuspended and renderSuspeded but get the same error
kapa.ai
kapa.ai3w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize that the previous suggestions didn't resolve your issue. Since you've tried multiple approaches without success, let's explore some other potential solutions and troubleshooting steps. 1. Component Stubbing: One possible reason for the empty DOMWrapper could be related to component stubbing. Try explicitly stubbing any child components or transitions that might be interfering with the rendering:
import { mountSuspended } from '@nuxt/test-utils/runtime'
import signInWithoutPasswordPage from './path-to-your-component'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage, {
global: {
stubs: {
// Add any child components or transitions here
// For example:
// 'SomeChildComponent': true,
'SlideYTransition': {
template: '<div><slot /></div>'
}
}
}
})

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
expect(emailOrPhoneField.exists()).toBe(true)
})
})
import { mountSuspended } from '@nuxt/test-utils/runtime'
import signInWithoutPasswordPage from './path-to-your-component'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage, {
global: {
stubs: {
// Add any child components or transitions here
// For example:
// 'SomeChildComponent': true,
'SlideYTransition': {
template: '<div><slot /></div>'
}
}
}
})

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
expect(emailOrPhoneField.exists()).toBe(true)
})
})
This approach is based on a solution mentioned in a Stack Overflow post about a similar issue Stack Overflow - Warning about wrong type (https://stackoverflow.com/questions/78371735). 2. Async Rendering: Ensure that you're allowing enough time for async operations to complete:
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { nextTick } from 'vue'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage)
await nextTick()
await wrapper.vm.$nextTick()

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
expect(emailOrPhoneField.exists()).toBe(true)
})
})
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { nextTick } from 'vue'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage)
await nextTick()
await wrapper.vm.$nextTick()

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
expect(emailOrPhoneField.exists()).toBe(true)
})
})
3. Check for Dynamic Rendering: If the component is rendering content dynamically, you might need to wait for that content to appear:
import { mountSuspended } from '@nuxt/test-utils/runtime'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage)

// Wait for the element to appear (adjust timeout as needed)
await wrapper.find('[data-testid="identifier"]').waitFor({ timeout: 5000 })

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
expect(emailOrPhoneField.exists()).toBe(true)
})
})
import { mountSuspended } from '@nuxt/test-utils/runtime'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage)

// Wait for the element to appear (adjust timeout as needed)
await wrapper.find('[data-testid="identifier"]').waitFor({ timeout: 5000 })

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
expect(emailOrPhoneField.exists()).toBe(true)
})
})
4. Verify HTML Output: As you mentioned you can see the element in the HTML output, let's verify that:
import { mountSuspended } from '@nuxt/test-utils/runtime'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage)

console.log(wrapper.html()) // Log the entire HTML

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
console.log('Found element:', emailOrPhoneField.html()) // Log the found element

expect(emailOrPhoneField.exists()).toBe(true)
})
})
import { mountSuspended } from '@nuxt/test-utils/runtime'

test('signInWithoutPasswordPage', async () => {
it('Renders the form and button', async () => {
const wrapper = await mountSuspended(signInWithoutPasswordPage)

console.log(wrapper.html()) // Log the entire HTML

const emailOrPhoneField = wrapper.find('[data-testid="identifier"]')
console.log('Found element:', emailOrPhoneField.html()) // Log the found element

expect(emailOrPhoneField.exists()).toBe(true)
})
})
This will help you see exactly what's being rendered and what's being found by wrapper.find(). 5. Check Selector: Ensure that the data-testid="identifier" attribute is correctly set on your component. If it's dynamically set, it might not be present when the test runs. If none of these approaches work, it might be helpful to create a minimal reproduction of the issue in a sandbox environment, as suggested in the Nuxt bug reporting guidelines (https://nuxt.com/docs/community/reporting-bugs). This would allow for a more detailed investigation of the specific problem you're encountering. Remember, when dealing with complex setups like Nuxt 3, sometimes issues can be environment-specific or related to particular configurations. If the problem persists, you might want to review your overall test setup and Nuxt configuration to ensure everything is correctly set up for testing. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@458955125701083146> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
zurg
zurgOP3w ago
I've got a screenshot of the error when using wrapper.get here. It says it's unable Unable to get [data-testid="identifier"] but data-testid="identifier" exists in the output html
No description
Want results from more Discord servers?
Add your server