Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions examples/app-vitest-full/tests/nuxt/mount-suspended.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,17 +592,17 @@ it('element should be changed', async () => {
expect(component.element.tagName).toBe('SPAN')
})

describe('composable state isolation', () => {
const { useCounterMock } = vi.hoisted(() => {
return {
useCounterMock: vi.fn(() => {
return {
isPositive: (): boolean => false,
}
}),
}
})
const { useCounterMock } = vi.hoisted(() => {
return {
useCounterMock: vi.fn(() => {
return {
isPositive: (): boolean => false,
}
}),
}
})

describe('composable state isolation', () => {
mockNuxtImport('useCounter', () => {
return useCounterMock
})
Expand Down
5 changes: 5 additions & 0 deletions examples/app-vitest-workspace/app3/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
28 changes: 28 additions & 0 deletions examples/app-vitest-workspace/app3/app/components/Counter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<div>
<h2>{{ title }}</h2>
<label for="count">
Count
</label>
<input
id="count"
v-model="count"
type="number"
>
<button @click="increment">
Increment
</button>
</div>
</template>

<script setup lang="ts">
import { useCounter } from '#imports'

const {
title = 'Counter Component',
} = defineProps<{
title?: string
}>()

const { count, increment } = useCounter()
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ref } from '#imports'

export function useCounter() {
const count = ref(0)

function increment() {
count.value++
}

return { count, increment }
}
3 changes: 3 additions & 0 deletions examples/app-vitest-workspace/app3/app/pages/counter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<Counter />
</template>
6 changes: 6 additions & 0 deletions examples/app-vitest-workspace/app3/app/pages/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<template>
<div>
<h1>Index</h1>
<NuxtLink to="/counter">Counter</NuxtLink>
</div>
</template>
8 changes: 8 additions & 0 deletions examples/app-vitest-workspace/app3/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
imports: {
autoImport: false,
},
devtools: { enabled: true },
compatibilityDate: '2024-04-03',
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { enableAutoUnmount } from '@vue/test-utils'
import { mountSuspended, mockNuxtImport } from '@nuxt/test-utils/runtime'

import { ref, useCounter } from '#imports'
import { Counter } from '#components'

mockNuxtImport(useCounter, original => vi.fn(original))

describe('mockNuxtImport', () => {
enableAutoUnmount(afterEach)

beforeEach(() => {
vi.restoreAllMocks()
vi.clearAllMocks()
})

it('should mock composable', () => {
vi.mocked(useCounter).mockImplementationOnce(() => ({
count: ref(100),
increment: vi.fn(),
}))

const { count, increment } = useCounter()
expect(count.value).toBe(100)

increment()
expect(vi.mocked(increment)).toHaveBeenCalled()
})

it('sould mock composable used by component', async () => {
const increment = vi.fn()

vi.mocked(useCounter).mockImplementationOnce(() => ({
count: ref(100),
increment,
}))

const wrapper = await mountSuspended(Counter)
const input = wrapper.find('input')
expect(input.exists()).toBe(true)
expect(input.element.value).toBe('100')

const button = wrapper.find('button')
expect(button.exists()).toBe(true)

await button.trigger('click')
expect(input.element.value).toBe('100')
expect(increment).toHaveBeenCalled()
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { afterEach, describe, expect, it } from 'vitest'
import { enableAutoUnmount } from '@vue/test-utils'
import { mountSuspended } from '@nuxt/test-utils/runtime'

import App from '~~/app.vue'
import { Counter } from '#components'

describe('mountSuspended', () => {
enableAutoUnmount(afterEach)

it('should mount page', async () => {
const wrapper = await mountSuspended(App, {
route: '/',
})

const title = wrapper.find('h1')
expect(title.text()).toBe('Index')

const link = wrapper.find('a[href="/counter"]')
expect(link.exists()).toBe(true)
})

it('should mount component', async () => {
const wrapper = await mountSuspended(Counter)

const title = wrapper.find('h2')
expect(title.exists()).toBe(true)
expect(title.text()).toBe('Counter Component')

const input = wrapper.find('input')
expect(input.exists()).toBe(true)
expect(input.element.value).toBe('0')
})

it('should handle event', async () => {
const wrapper = await mountSuspended(Counter)
const input = wrapper.find('input')

const button = wrapper.find('button')
expect(button.exists()).toBe(true)

await button.trigger('click')
expect(input.element.value).toBe('1')
})

it('should update props', async () => {
const wrapper = await mountSuspended(Counter, {
props: {
title: 'Title',
},
})

const title = wrapper.find('h2')
expect(title.text()).toBe('Title')

await wrapper.setProps({ title: 'Title(Updated)' })
expect(title.text()).toBe('Title(Updated)')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, expect, it } from 'vitest'
import { registerEndpoint } from '@nuxt/test-utils/runtime'

describe('registerEndpoint', () => {
it('should mock GET endpoint', async () => {
registerEndpoint('/api/test', () => 'test1')
await expect($fetch('/api/test')).resolves.toBe('test1')
})

it('should mock POST endpoint', async () => {
registerEndpoint('/api/test', {
method: 'POST',
handler: () => 'test2',
})
await expect($fetch('/api/test', { method: 'post' })).resolves.toBe('test2')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { afterEach, describe, expect, it } from 'vitest'
import { fireEvent, cleanup } from '@testing-library/vue'
import { renderSuspended } from '@nuxt/test-utils/runtime'

import App from '~~/app.vue'
import { Counter } from '#components'

describe('renderSuspended', () => {
afterEach(() => {
cleanup()
})

it('should render page', async () => {
const wrapper = await renderSuspended(App, {
route: '/',
})

const title = await wrapper.findByRole('heading', { level: 1 })
expect(title.textContent).toBe('Index')

const link = wrapper.findByRole('link', { name: 'Counter' })
expect((await link).getAttribute('href')).toBe('/counter')
})

it('should render component', async () => {
const wrapper = await renderSuspended(Counter)

const title = await wrapper.findByRole('heading', { level: 2 })
expect(title.textContent).toBe('Counter Component')

const input = await wrapper.findByLabelText<HTMLInputElement>('Count')
expect(input.value).toBe('0')
})

it('should handle event', async () => {
const wrapper = await renderSuspended(Counter)
const input = await wrapper.findByLabelText<HTMLInputElement>('Count')

const button = await wrapper.findByRole('button')
await fireEvent.click(button)

expect(input.value).toBe('1')
})

it('should update props', async () => {
const wrapper = await renderSuspended(Counter, {
props: {
title: 'Title',
},
})

const title = await wrapper.findByRole('heading', { level: 2 })
expect(title.textContent).toBe('Title')

await wrapper.rerender({ title: 'Title(Updated)' })
expect(title.textContent).toBe('Title(Updated)')
})
})
17 changes: 17 additions & 0 deletions examples/app-vitest-workspace/app3/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"files": [],
"references": [
{
"path": "./.nuxt/tsconfig.app.json"
},
{
"path": "./.nuxt/tsconfig.server.json"
},
{
"path": "./.nuxt/tsconfig.shared.json"
},
{
"path": "./.nuxt/tsconfig.node.json"
}
]
}
13 changes: 13 additions & 0 deletions examples/app-vitest-workspace/app3/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { fileURLToPath } from 'node:url'
import { defineVitestProject } from '@nuxt/test-utils/config'

export default defineVitestProject({
test: {
name: 'nuxt-app3',
environmentOptions: {
nuxt: {
rootDir: fileURLToPath(new URL('.', import.meta.url)),
},
},
},
})
2 changes: 1 addition & 1 deletion examples/app-vitest-workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"dev:prepare": "nuxt prepare app1 && nuxt prepare app2",
"dev:prepare": "nuxt prepare app1 && nuxt prepare app2 && nuxt prepare app3",
"postinstall": "pnpm dev:prepare",
"test": "vitest run"
},
Expand Down
5 changes: 5 additions & 0 deletions examples/app-vitest-workspace/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@ import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
projects: ['*/vitest*.config.ts'],
onConsoleLog(log) {
if (log.includes('<Suspense> is an experimental feature')) {
return false
}
},
},
})
Loading