¡Pruebas!
Cómo probar tu aplicación Nuxt.
Si eres un autor de módulos, puedes encontrar información más específica en la guía para autores de módulos.
Nuxt ofrece soporte de primera clase para pruebas de extremo a extremo y pruebas unitarias de tu aplicación Nuxt a través de @nuxt/test-utils
, una biblioteca de utilidades y configuraciones de prueba que actualmente impulsa las pruebas que usamos en Nuxt y pruebas en todo el ecosistema de módulos.
Instalación
Para permitirte gestionar tus otras dependencias de prueba, @nuxt/test-utils
se envía con varias dependencias opcionales de pares. Por ejemplo:
- puedes elegir entre
happy-dom
yjsdom
para un entorno de ejecución de Nuxt - puedes elegir entre
vitest
,cucumber
,jest
yplaywright
para ejecutores de pruebas de extremo a extremo playwright-core
solo es necesario si deseas usar las utilidades de prueba de navegador integradas (y no estás usando@playwright/test
como tu ejecutor de pruebas)
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
Pruebas Unitarias
Actualmente proporcionamos un entorno para pruebas unitarias de código que necesita un entorno de ejecución de Nuxt. Actualmente solo tiene soporte para vitest
(aunque se agradecería la contribución para agregar otros entornos de ejecución).
Configuración
-
Agrega
@nuxt/test-utils/module
a tu archivonuxt.config
(opcional). Agrega una integración de Vitest a tus Nuxt DevTools que admite ejecutar tus pruebas unitarias en desarrollo.export default defineNuxtConfig({ modules: [ '@nuxt/test-utils/module' ] })
-
Crea un
vitest.config.ts
con el siguiente contenido:import { defineVitestConfig } from '@nuxt/test-utils/config' export default defineVitestConfig({ // cualquier configuración personalizada de Vitest que necesites })
Al importar @nuxt/test-utils
en tu configuración de vitest, es necesario tener "type": "module"
especificado en tu package.json
o renombrar tu archivo de configuración de vitest adecuadamente.
es decir,
vitest.config.m{ts,js}
.
Es posible establecer variables de entorno para pruebas usando el archivo .env.test
.
Usando un Entorno de Ejecución de Nuxt
Por defecto, @nuxt/test-utils
no cambiará tu entorno predeterminado de Vitest, por lo que puedes optar por incluir y ejecutar pruebas de Nuxt junto con otras pruebas unitarias.
Puedes optar por un entorno de Nuxt agregando .nuxt.
al nombre del archivo de prueba (por ejemplo, mi-archivo.nuxt.test.ts
o mi-archivo.nuxt.spec.ts
) o agregando @vitest-environment nuxt
como un comentario directamente en el archivo de prueba.
// @vitest-environment nuxt
import { test } from 'vitest'
test('mi prueba', () => {
// ... ¡prueba con el entorno de Nuxt!
})
Alternativamente, puedes establecer environment: 'nuxt'
en tu configuración de Vitest para habilitar el entorno de Nuxt para todas las pruebas.
// vitest.config.ts
import { fileURLToPath } from 'node:url'
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environment: 'nuxt',
// opcionalmente puedes establecer opciones específicas del entorno de Nuxt
// environmentOptions: {
// nuxt: {
// rootDir: fileURLToPath(new URL('./playground', import.meta.url)),
// domEnvironment: 'happy-dom', // 'happy-dom' (predeterminado) o 'jsdom'
// overrides: {
// // otra configuración de Nuxt que quieras pasar
// }
// }
// }
}
})
Si has establecido environment: 'nuxt'
por defecto, puedes optar por no usar el entorno predeterminado por archivo de prueba según sea necesario.
// @vitest-environment node
import { test } from 'vitest'
test('mi prueba', () => {
// ... ¡prueba sin el entorno de Nuxt!
})
Cuando ejecutas tus pruebas dentro del entorno de Nuxt, se ejecutarán en un entorno happy-dom
o jsdom
. Antes de que se ejecuten tus pruebas, se inicializará una aplicación global de Nuxt (incluyendo, por ejemplo, ejecutar cualquier plugin o código que hayas definido en tu app.vue
).
Esto significa que debes tener especial cuidado de no mutar el estado global en tus pruebas (o, si necesitas hacerlo, restablecerlo después).
🎭 Mocks Integrados
@nuxt/test-utils
proporciona algunos mocks integrados para el entorno DOM.
intersectionObserver
Por defecto true
, crea una clase ficticia sin ninguna funcionalidad para la API de IntersectionObserver
indexedDB
Por defecto false
, utiliza fake-indexeddb
para crear un mock funcional de la API de IndexedDB
Estos se pueden configurar en la sección environmentOptions
de tu archivo vitest.config.ts
:
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environmentOptions: {
nuxt: {
mock: {
intersectionObserver: true,
indexedDb: true,
}
}
}
}
})
🛠️ Ayudantes
@nuxt/test-utils
proporciona una serie de ayudantes para facilitar las pruebas de aplicaciones Nuxt.
mountSuspended
mountSuspended
te permite montar cualquier componente de Vue dentro del entorno de Nuxt, permitiendo la configuración asíncrona y el acceso a inyecciones de tus plugins de Nuxt.
Internamente, mountSuspended
envuelve mount
de @vue/test-utils
, por lo que puedes consultar la documentación de Vue Test Utils para obtener más información sobre las opciones que puedes pasar y cómo usar esta utilidad.
Por ejemplo:
// @noErrors
import { it, expect } from 'vitest'
import type { Component } from 'vue'
declare module '#components' {
export const SomeComponent: Component
}
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { SomeComponent } from '#components'
it('puede montar algún componente', async () => {
const component = await mountSuspended(SomeComponent)
expect(component.text()).toMatchInlineSnapshot(
'"Este es un componente importado automáticamente"'
)
})
// @noErrors
import { it, expect } from 'vitest'
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { mountSuspended } from '@nuxt/test-utils/runtime'
import App from '~/app.vue'
// tests/App.nuxt.spec.ts
it('también puede montar una aplicación', async () => {
const component = await mountSuspended(App, { route: '/test' })
expect(component.html()).toMatchInlineSnapshot(`
"<div>Este es un componente importado automáticamente</div>
<div> Soy un componente global </div>
<div>/</div>
<a href="/test"> Enlace de prueba </a>"
`)
})
renderSuspended
renderSuspended
te permite renderizar cualquier componente de Vue dentro del entorno de Nuxt usando @testing-library/vue
, permitiendo la configuración asíncrona y el acceso a inyecciones de tus plugins de Nuxt.
Esto debe usarse junto con utilidades de Testing Library, por ejemplo, screen
y fireEvent
. Instala @testing-library/vue en tu proyecto para usar estas.
Además, Testing Library también depende de los globales de prueba para la limpieza. Debes activarlos en tu configuración de Vitest.
El componente pasado se renderizará dentro de un <div id="test-wrapper"></div>
.
Ejemplos:
// @noErrors
import { it, expect } from 'vitest'
import type { Component } from 'vue'
declare module '#components' {
export const SomeComponent: Component
}
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { renderSuspended } from '@nuxt/test-utils/runtime'
import { SomeComponent } from '#components'
import { screen } from '@testing-library/vue'
it('puede renderizar algún componente', async () => {
await renderSuspended(SomeComponent)
expect(screen.getByText('Este es un componente importado automáticamente')).toBeDefined()
})
// @noErrors
import { it, expect } from 'vitest'
// ---cut---
// tests/App.nuxt.spec.ts
import { renderSuspended } from '@nuxt/test-utils/runtime'
import App from '~/app.vue'
it('también puede renderizar una aplicación', async () => {
const html = await renderSuspended(App, { route: '/test' })
expect(html).toMatchInlineSnapshot(`
"<div id="test-wrapper">
<div>Este es un componente importado automáticamente</div>
<div> Soy un componente global </div>
<div>Página de índice</div><a href="/test"> Enlace de prueba </a>
</div>"
`)
})
mockNuxtImport
mockNuxtImport
te permite simular la funcionalidad de importación automática de Nuxt. Por ejemplo, para simular useStorage
, puedes hacerlo así:
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
return { value: 'almacenamiento simulado' }
}
})
// tus pruebas aquí
mockNuxtImport
solo se puede usar una vez por importación simulada por archivo de prueba. En realidad, es un macro que se transforma en vi.mock
y vi.mock
se eleva, como se describe en la documentación de Vitest.
Si necesitas simular una importación de Nuxt y proporcionar diferentes implementaciones entre pruebas, puedes hacerlo creando y exponiendo tus simulaciones usando vi.hoisted
, y luego usar esas simulaciones en mockNuxtImport
. Luego tienes acceso a las importaciones simuladas y puedes cambiar la implementación entre pruebas. Ten cuidado de restaurar las simulaciones antes o después de cada prueba para deshacer los cambios de estado de las simulaciones entre ejecuciones.
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
const { useStorageMock } = vi.hoisted(() => {
return {
useStorageMock: vi.fn(() => {
return { value: 'almacenamiento simulado'}
})
}
})
mockNuxtImport('useStorage', () => {
return useStorageMock
})
// Luego, dentro de una prueba
useStorageMock.mockImplementation(() => {
return { value: 'algo más' }
})
mockComponent
mockComponent
te permite simular el componente de Nuxt.
El primer argumento puede ser el nombre del componente en PascalCase, o la ruta relativa del componente.
El segundo argumento es una función de fábrica que devuelve el componente simulado.
Por ejemplo, para simular MyComponent
, puedes:
import { mockComponent } from '@nuxt/test-utils/runtime'
mockComponent('MyComponent', {
props: {
value: String
},
setup(props) {
// ...
}
})
// la ruta relativa o alias también funciona
mockComponent('~/components/my-component.vue', async () => {
// o una función de fábrica
return defineComponent({
setup(props) {
// ...
}
})
})
// o puedes usar SFC para redirigir a un componente simulado
mockComponent('MyComponent', () => import('./MockComponent.vue'))
// tus pruebas aquí
Nota: No puedes referenciar variables locales en la función de fábrica ya que se elevan. Si necesitas acceder a las API de Vue u otras variables, debes importarlas en tu función de fábrica.
import { mockComponent } from '@nuxt/test-utils/runtime'
mockComponent('MyComponent', async () => {
const { ref, h } = await import('vue')
return defineComponent({
setup(props) {
const counter = ref(0)
return () => h('div', null, counter.value)
}
})
})
registerEndpoint
registerEndpoint
te permite crear un endpoint de Nitro que devuelve datos simulados. Puede ser útil si deseas probar un componente que realiza solicitudes a una API para mostrar algunos datos.
El primer argumento es el nombre del endpoint (por ejemplo, /test/
).
El segundo argumento es una función de fábrica que devuelve los datos simulados.
Por ejemplo, para simular el endpoint /test/
, puedes hacer:
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint('/test/', () => ({
test: 'campo-de-prueba'
}))
Por defecto, tu solicitud se realizará usando el método GET
. Puedes usar otro método estableciendo un objeto como el segundo argumento en lugar de una función.
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint('/test/', {
method: 'POST',
handler: () => ({ test: 'campo-de-prueba' })
})
Nota: Si tus solicitudes en un componente van a una API externa, puedes usar
baseURL
y luego dejarla vacía usando Nuxt Environment Override Config ($test
) para que todas tus solicitudes vayan al servidor Nitro.
Conflicto con Pruebas de Extremo a Extremo
@nuxt/test-utils/runtime
y @nuxt/test-utils/e2e
necesitan ejecutarse en diferentes entornos de prueba y, por lo tanto, no se pueden usar en el mismo archivo.
Si deseas usar tanto la funcionalidad de pruebas de extremo a extremo como de pruebas unitarias de @nuxt/test-utils
, puedes dividir tus pruebas en archivos separados. Luego, especifica un entorno de prueba por archivo con el comentario especial // @vitest-environment nuxt
, o nombra tus archivos de prueba de unidad de entorno de ejecución con la extensión .nuxt.spec.ts
.
app.nuxt.spec.ts
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
return { value: 'almacenamiento simulado' }
}
})
app.e2e.spec.ts
import { setup, $fetch } from '@nuxt/test-utils/e2e'
await setup({
setupTimeout: 10000,
})
// ...
Usando @vue/test-utils
Si prefieres usar @vue/test-utils
por sí solo para pruebas unitarias en Nuxt, y solo estás probando componentes que no dependen de composables de Nuxt, importaciones automáticas o contexto, puedes seguir estos pasos para configurarlo.
-
Instala las dependencias necesarias
npm i --save-dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
-
Crea un
vitest.config.ts
con el siguiente contenido:import { defineConfig } from 'vitest/config' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], test: { environment: 'happy-dom', }, });
-
Agrega un nuevo comando para pruebas en tu
package.json
"scripts": { "build": "nuxt build", "dev": "nuxt dev", ... "test": "vitest" },
-
Crea un componente simple
<HelloWorld>
components/HelloWorld.vue
con el siguiente contenido:<template> <p>Hola mundo</p> </template>
-
Crea una prueba unitaria simple para este componente recién creado
~/components/HelloWorld.spec.ts
import { describe, it, expect } from 'vitest' import { mount } from '@vue/test-utils' import HelloWorld from './HelloWorld.vue' describe('HelloWorld', () => { it('el componente renderiza Hola mundo correctamente', () => { const wrapper = mount(HelloWorld) expect(wrapper.text()).toContain('Hola mundo') }) })
-
Ejecuta el comando de vitest
npm run test
¡Felicidades, estás listo para comenzar a realizar pruebas unitarias con @vue/test-utils
en Nuxt! ¡Felices pruebas!
Pruebas de Extremo a Extremo
Para pruebas de extremo a extremo, soportamos Vitest, Jest, Cucumber y Playwright como ejecutores de pruebas.
Configuración
En cada bloque describe
donde estés aprovechando los métodos de ayuda de @nuxt/test-utils/e2e
, necesitarás configurar el contexto de prueba antes de comenzar.
import { describe, test } from 'vitest'
import { setup, $fetch } from '@nuxt/test-utils/e2e'
describe('Mi prueba', async () => {
await setup({
// opciones del contexto de prueba
})
test('mi prueba', () => {
// ...
})
})
Detrás de escena, setup
realiza una serie de tareas en beforeAll
, beforeEach
, afterEach
y afterAll
para configurar correctamente el entorno de prueba de Nuxt.
Por favor, usa las opciones a continuación para el método setup
.
Configuración de Nuxt
rootDir
: Ruta a un directorio con una aplicación Nuxt que se pondrá a prueba.- Tipo:
string
- Predeterminado:
'.'
- Tipo:
configFile
: Nombre del archivo de configuración.- Tipo:
string
- Predeterminado:
'nuxt.config'
- Tipo:
Tiempos
setupTimeout
: La cantidad de tiempo (en milisegundos) para permitir quesetupTest
complete su trabajo (que podría incluir construir o generar archivos para una aplicación Nuxt, dependiendo de las opciones que se pasen).- Tipo:
number
- Predeterminado:
60000
- Tipo:
Características
-
build
: Si se debe ejecutar un paso de construcción separado.- Tipo:
boolean
- Predeterminado:
true
(false
sibrowser
oserver
están deshabilitados, o si se proporciona unhost
)
- Tipo:
-
server
: Si se debe lanzar un servidor para responder a las solicitudes en el conjunto de pruebas.- Tipo:
boolean
- Predeterminado:
true
(false
si se proporciona unhost
)
- Tipo:
-
port
: Si se proporciona, establece el puerto del servidor de prueba lanzado al valor.- Tipo:
number | undefined
- Predeterminado:
undefined
- Tipo:
-
host
: Si se proporciona, una URL para usar como objetivo de prueba en lugar de construir y ejecutar un nuevo servidor. Útil para ejecutar pruebas de extremo a extremo "reales" contra una versión desplegada de tu aplicación, o contra un servidor local ya en ejecución (lo que puede proporcionar una reducción significativa en los tiempos de ejecución de las pruebas). Consulta el ejemplo de extremo a extremo de host objetivo a continuación.- Tipo:
string
- Predeterminado:
undefined
- Tipo:
-
browser
: Internamente, las utilidades de prueba de Nuxt usanplaywright
para llevar a cabo pruebas de navegador. Si esta opción está configurada, se lanzará un navegador y se podrá controlar en el conjunto de pruebas posterior.- Tipo:
boolean
- Predeterminado:
false
- Tipo:
-
browserOptions
- Tipo:
object
con las siguientes propiedadestype
: El tipo de navegador a lanzar - ya seachromium
,firefox
owebkit
launch
:object
de opciones que se pasarán a playwright al lanzar el navegador. Consulta referencia completa de la API.
- Tipo:
-
runner
: Especifica el ejecutor para el conjunto de pruebas. Actualmente, se recomienda Vitest.- Tipo:
'vitest' | 'jest' | 'cucumber'
- Predeterminado:
'vitest'
- Tipo:
Ejemplo de extremo a extremo de host objetivo
Un caso de uso común para las pruebas de extremo a extremo es ejecutar las pruebas contra una aplicación desplegada que se ejecuta en el mismo entorno que normalmente se usa para Producción.
Para el desarrollo local o los pipelines de despliegue automatizados, probar contra un servidor local separado puede ser más eficiente y generalmente es más rápido que permitir que el marco de prueba reconstruya entre pruebas.
Para utilizar un host objetivo separado para pruebas de extremo a extremo, simplemente proporciona la propiedad host
de la función setup
con la URL deseada.
import { setup, createPage } from '@nuxt/test-utils/e2e'
import { describe, it, expect } from 'vitest'
describe('página de inicio de sesión', async () => {
await setup({
host: 'http://localhost:8787',
})
it('muestra los campos de correo electrónico y contraseña', async () => {
const page = await createPage('/login')
expect(await page.getByTestId('email').isVisible()).toBe(true)
expect(await page.getByTestId('password').isVisible()).toBe(true)
})
})
APIs
$fetch(url)
Obtén el HTML de una página renderizada en el servidor.
import { $fetch } from '@nuxt/test-utils/e2e'
const html = await $fetch('/')
fetch(url)
Obtén la respuesta de una página renderizada en el servidor.
import { fetch } from '@nuxt/test-utils/e2e'
const res = await fetch('/')
const { body, headers } = res
url(path)
Obtén la URL completa para una página dada (incluyendo el puerto en el que se está ejecutando el servidor de prueba).
import { url } from '@nuxt/test-utils/e2e'
const pageUrl = url('/page')
// 'http://localhost:6840/page'
Pruebas en un Navegador
Proporcionamos soporte integrado usando Playwright dentro de @nuxt/test-utils
, ya sea programáticamente o a través del ejecutor de pruebas de Playwright.
createPage(url)
Dentro de vitest
, jest
o cucumber
, puedes crear una instancia de navegador de Playwright configurada con createPage
, y (opcionalmente) apuntarla a una ruta desde el servidor en ejecución. Puedes encontrar más información sobre los métodos de la API disponibles en la documentación de Playwright.
import { createPage } from '@nuxt/test-utils/e2e'
const page = await createPage('/page')
// puedes acceder a todas las APIs de Playwright desde la variable `page`
Pruebas con el Ejecutador de Pruebas de Playwright
También proporcionamos soporte de primera clase para probar Nuxt dentro del ejecutor de pruebas de Playwright.
npm i --save-dev @playwright/test @nuxt/test-utils
Puedes proporcionar configuración global de Nuxt, con los mismos detalles de configuración que la función setup()
mencionada anteriormente en esta sección.
import { fileURLToPath } from 'node:url'
import { defineConfig, devices } from '@playwright/test'
import type { ConfigOptions } from '@nuxt/test-utils/playwright'
export default defineConfig<ConfigOptions>({
use: {
nuxt: {
rootDir: fileURLToPath(new URL('.', import.meta.url))
}
},
// ...
})
Tu archivo de prueba debería usar expect
y test
directamente desde @nuxt/test-utils/playwright
:
import { expect, test } from '@nuxt/test-utils/playwright'
test('prueba', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('¡Bienvenido a Playwright!')
})
Alternativamente, puedes configurar tu servidor Nuxt directamente dentro de tu archivo de prueba:
import { expect, test } from '@nuxt/test-utils/playwright'
test.use({
nuxt: {
rootDir: fileURLToPath(new URL('..', import.meta.url))
}
})
test('prueba', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('¡Bienvenido a Playwright!')
})
※Esta página es una traducción no oficial de la documentación oficial de Nuxt.js.
La página correspondiente en la documentación oficial está aquí:
https://nuxt.com/docs/3.x/getting-started/testing