Skip to content

Commit 9c87782

Browse files
committed
test: re-organise test suite
1 parent fe420b9 commit 9c87782

File tree

8 files changed

+236
-254
lines changed

8 files changed

+236
-254
lines changed
Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
1-
import { expect, it } from 'vitest'
1+
import { describe, expect, it } from 'vitest'
22

3-
it('should not mock', () => {
4-
expect(useAutoImportedTarget()).toMatchInlineSnapshot('"the original"')
5-
expect(useAutoImportedNonTarget()).toMatchInlineSnapshot('"the original"')
3+
describe('auto-imports', () => {
4+
it('can use core nuxt composables within test file', () => {
5+
expect(useAppConfig().hey).toMatchInlineSnapshot('false')
6+
})
7+
8+
it('can access auto-imported composables from within project', () => {
9+
const state = useSingleState()
10+
expect(state.value).toMatchInlineSnapshot('{}')
11+
state.value.field = 'new value'
12+
expect(state.value.field).toMatchInlineSnapshot('"new value"')
13+
expect(useSingleState().value.field).toMatchInlineSnapshot('"new value"')
14+
})
15+
16+
it('should not mock imports that are mocked in another test file', () => {
17+
expect(useAutoImportedTarget()).toMatchInlineSnapshot('"the original"')
18+
expect(useAutoImportedNonTarget()).toMatchInlineSnapshot('"the original"')
19+
})
620
})

examples/app-vitest-full/tests/nuxt/export-define-component.spec.ts

Lines changed: 0 additions & 58 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,26 @@
11
import { describe, expect, it } from 'vitest'
22

3-
import { mountSuspended, registerEndpoint } from '@nuxt/test-utils/runtime-utils'
4-
5-
import { listen } from 'listhen'
6-
import { createApp, eventHandler, toNodeListener } from 'h3'
3+
import { mountSuspended } from '@nuxt/test-utils/runtime-utils'
74

85
import App from '~/app.vue'
9-
import FetchComponent from '~/components/FetchComponent.vue'
106
import OptionsComponent from '~/components/OptionsComponent.vue'
117
import WrapperTests from '~/components/WrapperTests.vue'
128

139
import { mount } from '@vue/test-utils'
1410

15-
describe('client-side nuxt features', () => {
16-
it('can use core nuxt composables within test file', () => {
17-
expect(useAppConfig().hey).toMatchInlineSnapshot('false')
18-
})
11+
import ExportDefaultComponent from '~/components/ExportDefaultComponent.vue'
12+
import ExportDefineComponent from '~/components/ExportDefineComponent.vue'
13+
import ExportDefaultWithRenderComponent from '~/components/ExportDefaultWithRenderComponent.vue'
14+
import ExportDefaultReturnsRenderComponent from '~/components/ExportDefaultReturnsRenderComponent.vue'
1915

20-
it('can access auto-imported composables from within project', () => {
21-
const state = useSingleState()
22-
expect(state.value).toMatchInlineSnapshot('{}')
23-
state.value.field = 'new value'
24-
expect(state.value.field).toMatchInlineSnapshot('"new value"')
25-
expect(useSingleState().value.field).toMatchInlineSnapshot('"new value"')
26-
})
27-
28-
it('can access injections from nuxt plugins', () => {
29-
const app = useNuxtApp()
30-
expect(app.$auth.didInject).toMatchInlineSnapshot('true')
31-
expect(app.$router).toBeDefined()
32-
})
16+
const formats = {
17+
ExportDefaultComponent,
18+
ExportDefineComponent,
19+
ExportDefaultWithRenderComponent,
20+
ExportDefaultReturnsRenderComponent,
21+
}
3322

34-
it('defaults to index page', async () => {
35-
expect(useRoute().matched[0].meta).toMatchInlineSnapshot(`
36-
{
37-
"value": "set in index",
38-
}
39-
`)
40-
})
41-
42-
it('allows pushing to other pages', async () => {
43-
await navigateTo('/something')
44-
expect(useNuxtApp().$router.currentRoute.value.path).toEqual('/something')
45-
await nextTick()
46-
expect(useRoute().path).toEqual('/something')
47-
})
48-
})
49-
50-
describe('test utils', () => {
23+
describe('mountSuspended', () => {
5124
it('can mount components within nuxt suspense', async () => {
5225
const component = await mountSuspended(App)
5326
expect(component.html()).toMatchInlineSnapshot(`
@@ -114,19 +87,6 @@ describe('test utils', () => {
11487
`)
11588
})
11689

117-
it('can use $fetch', async () => {
118-
const app = createApp().use(
119-
'/todos/1',
120-
eventHandler(() => ({ id: 1 }))
121-
)
122-
const server = await listen(toNodeListener(app))
123-
const [{ url }] = await server.getURLs()
124-
expect(await $fetch<unknown>('/todos/1', { baseURL: url })).toMatchObject({
125-
id: 1,
126-
})
127-
await server.close()
128-
})
129-
13090
// This test works (you can delete it later)
13191
it('can receive emitted events from components using defineModel', () => {
13292
const component = mount(WrapperTests)
@@ -147,51 +107,19 @@ describe('test utils', () => {
147107
expect(component.vm.testExpose?.()).toBe('thing')
148108
expect(component.vm.someRef).toBe('thing')
149109
})
110+
})
150111

151-
it('can mock fetch requests', async () => {
152-
registerEndpoint('https://jsonplaceholder.typicode.com/todos/1', () => ({
153-
title: 'title from mocked api',
154-
}))
155-
const component = await mountSuspended(FetchComponent)
156-
expect(component.html()).toMatchInlineSnapshot(
157-
'"<div>title from mocked api</div>"'
158-
)
159-
})
160-
161-
it('can mock fetch requests', async () => {
162-
registerEndpoint('/with-query', () => ({
163-
title: 'mocked',
164-
}))
165-
expect(
166-
await $fetch<unknown>('/with-query', { query: { test: true } })
167-
).toMatchObject({
168-
title: 'mocked',
169-
})
170-
})
171-
172-
it('can mock fetch requests with explicit methods', async () => {
173-
registerEndpoint('/method', {
174-
method: 'POST',
175-
handler: () => ({ method: 'POST' }),
176-
})
177-
registerEndpoint('/method', {
178-
method: 'GET',
179-
handler: () => ({ method: 'GET' }),
180-
})
181-
expect(await $fetch<unknown>('/method', { method: 'POST' })).toMatchObject({
182-
method: 'POST',
112+
describe.each(Object.entries(formats))(`%s`, (name, component) => {
113+
it('mounts with props', async () => {
114+
const wrapper = await mountSuspended(component, {
115+
props: {
116+
myProp: 'Hello nuxt-vitest',
117+
},
183118
})
184-
expect(await $fetch<unknown>('/method')).toMatchObject({ method: 'GET' })
185-
})
186-
187-
// TODO: reenable when merging Nuxt 3.7
188-
it.skip('handles nuxt routing', async () => {
189-
const component = await mountSuspended(App, { route: '/test' })
190-
expect(component.html()).toMatchInlineSnapshot(`
191-
"<div>This is an auto-imported component</div>
192-
<div> I am a global component </div>
193-
<div>/test</div>
194-
<a href=\\"/test\\"> Test link </a>"
195-
`)
119+
expect(wrapper.html()).toEqual(`
120+
<div>
121+
<h1>${name}</h1><pre>Hello nuxt-vitest</pre><pre>XHello nuxt-vitest</pre>
122+
</div>
123+
`.trim())
196124
})
197125
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { describe, expect, it } from 'vitest'
2+
3+
describe('plugins', () => {
4+
it('can access injections', () => {
5+
const app = useNuxtApp()
6+
expect(app.$auth.didInject).toMatchInlineSnapshot('true')
7+
expect(app.$router).toBeDefined()
8+
})
9+
})
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { afterEach, describe, expect, it } from 'vitest'
2+
import { renderSuspended } from '@nuxt/test-utils/runtime-utils'
3+
import { cleanup, fireEvent, screen } from '@testing-library/vue'
4+
5+
import App from '~/app.vue'
6+
import OptionsComponent from '~/components/OptionsComponent.vue'
7+
import WrapperTests from '~/components/WrapperTests.vue'
8+
9+
describe('renderSuspended', () => {
10+
afterEach(() => {
11+
// since we're not running with Vitest globals when running the tests
12+
// from inside the test server. This means testing-library cannot
13+
// auto-attach the cleanup go testing globals, and we have to do
14+
// it here manually.
15+
if (process.env.NUXT_VITEST_DEV_TEST) {
16+
cleanup()
17+
}
18+
})
19+
20+
it('can render components within nuxt suspense', async () => {
21+
const { html } = await renderSuspended(App)
22+
expect(html()).toMatchInlineSnapshot(`
23+
"<div id="test-wrapper">
24+
<div>This is an auto-imported component</div>
25+
<div> I am a global component </div>
26+
<div>Index page</div><a href="/test"> Test link </a>
27+
</div>"
28+
`)
29+
})
30+
31+
it('should render default props within nuxt suspense', async () => {
32+
await renderSuspended(OptionsComponent)
33+
expect(screen.getByRole('heading', { level: 2 })).toMatchInlineSnapshot(
34+
`
35+
<h2>
36+
The original
37+
</h2>
38+
`
39+
)
40+
})
41+
42+
it('should render passed props within nuxt suspense', async () => {
43+
await renderSuspended(OptionsComponent, {
44+
props: {
45+
title: 'title from mount suspense props',
46+
},
47+
})
48+
expect(screen.getByRole('heading', { level: 2 })).toMatchInlineSnapshot(
49+
`
50+
<h2>
51+
title from mount suspense props
52+
</h2>
53+
`
54+
)
55+
})
56+
57+
it('can pass slots to rendered components within nuxt suspense', async () => {
58+
const text = 'slot from mount suspense'
59+
await renderSuspended(OptionsComponent, {
60+
slots: {
61+
default: () => text,
62+
},
63+
})
64+
expect(screen.getByText(text)).toBeDefined()
65+
})
66+
67+
it('can receive emitted events from components rendered within nuxt suspense', async () => {
68+
const { emitted } = await renderSuspended(WrapperTests)
69+
const button = screen.getByRole('button', { name: 'Click me!' })
70+
await fireEvent.click(button)
71+
72+
const emittedEvents = emitted()
73+
expect(emittedEvents.click).toMatchObject(
74+
expect.arrayContaining([
75+
expect.arrayContaining([expect.objectContaining({ type: 'click' })]),
76+
])
77+
)
78+
79+
// since this is a native event it doesn't serialize well
80+
delete emittedEvents.click
81+
expect(emittedEvents).toMatchInlineSnapshot(`
82+
{
83+
"customEvent": [
84+
[
85+
"foo",
86+
],
87+
],
88+
"otherEvent": [
89+
[],
90+
],
91+
}
92+
`)
93+
})
94+
})
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { describe, expect, it } from 'vitest'
2+
3+
import { mountSuspended } from '@nuxt/test-utils/runtime-utils'
4+
5+
import App from '~/app.vue'
6+
7+
describe('routing', () => {
8+
it('defaults to index page', async () => {
9+
expect(useRoute().matched[0].meta).toMatchInlineSnapshot(`
10+
{
11+
"value": "set in index",
12+
}
13+
`)
14+
})
15+
16+
it('allows pushing to other pages', async () => {
17+
await navigateTo('/something')
18+
expect(useNuxtApp().$router.currentRoute.value.path).toEqual('/something')
19+
await nextTick()
20+
expect(useRoute().path).toEqual('/something')
21+
})
22+
23+
it('handles nuxt routing', async () => {
24+
const component = await mountSuspended(App, { route: '/test' })
25+
expect(component.html()).toMatchInlineSnapshot(`
26+
"<div>This is an auto-imported component</div>
27+
<div> I am a global component </div>
28+
<div>/test</div>
29+
<a href="/test"> Test link </a>"
30+
`)
31+
})
32+
})

0 commit comments

Comments
 (0)