Testando!
Como testar sua aplicação Nuxt.
Se você é um autor de módulo, pode encontrar informações mais específicas no Guia do Autor de Módulos.
O Nuxt oferece suporte de primeira classe para testes de ponta a ponta e testes unitários de sua aplicação Nuxt via @nuxt/test-utils
, uma biblioteca de utilitários de teste e configuração que atualmente alimenta os testes que usamos no próprio Nuxt e testes em todo o ecossistema de módulos.
Instalação
Para permitir que você gerencie suas outras dependências de teste, @nuxt/test-utils
é fornecido com várias dependências peer opcionais. Por exemplo:
- você pode escolher entre
happy-dom
ejsdom
para um ambiente de execução Nuxt - você pode escolher entre
vitest
,cucumber
,jest
eplaywright
para executores de teste de ponta a ponta playwright-core
é necessário apenas se você desejar usar as utilidades de teste de navegador integradas (e não estiver usando@playwright/test
como seu executor de teste)
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
Testes Unitários
Atualmente, fornecemos um ambiente para testes unitários de código que precisa de um ambiente de execução Nuxt. Atualmente, apenas tem suporte para vitest
(embora contribuições para adicionar outros ambientes sejam bem-vindas).
Configuração
-
Adicione
@nuxt/test-utils/module
ao seu arquivonuxt.config
(opcional). Ele adiciona uma integração Vitest às suas Ferramentas de Desenvolvimento Nuxt, que suporta a execução de seus testes unitários em desenvolvimento.export default defineNuxtConfig({ modules: [ '@nuxt/test-utils/module' ] })
-
Crie um
vitest.config.ts
com o seguinte conteúdo:import { defineVitestConfig } from '@nuxt/test-utils/config' export default defineVitestConfig({ // qualquer configuração personalizada do Vitest que você precisar })
Ao importar @nuxt/test-utils
em sua configuração vitest, é necessário ter "type": "module"
especificado em seu package.json
ou renomear seu arquivo de configuração vitest adequadamente.
ou seja,
vitest.config.m{ts,js}
.
É possível definir variáveis de ambiente para teste usando o arquivo .env.test
.
Usando um Ambiente de Execução Nuxt
Por padrão, @nuxt/test-utils
não alterará seu ambiente Vitest padrão, para que você possa optar por testes Nuxt em conjunto com outros testes unitários.
Você pode optar por um ambiente Nuxt adicionando .nuxt.
ao nome do arquivo de teste (por exemplo, my-file.nuxt.test.ts
ou my-file.nuxt.spec.ts
) ou adicionando @vitest-environment nuxt
como um comentário diretamente no arquivo de teste.
// @vitest-environment nuxt
import { test } from 'vitest'
test('meu teste', () => {
// ... teste com ambiente Nuxt!
})
Alternativamente, você pode definir environment: 'nuxt'
em sua configuração Vitest para habilitar o ambiente Nuxt para todos os testes.
// vitest.config.ts
import { fileURLToPath } from 'node:url'
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environment: 'nuxt',
// você pode opcionalmente definir opções de ambiente específicas do Nuxt
// environmentOptions: {
// nuxt: {
// rootDir: fileURLToPath(new URL('./playground', import.meta.url)),
// domEnvironment: 'happy-dom', // 'happy-dom' (padrão) ou 'jsdom'
// overrides: {
// // outras configurações Nuxt que você deseja passar
// }
// }
// }
}
})
Se você definiu environment: 'nuxt'
por padrão, pode então optar por não usar o ambiente padrão por arquivo de teste conforme necessário.
// @vitest-environment node
import { test } from 'vitest'
test('meu teste', () => {
// ... teste sem ambiente Nuxt!
})
Quando você executa seus testes dentro do ambiente Nuxt, eles serão executados em um ambiente happy-dom
ou jsdom
. Antes de seus testes serem executados, um aplicativo Nuxt global será inicializado (incluindo, por exemplo, a execução de quaisquer plugins ou código que você definiu em seu app.vue
).
Isso significa que você deve ter cuidado especial para não alterar o estado global em seus testes (ou, se precisar, para redefini-lo posteriormente).
🎭 Mocks Integrados
@nuxt/test-utils
fornece alguns mocks integrados para o ambiente DOM.
intersectionObserver
Padrão true
, cria uma classe fictícia sem qualquer funcionalidade para a API IntersectionObserver
indexedDB
Padrão false
, usa fake-indexeddb
para criar um mock funcional da API IndexedDB
Esses podem ser configurados na seção environmentOptions
do seu arquivo vitest.config.ts
:
import { defineVitestConfig } from '@nuxt/test-utils/config'
export default defineVitestConfig({
test: {
environmentOptions: {
nuxt: {
mock: {
intersectionObserver: true,
indexedDb: true,
}
}
}
}
})
🛠️ Auxiliares
@nuxt/test-utils
fornece uma série de auxiliares para facilitar o teste de aplicativos Nuxt.
mountSuspended
mountSuspended
permite que você monte qualquer componente Vue dentro do ambiente Nuxt, permitindo configuração assíncrona e acesso a injeções de seus plugins Nuxt.
Por baixo dos panos, mountSuspended
envolve mount
de @vue/test-utils
, então você pode conferir a documentação do Vue Test Utils para mais informações sobre as opções que você pode passar e como usar essa utilidade.
Por exemplo:
// @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('pode montar algum componente', async () => {
const component = await mountSuspended(SomeComponent)
expect(component.text()).toMatchInlineSnapshot(
'"Este é um componente importado automaticamente"'
)
})
// @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('também pode montar um aplicativo', async () => {
const component = await mountSuspended(App, { route: '/test' })
expect(component.html()).toMatchInlineSnapshot(`
"<div>Este é um componente importado automaticamente</div>
<div> Eu sou um componente global </div>
<div>/</div>
<a href="/test"> Link de teste </a>"
`)
})
renderSuspended
renderSuspended
permite que você renderize qualquer componente Vue dentro do ambiente Nuxt usando @testing-library/vue
, permitindo configuração assíncrona e acesso a injeções de seus plugins Nuxt.
Isso deve ser usado junto com utilitários da Testing Library, por exemplo, screen
e fireEvent
. Instale @testing-library/vue em seu projeto para usar esses.
Além disso, a Testing Library também depende de globais de teste para limpeza. Você deve ativá-los em sua configuração Vitest.
O componente passado será renderizado dentro de um <div id="test-wrapper"></div>
.
Exemplos:
// @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('pode renderizar algum componente', async () => {
await renderSuspended(SomeComponent)
expect(screen.getByText('Este é um componente importado automaticamente')).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('também pode renderizar um aplicativo', async () => {
const html = await renderSuspended(App, { route: '/test' })
expect(html).toMatchInlineSnapshot(`
"<div id="test-wrapper">
<div>Este é um componente importado automaticamente</div>
<div> Eu sou um componente global </div>
<div>Página inicial</div><a href="/test"> Link de teste </a>
</div>"
`)
})
mockNuxtImport
mockNuxtImport
permite que você faça mock da funcionalidade de importação automática do Nuxt. Por exemplo, para fazer mock de useStorage
, você pode fazer assim:
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
return { value: 'armazenamento simulado' }
}
})
// seus testes aqui
mockNuxtImport
só pode ser usado uma vez por importação simulada por arquivo de teste. Na verdade, é um macro que é transformado em vi.mock
e vi.mock
é elevado, conforme descrito na documentação do Vitest.
Se você precisar fazer mock de uma importação Nuxt e fornecer implementações diferentes entre os testes, pode fazê-lo criando e expondo seus mocks usando vi.hoisted
, e então usar esses mocks em mockNuxtImport
. Você então tem acesso às importações simuladas e pode alterar a implementação entre os testes. Tenha cuidado para restaurar os mocks antes ou depois de cada teste para desfazer as alterações de estado do mock entre as execuções.
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
const { useStorageMock } = vi.hoisted(() => {
return {
useStorageMock: vi.fn(() => {
return { value: 'armazenamento simulado'}
})
}
})
mockNuxtImport('useStorage', () => {
return useStorageMock
})
// Então, dentro de um teste
useStorageMock.mockImplementation(() => {
return { value: 'algo diferente' }
})
mockComponent
mockComponent
permite que você faça mock do componente do Nuxt.
O primeiro argumento pode ser o nome do componente em PascalCase ou o caminho relativo do componente.
O segundo argumento é uma função de fábrica que retorna o componente simulado.
Por exemplo, para fazer mock de MyComponent
, você pode:
import { mockComponent } from '@nuxt/test-utils/runtime'
mockComponent('MyComponent', {
props: {
value: String
},
setup(props) {
// ...
}
})
// caminho relativo ou alias também funciona
mockComponent('~/components/my-component.vue', async () => {
// ou uma função de fábrica
return defineComponent({
setup(props) {
// ...
}
})
})
// ou você pode usar SFC para redirecionar para um componente simulado
mockComponent('MyComponent', () => import('./MockComponent.vue'))
// seus testes aqui
Nota: Você não pode referenciar variáveis locais na função de fábrica, pois elas são elevadas. Se você precisar acessar APIs do Vue ou outras variáveis, precisará importá-las em sua função 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
permite que você crie um endpoint Nitro que retorna dados simulados. Pode ser útil se você quiser testar um componente que faz solicitações a uma API para exibir alguns dados.
O primeiro argumento é o nome do endpoint (por exemplo, /test/
).
O segundo argumento é uma função de fábrica que retorna os dados simulados.
Por exemplo, para fazer mock do endpoint /test/
, você pode fazer:
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint('/test/', () => ({
test: 'campo-de-teste'
}))
Por padrão, sua solicitação será feita usando o método GET
. Você pode usar outro método definindo um objeto como o segundo argumento em vez de uma função.
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint('/test/', {
method: 'POST',
handler: () => ({ test: 'campo-de-teste' })
})
Nota: Se suas solicitações em um componente forem para uma API externa, você pode usar
baseURL
e então deixá-lo vazio usando Configuração de Substituição de Ambiente Nuxt ($test
) para que todas as suas solicitações sejam direcionadas ao servidor Nitro.
Conflito com Testes de Ponta a Ponta
@nuxt/test-utils/runtime
e @nuxt/test-utils/e2e
precisam ser executados em ambientes de teste diferentes e, portanto, não podem ser usados no mesmo arquivo.
Se você gostaria de usar tanto a funcionalidade de teste de ponta a ponta quanto de teste unitário de @nuxt/test-utils
, pode dividir seus testes em arquivos separados. Você pode então especificar um ambiente de teste por arquivo com o comentário especial // @vitest-environment nuxt
, ou nomear seus arquivos de teste unitário de tempo de execução com a extensão .nuxt.spec.ts
.
app.nuxt.spec.ts
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
return { value: 'armazenamento simulado' }
}
})
app.e2e.spec.ts
import { setup, $fetch } from '@nuxt/test-utils/e2e'
await setup({
setupTimeout: 10000,
})
// ...
Usando @vue/test-utils
Se você preferir usar @vue/test-utils
por conta própria para testes unitários no Nuxt, e estiver testando apenas componentes que não dependem de composables Nuxt, importações automáticas ou contexto, pode seguir estas etapas para configurá-lo.
-
Instale as dependências necessárias
npm i --save-dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
-
Crie um
vitest.config.ts
com o seguinte conteúdo:import { defineConfig } from 'vitest/config' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], test: { environment: 'happy-dom', }, });
-
Adicione um novo comando para teste em seu
package.json
"scripts": { "build": "nuxt build", "dev": "nuxt dev", ... "test": "vitest" },
-
Crie um componente simples
<HelloWorld>
components/HelloWorld.vue
com o seguinte conteúdo:<template> <p>Olá mundo</p> </template>
-
Crie um teste unitário simples para este novo componente
~/components/HelloWorld.spec.ts
import { describe, it, expect } from 'vitest' import { mount } from '@vue/test-utils' import HelloWorld from './HelloWorld.vue' describe('HelloWorld', () => { it('o componente renderiza Olá mundo corretamente', () => { const wrapper = mount(HelloWorld) expect(wrapper.text()).toContain('Olá mundo') }) })
-
Execute o comando vitest
npm run test
Parabéns, você está pronto para começar a testar unidades com @vue/test-utils
no Nuxt! Feliz teste!
Testes de Ponta a Ponta
Para testes de ponta a ponta, suportamos Vitest, Jest, Cucumber e Playwright como executores de teste.
Configuração
Em cada bloco describe
onde você está aproveitando os métodos auxiliares de @nuxt/test-utils/e2e
, você precisará configurar o contexto do teste antes de começar.
import { describe, test } from 'vitest'
import { setup, $fetch } from '@nuxt/test-utils/e2e'
describe('Meu teste', async () => {
await setup({
// opções de contexto de teste
})
test('meu teste', () => {
// ...
})
})
Nos bastidores, setup
realiza uma série de tarefas em beforeAll
, beforeEach
, afterEach
e afterAll
para configurar corretamente o ambiente de teste Nuxt.
Por favor, use as opções abaixo para o método setup
.
Configuração Nuxt
rootDir
: Caminho para um diretório com um aplicativo Nuxt a ser testado.- Tipo:
string
- Padrão:
'.'
- Tipo:
configFile
: Nome do arquivo de configuração.- Tipo:
string
- Padrão:
'nuxt.config'
- Tipo:
Temporizações
setupTimeout
: A quantidade de tempo (em milissegundos) para permitir quesetupTest
conclua seu trabalho (que pode incluir a construção ou geração de arquivos para um aplicativo Nuxt, dependendo das opções que são passadas).- Tipo:
number
- Padrão:
60000
- Tipo:
Funcionalidades
-
build
: Se deve executar uma etapa de construção separada.- Tipo:
boolean
- Padrão:
true
(false
sebrowser
ouserver
estiver desativado, ou se umhost
for fornecido)
- Tipo:
-
server
: Se deve lançar um servidor para responder a solicitações na suíte de testes.- Tipo:
boolean
- Padrão:
true
(false
se umhost
for fornecido)
- Tipo:
-
port
: Se fornecido, define a porta do servidor de teste lançado para o valor.- Tipo:
number | undefined
- Padrão:
undefined
- Tipo:
-
host
: Se fornecido, uma URL para usar como alvo de teste em vez de construir e executar um novo servidor. Útil para executar testes de ponta a ponta "reais" contra uma versão implantada de sua aplicação, ou contra um servidor local já em execução (o que pode proporcionar uma redução significativa nos tempos de execução dos testes). Veja o exemplo de ponta a ponta do host de destino abaixo.- Tipo:
string
- Padrão:
undefined
- Tipo:
-
browser
: Sob o capô, os utilitários de teste Nuxt usamplaywright
para realizar testes de navegador. Se esta opção for definida, um navegador será lançado e pode ser controlado na suíte de testes subsequente.- Tipo:
boolean
- Padrão:
false
- Tipo:
-
browserOptions
- Tipo:
object
com as seguintes propriedadestype
: O tipo de navegador a ser lançado -chromium
,firefox
ouwebkit
launch
:object
de opções que serão passadas para o playwright ao lançar o navegador. Veja referência completa da API.
- Tipo:
-
runner
: Especifica o executor para a suíte de testes. Atualmente, Vitest é recomendado.- Tipo:
'vitest' | 'jest' | 'cucumber'
- Padrão:
'vitest'
- Tipo:
Exemplo de ponta a ponta do host de destino
Um caso de uso comum para testes de ponta a ponta é executar os testes contra uma aplicação implantada em um ambiente normalmente usado para Produção.
Para desenvolvimento local ou pipelines de implantação automatizados, testar contra um servidor local separado pode ser mais eficiente e geralmente é mais rápido do que permitir que o framework de teste reconstrua entre os testes.
Para utilizar um host de destino separado para testes de ponta a ponta, basta fornecer a propriedade host
da função setup
com a URL desejada.
import { setup, createPage } from '@nuxt/test-utils/e2e'
import { describe, it, expect } from 'vitest'
describe('página de login', async () => {
await setup({
host: 'http://localhost:8787',
})
it('exibe os campos de email e senha', 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)
Obtenha o HTML de uma página renderizada no servidor.
import { $fetch } from '@nuxt/test-utils/e2e'
const html = await $fetch('/')
fetch(url)
Obtenha a resposta de uma página renderizada no servidor.
import { fetch } from '@nuxt/test-utils/e2e'
const res = await fetch('/')
const { body, headers } = res
url(path)
Obtenha a URL completa para uma determinada página (incluindo a porta em que o servidor de teste está sendo executado).
import { url } from '@nuxt/test-utils/e2e'
const pageUrl = url('/page')
// 'http://localhost:6840/page'
Testando em um Navegador
Fornecemos suporte integrado usando Playwright dentro de @nuxt/test-utils
, seja programaticamente ou via o executor de testes Playwright.
createPage(url)
Dentro de vitest
, jest
ou cucumber
, você pode criar uma instância de navegador Playwright configurada com createPage
, e (opcionalmente) apontá-la para um caminho do servidor em execução. Você pode encontrar mais informações sobre os métodos da API disponíveis na documentação do Playwright.
import { createPage } from '@nuxt/test-utils/e2e'
const page = await createPage('/page')
// você pode acessar todas as APIs do Playwright a partir da variável `page`
Testando com o Executor de Testes Playwright
Também fornecemos suporte de primeira classe para testar Nuxt dentro do executor de testes Playwright.
npm i --save-dev @playwright/test @nuxt/test-utils
Você pode fornecer configuração global Nuxt, com os mesmos detalhes de configuração da função setup()
mencionada anteriormente nesta seção.
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))
}
},
// ...
})
Seu arquivo de teste deve então usar expect
e test
diretamente de @nuxt/test-utils/playwright
:
import { expect, test } from '@nuxt/test-utils/playwright'
test('teste', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('Bem-vindo ao Playwright!')
})
Alternativamente, você pode configurar seu servidor Nuxt diretamente dentro de seu arquivo de teste:
import { expect, test } from '@nuxt/test-utils/playwright'
test.use({
nuxt: {
rootDir: fileURLToPath(new URL('..', import.meta.url))
}
})
test('teste', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('Bem-vindo ao Playwright!')
})
※Esta página é uma tradução não oficial da documentação oficial do Nuxt.js.
A página correspondente na documentação oficial está aqui:
https://nuxt.com/docs/3.x/getting-started/testing