diff --git a/examples/content/components/ComponentWithProse.vue b/examples/content/components/ComponentWithProse.vue new file mode 100644 index 000000000..4aa7397d2 --- /dev/null +++ b/examples/content/components/ComponentWithProse.vue @@ -0,0 +1,11 @@ + + + diff --git a/examples/content/components/ComponentWithUseRuntimeConfig.vue b/examples/content/components/ComponentWithUseRuntimeConfig.vue new file mode 100644 index 000000000..d746f0e74 --- /dev/null +++ b/examples/content/components/ComponentWithUseRuntimeConfig.vue @@ -0,0 +1,8 @@ + + + diff --git a/examples/content/components/SomeComponent.vue b/examples/content/components/SomeComponent.vue new file mode 100644 index 000000000..18e190625 --- /dev/null +++ b/examples/content/components/SomeComponent.vue @@ -0,0 +1,3 @@ + diff --git a/examples/content/package.json b/examples/content/package.json index e6137a303..f921e8e0e 100644 --- a/examples/content/package.json +++ b/examples/content/package.json @@ -1,4 +1,5 @@ { + "name": "example-app-vitest-content", "private": true, "type": "module", "scripts": { @@ -6,13 +7,17 @@ "dev": "nuxt dev", "dev:prepare": "nuxt prepare", "generate": "nuxt generate", - "test": "vitest run", + "test": "pnpm test:nuxt-environment && pnpm test:browser", + "test:browser": "VITEST_BROWSER_ENABLED=true vitest run", + "test:nuxt-environment": "vitest run", "preview": "nuxt preview" }, "devDependencies": { "@nuxt/content": "3.5.1", "@nuxt/test-utils": "latest", + "@vitest/browser": "3.1.3", "nuxt": "3.17.3", - "vitest": "3.1.3" + "vitest": "3.1.3", + "vitest-browser-vue": "0.2.0" } } diff --git a/examples/content/tests/browser/index.spec.ts b/examples/content/tests/browser/index.spec.ts new file mode 100644 index 000000000..699a67dc9 --- /dev/null +++ b/examples/content/tests/browser/index.spec.ts @@ -0,0 +1,30 @@ +import { describe, expect, it } from 'vitest' +import { mockNuxtImport, mountSuspended } from '@nuxt/test-utils/runtime' +import { render } from 'vitest-browser-vue' +import App from '~/app.vue' + +// Example usage: queryCollection(pages).path('/').first() +mockNuxtImport('queryCollection', () => (_id: string) => ({ + path: (_path: string) => ({ + first: () => ({ + title: 'My page', + }), + }), +})) + +describe('App', () => { + it('works with mountSuspended', async () => { + const component = await mountSuspended(App) + expect(component.html()).toMatchInlineSnapshot(` + "
Index page
+
title: My page
" + `) + }) + + // TODO: render does not currently support + it.skip('works with vitest-browser-vue', () => { + const { getByText } = render(App) + expect(getByText('Index page')).toBeInTheDocument() + expect(getByText('title: My page')).toBeInTheDocument() + }) +}) diff --git a/examples/content/tests/browser/mount.spec.ts b/examples/content/tests/browser/mount.spec.ts new file mode 100644 index 000000000..4fd11b613 --- /dev/null +++ b/examples/content/tests/browser/mount.spec.ts @@ -0,0 +1,31 @@ +import { expect, it } from 'vitest' +import { render } from 'vitest-browser-vue' +import { SomeComponent, ProseH3, ProseP, ComponentWithUseRuntimeConfig, ComponentWithProse } from '#components' + +it('should render any component', () => { + const { getByText } = render(SomeComponent) + expect(getByText('This is an auto-imported component')).toBeInTheDocument() +}) + +it('should render a ProseP component', () => { + const { getByText } = render(ProseP, { slots: { default: 'This is a Prose Paragraph component' } }) + expect(getByText('This is a Prose Paragraph component')).toBeInTheDocument() +}) + +it('should render a ProseH3 component', () => { + const { getByText } = render(ProseH3, { slots: { default: 'This is a Prose heading component' } }) + expect(getByText('This is a Prose heading component')).toBeInTheDocument() +}) + +it('should render a ComponentWithUseRuntimeConfig component', () => { + const { getByText } = render(ComponentWithUseRuntimeConfig) + expect(getByText('Use Runtime Config')).toBeInTheDocument() +}) + +it('should render a ComponentWithProse component', () => { + const headingText = 'Text rendered within ProseH3' + const paragraphText = 'Text rendered within paragraph' + const { getByText } = render(ComponentWithProse, { props: { heading: headingText, content: paragraphText } }) + expect(getByText(headingText)).toBeInTheDocument() + expect(getByText(paragraphText)).toBeInTheDocument() +}) diff --git a/examples/content/tests/mount.spec.ts b/examples/content/tests/mount.spec.ts new file mode 100644 index 000000000..c7bc9d0de --- /dev/null +++ b/examples/content/tests/mount.spec.ts @@ -0,0 +1,33 @@ +import { expect, it } from 'vitest' +import { mountSuspended } from '@nuxt/test-utils/runtime' +import { ComponentWithUseRuntimeConfig, ComponentWithProse, SomeComponent, ProseH3, ProseP } from '#components' + +it('should render any component', async () => { + const component = await mountSuspended(SomeComponent) + expect(component.html()).toContain('This is an auto-imported component') +}) + +it('should render a ProseH3 component', async () => { + const headingText = 'This is a Prose Heading component' + const component = await mountSuspended(ProseH3, { slots: { default: headingText } }) + expect(component.html()).toContain(headingText) +}) + +it('should render a ProseP component', async () => { + const paragraphText = 'This is a Prose Paragraph component' + const component = await mountSuspended(ProseP, { slots: { default: paragraphText } }) + expect(component.html()).toContain(paragraphText) +}) + +it('should render a ComponentWithUseRuntimeConfig component', async () => { + const component = await mountSuspended(ComponentWithUseRuntimeConfig) + expect(component.html()).toContain('Use Runtime Config') +}) + +it('should render a ComponentWithProse component', async () => { + const headingText = 'Text rendered within ProseH3' + const paragraphText = 'Text rendered within p' + const component = await mountSuspended(ComponentWithProse, { props: { heading: headingText, content: paragraphText } }) + expect(component.html()).toContain(headingText) + expect(component.html()).toContain(paragraphText) +}) diff --git a/examples/content/vitest.config.ts b/examples/content/vitest.config.ts index 6410ffd85..88ec45b06 100644 --- a/examples/content/vitest.config.ts +++ b/examples/content/vitest.config.ts @@ -1,7 +1,21 @@ import { defineVitestConfig } from '@nuxt/test-utils/config' -export default defineVitestConfig({ - test: { - environment: 'nuxt', +const browserConfig = { + browser: { + enabled: true, + provider: 'playwright', + instances: [{ browser: 'chromium' }], }, + environment: 'nuxt', + include: ['tests/browser/**/*.spec.ts'], + setupFiles: ['vitest-browser-vue'], +} + +const defaultConfig = { + environment: 'nuxt', + exclude: ['tests/browser/**/*.spec.ts', 'node_modules/**', 'dist/**', '.data/**'], +} + +export default defineVitestConfig({ + test: process.env.VITEST_BROWSER_ENABLED === 'true' ? browserConfig : defaultConfig, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b329b42e6..e637f51f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -388,12 +388,18 @@ importers: '@nuxt/test-utils': specifier: workspace:* version: link:../.. + '@vitest/browser': + specifier: 3.1.3 + version: 3.1.3(playwright@1.52.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.1))(vitest@3.1.3) nuxt: specifier: 3.17.3 version: 3.17.3(@parcel/watcher@2.5.1)(@types/node@22.15.17)(better-sqlite3@11.9.1)(db0@0.3.2(better-sqlite3@11.9.1))(encoding@0.1.13)(eslint@9.26.0(jiti@2.4.2))(idb-keyval@6.2.2)(ioredis@5.6.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.40.2)(terser@5.39.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.1))(vue-tsc@2.2.10(typescript@5.8.3))(yaml@2.7.1) vitest: specifier: 3.1.3 version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.17)(@vitest/browser@3.1.3)(happy-dom@17.4.7)(jiti@2.4.2)(jsdom@26.1.0)(terser@5.39.0)(yaml@2.7.1) + vitest-browser-vue: + specifier: 0.2.0 + version: 0.2.0(@vitest/browser@3.1.3)(vitest@3.1.3)(vue@3.5.13(typescript@5.8.3)) examples/i18n: devDependencies: